~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to srclib/apr/tables/apr_tables.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
 
2
 * applicable.
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * You may obtain a copy of the License at
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
10
 * Unless required by applicable law or agreed to in writing, software
 
11
 * distributed under the License is distributed on an "AS IS" BASIS,
 
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
 * See the License for the specific language governing permissions and
 
14
 * limitations under the License.
 
15
 */
 
16
 
 
17
/*
 
18
 * Resource allocation code... the code here is responsible for making
 
19
 * sure that nothing leaks.
 
20
 *
 
21
 * rst --- 4/95 --- 6/95
 
22
 */
 
23
 
 
24
#include "apr_private.h"
 
25
 
 
26
#include "apr_general.h"
 
27
#include "apr_pools.h"
 
28
#include "apr_tables.h"
 
29
#include "apr_strings.h"
 
30
#include "apr_lib.h"
 
31
#if APR_HAVE_STDLIB_H
 
32
#include <stdlib.h>
 
33
#endif
 
34
#if APR_HAVE_STRING_H
 
35
#include <string.h>
 
36
#endif
 
37
#if APR_HAVE_STRINGS_H
 
38
#include <strings.h>
 
39
#endif
 
40
 
 
41
#if APR_POOL_DEBUG && APR_HAVE_STDIO_H
 
42
#include <stdio.h>
 
43
#endif
 
44
 
 
45
/*****************************************************************
 
46
 * This file contains array and apr_table_t functions only.
 
47
 */
 
48
 
 
49
/*****************************************************************
 
50
 *
 
51
 * The 'array' functions...
 
52
 */
 
53
 
 
54
static void make_array_core(apr_array_header_t *res, apr_pool_t *p,
 
55
                            int nelts, int elt_size, int clear)
 
56
{
 
57
    /*
 
58
     * Assure sanity if someone asks for
 
59
     * array of zero elts.
 
60
     */
 
61
    if (nelts < 1) {
 
62
        nelts = 1;
 
63
    }
 
64
 
 
65
    if (clear) {
 
66
        res->elts = apr_pcalloc(p, nelts * elt_size);
 
67
    }
 
68
    else {
 
69
        res->elts = apr_palloc(p, nelts * elt_size);
 
70
    }
 
71
 
 
72
    res->pool = p;
 
73
    res->elt_size = elt_size;
 
74
    res->nelts = 0;             /* No active elements yet... */
 
75
    res->nalloc = nelts;        /* ...but this many allocated */
 
76
}
 
77
 
 
78
APR_DECLARE(int) apr_is_empty_array(const apr_array_header_t *a)
 
79
{
 
80
    return ((a == NULL) || (a->nelts == 0));
 
81
}
 
82
 
 
83
APR_DECLARE(apr_array_header_t *) apr_array_make(apr_pool_t *p,
 
84
                                                int nelts, int elt_size)
 
85
{
 
86
    apr_array_header_t *res;
 
87
 
 
88
    res = (apr_array_header_t *) apr_palloc(p, sizeof(apr_array_header_t));
 
89
    make_array_core(res, p, nelts, elt_size, 1);
 
90
    return res;
 
91
}
 
92
 
 
93
APR_DECLARE(void *) apr_array_pop(apr_array_header_t *arr)
 
94
{
 
95
    if (apr_is_empty_array(arr)) {
 
96
        return NULL;
 
97
    }
 
98
   
 
99
    return arr->elts + (arr->elt_size * (--arr->nelts));
 
100
}
 
101
 
 
102
APR_DECLARE(void *) apr_array_push(apr_array_header_t *arr)
 
103
{
 
104
    if (arr->nelts == arr->nalloc) {
 
105
        int new_size = (arr->nalloc <= 0) ? 1 : arr->nalloc * 2;
 
106
        char *new_data;
 
107
 
 
108
        new_data = apr_palloc(arr->pool, arr->elt_size * new_size);
 
109
 
 
110
        memcpy(new_data, arr->elts, arr->nalloc * arr->elt_size);
 
111
        memset(new_data + arr->nalloc * arr->elt_size, 0,
 
112
               arr->elt_size * (new_size - arr->nalloc));
 
113
        arr->elts = new_data;
 
114
        arr->nalloc = new_size;
 
115
    }
 
116
 
 
117
    ++arr->nelts;
 
118
    return arr->elts + (arr->elt_size * (arr->nelts - 1));
 
119
}
 
120
 
 
121
static void *apr_array_push_noclear(apr_array_header_t *arr)
 
122
{
 
123
    if (arr->nelts == arr->nalloc) {
 
124
        int new_size = (arr->nalloc <= 0) ? 1 : arr->nalloc * 2;
 
125
        char *new_data;
 
126
 
 
127
        new_data = apr_palloc(arr->pool, arr->elt_size * new_size);
 
128
 
 
129
        memcpy(new_data, arr->elts, arr->nalloc * arr->elt_size);
 
130
        arr->elts = new_data;
 
131
        arr->nalloc = new_size;
 
132
    }
 
133
 
 
134
    ++arr->nelts;
 
135
    return arr->elts + (arr->elt_size * (arr->nelts - 1));
 
136
}
 
137
 
 
138
APR_DECLARE(void) apr_array_cat(apr_array_header_t *dst,
 
139
                               const apr_array_header_t *src)
 
140
{
 
141
    int elt_size = dst->elt_size;
 
142
 
 
143
    if (dst->nelts + src->nelts > dst->nalloc) {
 
144
        int new_size = (dst->nalloc <= 0) ? 1 : dst->nalloc * 2;
 
145
        char *new_data;
 
146
 
 
147
        while (dst->nelts + src->nelts > new_size) {
 
148
            new_size *= 2;
 
149
        }
 
150
 
 
151
        new_data = apr_pcalloc(dst->pool, elt_size * new_size);
 
152
        memcpy(new_data, dst->elts, dst->nalloc * elt_size);
 
153
 
 
154
        dst->elts = new_data;
 
155
        dst->nalloc = new_size;
 
156
    }
 
157
 
 
158
    memcpy(dst->elts + dst->nelts * elt_size, src->elts,
 
159
           elt_size * src->nelts);
 
160
    dst->nelts += src->nelts;
 
161
}
 
162
 
 
163
APR_DECLARE(apr_array_header_t *) apr_array_copy(apr_pool_t *p,
 
164
                                                const apr_array_header_t *arr)
 
165
{
 
166
    apr_array_header_t *res =
 
167
        (apr_array_header_t *) apr_palloc(p, sizeof(apr_array_header_t));
 
168
    make_array_core(res, p, arr->nalloc, arr->elt_size, 0);
 
169
 
 
170
    memcpy(res->elts, arr->elts, arr->elt_size * arr->nelts);
 
171
    res->nelts = arr->nelts;
 
172
    memset(res->elts + res->elt_size * res->nelts, 0,
 
173
           res->elt_size * (res->nalloc - res->nelts));
 
174
    return res;
 
175
}
 
176
 
 
177
/* This cute function copies the array header *only*, but arranges
 
178
 * for the data section to be copied on the first push or arraycat.
 
179
 * It's useful when the elements of the array being copied are
 
180
 * read only, but new stuff *might* get added on the end; we have the
 
181
 * overhead of the full copy only where it is really needed.
 
182
 */
 
183
 
 
184
static APR_INLINE void copy_array_hdr_core(apr_array_header_t *res,
 
185
                                           const apr_array_header_t *arr)
 
186
{
 
187
    res->elts = arr->elts;
 
188
    res->elt_size = arr->elt_size;
 
189
    res->nelts = arr->nelts;
 
190
    res->nalloc = arr->nelts;   /* Force overflow on push */
 
191
}
 
192
 
 
193
APR_DECLARE(apr_array_header_t *)
 
194
    apr_array_copy_hdr(apr_pool_t *p,
 
195
                       const apr_array_header_t *arr)
 
196
{
 
197
    apr_array_header_t *res;
 
198
 
 
199
    res = (apr_array_header_t *) apr_palloc(p, sizeof(apr_array_header_t));
 
200
    res->pool = p;
 
201
    copy_array_hdr_core(res, arr);
 
202
    return res;
 
203
}
 
204
 
 
205
/* The above is used here to avoid consing multiple new array bodies... */
 
206
 
 
207
APR_DECLARE(apr_array_header_t *)
 
208
    apr_array_append(apr_pool_t *p,
 
209
                      const apr_array_header_t *first,
 
210
                      const apr_array_header_t *second)
 
211
{
 
212
    apr_array_header_t *res = apr_array_copy_hdr(p, first);
 
213
 
 
214
    apr_array_cat(res, second);
 
215
    return res;
 
216
}
 
217
 
 
218
/* apr_array_pstrcat generates a new string from the apr_pool_t containing
 
219
 * the concatenated sequence of substrings referenced as elements within
 
220
 * the array.  The string will be empty if all substrings are empty or null,
 
221
 * or if there are no elements in the array.
 
222
 * If sep is non-NUL, it will be inserted between elements as a separator.
 
223
 */
 
224
APR_DECLARE(char *) apr_array_pstrcat(apr_pool_t *p,
 
225
                                     const apr_array_header_t *arr,
 
226
                                     const char sep)
 
227
{
 
228
    char *cp, *res, **strpp;
 
229
    apr_size_t len;
 
230
    int i;
 
231
 
 
232
    if (arr->nelts <= 0 || arr->elts == NULL) {    /* Empty table? */
 
233
        return (char *) apr_pcalloc(p, 1);
 
234
    }
 
235
 
 
236
    /* Pass one --- find length of required string */
 
237
 
 
238
    len = 0;
 
239
    for (i = 0, strpp = (char **) arr->elts; ; ++strpp) {
 
240
        if (strpp && *strpp != NULL) {
 
241
            len += strlen(*strpp);
 
242
        }
 
243
        if (++i >= arr->nelts) {
 
244
            break;
 
245
        }
 
246
        if (sep) {
 
247
            ++len;
 
248
        }
 
249
    }
 
250
 
 
251
    /* Allocate the required string */
 
252
 
 
253
    res = (char *) apr_palloc(p, len + 1);
 
254
    cp = res;
 
255
 
 
256
    /* Pass two --- copy the argument strings into the result space */
 
257
 
 
258
    for (i = 0, strpp = (char **) arr->elts; ; ++strpp) {
 
259
        if (strpp && *strpp != NULL) {
 
260
            len = strlen(*strpp);
 
261
            memcpy(cp, *strpp, len);
 
262
            cp += len;
 
263
        }
 
264
        if (++i >= arr->nelts) {
 
265
            break;
 
266
        }
 
267
        if (sep) {
 
268
            *cp++ = sep;
 
269
        }
 
270
    }
 
271
 
 
272
    *cp = '\0';
 
273
 
 
274
    /* Return the result string */
 
275
 
 
276
    return res;
 
277
}
 
278
 
 
279
 
 
280
/*****************************************************************
 
281
 *
 
282
 * The "table" functions.
 
283
 */
 
284
 
 
285
#if APR_CHARSET_EBCDIC
 
286
#define CASE_MASK 0xbfbfbfbf
 
287
#else
 
288
#define CASE_MASK 0xdfdfdfdf
 
289
#endif
 
290
 
 
291
#define TABLE_HASH_SIZE 32
 
292
#define TABLE_INDEX_MASK 0x1f
 
293
#define TABLE_HASH(key)  (TABLE_INDEX_MASK & *(unsigned char *)(key))
 
294
#define TABLE_INDEX_IS_INITIALIZED(t, i) ((t)->index_initialized & (1 << (i)))
 
295
#define TABLE_SET_INDEX_INITIALIZED(t, i) ((t)->index_initialized |= (1 << (i)))
 
296
 
 
297
/* Compute the "checksum" for a key, consisting of the first
 
298
 * 4 bytes, normalized for case-insensitivity and packed into
 
299
 * an int...this checksum allows us to do a single integer
 
300
 * comparison as a fast check to determine whether we can
 
301
 * skip a strcasecmp
 
302
 */
 
303
#define COMPUTE_KEY_CHECKSUM(key, checksum)    \
 
304
{                                              \
 
305
    const char *k = (key);                     \
 
306
    apr_uint32_t c = (apr_uint32_t)*k;         \
 
307
    (checksum) = c;                            \
 
308
    (checksum) <<= 8;                          \
 
309
    if (c) {                                   \
 
310
        c = (apr_uint32_t)*++k;                \
 
311
        checksum |= c;                         \
 
312
    }                                          \
 
313
    (checksum) <<= 8;                          \
 
314
    if (c) {                                   \
 
315
        c = (apr_uint32_t)*++k;                \
 
316
        checksum |= c;                         \
 
317
    }                                          \
 
318
    (checksum) <<= 8;                          \
 
319
    if (c) {                                   \
 
320
        c = (apr_uint32_t)*++k;                \
 
321
        checksum |= c;                         \
 
322
    }                                          \
 
323
    checksum &= CASE_MASK;                     \
 
324
}
 
325
 
 
326
/** The opaque string-content table type */
 
327
struct apr_table_t {
 
328
    /* This has to be first to promote backwards compatibility with
 
329
     * older modules which cast a apr_table_t * to an apr_array_header_t *...
 
330
     * they should use the apr_table_elts() function for most of the
 
331
     * cases they do this for.
 
332
     */
 
333
    /** The underlying array for the table */
 
334
    apr_array_header_t a;
 
335
#ifdef MAKE_TABLE_PROFILE
 
336
    /** Who created the array. */
 
337
    void *creator;
 
338
#endif
 
339
    /* An index to speed up table lookups.  The way this works is:
 
340
     *   - Hash the key into the index:
 
341
     *     - index_first[TABLE_HASH(key)] is the offset within
 
342
     *       the table of the first entry with that key
 
343
     *     - index_last[TABLE_HASH(key)] is the offset within
 
344
     *       the table of the last entry with that key
 
345
     *   - If (and only if) there is no entry in the table whose
 
346
     *     key hashes to index element i, then the i'th bit
 
347
     *     of index_initialized will be zero.  (Check this before
 
348
     *     trying to use index_first[i] or index_last[i]!)
 
349
     */
 
350
    apr_uint32_t index_initialized;
 
351
    int index_first[TABLE_HASH_SIZE];
 
352
    int index_last[TABLE_HASH_SIZE];
 
353
};
 
354
 
 
355
/*
 
356
 * NOTICE: if you tweak this you should look at is_empty_table() 
 
357
 * and table_elts() in alloc.h
 
358
 */
 
359
#ifdef MAKE_TABLE_PROFILE
 
360
static apr_table_entry_t *table_push(apr_table_t *t)
 
361
{
 
362
    if (t->a.nelts == t->a.nalloc) {
 
363
        return NULL;
 
364
    }
 
365
    return (apr_table_entry_t *) apr_array_push_noclear(&t->a);
 
366
}
 
367
#else /* MAKE_TABLE_PROFILE */
 
368
#define table_push(t)   ((apr_table_entry_t *) apr_array_push_noclear(&(t)->a))
 
369
#endif /* MAKE_TABLE_PROFILE */
 
370
 
 
371
APR_DECLARE(const apr_array_header_t *) apr_table_elts(const apr_table_t *t)
 
372
{
 
373
    return (const apr_array_header_t *)t;
 
374
}
 
375
 
 
376
APR_DECLARE(int) apr_is_empty_table(const apr_table_t *t)
 
377
{
 
378
    return ((t == NULL) || (t->a.nelts == 0));
 
379
}
 
380
 
 
381
APR_DECLARE(apr_table_t *) apr_table_make(apr_pool_t *p, int nelts)
 
382
{
 
383
    apr_table_t *t = apr_palloc(p, sizeof(apr_table_t));
 
384
 
 
385
    make_array_core(&t->a, p, nelts, sizeof(apr_table_entry_t), 0);
 
386
#ifdef MAKE_TABLE_PROFILE
 
387
    t->creator = __builtin_return_address(0);
 
388
#endif
 
389
    t->index_initialized = 0;
 
390
    return t;
 
391
}
 
392
 
 
393
APR_DECLARE(apr_table_t *) apr_table_copy(apr_pool_t *p, const apr_table_t *t)
 
394
{
 
395
    apr_table_t *new = apr_palloc(p, sizeof(apr_table_t));
 
396
 
 
397
#if APR_POOL_DEBUG
 
398
    /* we don't copy keys and values, so it's necessary that t->a.pool
 
399
     * have a life span at least as long as p
 
400
     */
 
401
    if (!apr_pool_is_ancestor(t->a.pool, p)) {
 
402
        fprintf(stderr, "apr_table_copy: t's pool is not an ancestor of p\n");
 
403
        abort();
 
404
    }
 
405
#endif
 
406
    make_array_core(&new->a, p, t->a.nalloc, sizeof(apr_table_entry_t), 0);
 
407
    memcpy(new->a.elts, t->a.elts, t->a.nelts * sizeof(apr_table_entry_t));
 
408
    new->a.nelts = t->a.nelts;
 
409
    memcpy(new->index_first, t->index_first, sizeof(int) * TABLE_HASH_SIZE);
 
410
    memcpy(new->index_last, t->index_last, sizeof(int) * TABLE_HASH_SIZE);
 
411
    new->index_initialized = t->index_initialized;
 
412
    return new;
 
413
}
 
414
 
 
415
static void table_reindex(apr_table_t *t)
 
416
{
 
417
    int i;
 
418
    int hash;
 
419
    apr_table_entry_t *next_elt = (apr_table_entry_t *) t->a.elts;
 
420
 
 
421
    t->index_initialized = 0;
 
422
    for (i = 0; i < t->a.nelts; i++, next_elt++) {
 
423
        hash = TABLE_HASH(next_elt->key);
 
424
        t->index_last[hash] = i;
 
425
        if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) {
 
426
            t->index_first[hash] = i;
 
427
            TABLE_SET_INDEX_INITIALIZED(t, hash);
 
428
        }
 
429
    }
 
430
}
 
431
 
 
432
APR_DECLARE(void) apr_table_clear(apr_table_t *t)
 
433
{
 
434
    t->a.nelts = 0;
 
435
    t->index_initialized = 0;
 
436
}
 
437
 
 
438
APR_DECLARE(const char *) apr_table_get(const apr_table_t *t, const char *key)
 
439
{
 
440
    apr_table_entry_t *next_elt;
 
441
    apr_table_entry_t *end_elt;
 
442
    apr_uint32_t checksum;
 
443
    int hash;
 
444
 
 
445
    if (key == NULL) {
 
446
        return NULL;
 
447
    }
 
448
 
 
449
    hash = TABLE_HASH(key);
 
450
    if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) {
 
451
        return NULL;
 
452
    }
 
453
    COMPUTE_KEY_CHECKSUM(key, checksum);
 
454
    next_elt = ((apr_table_entry_t *) t->a.elts) + t->index_first[hash];;
 
455
    end_elt = ((apr_table_entry_t *) t->a.elts) + t->index_last[hash];
 
456
 
 
457
    for (; next_elt <= end_elt; next_elt++) {
 
458
        if ((checksum == next_elt->key_checksum) &&
 
459
            !strcasecmp(next_elt->key, key)) {
 
460
            return next_elt->val;
 
461
        }
 
462
    }
 
463
 
 
464
    return NULL;
 
465
}
 
466
 
 
467
APR_DECLARE(void) apr_table_set(apr_table_t *t, const char *key,
 
468
                                const char *val)
 
469
{
 
470
    apr_table_entry_t *next_elt;
 
471
    apr_table_entry_t *end_elt;
 
472
    apr_table_entry_t *table_end;
 
473
    apr_uint32_t checksum;
 
474
    int hash;
 
475
 
 
476
    COMPUTE_KEY_CHECKSUM(key, checksum);
 
477
    hash = TABLE_HASH(key);
 
478
    if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) {
 
479
        t->index_first[hash] = t->a.nelts;
 
480
        TABLE_SET_INDEX_INITIALIZED(t, hash);
 
481
        goto add_new_elt;
 
482
    }
 
483
    next_elt = ((apr_table_entry_t *) t->a.elts) + t->index_first[hash];;
 
484
    end_elt = ((apr_table_entry_t *) t->a.elts) + t->index_last[hash];
 
485
    table_end =((apr_table_entry_t *) t->a.elts) + t->a.nelts;
 
486
 
 
487
    for (; next_elt <= end_elt; next_elt++) {
 
488
        if ((checksum == next_elt->key_checksum) &&
 
489
            !strcasecmp(next_elt->key, key)) {
 
490
 
 
491
            /* Found an existing entry with the same key, so overwrite it */
 
492
 
 
493
            int must_reindex = 0;
 
494
            apr_table_entry_t *dst_elt = NULL;
 
495
 
 
496
            next_elt->val = apr_pstrdup(t->a.pool, val);
 
497
 
 
498
            /* Remove any other instances of this key */
 
499
            for (next_elt++; next_elt <= end_elt; next_elt++) {
 
500
                if ((checksum == next_elt->key_checksum) &&
 
501
                    !strcasecmp(next_elt->key, key)) {
 
502
                    t->a.nelts--;
 
503
                    if (!dst_elt) {
 
504
                        dst_elt = next_elt;
 
505
                    }
 
506
                }
 
507
                else if (dst_elt) {
 
508
                    *dst_elt++ = *next_elt;
 
509
                    must_reindex = 1;
 
510
                }
 
511
            }
 
512
 
 
513
            /* If we've removed anything, shift over the remainder
 
514
             * of the table (note that the previous loop didn't
 
515
             * run to the end of the table, just to the last match
 
516
             * for the index)
 
517
             */
 
518
            if (dst_elt) {
 
519
                for (; next_elt < table_end; next_elt++) {
 
520
                    *dst_elt++ = *next_elt;
 
521
                }
 
522
                must_reindex = 1;
 
523
            }
 
524
            if (must_reindex) {
 
525
                table_reindex(t);
 
526
            }
 
527
            return;
 
528
        }
 
529
    }
 
530
 
 
531
add_new_elt:
 
532
    t->index_last[hash] = t->a.nelts;
 
533
    next_elt = (apr_table_entry_t *) table_push(t);
 
534
    next_elt->key = apr_pstrdup(t->a.pool, key);
 
535
    next_elt->val = apr_pstrdup(t->a.pool, val);
 
536
    next_elt->key_checksum = checksum;
 
537
}
 
538
 
 
539
APR_DECLARE(void) apr_table_setn(apr_table_t *t, const char *key,
 
540
                                 const char *val)
 
541
{
 
542
    apr_table_entry_t *next_elt;
 
543
    apr_table_entry_t *end_elt;
 
544
    apr_table_entry_t *table_end;
 
545
    apr_uint32_t checksum;
 
546
    int hash;
 
547
 
 
548
    COMPUTE_KEY_CHECKSUM(key, checksum);
 
549
    hash = TABLE_HASH(key);
 
550
    if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) {
 
551
        t->index_first[hash] = t->a.nelts;
 
552
        TABLE_SET_INDEX_INITIALIZED(t, hash);
 
553
        goto add_new_elt;
 
554
    }
 
555
    next_elt = ((apr_table_entry_t *) t->a.elts) + t->index_first[hash];;
 
556
    end_elt = ((apr_table_entry_t *) t->a.elts) + t->index_last[hash];
 
557
    table_end =((apr_table_entry_t *) t->a.elts) + t->a.nelts;
 
558
 
 
559
    for (; next_elt <= end_elt; next_elt++) {
 
560
        if ((checksum == next_elt->key_checksum) &&
 
561
            !strcasecmp(next_elt->key, key)) {
 
562
 
 
563
            /* Found an existing entry with the same key, so overwrite it */
 
564
 
 
565
            int must_reindex = 0;
 
566
            apr_table_entry_t *dst_elt = NULL;
 
567
 
 
568
            next_elt->val = (char *)val;
 
569
 
 
570
            /* Remove any other instances of this key */
 
571
            for (next_elt++; next_elt <= end_elt; next_elt++) {
 
572
                if ((checksum == next_elt->key_checksum) &&
 
573
                    !strcasecmp(next_elt->key, key)) {
 
574
                    t->a.nelts--;
 
575
                    if (!dst_elt) {
 
576
                        dst_elt = next_elt;
 
577
                    }
 
578
                }
 
579
                else if (dst_elt) {
 
580
                    *dst_elt++ = *next_elt;
 
581
                    must_reindex = 1;
 
582
                }
 
583
            }
 
584
 
 
585
            /* If we've removed anything, shift over the remainder
 
586
             * of the table (note that the previous loop didn't
 
587
             * run to the end of the table, just to the last match
 
588
             * for the index)
 
589
             */
 
590
            if (dst_elt) {
 
591
                for (; next_elt < table_end; next_elt++) {
 
592
                    *dst_elt++ = *next_elt;
 
593
                }
 
594
                must_reindex = 1;
 
595
            }
 
596
            if (must_reindex) {
 
597
                table_reindex(t);
 
598
            }
 
599
            return;
 
600
        }
 
601
    }
 
602
 
 
603
add_new_elt:
 
604
    t->index_last[hash] = t->a.nelts;
 
605
    next_elt = (apr_table_entry_t *) table_push(t);
 
606
    next_elt->key = (char *)key;
 
607
    next_elt->val = (char *)val;
 
608
    next_elt->key_checksum = checksum;
 
609
}
 
610
 
 
611
APR_DECLARE(void) apr_table_unset(apr_table_t *t, const char *key)
 
612
{
 
613
    apr_table_entry_t *next_elt;
 
614
    apr_table_entry_t *end_elt;
 
615
    apr_table_entry_t *dst_elt;
 
616
    apr_uint32_t checksum;
 
617
    int hash;
 
618
    int must_reindex;
 
619
 
 
620
    hash = TABLE_HASH(key);
 
621
    if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) {
 
622
        return;
 
623
    }
 
624
    COMPUTE_KEY_CHECKSUM(key, checksum);
 
625
    next_elt = ((apr_table_entry_t *) t->a.elts) + t->index_first[hash];
 
626
    end_elt = ((apr_table_entry_t *) t->a.elts) + t->index_last[hash];
 
627
    must_reindex = 0;
 
628
    for (; next_elt <= end_elt; next_elt++) {
 
629
        if ((checksum == next_elt->key_checksum) &&
 
630
            !strcasecmp(next_elt->key, key)) {
 
631
 
 
632
            /* Found a match: remove this entry, plus any additional
 
633
             * matches for the same key that might follow
 
634
             */
 
635
            apr_table_entry_t *table_end = ((apr_table_entry_t *) t->a.elts) +
 
636
                t->a.nelts;
 
637
            t->a.nelts--;
 
638
            dst_elt = next_elt;
 
639
            for (next_elt++; next_elt <= end_elt; next_elt++) {
 
640
                if ((checksum == next_elt->key_checksum) &&
 
641
                    !strcasecmp(next_elt->key, key)) {
 
642
                    t->a.nelts--;
 
643
                }
 
644
                else {
 
645
                    *dst_elt++ = *next_elt;
 
646
                }
 
647
            }
 
648
 
 
649
            /* Shift over the remainder of the table (note that
 
650
             * the previous loop didn't run to the end of the table,
 
651
             * just to the last match for the index)
 
652
             */
 
653
            for (; next_elt < table_end; next_elt++) {
 
654
                *dst_elt++ = *next_elt;
 
655
            }
 
656
            must_reindex = 1;
 
657
            break;
 
658
        }
 
659
    }
 
660
    if (must_reindex) {
 
661
        table_reindex(t);
 
662
    }
 
663
}
 
664
 
 
665
APR_DECLARE(void) apr_table_merge(apr_table_t *t, const char *key,
 
666
                                 const char *val)
 
667
{
 
668
    apr_table_entry_t *next_elt;
 
669
    apr_table_entry_t *end_elt;
 
670
    apr_uint32_t checksum;
 
671
    int hash;
 
672
 
 
673
    COMPUTE_KEY_CHECKSUM(key, checksum);
 
674
    hash = TABLE_HASH(key);
 
675
    if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) {
 
676
        t->index_first[hash] = t->a.nelts;
 
677
        TABLE_SET_INDEX_INITIALIZED(t, hash);
 
678
        goto add_new_elt;
 
679
    }
 
680
    next_elt = ((apr_table_entry_t *) t->a.elts) + t->index_first[hash];
 
681
    end_elt = ((apr_table_entry_t *) t->a.elts) + t->index_last[hash];
 
682
 
 
683
    for (; next_elt <= end_elt; next_elt++) {
 
684
        if ((checksum == next_elt->key_checksum) &&
 
685
            !strcasecmp(next_elt->key, key)) {
 
686
 
 
687
            /* Found an existing entry with the same key, so merge with it */
 
688
            next_elt->val = apr_pstrcat(t->a.pool, next_elt->val, ", ",
 
689
                                        val, NULL);
 
690
            return;
 
691
        }
 
692
    }
 
693
 
 
694
add_new_elt:
 
695
    t->index_last[hash] = t->a.nelts;
 
696
    next_elt = (apr_table_entry_t *) table_push(t);
 
697
    next_elt->key = apr_pstrdup(t->a.pool, key);
 
698
    next_elt->val = apr_pstrdup(t->a.pool, val);
 
699
    next_elt->key_checksum = checksum;
 
700
}
 
701
 
 
702
APR_DECLARE(void) apr_table_mergen(apr_table_t *t, const char *key,
 
703
                                  const char *val)
 
704
{
 
705
    apr_table_entry_t *next_elt;
 
706
    apr_table_entry_t *end_elt;
 
707
    apr_uint32_t checksum;
 
708
    int hash;
 
709
 
 
710
#if APR_POOL_DEBUG
 
711
    {
 
712
        if (!apr_pool_is_ancestor(apr_pool_find(key), t->a.pool)) {
 
713
            fprintf(stderr, "apr_table_mergen: key not in ancestor pool of t\n");
 
714
            abort();
 
715
        }
 
716
        if (!apr_pool_is_ancestor(apr_pool_find(val), t->a.pool)) {
 
717
            fprintf(stderr, "apr_table_mergen: key not in ancestor pool of t\n");
 
718
            abort();
 
719
        }
 
720
    }
 
721
#endif
 
722
 
 
723
    COMPUTE_KEY_CHECKSUM(key, checksum);
 
724
    hash = TABLE_HASH(key);
 
725
    if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) {
 
726
        t->index_first[hash] = t->a.nelts;
 
727
        TABLE_SET_INDEX_INITIALIZED(t, hash);
 
728
        goto add_new_elt;
 
729
    }
 
730
    next_elt = ((apr_table_entry_t *) t->a.elts) + t->index_first[hash];;
 
731
    end_elt = ((apr_table_entry_t *) t->a.elts) + t->index_last[hash];
 
732
 
 
733
    for (; next_elt <= end_elt; next_elt++) {
 
734
        if ((checksum == next_elt->key_checksum) &&
 
735
            !strcasecmp(next_elt->key, key)) {
 
736
 
 
737
            /* Found an existing entry with the same key, so merge with it */
 
738
            next_elt->val = apr_pstrcat(t->a.pool, next_elt->val, ", ",
 
739
                                        val, NULL);
 
740
            return;
 
741
        }
 
742
    }
 
743
 
 
744
add_new_elt:
 
745
    t->index_last[hash] = t->a.nelts;
 
746
    next_elt = (apr_table_entry_t *) table_push(t);
 
747
    next_elt->key = (char *)key;
 
748
    next_elt->val = (char *)val;
 
749
    next_elt->key_checksum = checksum;
 
750
}
 
751
 
 
752
APR_DECLARE(void) apr_table_add(apr_table_t *t, const char *key,
 
753
                               const char *val)
 
754
{
 
755
    apr_table_entry_t *elts;
 
756
    apr_uint32_t checksum;
 
757
    int hash;
 
758
 
 
759
    hash = TABLE_HASH(key);
 
760
    t->index_last[hash] = t->a.nelts;
 
761
    if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) {
 
762
        t->index_first[hash] = t->a.nelts;
 
763
        TABLE_SET_INDEX_INITIALIZED(t, hash);
 
764
    }
 
765
    COMPUTE_KEY_CHECKSUM(key, checksum);
 
766
    elts = (apr_table_entry_t *) table_push(t);
 
767
    elts->key = apr_pstrdup(t->a.pool, key);
 
768
    elts->val = apr_pstrdup(t->a.pool, val);
 
769
    elts->key_checksum = checksum;
 
770
}
 
771
 
 
772
APR_DECLARE(void) apr_table_addn(apr_table_t *t, const char *key,
 
773
                                const char *val)
 
774
{
 
775
    apr_table_entry_t *elts;
 
776
    apr_uint32_t checksum;
 
777
    int hash;
 
778
 
 
779
#if APR_POOL_DEBUG
 
780
    {
 
781
        if (!apr_pool_is_ancestor(apr_pool_find(key), t->a.pool)) {
 
782
            fprintf(stderr, "apr_table_addn: key not in ancestor pool of t\n");
 
783
            abort();
 
784
        }
 
785
        if (!apr_pool_is_ancestor(apr_pool_find(val), t->a.pool)) {
 
786
            fprintf(stderr, "apr_table_addn: key not in ancestor pool of t\n");
 
787
            abort();
 
788
        }
 
789
    }
 
790
#endif
 
791
 
 
792
    hash = TABLE_HASH(key);
 
793
    t->index_last[hash] = t->a.nelts;
 
794
    if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) {
 
795
        t->index_first[hash] = t->a.nelts;
 
796
        TABLE_SET_INDEX_INITIALIZED(t, hash);
 
797
    }
 
798
    COMPUTE_KEY_CHECKSUM(key, checksum);
 
799
    elts = (apr_table_entry_t *) table_push(t);
 
800
    elts->key = (char *)key;
 
801
    elts->val = (char *)val;
 
802
    elts->key_checksum = checksum;
 
803
}
 
804
 
 
805
APR_DECLARE(apr_table_t *) apr_table_overlay(apr_pool_t *p,
 
806
                                             const apr_table_t *overlay,
 
807
                                             const apr_table_t *base)
 
808
{
 
809
    apr_table_t *res;
 
810
 
 
811
#if APR_POOL_DEBUG
 
812
    /* we don't copy keys and values, so it's necessary that
 
813
     * overlay->a.pool and base->a.pool have a life span at least
 
814
     * as long as p
 
815
     */
 
816
    if (!apr_pool_is_ancestor(overlay->a.pool, p)) {
 
817
        fprintf(stderr,
 
818
                "apr_table_overlay: overlay's pool is not an ancestor of p\n");
 
819
        abort();
 
820
    }
 
821
    if (!apr_pool_is_ancestor(base->a.pool, p)) {
 
822
        fprintf(stderr,
 
823
                "apr_table_overlay: base's pool is not an ancestor of p\n");
 
824
        abort();
 
825
    }
 
826
#endif
 
827
 
 
828
    res = apr_palloc(p, sizeof(apr_table_t));
 
829
    /* behave like append_arrays */
 
830
    res->a.pool = p;
 
831
    copy_array_hdr_core(&res->a, &overlay->a);
 
832
    apr_array_cat(&res->a, &base->a);
 
833
    table_reindex(res);
 
834
    return res;
 
835
}
 
836
 
 
837
/* And now for something completely abstract ...
 
838
 
 
839
 * For each key value given as a vararg:
 
840
 *   run the function pointed to as
 
841
 *     int comp(void *r, char *key, char *value);
 
842
 *   on each valid key-value pair in the apr_table_t t that matches the vararg key,
 
843
 *   or once for every valid key-value pair if the vararg list is empty,
 
844
 *   until the function returns false (0) or we finish the table.
 
845
 *
 
846
 * Note that we restart the traversal for each vararg, which means that
 
847
 * duplicate varargs will result in multiple executions of the function
 
848
 * for each matching key.  Note also that if the vararg list is empty,
 
849
 * only one traversal will be made and will cut short if comp returns 0.
 
850
 *
 
851
 * Note that the table_get and table_merge functions assume that each key in
 
852
 * the apr_table_t is unique (i.e., no multiple entries with the same key).  This
 
853
 * function does not make that assumption, since it (unfortunately) isn't
 
854
 * true for some of Apache's tables.
 
855
 *
 
856
 * Note that rec is simply passed-on to the comp function, so that the
 
857
 * caller can pass additional info for the task.
 
858
 *
 
859
 * ADDENDUM for apr_table_vdo():
 
860
 * 
 
861
 * The caching api will allow a user to walk the header values:
 
862
 *
 
863
 * apr_status_t apr_cache_el_header_walk(apr_cache_el *el, 
 
864
 *    int (*comp)(void *, const char *, const char *), void *rec, ...);
 
865
 *
 
866
 * So it can be ..., however from there I use a  callback that use a va_list:
 
867
 *
 
868
 * apr_status_t (*cache_el_header_walk)(apr_cache_el *el, 
 
869
 *    int (*comp)(void *, const char *, const char *), void *rec, va_list);
 
870
 *
 
871
 * To pass those ...'s on down to the actual module that will handle walking
 
872
 * their headers, in the file case this is actually just an apr_table - and
 
873
 * rather than reimplementing apr_table_do (which IMHO would be bad) I just
 
874
 * called it with the va_list. For mod_shmem_cache I don't need it since I
 
875
 * can't use apr_table's, but mod_file_cache should (though a good hash would
 
876
 * be better, but that's a different issue :). 
 
877
 *
 
878
 * So to make mod_file_cache easier to maintain, it's a good thing
 
879
 */
 
880
APR_DECLARE_NONSTD(int) apr_table_do(apr_table_do_callback_fn_t *comp,
 
881
                                     void *rec, const apr_table_t *t, ...)
 
882
{
 
883
    int rv;
 
884
 
 
885
    va_list vp;
 
886
    va_start(vp, t);
 
887
    rv = apr_table_vdo(comp, rec, t, vp);
 
888
    va_end(vp);
 
889
 
 
890
    return rv;
 
891
 
892
 
 
893
/* XXX: do the semantics of this routine make any sense?  Right now,
 
894
 * if the caller passed in a non-empty va_list of keys to search for,
 
895
 * the "early termination" facility only terminates on *that* key; other
 
896
 * keys will continue to process.  Note that this only has any effect
 
897
 * at all if there are multiple entries in the table with the same key,
 
898
 * otherwise the called function can never effectively early-terminate
 
899
 * this function, as the zero return value is effectively ignored.
 
900
 *
 
901
 * Note also that this behavior is at odds with the behavior seen if an
 
902
 * empty va_list is passed in -- in that case, a zero return value terminates
 
903
 * the entire apr_table_vdo (which is what I think should happen in
 
904
 * both cases).
 
905
 *
 
906
 * If nobody objects soon, I'm going to change the order of the nested
 
907
 * loops in this function so that any zero return value from the (*comp)
 
908
 * function will cause a full termination of apr_table_vdo.  I'm hesitant
 
909
 * at the moment because these (funky) semantics have been around for a
 
910
 * very long time, and although Apache doesn't seem to use them at all,
 
911
 * some third-party vendor might.  I can only think of one possible reason
 
912
 * the existing semantics would make any sense, and it's very Apache-centric,
 
913
 * which is this: if (*comp) is looking for matches of a particular
 
914
 * substring in request headers (let's say it's looking for a particular
 
915
 * cookie name in the Set-Cookie headers), then maybe it wants to be
 
916
 * able to stop searching early as soon as it finds that one and move
 
917
 * on to the next key.  That's only an optimization of course, but changing
 
918
 * the behavior of this function would mean that any code that tried
 
919
 * to do that would stop working right.
 
920
 *
 
921
 * Sigh.  --JCW, 06/28/02
 
922
 */
 
923
APR_DECLARE(int) apr_table_vdo(apr_table_do_callback_fn_t *comp,
 
924
                               void *rec, const apr_table_t *t, va_list vp)
 
925
{
 
926
    char *argp;
 
927
    apr_table_entry_t *elts = (apr_table_entry_t *) t->a.elts;
 
928
    int vdorv = 1;
 
929
 
 
930
    argp = va_arg(vp, char *);
 
931
    do {
 
932
        int rv = 1, i;
 
933
        if (argp) {
 
934
            /* Scan for entries that match the next key */
 
935
            int hash = TABLE_HASH(argp);
 
936
            if (TABLE_INDEX_IS_INITIALIZED(t, hash)) {
 
937
                apr_uint32_t checksum;
 
938
                COMPUTE_KEY_CHECKSUM(argp, checksum);
 
939
                for (i = t->index_first[hash];
 
940
                     rv && (i <= t->index_last[hash]); ++i) {
 
941
                    if (elts[i].key && (checksum == elts[i].key_checksum) &&
 
942
                                        !strcasecmp(elts[i].key, argp)) {
 
943
                        rv = (*comp) (rec, elts[i].key, elts[i].val);
 
944
                    }
 
945
                }
 
946
            }
 
947
        }
 
948
        else {
 
949
            /* Scan the entire table */
 
950
            for (i = 0; rv && (i < t->a.nelts); ++i) {
 
951
                if (elts[i].key) {
 
952
                    rv = (*comp) (rec, elts[i].key, elts[i].val);
 
953
                }
 
954
            }
 
955
        }
 
956
        if (rv == 0) {
 
957
            vdorv = 0;
 
958
        }
 
959
    } while (argp && ((argp = va_arg(vp, char *)) != NULL));
 
960
 
 
961
    return vdorv;
 
962
}
 
963
 
 
964
static apr_table_entry_t **table_mergesort(apr_pool_t *pool,
 
965
                                           apr_table_entry_t **values, 
 
966
                                           apr_size_t n)
 
967
{
 
968
    /* Bottom-up mergesort, based on design in Sedgewick's "Algorithms
 
969
     * in C," chapter 8
 
970
     */
 
971
    apr_table_entry_t **values_tmp =
 
972
        (apr_table_entry_t **)apr_palloc(pool, n * sizeof(apr_table_entry_t*));
 
973
    apr_size_t i;
 
974
    apr_size_t blocksize;
 
975
 
 
976
    /* First pass: sort pairs of elements (blocksize=1) */
 
977
    for (i = 0; i + 1 < n; i += 2) {
 
978
        if (strcasecmp(values[i]->key, values[i + 1]->key) > 0) {
 
979
            apr_table_entry_t *swap = values[i];
 
980
            values[i] = values[i + 1];
 
981
            values[i + 1] = swap;
 
982
        }
 
983
    }
 
984
 
 
985
    /* Merge successively larger blocks */
 
986
    blocksize = 2;
 
987
    while (blocksize < n) {
 
988
        apr_table_entry_t **dst = values_tmp;
 
989
        apr_size_t next_start;
 
990
        apr_table_entry_t **swap;
 
991
 
 
992
        /* Merge consecutive pairs blocks of the next blocksize.
 
993
         * Within a block, elements are in sorted order due to
 
994
         * the previous iteration.
 
995
         */
 
996
        for (next_start = 0; next_start + blocksize < n;
 
997
             next_start += (blocksize + blocksize)) {
 
998
 
 
999
            apr_size_t block1_start = next_start;
 
1000
            apr_size_t block2_start = block1_start + blocksize;
 
1001
            apr_size_t block1_end = block2_start;
 
1002
            apr_size_t block2_end = block2_start + blocksize;
 
1003
            if (block2_end > n) {
 
1004
                /* The last block may be smaller than blocksize */
 
1005
                block2_end = n;
 
1006
            }
 
1007
            for (;;) {
 
1008
 
 
1009
                /* Merge the next two blocks:
 
1010
                 * Pick the smaller of the next element from
 
1011
                 * block 1 and the next element from block 2.
 
1012
                 * Once either of the blocks is emptied, copy
 
1013
                 * over all the remaining elements from the
 
1014
                 * other block
 
1015
                 */
 
1016
                if (block1_start == block1_end) {
 
1017
                    for (; block2_start < block2_end; block2_start++) {
 
1018
                        *dst++ = values[block2_start];
 
1019
                    }
 
1020
                    break;
 
1021
                }
 
1022
                else if (block2_start == block2_end) {
 
1023
                    for (; block1_start < block1_end; block1_start++) {
 
1024
                        *dst++ = values[block1_start];
 
1025
                    }
 
1026
                    break;
 
1027
                }
 
1028
                if (strcasecmp(values[block1_start]->key,
 
1029
                               values[block2_start]->key) > 0) {
 
1030
                    *dst++ = values[block2_start++];
 
1031
                }
 
1032
                else {
 
1033
                    *dst++ = values[block1_start++];
 
1034
                }
 
1035
            }
 
1036
        }
 
1037
 
 
1038
        /* If n is not a multiple of 2*blocksize, some elements
 
1039
         * will be left over at the end of the array.
 
1040
         */
 
1041
        for (i = dst - values_tmp; i < n; i++) {
 
1042
            values_tmp[i] = values[i];
 
1043
        }
 
1044
 
 
1045
        /* The output array of this pass becomes the input
 
1046
         * array of the next pass, and vice versa
 
1047
         */
 
1048
        swap = values_tmp;
 
1049
        values_tmp = values;
 
1050
        values = swap;
 
1051
 
 
1052
        blocksize += blocksize;
 
1053
    }
 
1054
 
 
1055
    return values;
 
1056
}
 
1057
 
 
1058
APR_DECLARE(void) apr_table_compress(apr_table_t *t, unsigned flags)
 
1059
{
 
1060
    apr_table_entry_t **sort_array;
 
1061
    apr_table_entry_t **sort_next;
 
1062
    apr_table_entry_t **sort_end;
 
1063
    apr_table_entry_t *table_next;
 
1064
    apr_table_entry_t **last;
 
1065
    int i;
 
1066
    int dups_found;
 
1067
 
 
1068
    if (t->a.nelts <= 1) {
 
1069
        return;
 
1070
    }
 
1071
 
 
1072
    /* Copy pointers to all the table elements into an
 
1073
     * array and sort to allow for easy detection of
 
1074
     * duplicate keys
 
1075
     */
 
1076
    sort_array = (apr_table_entry_t **)
 
1077
        apr_palloc(t->a.pool, t->a.nelts * sizeof(apr_table_entry_t*));
 
1078
    sort_next = sort_array;
 
1079
    table_next = (apr_table_entry_t *)t->a.elts;
 
1080
    i = t->a.nelts;
 
1081
    do {
 
1082
        *sort_next++ = table_next++;
 
1083
    } while (--i);
 
1084
 
 
1085
    /* Note: the merge is done with mergesort instead of quicksort
 
1086
     * because mergesort is a stable sort and runs in n*log(n)
 
1087
     * time regardless of its inputs (quicksort is quadratic in
 
1088
     * the worst case)
 
1089
     */
 
1090
    sort_array = table_mergesort(t->a.pool, sort_array, t->a.nelts);
 
1091
 
 
1092
    /* Process any duplicate keys */
 
1093
    dups_found = 0;
 
1094
    sort_next = sort_array;
 
1095
    sort_end = sort_array + t->a.nelts;
 
1096
    last = sort_next++;
 
1097
    while (sort_next < sort_end) {
 
1098
        if (((*sort_next)->key_checksum == (*last)->key_checksum) &&
 
1099
            !strcasecmp((*sort_next)->key, (*last)->key)) {
 
1100
            apr_table_entry_t **dup_last = sort_next + 1;
 
1101
            dups_found = 1;
 
1102
            while ((dup_last < sort_end) &&
 
1103
                   ((*dup_last)->key_checksum == (*last)->key_checksum) &&
 
1104
                   !strcasecmp((*dup_last)->key, (*last)->key)) {
 
1105
                dup_last++;
 
1106
            }
 
1107
            dup_last--; /* Elements from last through dup_last, inclusive,
 
1108
                         * all have the same key
 
1109
                         */
 
1110
            if (flags == APR_OVERLAP_TABLES_MERGE) {
 
1111
                apr_size_t len = 0;
 
1112
                apr_table_entry_t **next = last;
 
1113
                char *new_val;
 
1114
                char *val_dst;
 
1115
                do {
 
1116
                    len += strlen((*next)->val);
 
1117
                    len += 2; /* for ", " or trailing null */
 
1118
                } while (++next <= dup_last);
 
1119
                new_val = (char *)apr_palloc(t->a.pool, len);
 
1120
                val_dst = new_val;
 
1121
                next = last;
 
1122
                for (;;) {
 
1123
                    strcpy(val_dst, (*next)->val);
 
1124
                    val_dst += strlen((*next)->val);
 
1125
                    next++;
 
1126
                    if (next > dup_last) {
 
1127
                        *val_dst = 0;
 
1128
                        break;
 
1129
                    }
 
1130
                    else {
 
1131
                        *val_dst++ = ',';
 
1132
                        *val_dst++ = ' ';
 
1133
                    }
 
1134
                }
 
1135
                (*last)->val = new_val;
 
1136
            }
 
1137
            else { /* overwrite */
 
1138
                (*last)->val = (*dup_last)->val;
 
1139
            }
 
1140
            do {
 
1141
                (*sort_next)->key = NULL;
 
1142
            } while (++sort_next <= dup_last);
 
1143
        }
 
1144
        else {
 
1145
            last = sort_next++;
 
1146
        }
 
1147
    }
 
1148
 
 
1149
    /* Shift elements to the left to fill holes left by removing duplicates */
 
1150
    if (dups_found) {
 
1151
        apr_table_entry_t *src = (apr_table_entry_t *)t->a.elts;
 
1152
        apr_table_entry_t *dst = (apr_table_entry_t *)t->a.elts;
 
1153
        apr_table_entry_t *last_elt = src + t->a.nelts;
 
1154
        do {
 
1155
            if (src->key) {
 
1156
                *dst++ = *src;
 
1157
            }
 
1158
        } while (++src < last_elt);
 
1159
        t->a.nelts -= (int)(last_elt - dst);
 
1160
    }
 
1161
 
 
1162
    table_reindex(t);
 
1163
}
 
1164
 
 
1165
static void apr_table_cat(apr_table_t *t, const apr_table_t *s)
 
1166
{
 
1167
    const int n = t->a.nelts;
 
1168
    register int idx;
 
1169
 
 
1170
    apr_array_cat(&t->a,&s->a);
 
1171
 
 
1172
    if (n == 0) {
 
1173
        memcpy(t->index_first,s->index_first,sizeof(int) * TABLE_HASH_SIZE);
 
1174
        memcpy(t->index_last, s->index_last, sizeof(int) * TABLE_HASH_SIZE);
 
1175
        t->index_initialized = s->index_initialized;
 
1176
        return;
 
1177
    }
 
1178
 
 
1179
    for (idx = 0; idx < TABLE_HASH_SIZE; ++idx) {
 
1180
        if (TABLE_INDEX_IS_INITIALIZED(s, idx)) {
 
1181
            t->index_last[idx] = s->index_last[idx] + n;
 
1182
            if (!TABLE_INDEX_IS_INITIALIZED(t, idx)) {
 
1183
                t->index_first[idx] = s->index_first[idx] + n;
 
1184
            }
 
1185
        }
 
1186
    }
 
1187
 
 
1188
    t->index_initialized |= s->index_initialized;
 
1189
}
 
1190
 
 
1191
APR_DECLARE(void) apr_table_overlap(apr_table_t *a, const apr_table_t *b,
 
1192
                                    unsigned flags)
 
1193
{
 
1194
    if (a->a.nelts + b->a.nelts == 0) {
 
1195
        return;
 
1196
    }
 
1197
 
 
1198
#if APR_POOL_DEBUG
 
1199
    /* Since the keys and values are not copied, it's required that
 
1200
     * b->a.pool has a lifetime at least as long as a->a.pool. */
 
1201
    if (!apr_pool_is_ancestor(b->a.pool, a->a.pool)) {
 
1202
        fprintf(stderr, "apr_table_overlap: b's pool is not an ancestor of a's\n");
 
1203
        abort();
 
1204
    }
 
1205
#endif
 
1206
 
 
1207
    apr_table_cat(a, b);
 
1208
 
 
1209
    apr_table_compress(a, flags);
 
1210
}