view buf.h @ 3:9c6b686f797d

misc: add extern C for C++ friends
author David Demelier <markand@malikania.fr>
date Thu, 29 Oct 2020 17:40:28 +0100
parents b1991ee4451d
children 9f4f7a266c0b
line wrap: on
line source

/*
 * buf.h -- simple string buffer for C
 *
 * Copyright (c) 2019-2020 David Demelier <markand@malikania.fr>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef BUF_H
#define BUF_H

/**
 * \file buf.h
 * \brief Simple string buffer for C
 *
 * This module is meant to be copied directly into your source code and adapted
 * to your needs.
 *
 * # Portability
 *
 * This module uses almost pure C99 functions without extensions but uses a few
 * POSIX macros: ENOMEM. The errno global value won't be set if those macros
 * are not present.
 *
 * It also requires the C99 features: `vsnprintf`, `va_copy`.
 *
 * # Allocation strategy
 *
 * This module will always try to allocate twice the existing buffer capacity
 * unless it reaches an overflow. If overflow occurs, it will try to reallocate
 * only the required portion instead. In any case, on 64-bits machine the
 * maximum number is usually around 18.5PB which is far from what the system
 * will allow.
 *
 * Functions use standard `malloc(3)`, `realloc(3)` and `free(3)` functions, if
 * custom allocations are desired, simply edit buf.c and adapt BUF_ macros
 * at the top of the file or set them at compile time.
 */

#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>

/*
 * User/developer options.
 *
 * These macros are only used at compile time and can be redefined using
 * preprocessor directives.
 *
 * - BUF_MALLOC: defaults to malloc
 * - BUF_REALLOC: defaults to realloc
 * - BUF_FREE: defaults to free
 */

/**
 * \brief Function to allocate memory (defaults to malloc).
 */
#if !defined(BUF_MALLOC)
#	define BUF_MALLOC malloc
#endif

/**
 * \brief Function to reallocate memory (defaults to realloc).
 */
#if !defined(BUF_REALLOC)
#	define BUF_REALLOC realloc
#endif

/**
 * \brief Function to free memory (defaults to free).
 */
#if !defined(BUF_FREE)
#	define BUF_FREE free
#endif

#if defined(__cplusplus)
extern "C" {
#endif

/**
 * \brief Buffer structure.
 *
 * You can initialize this structure with 0 before use.
 *
 * You may modify the data member yourself but make sure length member is set
 * accordingly if you change its length.
 *
 * The capacity member contains the available size **without** including the
 * null terminator, this means that a capacity of 5 means you can write 5
 * characters plus the null terminator as every function always allocate one
 * more byte to terminate strings.
 */
struct buf {
	char *data;             /*!< String data. */
	size_t length;          /*!< String length */
	size_t capacity;        /*!< Capacity **not** including null */
};

/**
 * Initialize the string.
 *
 * This is equivalent to `memset(b, 0, sizeof (*b))`.
 *
 * \pre b != NULL
 * \param b the buffer to initialize to 0
 */
void
buf_init(struct buf *b);

/**
 * Reserve more storage to avoid reallocations.
 *
 * This function only change capacity and may reallocate the buffer, length
 * is unchanged.
 *
 * \pre b != NULL
 * \param b the buffer to grow
 * \param desired the additional space to request
 * \return false on error and sets errno
 */
bool
buf_reserve(struct buf *b, size_t desired);

/**
 * Resize the string and sets character into the new storage area if needed.
 *
 * In contrast to \ref buf_reserve, this function change the string length
 * and update the new storage with the given character. If the new size is
 * smaller then only length is updated, otherwise new memory can be reallocated
 * if needed.
 *
 * Use '\0' if you only want to change the length but still have a NUL
 * terminated string.
 *
 * \pre b != NULL
 * \param b the buffer to grow
 * \param size the new size to set
 * \param c the character to fill (use '\0' if not needed)
 * \return false on error and sets errno
 */
bool
buf_resize(struct buf *b, size_t size, char c);

/**
 * Reallocate the string to the string's length.
 *
 * If the function could not reallocate the memory, the old string buffer is
 * kept so it is not strictly necessary to check the result.
 *
 * \pre b != NULL
 * \param b the buffer to grow
 * \return true if the string buffer was actually shrinked
 */
bool
buf_shrink(struct buf *b);

/**
 * Erase a portion of the string.
 *
 * \pre b != NULL
 * \pre pos <= b->length
 * \param b the string buffer
 * \param pos the beginning of the portion
 * \param count the number of characters to remove or -1 to remove up to the end
 */
void
buf_erase(struct buf *b, size_t pos, size_t count);

/**
 * Put a single character.
 *
 * \note This function can be slow for large amount of data.
 * \pre b != NULL
 * \param b the string buffer
 * \param c the character to append
 * \return false on error and sets errno
 */
bool
buf_putc(struct buf *b, char c);

/**
 * Put a string.
 *
 * \pre b != NULL
 * \pre s != NULL
 * \param b the string buffer
 * \param s the string to append
 * \return false on error and sets errno
 */
bool
buf_puts(struct buf *b, const char *s);

/**
 * Append to the string using printf(3) format.
 *
 * \pre b != NULL
 * \pre fmt != NULL
 * \param b the string buffer
 * \param fmt the printf(3) format string
 * \param ... additional arguments
 * \return false on error and sets errno
 */
bool
buf_printf(struct buf *b, const char *fmt, ...);

/**
 * Similar to \ref buf_printf but using `va_list`.
 *
 * \pre b != NULL
 * \pre fmt != NULL
 * \param b the string buffer
 * \param fmt the printf(3) format string
 * \param ap the variadic arguments pointer
 * \return false on error and sets errno
 */
bool
buf_vprintf(struct buf *b, const char *fmt, va_list ap);

/**
 * Cut a portion of the string pointed by src into b.
 *
 * The pointer b must not contain data as it will be overriden and may be let
 * uninitialized.
 *
 * \pre b != NULL
 * \pre src != NULL
 * \pre pos <= b->length
 * \param b the string buffer
 * \param src the source origin
 * \param pos the beginning of the portion
 * \param count the number of characters to remove or -1 to split up to the end
 * \return false on error and sets errno
 */
bool
buf_sub(struct buf *b, const struct buf *src, size_t pos, size_t count);

/**
 * Duplicate a string buffer.
 *
 * The pointer b must not contain data as it will be overriden and may be let
 * uninitialized.
 *
 * \pre b != NULL
 * \pre src != NULL
 * \param b the string buffer
 * \param src the source origin
 * \return false on error and sets errno
 */
bool
buf_dup(struct buf *b, const struct buf *src);

/**
 * Clear the buffer.
 *
 * This function only change the string length, use \ref buf_shrink if you
 * want to reduce memory usage.
 *
 * \pre b != NULL
 * \param b the string to update
 */
void
buf_clear(struct buf *b);

/**
 * Clear the buffer.
 *
 * This function will effectively free the data member and set all members to
 * 0.
 *
 * \pre b != NULL
 * \param b the buffer to clear
 */
void
buf_finish(struct buf *b);

#if defined(__cplusplus)
}
#endif

#endif /* !BUF_H */