| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- /*
- Copyright (c) 2008-2014, Troy D. Hanson http://troydhanson.github.com/uthash/
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 OWNER
- OR CONTRIBUTORS 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.
- */
- /* a ring-buffer implementation using macros
- */
- #ifndef UTRINGBUFFER_H
- #define UTRINGBUFFER_H
-
- #include <stdlib.h>
- #include <string.h>
- #include "utarray.h" // for "UT_icd"
-
- typedef struct {
- unsigned i; /* index of next available slot; wraps at n */
- unsigned n; /* capacity */
- unsigned char f; /* full */
- UT_icd icd; /* initializer, copy and destructor functions */
- char *d; /* n slots of size icd->sz */
- } UT_ringbuffer;
-
- #define utringbuffer_init(a, _n, _icd) do { \
- memset(a, 0, sizeof(UT_ringbuffer)); \
- (a)->icd = *(_icd); \
- (a)->n = (_n); \
- if ((a)->n) { (a)->d = malloc((a)->n * (_icd)->sz); } \
- } while(0)
-
- #define utringbuffer_clear(a) do { \
- if ((a)->icd.dtor) { \
- if ((a)->f) { \
- for (unsigned _ut_i=0; _ut_i < (a)->n; _ut_i++) { \
- (a)->icd.dtor(utringbuffer_eltptr(a, _ut_i)); \
- } \
- } else { \
- for (unsigned _ut_i=0; _ut_i < (a)->i; _ut_i++) { \
- (a)->icd.dtor(utringbuffer_eltptr(a, _ut_i)); \
- } \
- } \
- } \
- (a)->i = 0; \
- (a)->f = 0; \
- } while(0)
-
- #define utringbuffer_done(a) do { \
- utringbuffer_clear(a); \
- free((a)->d); (a)->d = NULL; \
- (a)->n = 0; \
- } while(0)
-
- #define utringbuffer_new(a,n,_icd) do { \
- a = (UT_ringbuffer*)malloc(sizeof(UT_ringbuffer)); \
- utringbuffer_init(a, n, _icd); \
- } while(0)
-
- #define utringbuffer_free(a) do { \
- utringbuffer_done(a); \
- free(a); \
- } while(0)
-
- #define utringbuffer_push_back(a,p) do { \
- if ((a)->icd.dtor && (a)->f) { (a)->icd.dtor(_utringbuffer_internalptr(a,(a)->i)); } \
- if ((a)->icd.copy) { (a)->icd.copy( _utringbuffer_internalptr(a,(a)->i), p); } \
- else { memcpy(_utringbuffer_internalptr(a,(a)->i), p, (a)->icd.sz); }; \
- if (++(a)->i == (a)->n) { (a)->i = 0; (a)->f = 1; } \
- } while(0)
-
- #define utringbuffer_len(a) ((a)->f ? (a)->n : (a)->i)
- #define utringbuffer_empty(a) ((a)->i == 0 && !(a)->f)
- #define utringbuffer_full(a) ((a)->f != 0)
-
- #define _utringbuffer_real_idx(a,j) ((a)->f ? ((j) + (a)->i) % (a)->n : (j))
- #define _utringbuffer_internalptr(a,j) ((void*)((char*)((a)->d + ((a)->icd.sz * (j)))))
- #define utringbuffer_eltptr(a,j) ((0 <= (j) && (j) < utringbuffer_len(a)) ? _utringbuffer_internalptr(a,_utringbuffer_real_idx(a,j)) : NULL)
-
- #define _utringbuffer_fake_idx(a,j) ((a)->f ? ((j) + (a)->n - (a)->i) % (a)->n : (j))
- #define _utringbuffer_internalidx(a,e) (((char*)(e) >= (char*)(a)->d) ? (((char*)(e) - (char*)(a)->d)/(size_t)(a)->icd.sz) : -1)
- #define utringbuffer_eltidx(a,e) _utringbuffer_fake_idx(a, _utringbuffer_internalidx(a,e))
-
- #define utringbuffer_front(a) utringbuffer_eltptr(a,0)
- #define utringbuffer_next(a,e) ((e)==NULL ? utringbuffer_front(a) : utringbuffer_eltptr(a, utringbuffer_eltidx(a,e)+1))
- #define utringbuffer_prev(a,e) ((e)==NULL ? utringbuffer_back(a) : utringbuffer_eltptr(a, utringbuffer_eltidx(a,e)-1))
- #define utringbuffer_back(a) (utringbuffer_empty(a) ? NULL : utringbuffer_eltptr(a, utringbuffer_len(a) - 1))
- #endif /* UTRINGBUFFER_H */
|