fspr_tables.c 38 KB

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