2
* Copyright 1999-2004 The Apache Software Foundation
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
8
* http://www.apache.org/licenses/LICENSE-2.0
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.
17
/***************************************************************************
18
* Description: General purpose map object *
19
* Author: Gal Shachor <shachor@il.ibm.com> *
20
* Author: Mladen Turk <mturk@apache.org> *
21
* Version: $Revision: 1.36 $ *
22
***************************************************************************/
24
#include "apr_xlate.h"
27
#include "jk_global.h"
34
#define CAPACITY_INC_SIZE (50)
35
#define LENGTH_OF_LINE (8192)
38
#define CASE_MASK 0xbfbfbfbf
40
#define CASE_MASK 0xdfdfdfdf
43
/* Compute the "checksum" for a key, consisting of the first
44
* 4 bytes, normalized for case-insensitivity and packed into
45
* an int...this checksum allows us to do a single integer
46
* comparison as a fast check to determine whether we can
49
#define COMPUTE_KEY_CHECKSUM(key, checksum) \
51
const char *k = (key); \
52
unsigned int c = (unsigned int)*k; \
56
c = (unsigned int)*++k; \
61
c = (unsigned int)*++k; \
66
c = (unsigned int)*++k; \
69
checksum &= CASE_MASK; \
75
jk_pool_atom_t buf[SMALL_POOL_SIZE];
81
unsigned int capacity;
85
static void trim_prp_comment(char *prp);
86
static size_t trim(char *s);
87
static int map_realloc(jk_map_t *m);
89
int jk_map_alloc(jk_map_t **m)
92
return jk_map_open(*m = (jk_map_t *)malloc(sizeof(jk_map_t)));
98
int jk_map_free(jk_map_t **m)
111
int jk_map_open(jk_map_t *m)
116
jk_open_pool(&m->p, m->buf, sizeof(jk_pool_atom_t) * SMALL_POOL_SIZE);
128
int jk_map_close(jk_map_t *m)
133
jk_close_pool(&m->p);
140
void *jk_map_get(jk_map_t *m, const char *name, const void *def)
142
const void *rc = (void *)def;
147
COMPUTE_KEY_CHECKSUM(name, key)
148
for (i = 0; i < m->size; i++) {
149
if (m->keys[i] == key && strcasecmp(m->names[i], name) == 0) {
156
return (void *)rc; /* DIRTY */
159
int jk_map_get_id(jk_map_t *m, const char *name)
165
COMPUTE_KEY_CHECKSUM(name, key)
166
for (i = 0; i < m->size; i++) {
167
if (m->keys[i] == key && strcasecmp(m->names[i], name) == 0) {
177
const char *jk_map_get_string(jk_map_t *m, const char *name, const char *def)
179
const char *rc = def;
184
COMPUTE_KEY_CHECKSUM(name, key)
185
for (i = 0; i < m->size; i++) {
186
if (m->keys[i] == key && strcasecmp(m->names[i], name) == 0) {
197
int jk_map_get_int(jk_map_t *m, const char *name, int def)
205
sprintf(buf, "%d", def);
206
rc = jk_map_get_string(m, name, buf);
210
char *lastchar = &buf[0] + len - 1;
212
if ('m' == *lastchar || 'M' == *lastchar) {
214
multit = 1024 * 1024;
216
else if ('k' == *lastchar || 'K' == *lastchar) {
225
return int_res * multit;
228
double jk_map_get_double(jk_map_t *m, const char *name, double def)
233
sprintf(buf, "%f", def);
234
rc = jk_map_get_string(m, name, buf);
239
int jk_map_get_bool(jk_map_t *m, const char *name, int def)
246
sprintf(buf, "%d", def);
247
rc = jk_map_get_string(m, name, buf);
251
if (strcasecmp(rc, "true") == 0 ||
252
*rc == 'Y' || *rc == 'y' || *rc == '1') {
259
char **jk_map_get_string_list(jk_map_t *m,
261
unsigned *list_len, const char *def)
263
const char *l = jk_map_get_string(m, name, def);
266
#if defined(AS400) || defined(_REENTRANT)
273
unsigned capacity = 0;
276
char *v = jk_pool_strdup(&m->p, l);
283
* GS, in addition to VG's patch, we now need to
284
* strtok also by a "*"
286
#if defined(AS400) || defined(_REENTRANT)
287
for (p = strtok_r(v, " \t,", &lasts);
288
p; p = strtok_r(NULL, " \t,", &lasts))
290
for (p = strtok(v, " \t,"); p; p = strtok(NULL, " \t,"))
295
if (idex == capacity) {
296
ar = jk_pool_realloc(&m->p,
297
sizeof(char *) * (capacity + 5),
298
ar, sizeof(char *) * capacity);
304
ar[idex] = jk_pool_strdup(&m->p, p);
314
int jk_map_put(jk_map_t *m, const char *name, const void *value, void **old)
321
COMPUTE_KEY_CHECKSUM(name, key)
322
for (i = 0; i < m->size; i++) {
323
if (m->keys[i] == key && strcasecmp(m->names[i], name) == 0) {
330
*old = (void *)m->values[i]; /* DIRTY */
331
m->values[i] = value;
337
if (m->size < m->capacity) {
338
m->values[m->size] = value;
339
m->names[m->size] = jk_pool_strdup(&m->p, name);
340
m->keys[m->size] = key;
350
int jk_map_read_property(jk_map_t *m, const char *str)
353
char buf[LENGTH_OF_LINE + 1];
356
if (strlen(str) > LENGTH_OF_LINE)
361
char *v = strchr(prp, '=');
367
if (strlen(v) && strlen(prp)) {
368
const char *oldv = jk_map_get_string(m, prp, NULL);
369
v = jk_map_replace_properties(v, m);
370
if (oldv && jk_is_unique_property(prp) == JK_FALSE) {
371
char *tmpv = jk_pool_alloc(&m->p,
372
strlen(v) + strlen(oldv) + 3);
375
if (jk_is_path_poperty(prp))
376
sep = PATH_SEPERATOR;
377
else if (jk_is_cmd_line_poperty(prp))
379
else if (!strcasecmp(prp, "worker.list"))
381
sprintf(tmpv, "%s%c%s", oldv, sep, v);
386
v = jk_pool_strdup(&m->p, v);
389
jk_map_put(m, prp, v, NULL);
401
int jk_map_read_properties(jk_map_t *m, const char *f, time_t *modified)
408
if ((rc = stat(f, &statbuf)) == -1)
411
fp = fopen(f, "r, o_ccsid=0");
417
char buf[LENGTH_OF_LINE + 1];
422
while (NULL != (prp = fgets(buf, LENGTH_OF_LINE, fp))) {
423
trim_prp_comment(prp);
425
if ((rc =jk_map_read_property(m, prp)) == JK_FALSE)
431
*modified = statbuf.st_mtime;
439
int jk_map_size(jk_map_t *m)
448
const char *jk_map_name_at(jk_map_t *m, int idex)
450
if (m && idex >= 0) {
451
return m->names[idex]; /* DIRTY */
457
void *jk_map_value_at(jk_map_t *m, int idex)
459
if (m && idex >= 0) {
460
return (void *)m->values[idex]; /* DIRTY */
466
static void trim_prp_comment(char *prp)
470
/* lots of lines that translate a '#' realtime deleted */
471
comment = strchr(prp, *APR_NUMBERSIGN);
473
char *comment = strchr(prp, '#');
480
static size_t trim(char *s)
484
/* check for empty strings */
485
if (!(i = strlen(s)))
487
for (i = i - 1; (i >= 0) &&
488
isspace((int)((unsigned char)s[i])); i--);
492
for (i = 0; ('\0' != s[i]) &&
493
isspace((int)((unsigned char)s[i])); i++);
502
static int map_realloc(jk_map_t *m)
504
if (m->size == m->capacity) {
508
int capacity = m->capacity + CAPACITY_INC_SIZE;
510
names = (char **)jk_pool_alloc(&m->p, sizeof(char *) * capacity);
511
values = (void **)jk_pool_alloc(&m->p, sizeof(void *) * capacity);
512
keys = (unsigned int *)jk_pool_alloc(&m->p, sizeof(unsigned int) * capacity);
514
if (values && names) {
515
if (m->capacity && m->names)
516
memcpy(names, m->names, sizeof(char *) * m->capacity);
518
if (m->capacity && m->values)
519
memcpy(values, m->values, sizeof(void *) * m->capacity);
521
if (m->capacity && m->keys)
522
memcpy(keys, m->keys, sizeof(unsigned int) * m->capacity);
524
m->names = (const char **)names;
525
m->values = (const void **)values;
527
m->capacity = capacity;
537
* Replace $(property) in value.
540
char *jk_map_replace_properties(const char *value, jk_map_t *m)
542
char *rc = (char *)value;
543
char *env_start = rc;
546
while ((env_start = strstr(env_start, "$(")) != NULL) {
547
char *env_end = strstr(env_start, ")");
551
char env_name[LENGTH_OF_LINE + 1] = "";
552
const char *env_value;
554
char env_buf[LENGTH_OF_LINE + 1];
557
strcpy(env_name, env_start + 2);
560
env_value = jk_map_get_string(m, env_name, NULL);
562
env_value = getenv(env_name);
566
/* Try the env block from calling process */
567
if (GetEnvironmentVariable(env_name, env_buf,
569
env_value = &env_buf[0];
574
char *new_value = jk_pool_alloc(&m->p,
577
strlen(env_value))));
582
strcpy(new_value, rc);
583
strcat(new_value, env_value);
584
strcat(new_value, env_end + 1);
585
offset = env_start - rc + strlen(env_value);
587
/* Avoid recursive subst */
588
env_start = rc + offset;