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:52:42 UTC

svn commit: r1480071 - in /apr/apr/branches/1.5.x: ./ CHANGES include/apr_tables.h tables/apr_tables.c test/testtable.c

Author: minfrin
Date: Tue May  7 20:52:42 2013
New Revision: 1480071

URL: http://svn.apache.org/r1480071
Log:
Backport r1480067 to v1.5 branch.
Add the apr_table_getm() call, which transparently handles the
merging of keys with multiple values.

Modified:
    apr/apr/branches/1.5.x/   (props changed)
    apr/apr/branches/1.5.x/CHANGES
    apr/apr/branches/1.5.x/include/apr_tables.h
    apr/apr/branches/1.5.x/tables/apr_tables.c
    apr/apr/branches/1.5.x/test/testtable.c

Propchange: apr/apr/branches/1.5.x/
------------------------------------------------------------------------------
  Merged /apr/apr/trunk:r1480067

Modified: apr/apr/branches/1.5.x/CHANGES
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.5.x/CHANGES?rev=1480071&r1=1480070&r2=1480071&view=diff
==============================================================================
--- apr/apr/branches/1.5.x/CHANGES [utf-8] (original)
+++ apr/apr/branches/1.5.x/CHANGES [utf-8] Tue May  7 20:52:42 2013
@@ -1,6 +1,9 @@
                                                      -*- coding: utf-8 -*-
 Changes for APR 1.5.0
 
+  *) Add the apr_table_getm() call, which transparently handles the
+     merging of keys with multiple values. [Graham Leggett]
+
   *) Fix amd64 assembler version of apr_atomic_xchgptr(). PR 51851. [Mattias
      EngdegÄrd <mattiase acm org>]
 

Modified: apr/apr/branches/1.5.x/include/apr_tables.h
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.5.x/include/apr_tables.h?rev=1480071&r1=1480070&r2=1480071&view=diff
==============================================================================
--- apr/apr/branches/1.5.x/include/apr_tables.h (original)
+++ apr/apr/branches/1.5.x/include/apr_tables.h Tue May  7 20:52:42 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/branches/1.5.x/tables/apr_tables.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.5.x/tables/apr_tables.c?rev=1480071&r1=1480070&r2=1480071&view=diff
==============================================================================
--- apr/apr/branches/1.5.x/tables/apr_tables.c (original)
+++ apr/apr/branches/1.5.x/tables/apr_tables.c Tue May  7 20:52:42 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
@@ -1236,3 +1244,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/branches/1.5.x/test/testtable.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.5.x/test/testtable.c?rev=1480071&r1=1480070&r2=1480071&view=diff
==============================================================================
--- apr/apr/branches/1.5.x/test/testtable.c (original)
+++ apr/apr/branches/1.5.x/test/testtable.c Tue May  7 20:52:42 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);