modified: n.fq
[GalaxyCodeBases.git] / c_cpp / lib / uthash / doc / utringbuffer.txt
blobeae99a7486420f0d47dc61ec4e0493a25b092bdd
1 utringbuffer: dynamic ring-buffer macros for C
2 ==============================================
3 Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
4 v2.0.2, March 2017
6 Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page].
8 Introduction
9 ------------
10 The functions in `utringbuffer.h` are based on the general-purpose array macros
11 provided in `utarray.h`, so before reading this page you should read
12 link:utarray.html[that page] first.
14 To use these macros in your own C program, copy both `utarray.h` and `utringbuffer.h`
15 into your source directory and use `utringbuffer.h` in your program.
17   #include "utringbuffer.h"
19 The provided <<operations,operations>> are based loosely on the C++ STL vector methods.
20 The ring-buffer data type supports construction (with a specified capacity),
21 destruction, iteration, and push, but not pop; once the ring-buffer reaches full
22 capacity, pushing a new element automatically pops and destroys the oldest element.
23 The elements contained in the ring-buffer can be any simple datatype or structure.
25 Internally the ring-buffer contains a pre-allocated memory region into which the
26 elements are copied, starting at position 0. When the ring-buffer reaches full
27 capacity, the next element to be pushed is pushed at position 0, overwriting the
28 oldest element, and the internal index representing the "start" of the ring-buffer
29 is incremented. A ring-buffer, once full, can never become un-full.
32 Download
33 ~~~~~~~~
34 To download the `utringbuffer.h` header file,
35 follow the links on https://github.com/troydhanson/uthash to clone uthash or get a zip file,
36 then look in the src/ sub-directory.
38 BSD licensed
39 ~~~~~~~~~~~~
40 This software is made available under the
41 link:license.html[revised BSD license].
42 It is free and open source.
44 Platforms
45 ~~~~~~~~~
46 The 'utringbuffer' macros have been tested on:
48  * Linux,
49  * Mac OS X,
50  * Windows, using Visual Studio 2008 and Visual Studio 2010
52 Usage
53 -----
55 Declaration
56 ~~~~~~~~~~~
58 The ring-buffer itself has the data type `UT_ringbuffer`, regardless of the type of
59 elements to be stored in it. It is declared like,
61   UT_ringbuffer *history;
63 New and free
64 ~~~~~~~~~~~~
65 The next step is to create the ring-buffer using `utringbuffer_new`. Later when you're
66 done with the ring-buffer, `utringbuffer_free` will free it and all its elements.
68 Push, etc
69 ~~~~~~~~~
70 The central features of the ring-buffer involve putting elements into it
71 and iterating over them. There are several <<operations,operations>>
72 that deal with either single elements or ranges of elements at a
73 time. In the examples below we will use only the push operation to insert
74 elements.
76 Elements
77 --------
79 Support for dynamic arrays of integers or strings is especially easy. These are
80 best shown by example:
82 Integers
83 ~~~~~~~~
84 This example makes a ring-buffer of integers, pushes 0-9 into it, then prints it
85 two different ways. Lastly it frees it.
87 .Integer elements
88 -------------------------------------------------------------------------------
89 #include <stdio.h>
90 #include "utringbuffer.h"
92 int main() {
93   UT_ringbuffer *history;
94   int i, *p;
96   utringbuffer_new(history, 7, &ut_int_icd);
97   for(i=0; i < 10; i++) utringbuffer_push_back(history, &i);
99   for (p = (int*)utringbuffer_front(history);
100        p != NULL;
101        p = (int*)utringbuffer_next(history, p)) {
102     printf("%d\n", *p);  /* prints "3 4 5 6 7 8 9" */
103   }
105   for (i=0; i < utringbuffer_len(history); i++) {
106     p = utringbuffer_eltptr(history, i);
107     printf("%d\n", *p);  /* prints "3 4 5 6 7 8 9" */
108   }
110   utringbuffer_free(history);
112   return 0;
114 -------------------------------------------------------------------------------
116 The second argument to `utringbuffer_push_back` is always a 'pointer' to the type
117 (so a literal cannot be used). So for integers, it is an `int*`.
119 Strings
120 ~~~~~~~
121 In this example we make a ring-buffer of strings, push two strings into it, print
122 it and free it.
124 .String elements
125 -------------------------------------------------------------------------------
126 #include <stdio.h>
127 #include "utringbuffer.h"
129 int main() {
130   UT_ringbuffer *strs;
131   char *s, **p;
133   utringbuffer_new(strs, 7, &ut_str_icd);
135   s = "hello"; utringbuffer_push_back(strs, &s);
136   s = "world"; utringbuffer_push_back(strs, &s);
137   p = NULL;
138   while ( (p=(char**)utringbuffer_next(strs,p))) {
139     printf("%s\n",*p);
140   }
142   utringbuffer_free(strs);
144   return 0;
146 -------------------------------------------------------------------------------
148 In this example, since the element is a `char*`, we pass a pointer to it
149 (`char**`) as the second argument to `utringbuffer_push_back`. Note that "push" makes
150 a copy of the source string and pushes that copy into the array.
152 About UT_icd
153 ~~~~~~~~~~~~
155 Arrays can be made of any type of element, not just integers and strings. The
156 elements can be basic types or structures. Unless you're dealing with integers
157 and strings (which use pre-defined `ut_int_icd` and `ut_str_icd`), you'll need
158 to define a `UT_icd` helper structure. This structure contains everything that
159 utringbuffer (or utarray) needs to initialize, copy or destruct elements.
161   typedef struct {
162       size_t sz;
163       init_f *init;
164       ctor_f *copy;
165       dtor_f *dtor;
166   } UT_icd;
168 The three function pointers `init`, `copy`, and `dtor` have these prototypes:
170   typedef void (ctor_f)(void *dst, const void *src);
171   typedef void (dtor_f)(void *elt);
172   typedef void (init_f)(void *elt);
174 The `sz` is just the size of the element being stored in the array.
176 The `init` function is used by utarray but is never used by utringbuffer;
177 you may safely set it to any value you want.
179 The `copy` function is used whenever an element is copied into the buffer.
180 It is invoked during `utringbuffer_push_back`.
181 If `copy` is `NULL`, it defaults to a bitwise copy using memcpy.
183 The `dtor` function is used to clean up an element that is being removed from
184 the buffer. It may be invoked due to `utringbuffer_push_back` (on the oldest
185 element in the buffer), `utringbuffer_clear`, `utringbuffer_done`, or
186 `utringbuffer_free`.
187 If the elements need no cleanup upon destruction, `dtor` may be `NULL`.
189 Scalar types
190 ~~~~~~~~~~~~
192 The next example uses `UT_icd` with all its defaults to make a ring-buffer of
193 `long` elements. This example pushes two longs into a buffer of capacity 1,
194 prints the contents of the buffer (which is to say, the most recent value
195 pushed), and then frees the buffer.
197 .long elements
198 -------------------------------------------------------------------------------
199 #include <stdio.h>
200 #include "utringbuffer.h"
202 UT_icd long_icd = {sizeof(long), NULL, NULL, NULL };
204 int main() {
205   UT_ringbuffer *nums;
206   long l, *p;
207   utringbuffer_new(nums, 1, &long_icd);
209   l=1; utringbuffer_push_back(nums, &l);
210   l=2; utringbuffer_push_back(nums, &l);
212   p=NULL;
213   while((p = (long*)utringbuffer_next(nums,p))) printf("%ld\n", *p);
215   utringbuffer_free(nums);
216   return 0;
218 -------------------------------------------------------------------------------
220 Structures
221 ~~~~~~~~~~
223 Structures can be used as utringbuffer elements. If the structure requires no
224 special effort to initialize, copy or destruct, we can use `UT_icd` with all
225 its defaults. This example shows a structure that consists of two integers. Here
226 we push two values, print them and free the buffer.
228 .Structure (simple)
229 -------------------------------------------------------------------------------
230 #include <stdio.h>
231 #include "utringbuffer.h"
233 typedef struct {
234     int a;
235     int b;
236 } intpair_t;
238 UT_icd intpair_icd = {sizeof(intpair_t), NULL, NULL, NULL};
240 int main() {
242   UT_ringbuffer *pairs;
243   intpair_t ip, *p;
244   utringbuffer_new(pairs, 7, &intpair_icd);
246   ip.a=1;  ip.b=2;  utringbuffer_push_back(pairs, &ip);
247   ip.a=10; ip.b=20; utringbuffer_push_back(pairs, &ip);
249   for(p=(intpair_t*)utringbuffer_front(pairs);
250       p!=NULL;
251       p=(intpair_t*)utringbuffer_next(pairs,p)) {
252     printf("%d %d\n", p->a, p->b);
253   }
255   utringbuffer_free(pairs);
256   return 0;
258 -------------------------------------------------------------------------------
260 The real utility of `UT_icd` is apparent when the elements stored in the
261 ring-buffer are structures that require special work to initialize, copy or
262 destruct.
264 For example, when a structure contains pointers to related memory areas that
265 need to be copied when the structure is copied (and freed when the structure is
266 freed), we can use custom `init`, `copy`, and `dtor` members in the `UT_icd`.
268 Here we take an example of a structure that contains an integer and a string.
269 When this element is copied (such as when an element is pushed),
270 we want to "deep copy" the `s` pointer (so the original element and the new
271 element point to their own copies of `s`). When an element is destructed, we
272 want to "deep free" its copy of `s`. Lastly, this example is written to work
273 even if `s` has the value `NULL`.
275 .Structure (complex)
276 -------------------------------------------------------------------------------
277 #include <stdio.h>
278 #include <stdlib.h>
279 #include "utringbuffer.h"
281 typedef struct {
282     int a;
283     char *s;
284 } intchar_t;
286 void intchar_copy(void *_dst, const void *_src) {
287   intchar_t *dst = (intchar_t*)_dst, *src = (intchar_t*)_src;
288   dst->a = src->a;
289   dst->s = src->s ? strdup(src->s) : NULL;
292 void intchar_dtor(void *_elt) {
293   intchar_t *elt = (intchar_t*)_elt;
294   free(elt->s);
297 UT_icd intchar_icd = {sizeof(intchar_t), NULL, intchar_copy, intchar_dtor};
299 int main() {
300   UT_ringbuffer *intchars;
301   intchar_t ic, *p;
302   utringbuffer_new(intchars, 2, &intchar_icd);
304   ic.a=1; ic.s="hello"; utringbuffer_push_back(intchars, &ic);
305   ic.a=2; ic.s="world"; utringbuffer_push_back(intchars, &ic);
306   ic.a=3; ic.s="peace"; utringbuffer_push_back(intchars, &ic);
308   p=NULL;
309   while( (p=(intchar_t*)utringbuffer_next(intchars,p))) {
310     printf("%d %s\n", p->a, (p->s ? p->s : "null"));
311     /* prints "2 world 3 peace" */
312   }
314   utringbuffer_free(intchars);
315   return 0;
318 -------------------------------------------------------------------------------
320 [[operations]]
321 Reference
322 ---------
323 This table lists all the utringbuffer operations. These are loosely based on the C++
324 vector class.
326 Operations
327 ~~~~~~~~~~
329 [width="100%",cols="50<m,40<",grid="none",options="none"]
330 |===============================================================================
331 | utringbuffer_new(UT_ringbuffer *a, int n, UT_icd *icd)  | allocate a new ringbuffer
332 | utringbuffer_free(UT_ringbuffer *a)                     | free an allocated ringbuffer
333 | utringbuffer_init(UT_ringbuffer *a, int n, UT_icd *icd) | init a ringbuffer (non-alloc)
334 | utringbuffer_done(UT_ringbuffer *a)                     | dispose of a ringbuffer (non-alloc)
335 | utringbuffer_clear(UT_ringbuffer *a)                    | clear all elements from a, making it empty
336 | utringbuffer_push_back(UT_ringbuffer *a, element *p)    | push element p onto a
337 | utringbuffer_len(UT_ringbuffer *a)                      | get length of a
338 | utringbuffer_empty(UT_ringbuffer *a)                    | get whether a is empty
339 | utringbuffer_full(UT_ringbuffer *a)                     | get whether a is full
340 | utringbuffer_eltptr(UT_ringbuffer *a, int j)            | get pointer of element from index
341 | utringbuffer_eltidx(UT_ringbuffer *a, element *e)       | get index of element from pointer
342 | utringbuffer_front(UT_ringbuffer *a)                    | get oldest element of a
343 | utringbuffer_next(UT_ringbuffer *a, element *e)         | get element of a following e (front if e is NULL)
344 | utringbuffer_prev(UT_ringbuffer *a, element *e)         | get element of a before e (back if e is NULL)
345 | utringbuffer_back(UT_ringbuffer *a)                     | get newest element of a
346 |===============================================================================
348 Notes
349 ~~~~~
351 1. `utringbuffer_new` and `utringbuffer_free` are used to allocate a new ring-buffer
352    and to free it,
353    while `utringbuffer_init` and `utringbuffer_done` can be used if the UT_ringbuffer
354    is already allocated and just needs to be initialized or have its internal resources
355    freed.
356 2. Both `utringbuffer_new` and `utringbuffer_init` take a second parameter `n` indicating
357    the capacity of the ring-buffer, that is, the size at which the ring-buffer is considered
358    "full" and begins to overwrite old elements with newly pushed ones.
359 3. Once a ring-buffer has become full, it will never again become un-full except by
360    means of `utringbuffer_clear`. There is no way to "pop" a single old item from the
361    front of the ring-buffer. You can simulate this ability by maintaining a separate
362    integer count of the number of "logically popped elements", and starting your iteration
363    with `utringbuffer_eltptr(a, popped_count)` instead of with `utringbuffer_front(a)`.
364 4. Pointers to elements (obtained using `utringbuffer_eltptr`, `utringbuffer_front`,
365    `utringbuffer_next`, etc.) are not generally invalidated by `utringbuffer_push_back`,
366    because utringbuffer does not perform reallocation; however, a pointer to the oldest
367    element may suddenly turn into a pointer to the 'newest' element if
368    `utringbuffer_push_back` is called while the buffer is full.
369 5. The elements of a ring-buffer are stored in contiguous memory, but once the ring-buffer
370    has become full, it is no longer true that the elements are contiguously in order from
371    oldest to newest; i.e., `(element *)utringbuffer_front(a) + utringbuffer_len(a)-1` is
372    not generally equal to `(element *)utringbuffer_back(a)`.
374 // vim: set nowrap syntax=asciidoc: