ossp-pkg/sio/BRAINSTORM/stash-buf.txt
/* -*- mode: c ; c-file-style: "canonware-c-style" -*-
****************************************************************************
*
* Copyright (C) 1996-1999 Jason Evans <jasone@canonware.com>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice(s), this list of conditions and the following disclaimer as
* the first lines of this file unmodified other than the possible
* addition of one or more copyright notices.
* 2. Redistributions in binary form must reproduce the above copyright
* notice(s), this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************
*
* Version: s19990524a
*
* <<< Description >>>
*
* The buf and bufc classes implement a buffer abstraction. These classes are
* designed specifically to handle streaming and transparent extensible
* buffering of data for applications such as socket programs. The main
* features include:
*
* - Dynamically extensible and contractible buffering.
* - Internal reference counting, which avoids copying between buf's, and allows
* for compact usage of memory buffers.
* - 8, 32, and 64 bit read functions for arbitrary byte offsets (within the
* valid data range) within buf's.
* - 8, 32, and 64 bit, and string, write/append functions for arbitrary byte
* offsets.
* - Easy ability to use with readv() and writev().
*
****************************************************************************/
/* Pseudo-opaque typedefs. */
typedef struct cw_buf_s cw_buf_t;
typedef struct cw_bufc_s cw_bufc_t;
/* Opaque typedef. */
typedef struct cw_bufel_s cw_bufel_t;
/* The following data types should be considered opaque. */
struct cw_bufc_s
{
#if (defined(_LIBSTASH_DBG) || defined(_LIBSTASH_DEBUG))
cw_uint32_t magic;
#endif
#ifdef _CW_REENTRANT
cw_mtx_t lock;
#endif
void (*dealloc_func)(void *, void *);
void * dealloc_arg;
void (*buffer_dealloc_func)(void *, void *);
void * buffer_dealloc_arg;
cw_uint32_t ref_count;
cw_bool_t is_writeable;
cw_uint32_t buf_size;
cw_uint8_t * buf;
};
struct cw_buf_s
{
#if (defined(_LIBSTASH_DBG) || defined(_LIBSTASH_DEBUG))
cw_uint32_t magic;
#endif
cw_bool_t is_malloced;
#ifdef _CW_REENTRANT
cw_bool_t is_threadsafe;
cw_mtx_t lock;
#endif
cw_uint32_t size;
cw_uint32_t array_size;
cw_uint32_t array_num_valid;
cw_uint32_t array_start;
cw_uint32_t array_end;
cw_bool_t is_cumulative_valid;
cw_bool_t is_cached_bufel_valid;
cw_uint32_t cached_bufel;
cw_bufel_t * bufel_array;
cw_uint32_t * cumulative_index;
struct iovec * iov;
};
/****************************************************************************
*
* <<< Input(s) >>>
*
* a_buf : Pointer to space for a buf, or NULL.
*
* a_is_thread_safe : FALSE == not thread safe, TRUE == thread safe.
*
* <<< Output(s) >>>
*
* retval : Pointer to a buf, or NULL.
* NULL : Memory allocation error.
*
* <<< Description >>>
*
* Constructor.
*
****************************************************************************/
#ifdef _CW_REENTRANT
cw_buf_t *
buf_new(cw_buf_t * a_buf, cw_bool_t a_is_threadsafe);
#else
cw_buf_t *
buf_new(cw_buf_t * a_buf);
#endif
/****************************************************************************
*
* <<< Input(s) >>>
*
* a_buf : Pointer to a buf.
*
* <<< Output(s) >>>
*
* None.
*
* <<< Description >>>
*
* Destructor.
*
****************************************************************************/
void
buf_delete(cw_buf_t * a_buf);
/****************************************************************************
*
* <<< Input(s) >>>
*
* a_buf : Pointer to a buf.
*
* a_prefix : Pointer to a string that represents a string to be prefixed to
* each line of output.
*
* <<< Output(s) >>>
*
* None.
*
* <<< Description >>>
*
* Dump the internal state of a_buf to cw_g_log.
*
****************************************************************************/
void
buf_dump(cw_buf_t * a_buf, const char * a_prefix);
/****************************************************************************
*
* <<< Input(s) >>>
*
* a_buf : Pointer to a buf.
*
* <<< Output(s) >>>
*
* retval : Number of bytes of valid data.
*
* <<< Description >>>
*
* Return the amount of valid data in bytes.
*
****************************************************************************/
cw_uint32_t
buf_get_size(cw_buf_t * a_buf);
/****************************************************************************
*
* <<< Input(s) >>>
*
* a_buf : Pointer to a buf.
*
* <<< Output(s) >>>
*
* retval : Number of bufel's in a_buf (same as iovec count in buf_get_iovec()).
*
* <<< Description >>>
*
* Return the number of bufel's in a_buf.
*
****************************************************************************/
cw_uint32_t
buf_get_num_bufels(cw_buf_t * a_buf);
/****************************************************************************
*
* <<< Input(s) >>>
*
* a_buf : Pointer to a buf.
*
* a_max_data : Maximum number of bytes of space to include in the iovec.
*
* a_is_sys_iovec : If TRUE, limit *r_iovec_count to the maximum iovec count
* supported by this system for readv()/writev().
*
* a_iovec_count : Pointer to an int.
*
* <<< Output(s) >>>
*
* retval : Pointer to an iovec array that represents the internal data buffers
* in a_buf.
*
* *r_iovec_count : Number of valid iovec structures in retval.
*
* <<< Description >>>
*
* Build an iovec array that represents the valid data in a_buf's internal
* buffers (up to a_max_data bytes) and return a pointer to it.
*
****************************************************************************/
const struct iovec *
buf_get_iovec(cw_buf_t * a_buf, cw_uint32_t a_max_data,
cw_bool_t a_is_sys_iovec, int * r_iovec_count);
/****************************************************************************
*
* <<< Input(s) >>>
*
* a_a : Pointer to a buf.
*
* a_b : Pointer to a buf.
*
* a_preserve : If TRUE, preserve a_b (don't modify it). If FALSE, release the
* data in a_b after catenating a_b to a_a.
*
* <<< Output(s) >>>
*
* retval : FALSE == success, TRUE == error.
* TRUE : Memory allocation error.
*
* <<< Description >>>
*
* Catenate two bufs. a_b is left unmodified if a_preserve is TRUE.
*
****************************************************************************/
cw_bool_t
buf_catenate_buf(cw_buf_t * a_a, cw_buf_t * a_b, cw_bool_t a_preserve);
/****************************************************************************
*
* <<< Input(s) >>>
*
* a_a : Pointer to a buf.
*
* a_b : Pointer to a buf.
*
* a_offset : Offset at which to split a_b.
*
* <<< Output(s) >>>
*
* retval : FALSE == success, TRUE == error.
* TRUE : Memory allocation error. a_a and a_b are returned to their
* original states.
*
* <<< Description >>>
*
* Split a_b at offset a_offset. Append the data before a_offset to a_a, and
* leave the remainder in a_b.
*
****************************************************************************/
cw_bool_t
buf_split(cw_buf_t * a_a, cw_buf_t * a_b, cw_uint32_t a_offset);
/****************************************************************************
*
* <<< Input(s) >>>
*
* a_buf : Pointer to a buf.
*
* a_bufel : Pointer to a bufel.
*
* <<< Output(s) >>>
*
* retval : FALSE == success, TRUE == error.
* TRUE : Memory allocation error. a_buf is still valid.
*
* <<< Description >>>
*
* Prepend the data from a_bufel to a_buf. a_bufel is not modified.
*
****************************************************************************/
cw_bool_t
buf_prepend_bufel(cw_buf_t * a_buf, cw_bufel_t * a_bufel);
/****************************************************************************
*
* <<< Input(s) >>>
*
* a_buf : Pointer to a buf.
*
* a_bufc : Pointer to a bufc.
*
* a_beg_offset : Offset of first valid byte in a_bufc's memory buffer.
*
* a_end_offset : Offset of first byte past the valid range of bytes in a_bufc's
* memory buffer.
*
* <<< Output(s) >>>
*
* retval : FALSE == success, TRUE == error.
* TRUE : Memory allocation error. a_buf is still valid.
*
* <<< Description >>>
*
* Prepend a_bufc, bytes a_beg_offset .. (a_end_offset - 1) to a_buf.
*
****************************************************************************/
cw_bool_t
buf_prepend_bufc(cw_buf_t * a_buf, cw_bufc_t * a_bufc,
cw_uint32_t a_beg_offset, cw_uint32_t a_end_offset);
/****************************************************************************
*
* <<< Input(s) >>>
*
* a_buf : Pointer to a buf.
*
* a_bufc : Pointer to a bufc.
*
* a_beg_offset : Offset of first valid byte in a_bufc's memory buffer.
*
* a_end_offset : Offset of first byte past the valid range of bytes in a_bufc's
* memory buffer.
*
* <<< Output(s) >>>
*
* retval : FALSE == success, TRUE == error.
* TRUE : Memory allocation error. a_buf is still valid.
*
* <<< Description >>>
*
* Append a_bufc, bytes a_beg_offset .. (a_end_offset - 1) to a_buf.
*
****************************************************************************/
cw_bool_t
buf_append_bufc(cw_buf_t * a_buf, cw_bufc_t * a_bufc,
cw_uint32_t a_beg_offset, cw_uint32_t a_end_offset);
/****************************************************************************
*
* <<< Input(s) >>>
*
* a_buf : Pointer to a buf.
*
* a_bufel : Pointer to a bufel.
*
* <<< Output(s) >>>
*
* retval : FALSE == success, TRUE == error.
* TRUE : Memory allocation error. a_buf is still valid.
*
* <<< Description >>>
*
* Append the data from a_bufel to a_buf. a_bufel is not modified.
*
****************************************************************************/
cw_bool_t
buf_append_bufel(cw_buf_t * a_buf, cw_bufel_t * a_bufel);
/****************************************************************************
*
* <<< Input(s) >>>
*
* a_buf : Pointer to a buf.
*
* a_amount : Number of bytes of data to release from the head of a_buf.
*
* <<< Output(s) >>>
*
* retval : FALSE == success, TRUE == error.
*
* <<< Description >>>
*
* Release a_amount bytes from the head of a_buf.
*
****************************************************************************/
cw_bool_t
buf_release_head_data(cw_buf_t * a_buf, cw_uint32_t a_amount);
/****************************************************************************
*
* <<< Input(s) >>>
*
* a_buf : Pointer to a buf.
*
* a_amount : Number of bytes of data to release from the tail of a_buf.
*
* <<< Output(s) >>>
*
* retval : FALSE == success, TRUE == error.
*
* <<< Description >>>
*
* Release a_amount bytes from the tail of a_buf.
*
****************************************************************************/
cw_bool_t
buf_release_tail_data(cw_buf_t * a_buf, cw_uint32_t a_amount);
/****************************************************************************
*
* <<< Input(s) >>>
*
* a_buf : Pointer to a buf.
*
* a_offset : Offset in bytes of uint8 to return.
*
* <<< Output(s) >>>
*
* retval : Value of the uint8 at offset a_offset in a_buf.
*
* <<< Description >>>
*
* Return the uint8 at offset a_offset.
*
****************************************************************************/
cw_uint8_t
buf_get_uint8(cw_buf_t * a_buf, cw_uint32_t a_offset);
/****************************************************************************
*
* <<< Input(s) >>>
*
* a_buf : Pointer to a buf.
*
* a_offset : Offset in bytes of uint32 to return.
*
* <<< Output(s) >>>
*
* retval : Value of the uint32 at offset a_offset in a_buf.
*
* <<< Description >>>
*
* Return the uint32 at offset a_offset.
*
****************************************************************************/
cw_uint32_t
buf_get_uint32(cw_buf_t * a_buf, cw_uint32_t a_offset);
/****************************************************************************
*
* <<< Input(s) >>>
*
* a_buf : Pointer to a buf.
*
* a_offset : Offset in bytes of uint64 to return.
*
* <<< Output(s) >>>
*
* retval : Value of the uint64 at offset a_offset in a_buf.
*
* <<< Description >>>
*
* Return the uint64 at offset a_offset.
*
****************************************************************************/
cw_uint64_t
buf_get_uint64(cw_buf_t * a_buf, cw_uint32_t a_offset);
/****************************************************************************
*
* <<< Input(s) >>>
*
* a_buf : Pointer to a buf.
*
* a_offset : Offset in bytes of data to set. (a_offset <= buf_get_size(a_buf))
*
* a_val : Value to set data at a_offset to.
*
* <<< Output(s) >>>
*
* retval : FALSE == success, TRUE == error.
* TRUE : memory allocation error.
*
* <<< Description >>>
*
* Set the uint8 at a_offset to a_val.
*
****************************************************************************/
cw_bool_t
buf_set_uint8(cw_buf_t * a_buf, cw_uint32_t a_offset, cw_uint8_t a_val);
/****************************************************************************
*
* <<< Input(s) >>>
*
* a_buf : Pointer to a buf.
*
* a_offset : Offset in bytes of data to set. (a_offset <= buf_get_size(a_buf))
*
* a_val : Value to set data at a_offset to.
*
* <<< Output(s) >>>
*
* retval : FALSE == success, TRUE == error.
* TRUE : memory allocation error.
*
* <<< Description >>>
*
* Set the uint32 at a_offset to a_val.
*
****************************************************************************/
cw_bool_t
buf_set_uint32(cw_buf_t * a_buf, cw_uint32_t a_offset, cw_uint32_t a_val);
/****************************************************************************
*
* <<< Input(s) >>>
*
* a_buf : Pointer to a buf.
*
* a_offset : Offset in bytes of data to set. (a_offset <= buf_get_size(a_buf))
*
* a_val : Value to set data at a_offset to.
*
* <<< Output(s) >>>
*
* retval : FALSE == success, TRUE == error.
* TRUE : memory allocation error.
*
* <<< Description >>>
*
* Set the uint64 at a_offset to a_val.
*
****************************************************************************/
cw_bool_t
buf_set_uint64(cw_buf_t * a_buf, cw_uint32_t a_offset, cw_uint64_t a_val);
/****************************************************************************
*
* <<< Input(s) >>>
*
* a_buf : Pointer to a buf.
*
* a_offset : Offset in bytes of data to set. (a_offset <= buf_get_size(a_buf))
*
* a_length : Number of bytes to copy from a_val.
*
* a_val : Value to set data at a_offset to.
*
* a_is_writeable : FALSE == non-writeable buffer, TRUE == writeable buffer.
*
* <<< Output(s) >>>
*
* retval : FALSE == success, TRUE == error.
* TRUE : memory allocation error.
*
* <<< Description >>>
*
* Copy a_offset bytes from a_val to a_buf at offset a_offset.
*
****************************************************************************/
cw_bool_t
buf_set_range(cw_buf_t * a_buf, cw_uint32_t a_offset, cw_uint32_t a_length,
cw_uint8_t * a_val, cw_bool_t a_is_writeable);
/****************************************************************************
*
* <<< Input(s) >>>
*
* a_bufc : Pointer to space for a bufc, or NULL.
*
* a_dealloc_func : Pointer to a deallocation function for a_bufc, or NULL.
* Ignored if a_bufc == NULL.
*
* a_dealloc_arg : First argument to a_dealloc_func.
*
* <<< Output(s) >>>
*
* retval : Pointer to an initialized bufc, or NULL.
* NULL : Memory allocation error.
*
* <<< Description >>>
*
* Constructor. The return value should be used in a call to bufc_set_buffer(),
* then bufel_set_bufc(). bufc_delete() can be called at any time up until the
* call to bufel_set_bufc() to deallocate, but should not be called thereafter.
*
****************************************************************************/
cw_bufc_t *
bufc_new(cw_bufc_t * a_bufc,
void (*a_dealloc_func)(void * dealloc_arg, void * bufel),
void * a_dealloc_arg);
/****************************************************************************
*
* <<< Input(s) >>>
*
* a_bufc : Pointer to a bufc.
*
* <<< Output(s) >>>
*
* None.
*
* <<< Description >>>
*
* Destructor. Only call this if a_bufc was never used in a call to
* bufel_set_bufc().
*
****************************************************************************/
void
bufc_delete(cw_bufc_t * a_bufc);
/****************************************************************************
*
* <<< Input(s) >>>
*
* a_bufc : Pointer to a bufc.
*
* a_buffer : Pointer to a buffer.
*
* a_size : Size of *a_buffer.
*
* a_dealloc_func : Pointer to a deallocation function for a_buffer, or NULL.
*
* a_dealloc_arg : First argument to a_dealloc_func.
*
* <<< Output(s) >>>
*
* None.
*
* <<< Description >>>
*
* Set a_bufc's internal data buffer to a_buffer, with size a_size, and
* deallocation function a_dealloc_func(a_dealloc_arg, a_buffer).
*
****************************************************************************/
void
bufc_set_buffer(cw_bufc_t * a_bufc, void * a_buffer, cw_uint32_t a_size,
cw_bool_t a_is_writeable,
void (*a_dealloc_func)(void * dealloc_arg, void * buffer),
void * a_dealloc_arg);