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

« back to all changes in this revision

Viewing changes to srclib/apr/strings/apr_strings.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
 * Copyright (c) 1990, 1993
 
18
 *      The Regents of the University of California.  All rights reserved.
 
19
 *
 
20
 * Redistribution and use in source and binary forms, with or without
 
21
 * modification, are permitted provided that the following conditions
 
22
 * are met:
 
23
 * 1. Redistributions of source code must retain the above copyright
 
24
 *    notice, this list of conditions and the following disclaimer.
 
25
 * 2. Redistributions in binary form must reproduce the above copyright
 
26
 *    notice, this list of conditions and the following disclaimer in the
 
27
 *    documentation and/or other materials provided with the distribution.
 
28
 * 3. All advertising materials mentioning features or use of this software
 
29
 *    must display the following acknowledgement:
 
30
 *      This product includes software developed by the University of
 
31
 *      California, Berkeley and its contributors.
 
32
 * 4. Neither the name of the University nor the names of its contributors
 
33
 *    may be used to endorse or promote products derived from this software
 
34
 *    without specific prior written permission.
 
35
 *
 
36
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 
37
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
38
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
39
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 
40
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
41
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
42
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
43
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
44
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
45
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
46
 * SUCH DAMAGE.
 
47
 */
 
48
 
 
49
#include "apr.h"
 
50
#include "apr_strings.h"
 
51
#include "apr_general.h"
 
52
#include "apr_private.h"
 
53
#include "apr_lib.h"
 
54
#define APR_WANT_STDIO
 
55
#define APR_WANT_STRFUNC
 
56
#include "apr_want.h"
 
57
 
 
58
#ifdef HAVE_STDDEF_H
 
59
#include <stddef.h> /* NULL */
 
60
#endif
 
61
 
 
62
#ifdef HAVE_STDLIB_H
 
63
#include <stdlib.h> /* strtol and strtoll */
 
64
#endif
 
65
 
 
66
/** this is used to cache lengths in apr_pstrcat */
 
67
#define MAX_SAVED_LENGTHS  6
 
68
 
 
69
APR_DECLARE(char *) apr_pstrdup(apr_pool_t *a, const char *s)
 
70
{
 
71
    char *res;
 
72
    apr_size_t len;
 
73
 
 
74
    if (s == NULL) {
 
75
        return NULL;
 
76
    }
 
77
    len = strlen(s) + 1;
 
78
    res = apr_palloc(a, len);
 
79
    memcpy(res, s, len);
 
80
    return res;
 
81
}
 
82
 
 
83
APR_DECLARE(char *) apr_pstrndup(apr_pool_t *a, const char *s, apr_size_t n)
 
84
{
 
85
    char *res;
 
86
    const char *end;
 
87
 
 
88
    if (s == NULL) {
 
89
        return NULL;
 
90
    }
 
91
    end = memchr(s, '\0', n);
 
92
    if (end != NULL)
 
93
        n = end - s;
 
94
    res = apr_palloc(a, n + 1);
 
95
    memcpy(res, s, n);
 
96
    res[n] = '\0';
 
97
    return res;
 
98
}
 
99
 
 
100
APR_DECLARE(char *) apr_pstrmemdup(apr_pool_t *a, const char *s, apr_size_t n)
 
101
{
 
102
    char *res;
 
103
 
 
104
    if (s == NULL) {
 
105
        return NULL;
 
106
    }
 
107
    res = apr_palloc(a, n + 1);
 
108
    memcpy(res, s, n);
 
109
    res[n] = '\0';
 
110
    return res;
 
111
}
 
112
 
 
113
APR_DECLARE(void *) apr_pmemdup(apr_pool_t *a, const void *m, apr_size_t n)
 
114
{
 
115
    void *res;
 
116
 
 
117
    if (m == NULL)
 
118
        return NULL;
 
119
    res = apr_palloc(a, n);
 
120
    memcpy(res, m, n);
 
121
    return res;
 
122
}
 
123
 
 
124
APR_DECLARE_NONSTD(char *) apr_pstrcat(apr_pool_t *a, ...)
 
125
{
 
126
    char *cp, *argp, *res;
 
127
    apr_size_t saved_lengths[MAX_SAVED_LENGTHS];
 
128
    int nargs = 0;
 
129
 
 
130
    /* Pass one --- find length of required string */
 
131
 
 
132
    apr_size_t len = 0;
 
133
    va_list adummy;
 
134
 
 
135
    va_start(adummy, a);
 
136
 
 
137
    while ((cp = va_arg(adummy, char *)) != NULL) {
 
138
        apr_size_t cplen = strlen(cp);
 
139
        if (nargs < MAX_SAVED_LENGTHS) {
 
140
            saved_lengths[nargs++] = cplen;
 
141
        }
 
142
        len += cplen;
 
143
    }
 
144
 
 
145
    va_end(adummy);
 
146
 
 
147
    /* Allocate the required string */
 
148
 
 
149
    res = (char *) apr_palloc(a, len + 1);
 
150
    cp = res;
 
151
 
 
152
    /* Pass two --- copy the argument strings into the result space */
 
153
 
 
154
    va_start(adummy, a);
 
155
 
 
156
    nargs = 0;
 
157
    while ((argp = va_arg(adummy, char *)) != NULL) {
 
158
        if (nargs < MAX_SAVED_LENGTHS) {
 
159
            len = saved_lengths[nargs++];
 
160
        }
 
161
        else {
 
162
            len = strlen(argp);
 
163
        }
 
164
 
 
165
        memcpy(cp, argp, len);
 
166
        cp += len;
 
167
    }
 
168
 
 
169
    va_end(adummy);
 
170
 
 
171
    /* Return the result string */
 
172
 
 
173
    *cp = '\0';
 
174
 
 
175
    return res;
 
176
}
 
177
 
 
178
APR_DECLARE(char *) apr_pstrcatv(apr_pool_t *a, const struct iovec *vec,
 
179
                                 apr_size_t nvec, apr_size_t *nbytes)
 
180
{
 
181
    apr_size_t i;
 
182
    apr_size_t len;
 
183
    const struct iovec *src;
 
184
    char *res;
 
185
    char *dst;
 
186
 
 
187
    /* Pass one --- find length of required string */
 
188
    len = 0;
 
189
    src = vec;
 
190
    for (i = nvec; i; i--) {
 
191
        len += src->iov_len;
 
192
        src++;
 
193
    }
 
194
    if (nbytes) {
 
195
        *nbytes = len;
 
196
    }
 
197
 
 
198
    /* Allocate the required string */
 
199
    res = (char *) apr_palloc(a, len + 1);
 
200
    
 
201
    /* Pass two --- copy the argument strings into the result space */
 
202
    src = vec;
 
203
    dst = res;
 
204
    for (i = nvec; i; i--) {
 
205
        memcpy(dst, src->iov_base, src->iov_len);
 
206
        dst += src->iov_len;
 
207
        src++;
 
208
    }
 
209
 
 
210
    /* Return the result string */
 
211
    *dst = '\0';
 
212
 
 
213
    return res;
 
214
}
 
215
 
 
216
#if (!APR_HAVE_MEMCHR)
 
217
void *memchr(const void *s, int c, size_t n)
 
218
{
 
219
    const char *cp;
 
220
 
 
221
    for (cp = s; n > 0; n--, cp++) {
 
222
        if (*cp == c)
 
223
            return (char *) cp; /* Casting away the const here */
 
224
    }
 
225
 
 
226
    return NULL;
 
227
}
 
228
#endif
 
229
 
 
230
#ifndef INT64_MAX
 
231
#define INT64_MAX  APR_INT64_C(0x7fffffffffffffff)
 
232
#endif
 
233
#ifndef INT64_MIN
 
234
#define INT64_MIN (-APR_INT64_C(0x7fffffffffffffff) - APR_INT64_C(1))
 
235
#endif
 
236
 
 
237
APR_DECLARE(apr_status_t) apr_strtoff(apr_off_t *offset, const char *nptr,
 
238
                                      char **endptr, int base)
 
239
{
 
240
    errno = 0;
 
241
    *offset = APR_OFF_T_STRFN(nptr, endptr, base);
 
242
    return APR_FROM_OS_ERROR(errno);
 
243
}
 
244
 
 
245
APR_DECLARE(apr_int64_t) apr_strtoi64(const char *nptr, char **endptr, int base)
 
246
{
 
247
#ifdef APR_INT64_STRFN
 
248
    return APR_INT64_STRFN(nptr, endptr, base);
 
249
#else
 
250
    const char *s;
 
251
    apr_int64_t acc;
 
252
    apr_int64_t val;
 
253
    int neg, any;
 
254
    char c;
 
255
 
 
256
    /*
 
257
     * Skip white space and pick up leading +/- sign if any.
 
258
     * If base is 0, allow 0x for hex and 0 for octal, else
 
259
     * assume decimal; if base is already 16, allow 0x.
 
260
     */
 
261
    s = nptr;
 
262
    do {
 
263
        c = *s++;
 
264
    } while (apr_isspace(c));
 
265
    if (c == '-') {
 
266
        neg = 1;
 
267
        c = *s++;
 
268
    } else {
 
269
        neg = 0;
 
270
        if (c == '+')
 
271
            c = *s++;
 
272
    }
 
273
    if ((base == 0 || base == 16) &&
 
274
        c == '0' && (*s == 'x' || *s == 'X')) {
 
275
            c = s[1];
 
276
            s += 2;
 
277
            base = 16;
 
278
    }
 
279
    if (base == 0)
 
280
        base = c == '0' ? 8 : 10;
 
281
    acc = any = 0;
 
282
    if (base < 2 || base > 36) {
 
283
        errno = EINVAL;
 
284
        if (endptr != NULL)
 
285
            *endptr = (char *)(any ? s - 1 : nptr);
 
286
        return acc;
 
287
    }
 
288
 
 
289
    /* The classic bsd implementation requires div/mod operators
 
290
     * to compute a cutoff.  Benchmarking proves that is very, very
 
291
     * evil to some 32 bit processors.  Instead, look for underflow
 
292
     * in both the mult and add/sub operation.  Unlike the bsd impl,
 
293
     * we also work strictly in a signed int64 word as we haven't
 
294
     * implemented the unsigned type in win32.
 
295
     * 
 
296
     * Set 'any' if any `digits' consumed; make it negative to indicate
 
297
     * overflow.
 
298
     */
 
299
    val = 0;
 
300
    for ( ; ; c = *s++) {
 
301
        if (c >= '0' && c <= '9')
 
302
            c -= '0';
 
303
#if (('Z' - 'A') == 25)
 
304
        else if (c >= 'A' && c <= 'Z')
 
305
            c -= 'A' - 10;
 
306
        else if (c >= 'a' && c <= 'z')
 
307
            c -= 'a' - 10;
 
308
#elif APR_CHARSET_EBCDIC
 
309
        else if (c >= 'A' && c <= 'I')
 
310
            c -= 'A' - 10;
 
311
        else if (c >= 'J' && c <= 'R')
 
312
            c -= 'J' - 19;
 
313
        else if (c >= 'S' && c <= 'Z')
 
314
            c -= 'S' - 28;
 
315
        else if (c >= 'a' && c <= 'i')
 
316
            c -= 'a' - 10;
 
317
        else if (c >= 'j' && c <= 'r')
 
318
            c -= 'j' - 19;
 
319
        else if (c >= 's' && c <= 'z')
 
320
            c -= 'z' - 28;
 
321
#else
 
322
#error "CANNOT COMPILE apr_strtoi64(), only ASCII and EBCDIC supported" 
 
323
#endif
 
324
        else
 
325
            break;
 
326
        if (c >= base)
 
327
            break;
 
328
        val *= base;
 
329
        if ( (any < 0)  /* already noted an over/under flow - short circuit */
 
330
           || (neg && (val > acc || (val -= c) > acc)) /* underflow */
 
331
           || (!neg && (val < acc || (val += c) < acc))) {       /* overflow */
 
332
            any = -1;   /* once noted, over/underflows never go away */
 
333
#ifdef APR_STRTOI64_OVERFLOW_IS_BAD_CHAR
 
334
            break;
 
335
#endif
 
336
        } else {
 
337
            acc = val;
 
338
            any = 1;
 
339
        }
 
340
    }
 
341
 
 
342
    if (any < 0) {
 
343
        acc = neg ? INT64_MIN : INT64_MAX;
 
344
        errno = ERANGE;
 
345
    } else if (!any) {
 
346
        errno = EINVAL;
 
347
    }
 
348
    if (endptr != NULL)
 
349
        *endptr = (char *)(any ? s - 1 : nptr);
 
350
    return (acc);
 
351
#endif
 
352
}
 
353
 
 
354
APR_DECLARE(apr_int64_t) apr_atoi64(const char *buf)
 
355
{
 
356
    return apr_strtoi64(buf, NULL, 10);
 
357
}
 
358
 
 
359
APR_DECLARE(char *) apr_itoa(apr_pool_t *p, int n)
 
360
{
 
361
    const int BUFFER_SIZE = sizeof(int) * 3 + 2;
 
362
    char *buf = apr_palloc(p, BUFFER_SIZE);
 
363
    char *start = buf + BUFFER_SIZE - 1;
 
364
    int negative;
 
365
    if (n < 0) {
 
366
        negative = 1;
 
367
        n = -n;
 
368
    }
 
369
    else {
 
370
        negative = 0;
 
371
    }
 
372
    *start = 0;
 
373
    do {
 
374
        *--start = '0' + (n % 10);
 
375
        n /= 10;
 
376
    } while (n);
 
377
    if (negative) {
 
378
        *--start = '-';
 
379
    }
 
380
    return start;
 
381
}
 
382
 
 
383
APR_DECLARE(char *) apr_ltoa(apr_pool_t *p, long n)
 
384
{
 
385
    const int BUFFER_SIZE = sizeof(long) * 3 + 2;
 
386
    char *buf = apr_palloc(p, BUFFER_SIZE);
 
387
    char *start = buf + BUFFER_SIZE - 1;
 
388
    int negative;
 
389
    if (n < 0) {
 
390
        negative = 1;
 
391
        n = -n;
 
392
    }
 
393
    else {
 
394
        negative = 0;
 
395
    }
 
396
    *start = 0;
 
397
    do {
 
398
        *--start = (char)('0' + (n % 10));
 
399
        n /= 10;
 
400
    } while (n);
 
401
    if (negative) {
 
402
        *--start = '-';
 
403
    }
 
404
    return start;
 
405
}
 
406
 
 
407
APR_DECLARE(char *) apr_off_t_toa(apr_pool_t *p, apr_off_t n)
 
408
{
 
409
    const int BUFFER_SIZE = sizeof(apr_off_t) * 3 + 2;
 
410
    char *buf = apr_palloc(p, BUFFER_SIZE);
 
411
    char *start = buf + BUFFER_SIZE - 1;
 
412
    int negative;
 
413
    if (n < 0) {
 
414
        negative = 1;
 
415
        n = -n;
 
416
    }
 
417
    else {
 
418
        negative = 0;
 
419
    }
 
420
    *start = 0;
 
421
    do {
 
422
        *--start = '0' + (char)(n % 10);
 
423
        n /= 10;
 
424
    } while (n);
 
425
    if (negative) {
 
426
        *--start = '-';
 
427
    }
 
428
    return start;
 
429
}
 
430
 
 
431
APR_DECLARE(char *) apr_strfsize(apr_off_t size, char *buf)
 
432
{
 
433
    const char ord[] = "KMGTPE";
 
434
    const char *o = ord;
 
435
    int remain;
 
436
 
 
437
    if (size < 0) {
 
438
        return strcpy(buf, "  - ");
 
439
    }
 
440
    if (size < 973) {
 
441
        if (apr_snprintf(buf, 5, "%3d ", (int) size) < 0)
 
442
            return strcpy(buf, "****");
 
443
        return buf;
 
444
    }
 
445
    do {
 
446
        remain = (int)(size & 1023);
 
447
        size >>= 10;
 
448
        if (size >= 973) {
 
449
            ++o;
 
450
            continue;
 
451
        }
 
452
        if (size < 9 || (size == 9 && remain < 973)) {
 
453
            if ((remain = ((remain * 5) + 256) / 512) >= 10)
 
454
                ++size, remain = 0;
 
455
            if (apr_snprintf(buf, 5, "%d.%d%c", (int) size, remain, *o) < 0)
 
456
                return strcpy(buf, "****");
 
457
            return buf;
 
458
        }
 
459
        if (remain >= 512)
 
460
            ++size;
 
461
        if (apr_snprintf(buf, 5, "%3d%c", (int) size, *o) < 0)
 
462
            return strcpy(buf, "****");
 
463
        return buf;
 
464
    } while (1);
 
465
}
 
466