Return-Path: X-Original-To: apmail-apr-commits-archive@www.apache.org Delivered-To: apmail-apr-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 8094BF22D for ; Tue, 7 May 2013 20:49:41 +0000 (UTC) Received: (qmail 33932 invoked by uid 500); 7 May 2013 20:49:41 -0000 Delivered-To: apmail-apr-commits-archive@apr.apache.org Received: (qmail 33805 invoked by uid 500); 7 May 2013 20:49:40 -0000 Mailing-List: contact commits-help@apr.apache.org; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: Reply-To: dev@apr.apache.org List-Id: Delivered-To: mailing list commits@apr.apache.org Received: (qmail 33795 invoked by uid 99); 7 May 2013 20:49:40 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 07 May 2013 20:49:40 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 07 May 2013 20:49:37 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id EEC4123888E3; Tue, 7 May 2013 20:49:15 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1480067 - in /apr/apr/trunk: CHANGES include/apr_tables.h tables/apr_tables.c test/testtable.c Date: Tue, 07 May 2013 20:49:15 -0000 To: commits@apr.apache.org From: minfrin@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20130507204915.EEC4123888E3@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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);