From acc5344796192524e66315f3a8831b419314f88c Mon Sep 17 00:00:00 2001 From: Michal Vaner Date: Tue, 4 Nov 2008 22:46:56 +0100 Subject: [PATCH] ucw docs: growing buffers --- ucw/bbuf.h | 24 ++++++++++++++++++++ ucw/doc/Makefile | 2 +- ucw/doc/generic.txt | 1 + ucw/doc/growbuf.txt | 41 +++++++++++++++++++++++++++++++++ ucw/gbuf.h | 55 +++++++++++++++++++++++++++++++++------------ ucw/mempool.h | 2 ++ 6 files changed, 110 insertions(+), 15 deletions(-) create mode 100644 ucw/doc/growbuf.txt diff --git a/ucw/bbuf.h b/ucw/bbuf.h index 24c2c0b9..ecc1f66c 100644 --- a/ucw/bbuf.h +++ b/ucw/bbuf.h @@ -14,9 +14,33 @@ #define GBUF_PREFIX(x) bb_##x #include "ucw/gbuf.h" +/** + * printf() into a growing buffer with `va_list` arguments. + * Generates a `'\0'`-terminated string at the beginning of the buffer + * and returns pointer to it. + * + * See @bb_printf(). + **/ char *bb_vprintf(bb_t *bb, const char *fmt, va_list args); +/** + * printf() into a growing buffer. + * Generates a `'\0'`-terminated string at the beginning of the buffer + * and returns pointer to it. + * + * See @bb_vprintf(). + **/ char *bb_printf(bb_t *bb, const char *fmt, ...); +/** + * Like @bb_vprintf(), but it does not start at the beginning of the + * buffer, but @ofs bytes further. + * + * Returns pointer to the new string (eg. @ofs bytes after the + * beginning of buffer). + **/ char *bb_vprintf_at(bb_t *bb, uns ofs, const char *fmt, va_list args); +/** + * Like @bb_vprintf_at(), but it takes individual arguments. + **/ char *bb_printf_at(bb_t *bb, uns ofs, const char *fmt, ...); #endif diff --git a/ucw/doc/Makefile b/ucw/doc/Makefile index b404bf93..d416f9f3 100644 --- a/ucw/doc/Makefile +++ b/ucw/doc/Makefile @@ -2,7 +2,7 @@ DIRS+=ucw/doc -UCW_DOCS=fastbuf index config configure install basecode hash docsys conf mempool mainloop generic +UCW_DOCS=fastbuf index config configure install basecode hash docsys conf mempool mainloop generic growbuf UCW_INDEX=$(o)/ucw/doc/def_index.html UCW_DOCS_HTML=$(addprefix $(o)/ucw/doc/,$(addsuffix .html,$(UCW_DOCS))) diff --git a/ucw/doc/generic.txt b/ucw/doc/generic.txt index 0be825a3..3e1c1e3b 100644 --- a/ucw/doc/generic.txt +++ b/ucw/doc/generic.txt @@ -10,6 +10,7 @@ libUCW, and also hints for use of these structures. - <> - <> - Modules with generics + * <> // TODO The module list diff --git a/ucw/doc/growbuf.txt b/ucw/doc/growbuf.txt new file mode 100644 index 00000000..218f7d24 --- /dev/null +++ b/ucw/doc/growbuf.txt @@ -0,0 +1,41 @@ +Growing buffers +=============== + +It is quite usual situation when you need an array of items and you +don not know how large it will be in the time you allocate it. Then +you need some kind of dynamically growing buffer. + +You can either use <>, which has similar +functionality, or this module. + +- <> +- <> + +[[gbuf]] +Generic growing buffers +----------------------- + +The generic buffers are in `ucw/gbuf.h`. They are <>. To use them, you need to define: + +- `GBUF_PREFIX(name)` -- the identifier generating macro. +- `GBUF_TYPE` -- the data type they operate with. + +You may define `GBUF_TRACE(\...)` macro. If you do, it will be used to +log the growing of the buffer. The macro should act like printf() -- +the first parameter will be format, the rest variables for it. + +!!ucw/gbuf.h GBUF_PREFIX + +[[bbuf]] +Growing buffers for byte-sized items +------------------------------------ + +It is often needed to allocate the buffer by bytes (if you handle some +anonymous data) or characters (strings of unknown length). + +With the `ucw/bbuf.h` header, you get an instance of growing buffers +with type `byte` and prefix `bb_`. Aside from that, you get few +functions to manipulate strings in the buffers. + +!!ucw/bbuf.h diff --git a/ucw/gbuf.h b/ucw/gbuf.h index daf0bfbb..4bcbe27d 100644 --- a/ucw/gbuf.h +++ b/ucw/gbuf.h @@ -14,24 +14,37 @@ * of the GNU Lesser General Public License. */ +/** + * Type identifier of the buffer. + * The macro is not available outside the header file, + * but it is used in the definitions of functions. + **/ #define BUF_T GBUF_PREFIX(t) -typedef struct BUF_T -{ +/** + * The growing buffer. + * `ptr` holds the memory and `len` is the current + * length of available memory. + **/ +typedef struct BUF_T { uns len; GBUF_TYPE *ptr; -} -BUF_T; +} BUF_T; -static inline void -GBUF_PREFIX(init)(BUF_T *b) +/** + * Initializes an empty growing buffer in @b. + **/ +static inline void GBUF_PREFIX(init)(BUF_T *b) { b->ptr = NULL; b->len = 0; } -static void UNUSED -GBUF_PREFIX(done)(BUF_T *b) +/** + * Frees all memory in the buffer and returns it + * to an empty state. + **/ +static void UNUSED GBUF_PREFIX(done)(BUF_T *b) { if (b->ptr) xfree(b->ptr); @@ -39,8 +52,15 @@ GBUF_PREFIX(done)(BUF_T *b) b->len = 0; } -static void UNUSED -GBUF_PREFIX(set_size)(BUF_T *b, uns len) +/** + * Sets the length of the buffer @b to exactly @len. + * Do not use for the growing (you can use this at the end, + * when you know the exact size), it would be slow. + * + * Use <> + * for growing. + **/ +static void UNUSED GBUF_PREFIX(set_size)(BUF_T *b, uns len) { b->len = len; b->ptr = xrealloc(b->ptr, len * sizeof(GBUF_TYPE)); @@ -49,16 +69,23 @@ GBUF_PREFIX(set_size)(BUF_T *b, uns len) #endif } -static void UNUSED -GBUF_PREFIX(do_grow)(BUF_T *b, uns len) +static void UNUSED GBUF_PREFIX(do_grow)(BUF_T *b, uns len) { if (len < 2*b->len) // to ensure logarithmic cost len = 2*b->len; GBUF_PREFIX(set_size)(b, len); } -static inline GBUF_TYPE * -GBUF_PREFIX(grow)(BUF_T *b, uns len) +/** + * Sets the size of the buffer @b to at last @len. + * It grows in exponential manner, to ensure the total cost + * of reallocs is linear with the final size. + * + * You can tweak the final size (when you do not need to grow + * any more) by + * <>. + **/ +static inline GBUF_TYPE *GBUF_PREFIX(grow)(BUF_T *b, uns len) { if (unlikely(len > b->len)) GBUF_PREFIX(do_grow)(b, len); diff --git a/ucw/mempool.h b/ucw/mempool.h index f566b79c..e9755983 100644 --- a/ucw/mempool.h +++ b/ucw/mempool.h @@ -157,6 +157,8 @@ static inline void *mp_alloc_fast_noalign(struct mempool *pool, uns size) * You do not need to know, how a buffer will need to be large, * you can grow it incrementally to needed size. You can grow only * one buffer at a time on a given mempool. + * + * Similar functionality is provided by <> module. ***/ /* For internal use only, do not call directly */ -- 2.39.2