Joe Schaefer <[EMAIL PROTECTED]> writes:
[...]
> Has anyone given any thought to the changes I proposed
> to the table implementation?
Hmm, since the patch to apr_tables.c is pretty large,
maybe I should start by posting the small patch to
apr_tables.h and discuss that first.
Here is a list of the changes:
1) use a native unsigned int for the key_checksum. This should
allow 64 bit machines to use 8 chars for the table hash & key_offset
instead of just 4.
2) superimpose a tree-node onto the table entry, with a next
node to keep track of multivalued keys. These are implemented
as ints (which represent offsets from t->a.elts) instead of
raw pointers to memory addresses. This is necessary to allow
the underlying array to realloc itself as new entries are added.
3) add some bitfields to the table_entry:
key_offset- marks where the checksum leaves off so we
don't have to start strcasecmp at the start of
the string.
color- tracks the color (red or black) of the entry.
dead- marks the entry as dead. Dead entries are entries
that were removed from the table, but haven't been
"paved over" yet by shifting & reindexing the remaining
(live) entries. Potential dead entries are expunged
from the table by calling apr_table_elts().
4) associate copy & merge functions with a table, which allows the
values in the table to be treated more generally than just as
", "-combinable header strings.
5) apr_array_pstrcat would be more useful if it allowed the separator
to be a string instead of just a single character. I added
a new function that does this and called it apr_array_pstrjoin.
6) Add a new function called apr_table_cat.
The apr_tables.h patch is below. Thanks in advance.
-- Joe Schaefer
Index: include/apr_tables.h
===================================================================
RCS file: /home/cvspublic/apr/include/apr_tables.h,v
retrieving revision 1.37
diff -u -r1.37 apr_tables.h
--- include/apr_tables.h 5 Mar 2003 21:22:26 -0000 1.37
+++ include/apr_tables.h 10 May 2003 21:33:49 -0000
@@ -108,14 +108,20 @@
/** The type for each entry in a string-content table */
struct apr_table_entry_t {
/** The key for the current table entry */
- char *key; /* maybe NULL in future;
- * check when iterating thru table_elts
- */
+ const char *key; /* maybe NULL in future;
+ * check when iterating thru table_elts
+ */
/** The value for the current table entry */
- char *val;
+ const char *val;
+ /** indices of related entries: LEFT RIGHT UP NEXT */
+ int tree[4];
/** A checksum for the key, for use by the apr_table internals */
- apr_uint32_t key_checksum;
+ unsigned int key_checksum;
+ unsigned int key_offset : 4;
+
+ unsigned int color : 1;
+ unsigned int dead : 1;
};
/**
@@ -123,7 +129,7 @@
* @param t The table
* @return An array containing the contents of the table
*/
-APR_DECLARE(const apr_array_header_t *) apr_table_elts(const apr_table_t *t);
+APR_DECLARE(const apr_array_header_t *) apr_table_elts(apr_table_t *t);
/**
* Determine if the table is empty
@@ -131,6 +137,8 @@
* @return True if empty, False otherwise
*/
APR_DECLARE(int) apr_is_empty_table(const apr_table_t *t);
+#define apr_is_empty_table(t) ( apr_table_nelts(t) == 0 )
+
/**
* Determine if the array is empty
@@ -222,6 +230,15 @@
APR_DECLARE(char *) apr_array_pstrcat(apr_pool_t *p,
const apr_array_header_t *arr,
const char sep);
+/**
+ * Same as apr_array_pstrcat, but takes a (char *) as third argument.
+ * This allows the array elements to be joined on a string instead of
+ * a single character.
+ */
+
+APR_DECLARE(char *)apr_array_pstrjoin(apr_pool_t *p,
+ const apr_array_header_t *arr,
+ const char *sep);
/**
* Make a new table
@@ -242,6 +259,37 @@
const apr_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).
+ */
+typedef char *(apr_table_copier_t)(apr_pool_t *p, const char *val);
+
+APR_DECLARE(apr_table_copier_t *) apr_table_copier(apr_table_t *t,
+ apr_table_copier_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).
+ */
+typedef char *(apr_table_merger_t)(apr_pool_t *p,
+ const apr_array_header_t *a);
+
+APR_DECLARE(apr_table_merger_t *) apr_table_merger(apr_table_t *t,
+ apr_table_merger_t *m);
+
+/**
+ * Return the number of elements within the table.
+ * @param t The table
+ */
+APR_DECLARE(int) apr_table_nelts(const apr_table_t *t);
+
+/**
* Delete all of the elements from a table
* @param t The table to clear
*/
@@ -336,6 +384,24 @@
const char *val);
/**
+ * Merges multivalued entries together, eliminating redunandant
+ * entries with t->merge.
+ *
+ * @param t Table.
+ */
+APR_DECLARE(apr_status_t)apr_table_normalize(apr_table_t *t);
+
+/**
+ * Append one table to the end of another.
+ * @param t The table to be modified.
+ * @param s The entries from this table are added to "t".
+ * @remark This function splices the internal trees from "s"
+ * into "t", so it will be faster than iterating over s with apr_table_addn.
+ * From a user's perspective, the result should be identical.
+ */
+APR_DECLARE(void) apr_table_cat(apr_table_t *t, const apr_table_t *s);
+
+/**
* Merge two tables into one new table
* @param p The pool to use for the new table
* @param overlay The first table to put in the new table
@@ -439,7 +505,7 @@
*/
APR_DECLARE(void) apr_table_overlap(apr_table_t *a, const apr_table_t *b,
- unsigned flags);
+ unsigned flags);
/** @} */