sync \
qache \
string str-esc str-split str-match str-imatch str-hex \
- bbuf \
+ bbuf gary \
getopt \
strtonum
string.h stkstring.h unicode.h chartype.h regex.h \
wildmatch.h \
unaligned.h prefetch.h \
- bbuf.h gbuf.h bitarray.h bitsig.h \
+ bbuf.h gbuf.h gary.h bitarray.h bitsig.h \
hashfunc.h hashtable.h \
heap.h binheap.h binheap-node.h \
redblack.h \
slists.test bbuf.test kmp-test.test getopt.test ff-unicode.test eltpool.test \
fb-socket.test trie-test.test string.test sha1.test asort-test.test binheap-test.test \
redblack-test.test fb-file.test fb-grow.test fb-pool.test fb-atomic.test \
- fb-limfd.test fb-temp.test fb-mem.test fb-buffer.test fb-mmap.test url.test strtonum-test.test)
+ fb-limfd.test fb-temp.test fb-mem.test fb-buffer.test fb-mmap.test url.test strtonum-test.test \
+ gary.test)
$(o)/ucw/regex.test: $(o)/ucw/regex-t
$(o)/ucw/unicode.test: $(o)/ucw/unicode-t
$(addprefix $(o)/ucw/fb-,file.test grow.test pool.test socket.test atomic.test \
limfd.test temp.test mem.test buffer.test mmap.test): %.test: %-t
$(o)/ucw/url.test: $(o)/ucw/url-t
+$(o)/ucw/gary.test: $(o)/ucw/gary-t
ifdef CONFIG_UCW_THREADS
TESTS+=$(addprefix $(o)/ucw/,asio.test)
--- /dev/null
+/*
+ * UCW Library -- A simple growing array of an arbitrary type
+ *
+ * (c) 2010 Martin Mares <mj@ucw.cz>
+ */
+
+#undef LOCAL_DEBUG
+
+#include "ucw/lib.h"
+#include "ucw/gary.h"
+
+void *
+gary_init(size_t elt_size, size_t num_elts)
+{
+ DBG("GARY: Init to %zd elements", num_elts);
+ struct gary_hdr *h = xmalloc(GARY_HDR_SIZE + elt_size * num_elts);
+ h->num_elts = h->have_space = num_elts;
+ h->elt_size = elt_size;
+ return (byte *)h + GARY_HDR_SIZE;
+}
+
+void
+gary_free(void *array)
+{
+ xfree(GARY_HDR(array));
+}
+
+static struct gary_hdr *
+gary_realloc(struct gary_hdr *h, size_t n)
+{
+ if (n > 2*h->have_space)
+ h->have_space = n;
+ else
+ h->have_space *= 2;
+ DBG("GARY: Resize to %zd elements (need %zd)", h->have_space, n);
+ return xrealloc(h, GARY_HDR_SIZE + h->have_space * h->elt_size);
+}
+
+void *
+gary_set_size(void *array, size_t n)
+{
+ struct gary_hdr *h = GARY_HDR(array);
+ h->num_elts = n;
+ if (n <= h->have_space)
+ return array;
+
+ h = gary_realloc(h, n);
+ return GARY_BODY(h);
+}
+
+void *
+gary_push_helper(void *array, size_t n, byte **cptr)
+{
+ struct gary_hdr *h = GARY_HDR(array);
+ h = gary_realloc(h, h->num_elts);
+ *cptr = GARY_BODY(h) + (h->num_elts - n) * h->elt_size;
+ return GARY_BODY(h);
+}
+
+void *
+gary_fix(void *array)
+{
+ struct gary_hdr *h = GARY_HDR(array);
+ if (h->num_elts != h->have_space)
+ {
+ h = xrealloc(h, GARY_HDR_SIZE + h->num_elts * h->elt_size);
+ h->have_space = h->num_elts;
+ }
+ return GARY_BODY(h);
+}
+
+#ifdef TEST
+
+#include <stdio.h>
+
+int main(void)
+{
+ int *a;
+ GARY_INIT(a, 5);
+
+ for (int i=0; i<5; i++)
+ a[i] = i+1;
+
+ *GARY_PUSH(a, 1) = 10;
+ *GARY_PUSH(a, 1) = 20;
+ *GARY_PUSH(a, 1) = 30;
+ GARY_POP(a, 1);
+ GARY_FIX(a);
+
+ for (int i=0; i<(int)GARY_SIZE(a); i++)
+ printf("%d\n", a[i]);
+
+ GARY_FREE(a);
+ return 0;
+}
+
+#endif
--- /dev/null
+/*
+ * UCW Library -- A simple growing array of an arbitrary type
+ *
+ * (c) 2010 Martin Mares <mj@ucw.cz>
+ */
+
+#ifndef _UCW_GARY_H
+#define _UCW_GARY_H
+
+struct gary_hdr {
+ size_t num_elts;
+ size_t have_space;
+ size_t elt_size;
+};
+
+#define GARY_HDR_SIZE ALIGN_TO(sizeof(struct gary_hdr), CPU_STRUCT_ALIGN)
+#define GARY_HDR(ptr) ((struct gary_hdr *)((byte*)(ptr) - GARY_HDR_SIZE))
+#define GARY_BODY(ptr) ((byte *)(ptr) + GARY_HDR_SIZE)
+
+#define GARY_INIT(ptr, n) (ptr) = gary_init(sizeof(*(ptr)), (n))
+#define GARY_FREE(ptr) xfree(GARY_HDR(ptr))
+#define GARY_SIZE(ptr) (GARY_HDR(ptr)->num_elts)
+#define GARY_SET_SIZE(ptr, n) (ptr) = gary_set_size((ptr), (n))
+
+#define GARY_PUSH(ptr, n) ({ \
+ struct gary_hdr *_h = GARY_HDR(ptr); \
+ typeof(*(ptr)) *_c = &(ptr)[_h->num_elts]; \
+ size_t _n = n; \
+ _h->num_elts += _n; \
+ if (_h->num_elts > _h->have_space) \
+ (ptr) = gary_push_helper((ptr), _n, (byte **) &_c); \
+ _c; })
+
+#define GARY_POP(ptr, n) GARY_HDR(ptr)->num_elts -= (n)
+#define GARY_FIX(ptr) (ptr) = gary_fix((ptr))
+
+/* Internal functions */
+void *gary_init(size_t elt_size, size_t num_elts);
+void gary_free(void *array);
+void *gary_set_size(void *array, size_t n);
+void *gary_push_helper(void *array, size_t n, byte **cptr);
+void *gary_fix(void *array);
+
+#endif
--- /dev/null
+# Tests for gary module
+
+Run: ../obj/ucw/gary-t -e
+Output: 1
+ 2
+ 3
+ 4
+ 5
+ 10
+ 20