10
25
which is major mmn 20020903, minor mmn 4 */
11
26
#if ! AP_MODULE_MAGIC_AT_LEAST(20020903,4)
13
/* added in APACHE_2_0_47/APR_0_9_4 */
28
/* added in APACHE_2_0_47/APR_0_9_4 - duplicated here for 2.0.46.
29
* I'd rather not duplicate it, but we use apr_table_compress
30
* in the directive merge routines, so it's either duplicate it
31
* here, recode the compress logic there, or drop 2.0.46 support
34
#define TABLE_HASH_SIZE 32
38
#ifdef MAKE_TABLE_PROFILE
39
/** Who created the array. */
42
apr_uint32_t index_initialized;
43
int index_first[TABLE_HASH_SIZE];
44
int index_last[TABLE_HASH_SIZE];
47
static apr_table_entry_t **table_mergesort(apr_pool_t *pool,
48
apr_table_entry_t **values, int n)
50
/* Bottom-up mergesort, based on design in Sedgewick's "Algorithms
53
apr_table_entry_t **values_tmp =
54
(apr_table_entry_t **)apr_palloc(pool, n * sizeof(apr_table_entry_t*));
58
/* First pass: sort pairs of elements (blocksize=1) */
59
for (i = 0; i + 1 < n; i += 2) {
60
if (strcasecmp(values[i]->key, values[i + 1]->key) > 0) {
61
apr_table_entry_t *swap = values[i];
62
values[i] = values[i + 1];
67
/* Merge successively larger blocks */
69
while (blocksize < n) {
70
apr_table_entry_t **dst = values_tmp;
72
apr_table_entry_t **swap;
74
/* Merge consecutive pairs blocks of the next blocksize.
75
* Within a block, elements are in sorted order due to
76
* the previous iteration.
78
for (next_start = 0; next_start + blocksize < n;
79
next_start += (blocksize + blocksize)) {
81
int block1_start = next_start;
82
int block2_start = block1_start + blocksize;
83
int block1_end = block2_start;
84
int block2_end = block2_start + blocksize;
86
/* The last block may be smaller than blocksize */
91
/* Merge the next two blocks:
92
* Pick the smaller of the next element from
93
* block 1 and the next element from block 2.
94
* Once either of the blocks is emptied, copy
95
* over all the remaining elements from the
98
if (block1_start == block1_end) {
99
for (; block2_start < block2_end; block2_start++) {
100
*dst++ = values[block2_start];
104
else if (block2_start == block2_end) {
105
for (; block1_start < block1_end; block1_start++) {
106
*dst++ = values[block1_start];
110
if (strcasecmp(values[block1_start]->key,
111
values[block2_start]->key) > 0) {
112
*dst++ = values[block2_start++];
115
*dst++ = values[block1_start++];
120
/* If n is not a multiple of 2*blocksize, some elements
121
* will be left over at the end of the array.
123
for (i = dst - values_tmp; i < n; i++) {
124
values_tmp[i] = values[i];
127
/* The output array of this pass becomes the input
128
* array of the next pass, and vice versa
134
blocksize += blocksize;
14
139
void apr_table_compress(apr_table_t *t, unsigned flags)
16
modperl_apr_func_not_implemented(apr_table_compress, 2.0.47, 0.9.4);
141
apr_table_entry_t **sort_array;
142
apr_table_entry_t **sort_next;
143
apr_table_entry_t **sort_end;
144
apr_table_entry_t *table_next;
145
apr_table_entry_t **last;
149
if (t->a.nelts <= 1) {
153
/* Copy pointers to all the table elements into an
154
* array and sort to allow for easy detection of
157
sort_array = (apr_table_entry_t **)
158
apr_palloc(t->a.pool, t->a.nelts * sizeof(apr_table_entry_t*));
159
sort_next = sort_array;
160
table_next = (apr_table_entry_t *)t->a.elts;
163
*sort_next++ = table_next++;
166
/* Note: the merge is done with mergesort instead of quicksort
167
* because mergesort is a stable sort and runs in n*log(n)
168
* time regardless of its inputs (quicksort is quadratic in
171
sort_array = table_mergesort(t->a.pool, sort_array, t->a.nelts);
173
/* Process any duplicate keys */
175
sort_next = sort_array;
176
sort_end = sort_array + t->a.nelts;
178
while (sort_next < sort_end) {
179
if (((*sort_next)->key_checksum == (*last)->key_checksum) &&
180
!strcasecmp((*sort_next)->key, (*last)->key)) {
181
apr_table_entry_t **dup_last = sort_next + 1;
183
while ((dup_last < sort_end) &&
184
((*dup_last)->key_checksum == (*last)->key_checksum) &&
185
!strcasecmp((*dup_last)->key, (*last)->key)) {
188
dup_last--; /* Elements from last through dup_last, inclusive,
189
* all have the same key
191
if (flags == APR_OVERLAP_TABLES_MERGE) {
193
apr_table_entry_t **next = last;
197
len += strlen((*next)->val);
198
len += 2; /* for ", " or trailing null */
199
} while (++next <= dup_last);
200
new_val = (char *)apr_palloc(t->a.pool, len);
204
strcpy(val_dst, (*next)->val);
205
val_dst += strlen((*next)->val);
207
if (next > dup_last) {
216
(*last)->val = new_val;
218
else { /* overwrite */
219
(*last)->val = (*dup_last)->val;
222
(*sort_next)->key = NULL;
223
} while (++sort_next <= dup_last);
230
/* Shift elements to the left to fill holes left by removing duplicates */
232
apr_table_entry_t *src = (apr_table_entry_t *)t->a.elts;
233
apr_table_entry_t *dst = (apr_table_entry_t *)t->a.elts;
234
apr_table_entry_t *last_elt = src + t->a.nelts;
239
} while (++src < last_elt);
240
t->a.nelts -= (last_elt - dst);
243
/* XXX mod_perl: remove to avoid more code duplication.
244
* XXX makes us slower on 2.0.46
246
/* table_reindex(t); */
19
249
#endif /* pre-APR_0_9_5 (APACHE_2_0_47) */