From 8455734f4ae908735fd0d4aa9524301aa8915397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Sat, 19 Mar 2016 15:27:36 +0000 Subject: [PATCH] [core] add generic vector implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Stefan Bühler git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@3115 152afb58-edef-0310-8abb-c4023f1b3aa9 --- NEWS | 1 + src/CMakeLists.txt | 1 + src/Makefile.am | 3 +- src/SConscript | 1 + src/vector.c | 17 +++++++++++ src/vector.h | 75 ++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 src/vector.c create mode 100644 src/vector.h diff --git a/NEWS b/NEWS index dfd8b9ef..bbe3814c 100644 --- a/NEWS +++ b/NEWS @@ -42,6 +42,7 @@ NEWS * [core] fix request_start in keep-alive requests to mark time when received first byte (fixes #2412) * [core] truncate pidfile on exit (fixes #2695) * consistent inclusion of config.h at top of files (fixes #2073) + * [core] add generic vector implementation - 1.4.39 - 2016-01-02 * [core] fix memset_s call (fixes #2698) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d99b2c2c..93199f27 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -482,6 +482,7 @@ set(COMMON_SRC stat_cache.c plugin.c joblist.c etag.c array.c data_string.c data_count.c data_array.c data_integer.c md5.c data_fastcgi.c + vector.c fdevent_select.c fdevent_libev.c fdevent_poll.c fdevent_linux_sysepoll.c fdevent_solaris_devpoll.c fdevent_solaris_port.c diff --git a/src/Makefile.am b/src/Makefile.am index 9b4a1124..02736d54 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -62,6 +62,7 @@ common_src=base64.c buffer.c log.c \ stat_cache.c plugin.c joblist.c etag.c array.c \ data_string.c data_count.c data_array.c \ data_integer.c md5.c data_fastcgi.c \ + vector.c \ fdevent_select.c fdevent_libev.c \ fdevent_poll.c fdevent_linux_sysepoll.c \ fdevent_solaris_devpoll.c fdevent_solaris_port.c \ @@ -274,7 +275,7 @@ hdr = server.h base64.h buffer.h network.h log.h keyvalue.h \ md5.h http_auth.h stream.h \ fdevent.h connections.h base.h stat_cache.h \ plugin.h mod_auth.h \ - etag.h joblist.h array.h crc32.h \ + etag.h joblist.h array.h vector.h crc32.h \ network_backends.h configfile.h \ mod_ssi.h mod_ssi_expr.h inet_ntop_cache.h \ configparser.h mod_ssi_exprparser.h \ diff --git a/src/SConscript b/src/SConscript index 84ae4ff8..524b090a 100644 --- a/src/SConscript +++ b/src/SConscript @@ -44,6 +44,7 @@ common_src = Split("base64.c buffer.c log.c \ stat_cache.c plugin.c joblist.c etag.c array.c \ data_string.c data_count.c data_array.c \ data_integer.c md5.c data_fastcgi.c \ + vector.c \ fdevent_select.c fdevent_libev.c \ fdevent_poll.c fdevent_linux_sysepoll.c \ fdevent_solaris_devpoll.c fdevent_solaris_port.c \ diff --git a/src/vector.c b/src/vector.c new file mode 100644 index 00000000..6c70f663 --- /dev/null +++ b/src/vector.c @@ -0,0 +1,17 @@ +#include "first.h" + +#include "vector.h" +#include "base.h" + +void *vector_realloc(void *data, size_t elem_size, size_t size, size_t used) { + const size_t total_size = elem_size * size; + const size_t used_size = elem_size * used; + force_assert(size <= SIZE_MAX / elem_size); + data = realloc(data, total_size); + force_assert(NULL != data); + + /* clear new memory */ + memset(((char*)data) + used_size, 0, total_size - used_size); + + return data; +} diff --git a/src/vector.h b/src/vector.h new file mode 100644 index 00000000..7ba5dcf2 --- /dev/null +++ b/src/vector.h @@ -0,0 +1,75 @@ +#ifndef LI_VECTOR_H +#define LI_VECTOR_H +#include "first.h" + +#ifndef SIZE_MAX +# ifdef SIZE_T_MAX +# define SIZE_MAX SIZE_T_MAX +# else +# define SIZE_MAX ((size_t)~0) +# endif +#endif + +#include +#include + +static inline size_t vector_align_size(size_t s) { + size_t a = (s + 16) & ((size_t)~15); + return (a < s) ? s : a; +} + +void *vector_realloc(void *data, size_t elem_size, size_t size, size_t used); + +#define DEFINE_TYPED_VECTOR(name, entry, release) \ + typedef struct vector_ ## name { \ + entry* data; \ + size_t used; \ + size_t size; \ + } vector_ ## name; \ + static inline void vector_ ## name ## _init(vector_ ## name *v) { \ + v->data = NULL; \ + v->used = v->size = 0; \ + } \ + static inline vector_ ## name *vector_ ## name ## _alloc() { \ + vector_ ## name *v = malloc(sizeof(*v)); \ + force_assert(NULL != v); \ + vector_ ## name ## _init(v); \ + return v; \ + } \ + static inline void vector_ ## name ## _clear(vector_ ## name *v) { \ + size_t ndx; \ + vector_ ## name vcopy = *v; \ + vector_ ## name ## _init(v); \ + if (release) for (ndx = 0; ndx < vcopy.used; ++ndx) release(vcopy.data[ndx]); \ + free(vcopy.data); \ + } \ + static inline void vector_ ## name ## _free(vector_ ## name *v) { \ + if (NULL != v) { \ + vector_ ## name ## _clear(v); \ + free(v); \ + } \ + } \ + static inline void vector_ ## name ## _reserve(vector_ ## name *v, size_t p) { \ + force_assert(v->used < SIZE_MAX - p); \ + if (v->size < v->used + p) { \ + v->size = vector_align_size(v->used + p); \ + v->data = vector_realloc(v->data, sizeof(entry), v->size, v->used); \ + } \ + } \ + static inline void vector_ ## name ## _push(vector_ ## name *v, entry e) { \ + vector_ ## name ## _reserve(v, 1); \ + v->data[v->used++] = e; \ + } \ + static inline entry vector_ ## name ## _pop(vector_ ## name *v) { \ + force_assert(v->used > 0); \ + return v->data[--v->used]; \ + } \ + struct vector_ ## name /* expect trailing semicolon */ \ + /* end of DEFINE_TYPED_VECTOR */ + +#define DEFINE_TYPED_VECTOR_NO_RELEASE(name, entry) \ + DEFINE_TYPED_VECTOR(name, entry, ((void(*)(entry)) NULL)) \ + /* end of DEFINE_TYPED_VECTOR_NO_RELEASE */ + + +#endif