diff options
author | coar <coar@13f79535-47bb-0310-9956-ffa450edef68> | 2000-08-22 21:55:34 +0000 |
---|---|---|
committer | coar <coar@13f79535-47bb-0310-9956-ffa450edef68> | 2000-08-22 21:55:34 +0000 |
commit | 1e2da9299925254ccea43e1ab91c4941c50c49b1 (patch) | |
tree | 172ca04019e63bb1f47b48f5c93603f85a67f8a7 /tables | |
parent | a9484560cd363e2b1771fb1f1795ed7a63264af5 (diff) | |
download | libapr-1e2da9299925254ccea43e1ab91c4941c50c49b1.tar.gz |
Add UNTESTED routines and structures to APR's table implementation
to allow for tables with string keys and non-string values.
Instead of a char * value field, these tables have an apr_item_t *
value field, which in turn is a structure containing a size and
a void * pointer to the data themselves. I've kept the types
distinct to keep type-checking useful, so they can't be accidentally
intermixed in function calls.
I've used 'btable' in place of 'table' in all cases, so the
structures are apr_btable_t and apr_btable_entry_t. I've
prototyped and cloned all of the relevant routines except
apr_table_to() and apr_overlap_tables(), which were both too
complex for me to want to tackle to-night. Some of the routines
don't make sense to clone, like apr_table_merge*().
So maybe this all sucks and someone can rip it out, but I'm
sick of waiting for this functionality so I hope someone
takes this and improves it instead.
We *could* reimplement the string-value tables as a special
case of btables, which would conceivably save on strlen() cycles,
but I'm not sure it would be worth it.
git-svn-id: http://svn.apache.org/repos/asf/apr/apr/trunk@60510 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'tables')
-rw-r--r-- | tables/apr_tables.c | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/tables/apr_tables.c b/tables/apr_tables.c index 0ae34bbe1..a5dbdd6f4 100644 --- a/tables/apr_tables.c +++ b/tables/apr_tables.c @@ -305,6 +305,17 @@ APR_EXPORT(apr_table_t *) apr_make_table(apr_pool_t *p, int nelts) return t; } +APR_EXPORT(apr_btable_t *) apr_make_btable(apr_pool_t *p, int nelts) +{ + apr_btable_t *t = apr_palloc(p, sizeof(apr_btable_t)); + + make_array_core(&t->a, p, nelts, sizeof(apr_btable_entry_t)); +#ifdef MAKE_TABLE_PROFILE + t->creator = __builtin_return_address(0); +#endif + return t; +} + APR_EXPORT(apr_table_t *) apr_copy_table(apr_pool_t *p, const apr_table_t *t) { apr_table_t *new = apr_palloc(p, sizeof(apr_table_t)); @@ -324,11 +335,36 @@ APR_EXPORT(apr_table_t *) apr_copy_table(apr_pool_t *p, const apr_table_t *t) return new; } +APR_EXPORT(apr_btable_t *) apr_copy_btable(apr_pool_t *p, + const apr_btable_t *t) +{ + apr_btable_t *new = apr_palloc(p, sizeof(apr_btable_entry_t)); + +#ifdef POOL_DEBUG + /* we don't copy keys and values, so it's necessary that t->a.pool + * have a life span at least as long as p + */ + if (!apr_pool_is_ancestor(t->a.cont, p)) { + fprintf(stderr, "copy_btable: t's pool is not an ancestor of p\n"); + abort(); + } +#endif + make_array_core(&new->a, p, t->a.nalloc, sizeof(apr_btable_entry_t)); + memcpy(new->a.elts, t->a.elts, t->a.nelts * sizeof(apr_btable_entry_t)); + new->a.nelts = t->a.nelts; + return new; +} + APR_EXPORT(void) apr_clear_table(apr_table_t *t) { t->a.nelts = 0; } +APR_EXPORT(void) apr_clear_btable(apr_btable_t *t) +{ + t->a.nelts = 0; +} + APR_EXPORT(const char *) apr_table_get(const apr_table_t *t, const char *key) { apr_table_entry_t *elts = (apr_table_entry_t *) t->a.elts; @@ -347,6 +383,25 @@ APR_EXPORT(const char *) apr_table_get(const apr_table_t *t, const char *key) return NULL; } +APR_EXPORT(const apr_item_t *) apr_btable_get(const apr_btable_t *t, + const char *key) +{ + apr_btable_entry_t *elts = (apr_btable_entry_t *) t->a.elts; + int i; + + if (key == NULL) { + return NULL; + } + + for (i = 0; i < t->a.nelts; ++i) { + if (!strcasecmp(elts[i].key, key)) { + return elts[i].val; + } + } + + return NULL; +} + APR_EXPORT(void) apr_table_set(apr_table_t *t, const char *key, const char *val) { @@ -381,6 +436,46 @@ APR_EXPORT(void) apr_table_set(apr_table_t *t, const char *key, } } +APR_EXPORT(void) apr_btable_set(apr_btable_t *t, const char *key, + size_t size, const void *val) +{ + register int i, j, k; + apr_btable_entry_t *elts = (apr_btable_entry_t *) t->a.elts; + apr_item_t *item; + int done = 0; + + item = apr_pcalloc(t->a.cont, sizeof(apr_item_t)); + item->size = size; + item->data = apr_pcalloc(t->a.cont, size); + memcpy(item->data, val, size); + + for (i = 0; i < t->a.nelts; ) { + if (!strcasecmp(elts[i].key, key)) { + if (!done) { + elts[i].val = item; + done = 1; + ++i; + } + else { /* delete an extraneous element */ + for (j = i, k = i + 1; k < t->a.nelts; ++j, ++k) { + elts[j].key = elts[k].key; + elts[j].val = elts[k].val; + } + --t->a.nelts; + } + } + else { + ++i; + } + } + + if (!done) { + elts = (apr_btable_entry_t *) table_push((apr_btable_t *) t); + elts->key = apr_pstrdup(t->a.cont, key); + elts->val = item; + } +} + APR_EXPORT(void) apr_table_setn(apr_table_t *t, const char *key, const char *val) { @@ -428,6 +523,58 @@ APR_EXPORT(void) apr_table_setn(apr_table_t *t, const char *key, } } +APR_EXPORT(void) apr_btable_setn(apr_btable_t *t, const char *key, + size_t size, const void *val) +{ + register int i, j, k; + apr_btable_entry_t *elts = (apr_btable_entry_t *) t->a.elts; + int done = 0; + apr_item_t *item; + +#ifdef POOL_DEBUG + { + if (!apr_pool_is_ancestor(apr_find_pool(key), t->a.cont)) { + fprintf(stderr, "table_set: key not in ancestor pool of t\n"); + abort(); + } + if (!apr_pool_is_ancestor(apr_find_pool(val), t->a.cont)) { + fprintf(stderr, "table_set: val not in ancestor pool of t\n"); + abort(); + } + } +#endif + + item = (apr_item_t *) apr_pcalloc(t->a.cont, size); + item->size = size; + item->data = (void *)val; + + for (i = 0; i < t->a.nelts; ) { + if (!strcasecmp(elts[i].key, key)) { + if (!done) { + elts[i].val = item; + done = 1; + ++i; + } + else { /* delete an extraneous element */ + for (j = i, k = i + 1; k < t->a.nelts; ++j, ++k) { + elts[j].key = elts[k].key; + elts[j].val = elts[k].val; + } + --t->a.nelts; + } + } + else { + ++i; + } + } + + if (!done) { + elts = (apr_btable_entry_t *) table_push((apr_table_t *)t); + elts->key = (char *)key; + elts->val = item; + } +} + APR_EXPORT(void) apr_table_unset(apr_table_t *t, const char *key) { register int i, j, k; @@ -453,6 +600,31 @@ APR_EXPORT(void) apr_table_unset(apr_table_t *t, const char *key) } } +APR_EXPORT(void) apr_btable_unset(apr_btable_t *t, const char *key) +{ + register int i, j, k; + apr_btable_entry_t *elts = (apr_btable_entry_t *) t->a.elts; + + for (i = 0; i < t->a.nelts; ) { + if (!strcasecmp(elts[i].key, key)) { + + /* found an element to skip over + * there are any number of ways to remove an element from + * a contiguous block of memory. I've chosen one that + * doesn't do a memcpy/bcopy/array_delete, *shrug*... + */ + for (j = i, k = i + 1; k < t->a.nelts; ++j, ++k) { + elts[j].key = elts[k].key; + elts[j].val = elts[k].val; + } + --t->a.nelts; + } + else { + ++i; + } + } +} + APR_EXPORT(void) apr_table_merge(apr_table_t *t, const char *key, const char *val) { @@ -512,6 +684,21 @@ APR_EXPORT(void) apr_table_add(apr_table_t *t, const char *key, elts->val = apr_pstrdup(t->a.cont, val); } +APR_EXPORT(void) apr_btable_add(apr_btable_t *t, const char *key, + size_t size, const void *val) +{ + apr_btable_entry_t *elts = (apr_btable_entry_t *) t->a.elts; + apr_item_t *item; + + item = (apr_item_t *) apr_pcalloc(t->a.cont, sizeof(apr_item_t)); + item->size = size; + item->data = apr_pcalloc(t->a.cont, size); + memcpy(item->data, val, size); + elts = (apr_btable_entry_t *) table_push((apr_btable_t *)t); + elts->key = apr_pstrdup(t->a.cont, key); + elts->val = item; +} + APR_EXPORT(void) apr_table_addn(apr_table_t *t, const char *key, const char *val) { @@ -535,6 +722,34 @@ APR_EXPORT(void) apr_table_addn(apr_table_t *t, const char *key, elts->val = (char *)val; } +APR_EXPORT(void) apr_btable_addn(apr_btable_t *t, const char *key, + size_t size, const void *val) +{ + apr_btable_entry_t *elts = (apr_btable_entry_t *) t->a.elts; + apr_item_t *item; + +#ifdef POOL_DEBUG + { + if (!apr_pool_is_ancestor(apr_find_pool(key), t->a.cont)) { + fprintf(stderr, "table_set: key not in ancestor pool of t\n"); + abort(); + } + if (!apr_pool_is_ancestor(apr_find_pool(val), t->a.cont)) { + fprintf(stderr, "table_set: key not in ancestor pool of t\n"); + abort(); + } + } +#endif + + item = (apr_item_t *) apr_pcalloc(t->a.cont, sizeof(apr_item_t)); + item->size = size; + item->data = apr_pcalloc(t->a.cont, size); + memcpy(item->data, val, size); + elts = (apr_btable_entry_t *) table_push((apr_btable_t *)t); + elts->key = (char *)key; + elts->val = item; +} + APR_EXPORT(apr_table_t *) apr_overlay_tables(apr_pool_t *p, const apr_table_t *overlay, const apr_table_t *base) @@ -567,6 +782,38 @@ APR_EXPORT(apr_table_t *) apr_overlay_tables(apr_pool_t *p, return res; } +APR_EXPORT(apr_btable_t *) apr_overlay_btables(apr_pool_t *p, + const apr_btable_t *overlay, + const apr_btable_t *base) +{ + apr_btable_t *res; + +#ifdef POOL_DEBUG + /* we don't copy keys and values, so it's necessary that + * overlay->a.pool and base->a.pool have a life span at least + * as long as p + */ + if (!apr_pool_is_ancestor(overlay->a.cont, p)) { + fprintf(stderr, + "overlay_tables: overlay's pool is not an ancestor of p\n"); + abort(); + } + if (!apr_pool_is_ancestor(base->a.cont, p)) { + fprintf(stderr, + "overlay_tables: base's pool is not an ancestor of p\n"); + abort(); + } +#endif + + res = apr_palloc(p, sizeof(apr_btable_t)); + /* behave like append_arrays */ + res->a.cont = p; + copy_array_hdr_core(&res->a, &overlay->a); + apr_array_cat(&res->a, &base->a); + + return res; +} + /* And now for something completely abstract ... * For each key value given as a vararg: |