| /* |
| ** Copyright 2003-2004 The Apache Software Foundation |
| ** |
| ** Licensed under the Apache License, Version 2.0 (the "License"); |
| ** you may not use this file except in compliance with the License. |
| ** You may obtain a copy of the License at |
| ** |
| ** http://www.apache.org/licenses/LICENSE-2.0 |
| ** |
| ** Unless required by applicable law or agreed to in writing, software |
| ** distributed under the License is distributed on an "AS IS" BASIS, |
| ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| ** See the License for the specific language governing permissions and |
| ** limitations under the License. |
| */ |
| |
| #ifndef APREQ_TABLES_H |
| #define APREQ_TABLES_H |
| |
| #include "apr_tables.h" |
| #include "apreq.h" |
| #include <stddef.h> |
| #if APR_HAVE_STDARG_H |
| #include <stdarg.h> /* for va_list */ |
| #endif |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif /* __cplusplus */ |
| |
| /** |
| * @file apreq_tables.h |
| * @brief APREQ Table library |
| */ |
| /** |
| * @defgroup APREQ_Table Table routines |
| * @ingroup APREQ |
| * |
| * Basic ADT for managing collections in APREQ. Tables |
| * remember the order in which entries are added, and respect |
| * this order whenever iterator APIs are used. |
| * |
| * APREQ Tables have a hash-like lookup API as well, and support |
| * multivalued keys. Table keys are C strings, but the return values |
| * are guaranteed to point at the "data" attribute of an apreq_value_t. |
| * (The table key for an apreq_value_t is its "name".) Thus tables can |
| * be used to do lookups on binary/opaque data stored within an |
| * apreq_value_t. |
| * |
| * Tables also provide an abstract API for merging and copying the |
| * values it contains. |
| * @{ |
| */ |
| |
| /** the table abstract data type */ |
| typedef struct apreq_table_t apreq_table_t; |
| |
| /** |
| * Make a new table |
| * @param p The pool to allocate the pool out of |
| * @param nelts The number of elements in the initial table. |
| * @return The new table. |
| */ |
| APREQ_DECLARE(apreq_table_t *) apreq_table_make(apr_pool_t *p, int nelts); |
| #define apreq_make_table(p,n) apreq_table_make(p,n) |
| |
| /** |
| * Create a new table and copy another table into it |
| * @param p The pool to allocate the new table out of |
| * @param t The table to copy |
| * @return A copy of the table passed in |
| */ |
| APREQ_DECLARE(apreq_table_t *) apreq_table_copy(apr_pool_t *p, |
| const apreq_table_t *t); |
| |
| |
| /** |
| * Create an APR Table from an APREQ Table. |
| * @param p The pool to allocate the APR table from |
| * @param t The APREQ table to copy |
| */ |
| APREQ_DECLARE(apr_table_t *) apreq_table_export(apr_pool_t *p, |
| const apreq_table_t *t); |
| |
| /** |
| * Create an APREQ Table from an APR Table. |
| * @param p The pool to allocate the APREQ table from |
| * @param t The APR table to copy |
| */ |
| APREQ_DECLARE(apreq_table_t *)apreq_table_import(apr_pool_t *p, |
| apr_table_t *t); |
| |
| /** |
| * Delete all of the elements from a table |
| * @param t The table to clear |
| */ |
| APR_INLINE |
| APREQ_DECLARE(void) apreq_table_clear(apreq_table_t *t); |
| |
| /** |
| * Return the number of elements within the table. |
| * @param t The table to clear |
| */ |
| APR_INLINE |
| APREQ_DECLARE(int) apreq_table_nelts(const apreq_table_t *t); |
| #define apreq_table_is_empty(t) ( apreq_table_nelts(t) == 0 ) |
| |
| /** |
| * Returns the pool associated to the table's underlying array. |
| * @param t The table. |
| */ |
| |
| APR_INLINE |
| APREQ_DECLARE(apr_pool_t *) apreq_table_pool(apreq_table_t *t); |
| |
| |
| /** |
| * Get/set method for the table's value copier. |
| * @param t Table. |
| * @param c The new t->copy callback. c = NULL is ignored; |
| * a non-NULL value replaces the table's internal copier. |
| * @return The original t->copy callback (prior to any assignment). |
| */ |
| APR_INLINE |
| APREQ_DECLARE(apreq_value_copy_t *) apreq_table_copier(apreq_table_t *t, |
| apreq_value_copy_t *c); |
| |
| /** |
| * Get/set method for the table's value merger. |
| * @param t Table. |
| * @param m The new t->merge callback. m = NULL is ignored; |
| * a non-NULL value replaces the table's internal merger. |
| * @return The original t->merge callback (prior to any assignment). |
| */ |
| APR_INLINE |
| APREQ_DECLARE(apreq_value_merge_t *) apreq_table_merger(apreq_table_t *t, |
| apreq_value_merge_t *m); |
| |
| /** |
| * Attempt to merge multivalued entries together, eliminating |
| * redunandant entries with t->merge. See apreq_table_merger |
| * for additional details. |
| * |
| * @param t Table. |
| */ |
| APREQ_DECLARE(apr_status_t) apreq_table_normalize(apreq_table_t *t); |
| |
| /** |
| * Count the number of dead entries within the table. |
| * Mainly used for diagnostic purposes, since ghost entries are |
| * ignored by the table's accessor APIs. |
| * |
| * @param t Table. |
| */ |
| APR_INLINE |
| APREQ_DECLARE(int) apreq_table_ghosts(apreq_table_t *t); |
| |
| /** |
| * Remove dead entries from the table. This can |
| * be a very expensive and somewhat useless function |
| * as far as the table API goes. It's voodoo, so |
| * try not to use it. |
| * |
| * @param t Table. |
| */ |
| APREQ_DECLARE(int) apreq_table_exorcise(apreq_table_t *t); |
| |
| |
| /** |
| * Get the value associated with a given key from the table. |
| * @param t The table to search for the key |
| * @param key The key to search for |
| * @return The data associated with the key, guaranteed to |
| * point at the "data" attribute of an apreq_value_t struct. |
| * |
| */ |
| APREQ_DECLARE(const char*) apreq_table_get(const apreq_table_t *t, |
| const char *key); |
| |
| /** |
| * Return the keys (i.e. value names) in an (char *) array, |
| * preserving their original order. |
| * @param t Table. |
| * @param keys array used to store the result. |
| */ |
| |
| APREQ_DECLARE(apr_status_t) apreq_table_keys(const apreq_table_t *t, |
| apr_array_header_t *keys); |
| |
| /** |
| * Add an apreq_value_t to the table. If another value already exists |
| * with the same name, this will replace the old value. |
| * @param t The table to add the data to. |
| * @param val The value to add |
| * @remark When adding data, this function uses the value's name as key. |
| * Nothing is copied. |
| */ |
| APREQ_DECLARE(void) apreq_table_set(apreq_table_t *t, const apreq_value_t *v); |
| |
| /** |
| * Remove a key from the table. |
| * @param t Table. |
| * @param key The name of the apreq_values to remove. |
| * @remark The table will drops ALL values associated with the key. |
| */ |
| APREQ_DECLARE(void) apreq_table_unset(apreq_table_t *t, const char *key); |
| |
| /** |
| * Add data to a table by merging the value with previous ones. |
| * @param t The table to search for the data |
| * @param key The key for locating previous values to merge with this one. |
| * @param val The data to add |
| * @remark If the key is not found, then this function acts like apr_table_add. |
| * If multiple entries are found, they are all merged into a single value |
| * via t->merge. |
| */ |
| |
| APREQ_DECLARE(apr_status_t) apreq_table_merge(apreq_table_t *t, |
| const apreq_value_t *v); |
| |
| /** |
| * Add data to a table, regardless of whether there is another element with the |
| * same key. |
| * @param t The table to add to |
| * @param val The value to add. |
| * @remark This function does not make copies. |
| */ |
| APREQ_DECLARE(apr_status_t) apreq_table_addv(apreq_table_t *t, |
| const apreq_value_t *v); |
| |
| /** |
| * Merge two tables into one new table |
| * @param p The pool to use for the new table |
| * @param over The first table to put in the new table |
| * @param under The table to add at the end of the new table |
| * @return A new table containing all of the data from the two passed in. |
| */ |
| APREQ_DECLARE(apreq_table_t *) apreq_table_overlay(apr_pool_t *p, |
| const apreq_table_t *over, |
| const apreq_table_t *under); |
| /** |
| * Append one table to the end of another. |
| * @param t The table to be modified. |
| * @param s The values from this table are added to "t". |
| * @remark This function splices the internal binary trees from "s" |
| * into "t", so it will be faster than iterating s with apreq_table_add. |
| * From a user's perspective, the result should be identical. |
| */ |
| APREQ_DECLARE(void) apreq_table_cat(apreq_table_t *t, const apreq_table_t *s); |
| |
| /** |
| * XXX: This doc needs to be modified for APREQ. Volunteers? |
| |
| * For each element in table b, either use setn or mergen to add the data |
| * to table a. Which method is used is determined by the flags passed in. |
| * @param a The table to add the data to. |
| * @param b The table to iterate over, adding its data to table a |
| * @param flags How to add the table to table a. One of: |
| * APR_OVERLAP_TABLES_SET Use apr_table_setn |
| * APR_OVERLAP_TABLES_MERGE Use apr_table_mergen |
| * @remark This function is highly optimized, and uses less memory and CPU cycles |
| * than a function that just loops through table b calling other functions. |
| */ |
| /** |
| *<PRE> |
| * Conceptually, apr_table_overlap does this: |
| * |
| * apr_array_header_t *barr = apr_table_elts(b); |
| * apr_table_entry_t *belt = (apr_table_entry_t *)barr->elts; |
| * int i; |
| * |
| * for (i = 0; i < barr->nelts; ++i) { |
| * if (flags & APR_OVERLAP_TABLES_MERGE) { |
| * apr_table_mergen(a, belt[i].key, belt[i].val); |
| * } |
| * else { |
| * apr_table_setn(a, belt[i].key, belt[i].val); |
| * } |
| * } |
| * |
| * Except that it is more efficient (less space and cpu-time) especially |
| * when b has many elements. |
| * |
| * Notice the assumptions on the keys and values in b -- they must be |
| * in an ancestor of a's pool. In practice b and a are usually from |
| * the same pool. |
| * </PRE> |
| */ |
| |
| APREQ_DECLARE(apr_status_t) apreq_table_overlap(apreq_table_t *a, |
| const apreq_table_t *b, |
| const unsigned flags); |
| |
| /** Iterator API */ |
| |
| /** |
| * NOTE: elt_size > sizeof(apreq_value_t *) !!! |
| * So iterating over the values in the array must go something like this: |
| * |
| * apr_array_header_t *arr = apreq_table_elts(t); |
| * char *current, *end = arr->elts + arr->elt_size * arr->nelts; |
| * |
| * for (current = arr->elts; current < end; current += arr->elt_size) { |
| * apreq_value_t *v = *(apreq_value_t **)current; |
| * |
| * ... do something with "v" .. |
| * } |
| */ |
| |
| APR_INLINE |
| APREQ_DECLARE(const apr_array_header_t *)apreq_table_elts(apreq_table_t *t); |
| |
| /** |
| * Declaration prototype for the iterator callback function of apr_table_do() |
| * and apr_table_vdo(). |
| * @param rec The data passed as the first argument to apr_table_[v]do() |
| * @param key The key from this iteration of the table |
| * @param val The v->data from this iteration of the table |
| * @remark Iteration continues while this callback function returns non-zero. |
| * To export the callback function for apr_table_[v]do() it must be declared |
| * in the _NONSTD convention. |
| */ |
| typedef int (apreq_table_do_callback_fn_t)(void *ctx, const char *key, |
| const char *val); |
| |
| /** |
| * Iterate over a table running the provided function once for every |
| * element in the table. If there is data passed in as a vararg, then the |
| * function is only run on those elements whose key matches something in |
| * the vararg. If the vararg is NULL, then every element is run through the |
| * function. Iteration continues while the function returns non-zero. |
| * @param comp The function to run |
| * @param rec The data to pass as the first argument to the function |
| * @param t The table to iterate over |
| * @param ... The vararg. If this is NULL, then all elements in the table are |
| * run through the function, otherwise only those whose key matches |
| * are run. |
| * @return FALSE if one of the comp() iterations returned zero; TRUE if all |
| * iterations returned non-zero |
| * @see apreq_table_do_callback_fn_t |
| */ |
| APREQ_DECLARE_NONSTD(int) apreq_table_do(apreq_table_do_callback_fn_t *comp, |
| void *ctx, |
| const apreq_table_t *t, ...); |
| |
| /** |
| * Iterate over a table running the provided function once for every |
| * element in the table. If there is data passed in as a vararg, then the |
| * function is only run on those element's whose key matches something in |
| * the vararg. If the vararg is NULL, then every element is run through the |
| * function. Iteration continues while the function returns non-zero. |
| * @param comp The function to run |
| * @param rec The data to pass as the first argument to the function |
| * @param t The table to iterate over |
| * @param vp The vararg table. If this is NULL, then all elements in the |
| * table are run through the function, otherwise only those |
| * whose key matches are run. |
| * @return FALSE if one of the comp() iterations returned zero; TRUE if all |
| * iterations returned non-zero |
| * @see apreq_table_do_callback_fn_t |
| */ |
| APREQ_DECLARE(int) apreq_table_vdo(apreq_table_do_callback_fn_t *comp, |
| void *ctx, const apreq_table_t *t, |
| va_list vp); |
| |
| |
| |
| /** @} */ |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* ! APR_TABLES_H */ |