Main Page | Modules | Namespace List | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages | Examples

apr_strings.c

Go to the documentation of this file.
00001 /* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
00002  * applicable.
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 /*
00017  * Copyright (c) 1990, 1993
00018  *      The Regents of the University of California.  All rights reserved.
00019  *
00020  * Redistribution and use in source and binary forms, with or without
00021  * modification, are permitted provided that the following conditions
00022  * are met:
00023  * 1. Redistributions of source code must retain the above copyright
00024  *    notice, this list of conditions and the following disclaimer.
00025  * 2. Redistributions in binary form must reproduce the above copyright
00026  *    notice, this list of conditions and the following disclaimer in the
00027  *    documentation and/or other materials provided with the distribution.
00028  * 3. All advertising materials mentioning features or use of this software
00029  *    must display the following acknowledgement:
00030  *      This product includes software developed by the University of
00031  *      California, Berkeley and its contributors.
00032  * 4. Neither the name of the University nor the names of its contributors
00033  *    may be used to endorse or promote products derived from this software
00034  *    without specific prior written permission.
00035  *
00036  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00037  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00038  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00039  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00040  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00041  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00042  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00043  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00044  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00045  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00046  * SUCH DAMAGE.
00047  */
00048 
00049 #include "apr.h"
00050 #include "apr_strings.h"
00051 #include "apr_general.h"
00052 #include "apr_private.h"
00053 #include "apr_lib.h"
00054 #define APR_WANT_STDIO
00055 #define APR_WANT_STRFUNC
00056 #include "apr_want.h"
00057 
00058 #ifdef HAVE_STDDEF_H
00059 #include <stddef.h> /* NULL */
00060 #endif
00061 
00062 #ifdef HAVE_STDLIB_H
00063 #include <stdlib.h> /* strtol and strtoll */
00064 #endif
00065 
00066 /** this is used to cache lengths in apr_pstrcat */
00067 #define MAX_SAVED_LENGTHS  6
00068 
00069 APR_DECLARE(char *) apr_pstrdup(apr_pool_t *a, const char *s)
00070 {
00071     char *res;
00072     apr_size_t len;
00073 
00074     if (s == NULL) {
00075         return NULL;
00076     }
00077     len = strlen(s) + 1;
00078     res = apr_palloc(a, len);
00079     memcpy(res, s, len);
00080     return res;
00081 }
00082 
00083 APR_DECLARE(char *) apr_pstrndup(apr_pool_t *a, const char *s, apr_size_t n)
00084 {
00085     char *res;
00086     const char *end;
00087 
00088     if (s == NULL) {
00089         return NULL;
00090     }
00091     end = memchr(s, '\0', n);
00092     if (end != NULL)
00093         n = end - s;
00094     res = apr_palloc(a, n + 1);
00095     memcpy(res, s, n);
00096     res[n] = '\0';
00097     return res;
00098 }
00099 
00100 APR_DECLARE(char *) apr_pstrmemdup(apr_pool_t *a, const char *s, apr_size_t n)
00101 {
00102     char *res;
00103 
00104     if (s == NULL) {
00105         return NULL;
00106     }
00107     res = apr_palloc(a, n + 1);
00108     memcpy(res, s, n);
00109     res[n] = '\0';
00110     return res;
00111 }
00112 
00113 APR_DECLARE(void *) apr_pmemdup(apr_pool_t *a, const void *m, apr_size_t n)
00114 {
00115     void *res;
00116 
00117     if (m == NULL)
00118         return NULL;
00119     res = apr_palloc(a, n);
00120     memcpy(res, m, n);
00121     return res;
00122 }
00123 
00124 APR_DECLARE_NONSTD(char *) apr_pstrcat(apr_pool_t *a, ...)
00125 {
00126     char *cp, *argp, *res;
00127     apr_size_t saved_lengths[MAX_SAVED_LENGTHS];
00128     int nargs = 0;
00129 
00130     /* Pass one --- find length of required string */
00131 
00132     apr_size_t len = 0;
00133     va_list adummy;
00134 
00135     va_start(adummy, a);
00136 
00137     while ((cp = va_arg(adummy, char *)) != NULL) {
00138         apr_size_t cplen = strlen(cp);
00139         if (nargs < MAX_SAVED_LENGTHS) {
00140             saved_lengths[nargs++] = cplen;
00141         }
00142         len += cplen;
00143     }
00144 
00145     va_end(adummy);
00146 
00147     /* Allocate the required string */
00148 
00149     res = (char *) apr_palloc(a, len + 1);
00150     cp = res;
00151 
00152     /* Pass two --- copy the argument strings into the result space */
00153 
00154     va_start(adummy, a);
00155 
00156     nargs = 0;
00157     while ((argp = va_arg(adummy, char *)) != NULL) {
00158         if (nargs < MAX_SAVED_LENGTHS) {
00159             len = saved_lengths[nargs++];
00160         }
00161         else {
00162             len = strlen(argp);
00163         }
00164  
00165         memcpy(cp, argp, len);
00166         cp += len;
00167     }
00168 
00169     va_end(adummy);
00170 
00171     /* Return the result string */
00172 
00173     *cp = '\0';
00174 
00175     return res;
00176 }
00177 
00178 APR_DECLARE(char *) apr_pstrcatv(apr_pool_t *a, const struct iovec *vec,
00179                                  apr_size_t nvec, apr_size_t *nbytes)
00180 {
00181     apr_size_t i;
00182     apr_size_t len;
00183     const struct iovec *src;
00184     char *res;
00185     char *dst;
00186 
00187     /* Pass one --- find length of required string */
00188     len = 0;
00189     src = vec;
00190     for (i = nvec; i; i--) {
00191         len += src->iov_len;
00192         src++;
00193     }
00194     if (nbytes) {
00195         *nbytes = len;
00196     }
00197 
00198     /* Allocate the required string */
00199     res = (char *) apr_palloc(a, len + 1);
00200     
00201     /* Pass two --- copy the argument strings into the result space */
00202     src = vec;
00203     dst = res;
00204     for (i = nvec; i; i--) {
00205         memcpy(dst, src->iov_base, src->iov_len);
00206         dst += src->iov_len;
00207         src++;
00208     }
00209 
00210     /* Return the result string */
00211     *dst = '\0';
00212 
00213     return res;
00214 }
00215 
00216 #if (!APR_HAVE_MEMCHR)
00217 void *memchr(const void *s, int c, size_t n)
00218 {
00219     const char *cp;
00220 
00221     for (cp = s; n > 0; n--, cp++) {
00222         if (*cp == c)
00223             return (char *) cp; /* Casting away the const here */
00224     }
00225 
00226     return NULL;
00227 }
00228 #endif
00229 
00230 #ifndef INT64_MAX
00231 #define INT64_MAX  APR_INT64_C(0x7fffffffffffffff)
00232 #endif
00233 #ifndef INT64_MIN
00234 #define INT64_MIN (-APR_INT64_C(0x7fffffffffffffff) - APR_INT64_C(1))
00235 #endif
00236 
00237 APR_DECLARE(apr_int64_t) apr_strtoi64(const char *nptr, char **endptr, int base)
00238 {
00239 #if (APR_HAVE_INT64_STRFN)
00240     return APR_INT64_STRFN(nptr, endptr, base);
00241 #else
00242     const char *s;
00243     apr_int64_t acc;
00244     apr_int64_t val;
00245     int neg, any;
00246     char c;
00247 
00248     /*
00249      * Skip white space and pick up leading +/- sign if any.
00250      * If base is 0, allow 0x for hex and 0 for octal, else
00251      * assume decimal; if base is already 16, allow 0x.
00252      */
00253     s = nptr;
00254     do {
00255         c = *s++;
00256     } while (apr_isspace(c));
00257     if (c == '-') {
00258         neg = 1;
00259         c = *s++;
00260     } else {
00261         neg = 0;
00262         if (c == '+')
00263             c = *s++;
00264     }
00265     if ((base == 0 || base == 16) &&
00266         c == '0' && (*s == 'x' || *s == 'X')) {
00267             c = s[1];
00268             s += 2;
00269             base = 16;
00270     }
00271     if (base == 0)
00272         base = c == '0' ? 8 : 10;
00273     acc = any = 0;
00274     if (base < 2 || base > 36) {
00275         errno = EINVAL;
00276         if (endptr != NULL)
00277             *endptr = (char *)(any ? s - 1 : nptr);
00278         return acc;
00279     }
00280 
00281     /* The classic bsd implementation requires div/mod operators
00282      * to compute a cutoff.  Benchmarking proves that is very, very
00283      * evil to some 32 bit processors.  Instead, look for underflow
00284      * in both the mult and add/sub operation.  Unlike the bsd impl,
00285      * we also work strictly in a signed int64 word as we haven't
00286      * implemented the unsigned type in win32.
00287      * 
00288      * Set 'any' if any `digits' consumed; make it negative to indicate
00289      * overflow.
00290      */
00291     val = 0;
00292     for ( ; ; c = *s++) {
00293         if (c >= '0' && c <= '9')
00294             c -= '0';
00295 #if (('Z' - 'A') == 25)
00296         else if (c >= 'A' && c <= 'Z')
00297             c -= 'A' - 10;
00298         else if (c >= 'a' && c <= 'z')
00299             c -= 'a' - 10;
00300 #elif APR_CHARSET_EBCDIC
00301         else if (c >= 'A' && c <= 'I')
00302             c -= 'A' - 10;
00303         else if (c >= 'J' && c <= 'R')
00304             c -= 'J' - 19;
00305         else if (c >= 'S' && c <= 'Z')
00306             c -= 'S' - 28;
00307         else if (c >= 'a' && c <= 'i')
00308             c -= 'a' - 10;
00309         else if (c >= 'j' && c <= 'r')
00310             c -= 'j' - 19;
00311         else if (c >= 's' && c <= 'z')
00312             c -= 'z' - 28;
00313 #else
00314 #error "CANNOT COMPILE apr_strtoi64(), only ASCII and EBCDIC supported" 
00315 #endif
00316         else
00317             break;
00318         if (c >= base)
00319             break;
00320         val *= base;
00321         if ( (any < 0)  /* already noted an over/under flow - short circuit */
00322            || (neg && (val > acc || (val -= c) > acc)) /* underflow */
00323            || (!neg && (val < acc || (val += c) < acc))) {       /* overflow */
00324             any = -1;   /* once noted, over/underflows never go away */
00325 #ifdef APR_STRTOI64_OVERFLOW_IS_BAD_CHAR
00326             break;
00327 #endif
00328         } else {
00329             acc = val;
00330             any = 1;
00331         }
00332     }
00333 
00334     if (any < 0) {
00335         acc = neg ? INT64_MIN : INT64_MAX;
00336         errno = ERANGE;
00337     } else if (!any) {
00338         errno = EINVAL;
00339     }
00340     if (endptr != NULL)
00341         *endptr = (char *)(any ? s - 1 : nptr);
00342     return (acc);
00343 #endif
00344 }
00345 
00346 APR_DECLARE(apr_int64_t) apr_atoi64(const char *buf)
00347 {
00348     return apr_strtoi64(buf, NULL, 10);
00349 }
00350 
00351 APR_DECLARE(char *) apr_itoa(apr_pool_t *p, int n)
00352 {
00353     const int BUFFER_SIZE = sizeof(int) * 3 + 2;
00354     char *buf = apr_palloc(p, BUFFER_SIZE);
00355     char *start = buf + BUFFER_SIZE - 1;
00356     int negative;
00357     if (n < 0) {
00358         negative = 1;
00359         n = -n;
00360     }
00361     else {
00362         negative = 0;
00363     }
00364     *start = 0;
00365     do {
00366         *--start = '0' + (n % 10);
00367         n /= 10;
00368     } while (n);
00369     if (negative) {
00370         *--start = '-';
00371     }
00372     return start;
00373 }
00374 
00375 APR_DECLARE(char *) apr_ltoa(apr_pool_t *p, long n)
00376 {
00377     const int BUFFER_SIZE = sizeof(long) * 3 + 2;
00378     char *buf = apr_palloc(p, BUFFER_SIZE);
00379     char *start = buf + BUFFER_SIZE - 1;
00380     int negative;
00381     if (n < 0) {
00382         negative = 1;
00383         n = -n;
00384     }
00385     else {
00386         negative = 0;
00387     }
00388     *start = 0;
00389     do {
00390         *--start = (char)('0' + (n % 10));
00391         n /= 10;
00392     } while (n);
00393     if (negative) {
00394         *--start = '-';
00395     }
00396     return start;
00397 }
00398 
00399 APR_DECLARE(char *) apr_off_t_toa(apr_pool_t *p, apr_off_t n)
00400 {
00401     const int BUFFER_SIZE = sizeof(apr_off_t) * 3 + 2;
00402     char *buf = apr_palloc(p, BUFFER_SIZE);
00403     char *start = buf + BUFFER_SIZE - 1;
00404     int negative;
00405     if (n < 0) {
00406         negative = 1;
00407         n = -n;
00408     }
00409     else {
00410         negative = 0;
00411     }
00412     *start = 0;
00413     do {
00414         *--start = '0' + (char)(n % 10);
00415         n /= 10;
00416     } while (n);
00417     if (negative) {
00418         *--start = '-';
00419     }
00420     return start;
00421 }
00422 
00423 APR_DECLARE(char *) apr_strfsize(apr_off_t size, char *buf)
00424 {
00425     const char ord[] = "KMGTPE";
00426     const char *o = ord;
00427     int remain;
00428 
00429     if (size < 0) {
00430         return strcpy(buf, "  - ");
00431     }
00432     if (size < 973) {
00433         if (apr_snprintf(buf, 5, "%3d ", (int) size) < 0)
00434             return strcpy(buf, "****");
00435         return buf;
00436     }
00437     do {
00438         remain = (int)(size & 1023);
00439         size >>= 10;
00440         if (size >= 973) {
00441             ++o;
00442             continue;
00443         }
00444         if (size < 9 || (size == 9 && remain < 973)) {
00445             if ((remain = ((remain * 5) + 256) / 512) >= 10)
00446                 ++size, remain = 0;
00447             if (apr_snprintf(buf, 5, "%d.%d%c", (int) size, remain, *o) < 0)
00448                 return strcpy(buf, "****");
00449             return buf;
00450         }
00451         if (remain >= 512)
00452             ++size;
00453         if (apr_snprintf(buf, 5, "%3d%c", (int) size, *o) < 0)
00454             return strcpy(buf, "****");
00455         return buf;
00456     } while (1);
00457 }
00458