You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by mi...@apache.org on 2013/05/07 22:49:15 UTC
svn commit: r1480067 - in /apr/apr/trunk: CHANGES include/apr_tables.h
tables/apr_tables.c test/testtable.c
Author: minfrin
Date: Tue May 7 20:49:15 2013
New Revision: 1480067
URL: http://svn.apache.org/r1480067
Log:
Add the apr_table_getm() call, which transparently handles the
merging of keys with multiple values.
Modified:
apr/apr/trunk/CHANGES
apr/apr/trunk/include/apr_tables.h
apr/apr/trunk/tables/apr_tables.c
apr/apr/trunk/test/testtable.c
Modified: apr/apr/trunk/CHANGES
URL: http://svn.apache.org/viewvc/apr/apr/trunk/CHANGES?rev=1480067&r1=1480066&r2=1480067&view=diff
==============================================================================
--- apr/apr/trunk/CHANGES [utf-8] (original)
+++ apr/apr/trunk/CHANGES [utf-8] Tue May 7 20:49:15 2013
@@ -1,6 +1,9 @@
-*- coding: utf-8 -*-
Changes for APR 2.0.0
+ *) Add the apr_table_getm() call, which transparently handles the
+ merging of keys with multiple values. [Graham Leggett]
+
*) Mark apr_dbd_freetds as unsupported, and remove it from all builds
[Nick Kew]
Modified: apr/apr/trunk/include/apr_tables.h
URL: http://svn.apache.org/viewvc/apr/apr/trunk/include/apr_tables.h?rev=1480067&r1=1480066&r2=1480067&view=diff
==============================================================================
--- apr/apr/trunk/include/apr_tables.h (original)
+++ apr/apr/trunk/include/apr_tables.h Tue May 7 20:49:15 2013
@@ -268,6 +268,18 @@ APR_DECLARE(void) apr_table_clear(apr_ta
APR_DECLARE(const char *) apr_table_get(const apr_table_t *t, const char *key);
/**
+ * Get values associated with a given key from the table. If more than one
+ * value exists, return a comma separated list of values. After this call, the
+ * data is still in the table.
+ * @param p The pool to allocate the combined value from, if necessary
+ * @param t The table to search for the key
+ * @param key The key to search for (case does not matter)
+ * @return The value associated with the key, or NULL if the key does not exist.
+ */
+APR_DECLARE(const char *) apr_table_getm(apr_pool_t *p, const apr_table_t *t,
+ const char *key);
+
+/**
* Add a key/value pair to a table. If another element already exists with the
* same key, this will overwrite the old data.
* @param t The table to add the data to.
Modified: apr/apr/trunk/tables/apr_tables.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/tables/apr_tables.c?rev=1480067&r1=1480066&r2=1480067&view=diff
==============================================================================
--- apr/apr/trunk/tables/apr_tables.c (original)
+++ apr/apr/trunk/tables/apr_tables.c Tue May 7 20:49:15 2013
@@ -357,6 +357,14 @@ struct apr_table_t {
int index_last[TABLE_HASH_SIZE];
};
+/* keep state for apr_table_getm() */
+typedef struct
+{
+ apr_pool_t *p;
+ const char *first;
+ apr_array_header_t *merged;
+} table_getm_t;
+
/*
* NOTICE: if you tweak this you should look at is_empty_table()
* and table_elts() in alloc.h
@@ -1238,3 +1246,51 @@ APR_DECLARE(void) apr_table_overlap(apr_
apr_table_compress(a, flags);
}
+
+static int table_getm_do(void *v, const char *key, const char *val)
+{
+ table_getm_t *state = (table_getm_t *) v;
+
+ if (!state->first) {
+ /**
+ * The most common case is a single header, and this is covered by
+ * a fast path that doesn't allocate any memory. On the second and
+ * subsequent header, an array is created and the array concatenated
+ * together to form the final value.
+ */
+ state->first = val;
+ }
+ else {
+ const char **elt;
+ if (!state->merged) {
+ state->merged = apr_array_make(state->p, 10, sizeof(const char *));
+ elt = apr_array_push(state->merged);
+ *elt = state->first;
+ }
+ elt = apr_array_push(state->merged);
+ *elt = val;
+ }
+ return 1;
+}
+
+APR_DECLARE(const char *) apr_table_getm(apr_pool_t *p, const apr_table_t *t,
+ const char *key)
+{
+ table_getm_t state;
+
+ state.p = p;
+ state.first = NULL;
+ state.merged = NULL;
+
+ apr_table_do(table_getm_do, &state, t, key, NULL);
+
+ if (!state.first) {
+ return NULL;
+ }
+ else if (!state.merged) {
+ return state.first;
+ }
+ else {
+ return apr_array_pstrcat(p, state.merged, ',');
+ }
+}
Modified: apr/apr/trunk/test/testtable.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/test/testtable.c?rev=1480067&r1=1480066&r2=1480067&view=diff
==============================================================================
--- apr/apr/trunk/test/testtable.c (original)
+++ apr/apr/trunk/test/testtable.c Tue May 7 20:49:15 2013
@@ -57,6 +57,25 @@ static void table_get(abts_case *tc, voi
ABTS_STR_EQUAL(tc, "bar", val);
}
+static void table_getm(abts_case *tc, void *data)
+{
+ const char *orig, *val;
+ apr_pool_t *subp;
+
+ apr_pool_create(&subp, p);
+
+ orig = "bar";
+ apr_table_setn(t1, "foo", orig);
+ val = apr_table_getm(subp, t1, "foo");
+ ABTS_PTR_EQUAL(tc, orig, val);
+ ABTS_STR_EQUAL(tc, "bar", val);
+ apr_table_add(t1, "foo", "baz");
+ val = apr_table_getm(subp, t1, "foo");
+ ABTS_STR_EQUAL(tc, "bar,baz", val);
+
+ apr_pool_destroy(subp);
+}
+
static void table_set(abts_case *tc, void *data)
{
const char *val;
@@ -187,6 +206,7 @@ abts_suite *testtable(abts_suite *suite)
abts_run_test(suite, array_clear, NULL);
abts_run_test(suite, table_make, NULL);
abts_run_test(suite, table_get, NULL);
+ abts_run_test(suite, table_getm, NULL);
abts_run_test(suite, table_set, NULL);
abts_run_test(suite, table_getnotthere, NULL);
abts_run_test(suite, table_add, NULL);