123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691 |
- /*
- * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
- * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- #include <pj/string.h>
- #include <pj/assert.h>
- #include <pj/pool.h>
- #include <pj/ctype.h>
- #include <pj/rand.h>
- #include <pj/os.h>
- #include <pj/errno.h>
- #include <pj/limits.h>
- #if PJ_FUNCTIONS_ARE_INLINED==0
- # include <pj/string_i.h>
- #endif
- PJ_DEF(pj_ssize_t) pj_strspn(const pj_str_t *str, const pj_str_t *set_char)
- {
- pj_ssize_t i, j, count = 0;
- for (i = 0; i < str->slen; i++) {
- if (count != i)
- break;
- for (j = 0; j < set_char->slen; j++) {
- if (str->ptr[i] == set_char->ptr[j])
- count++;
- }
- }
- return count;
- }
- PJ_DEF(pj_ssize_t) pj_strspn2(const pj_str_t *str, const char *set_char)
- {
- pj_ssize_t i, j, count = 0;
- for (i = 0; i < str->slen; i++) {
- if (count != i)
- break;
- for (j = 0; set_char[j] != 0; j++) {
- if (str->ptr[i] == set_char[j])
- count++;
- }
- }
- return count;
- }
- PJ_DEF(pj_ssize_t) pj_strcspn(const pj_str_t *str, const pj_str_t *set_char)
- {
- pj_ssize_t i, j;
- for (i = 0; i < str->slen; i++) {
- for (j = 0; j < set_char->slen; j++) {
- if (str->ptr[i] == set_char->ptr[j])
- return i;
- }
- }
- return i;
- }
- PJ_DEF(pj_ssize_t) pj_strcspn2(const pj_str_t *str, const char *set_char)
- {
- pj_ssize_t i, j;
- for (i = 0; i < str->slen; i++) {
- for (j = 0; set_char[j] != 0; j++) {
- if (str->ptr[i] == set_char[j])
- return i;
- }
- }
- return i;
- }
- PJ_DEF(pj_ssize_t) pj_strtok(const pj_str_t *str, const pj_str_t *delim,
- pj_str_t *tok, pj_size_t start_idx)
- {
- pj_ssize_t str_idx;
- pj_assert(str->slen >= 0);
- pj_assert(delim->slen >= 0);
- tok->slen = 0;
- if ((str->slen <= 0) || ((pj_size_t)str->slen < start_idx)) {
- return str->slen;
- }
- tok->ptr = str->ptr + start_idx;
- tok->slen = str->slen - start_idx;
- str_idx = pj_strspn(tok, delim);
- if (start_idx+str_idx == (pj_size_t)str->slen) {
- return str->slen;
- }
- tok->ptr += str_idx;
- tok->slen -= str_idx;
- tok->slen = pj_strcspn(tok, delim);
- return start_idx + str_idx;
- }
- PJ_DEF(pj_ssize_t) pj_strtok2(const pj_str_t *str, const char *delim,
- pj_str_t *tok, pj_size_t start_idx)
- {
- pj_ssize_t str_idx;
- pj_assert(str->slen >= 0);
- tok->slen = 0;
- if ((str->slen <= 0) || ((pj_size_t)str->slen < start_idx)) {
- return str->slen;
- }
- tok->ptr = str->ptr + start_idx;
- tok->slen = str->slen - start_idx;
- str_idx = pj_strspn2(tok, delim);
- if (start_idx + str_idx == (pj_size_t)str->slen) {
- return str->slen;
- }
- tok->ptr += str_idx;
- tok->slen -= str_idx;
- tok->slen = pj_strcspn2(tok, delim);
- return start_idx + str_idx;
- }
- PJ_DEF(char*) pj_strstr(const pj_str_t *str, const pj_str_t *substr)
- {
- const char *s, *ends;
- PJ_ASSERT_RETURN(str->slen >= 0 && substr->slen >= 0, NULL);
- /* Check if the string is empty */
- if (str->slen <= 0)
- return NULL;
- /* Special case when substr is empty */
- if (substr->slen <= 0) {
- return (char*)str->ptr;
- }
- s = str->ptr;
- ends = str->ptr + str->slen - substr->slen;
- for (; s<=ends; ++s) {
- if (pj_ansi_strncmp(s, substr->ptr, substr->slen)==0)
- return (char*)s;
- }
- return NULL;
- }
- PJ_DEF(char*) pj_stristr(const pj_str_t *str, const pj_str_t *substr)
- {
- const char *s, *ends;
- PJ_ASSERT_RETURN(str->slen >= 0 && substr->slen >= 0, NULL);
- /* Check if the string is empty */
- if (str->slen <= 0)
- return NULL;
- /* Special case when substr is empty */
- if (substr->slen == 0) {
- return (char*)str->ptr;
- }
- s = str->ptr;
- ends = str->ptr + str->slen - substr->slen;
- for (; s<=ends; ++s) {
- if (pj_ansi_strnicmp(s, substr->ptr, substr->slen)==0)
- return (char*)s;
- }
- return NULL;
- }
- PJ_DEF(pj_str_t*) pj_strltrim( pj_str_t *str )
- {
- char *end = str->ptr + str->slen;
- register char *p = str->ptr;
- pj_assert(str->slen >= 0);
- while (p < end && pj_isspace(*p))
- ++p;
- str->slen -= (p - str->ptr);
- str->ptr = p;
- return str;
- }
- PJ_DEF(pj_str_t*) pj_strrtrim( pj_str_t *str )
- {
- char *end = str->ptr + str->slen;
- register char *p = end - 1;
- pj_assert(str->slen >= 0);
- while (p >= str->ptr && pj_isspace(*p))
- --p;
- str->slen -= ((end - p) - 1);
- return str;
- }
- PJ_DEF(char*) pj_create_random_string(char *str, pj_size_t len)
- {
- unsigned i;
- char *p = str;
- PJ_CHECK_STACK();
- for (i=0; i<len/8; ++i) {
- pj_uint32_t val = pj_rand();
- pj_val_to_hex_digit( (val & 0xFF000000) >> 24, p+0 );
- pj_val_to_hex_digit( (val & 0x00FF0000) >> 16, p+2 );
- pj_val_to_hex_digit( (val & 0x0000FF00) >> 8, p+4 );
- pj_val_to_hex_digit( (val & 0x000000FF) >> 0, p+6 );
- p += 8;
- }
- for (i=i * 8; i<len; ++i) {
- *p++ = pj_hex_digits[ pj_rand() & 0x0F ];
- }
- return str;
- }
- PJ_DEF(long) pj_strtol(const pj_str_t *str)
- {
- pj_bool_t is_negative = PJ_FALSE;
- unsigned long uval;
- long val;
- PJ_CHECK_STACK();
- if (str->slen > 0 && (str->ptr[0] == '+' || str->ptr[0] == '-')) {
- pj_str_t s;
- s.ptr = str->ptr + 1;
- s.slen = str->slen - 1;
- uval = pj_strtoul(&s);
- is_negative = (str->ptr[0] == '-');
- } else
- uval = pj_strtoul(str);
- if (is_negative)
- val = uval > PJ_MAXLONG ? PJ_MINLONG : -(long)uval;
- else
- val = uval > PJ_MAXLONG ? PJ_MAXLONG : uval;
- return val;
- }
- PJ_DEF(pj_status_t) pj_strtol2(const pj_str_t *str, long *value)
- {
- pj_str_t s;
- unsigned long retval = 0;
- pj_bool_t is_negative = PJ_FALSE;
- int rc = 0;
- PJ_CHECK_STACK();
- if (!str || !value) {
- return PJ_EINVAL;
- }
- PJ_ASSERT_RETURN(str->slen >= 0, PJ_EINVAL);
- s = *str;
- pj_strltrim(&s);
- if (s.slen == 0)
- return PJ_EINVAL;
- if (s.ptr[0] == '+' || s.ptr[0] == '-') {
- is_negative = (s.ptr[0] == '-');
- s.ptr += 1;
- s.slen -= 1;
- }
- rc = pj_strtoul3(&s, &retval, 10);
- if (rc == PJ_EINVAL) {
- return rc;
- } else if (rc != PJ_SUCCESS) {
- *value = is_negative ? PJ_MINLONG : PJ_MAXLONG;
- return is_negative ? PJ_ETOOSMALL : PJ_ETOOBIG;
- }
- if (retval > PJ_MAXLONG && !is_negative) {
- *value = PJ_MAXLONG;
- return PJ_ETOOBIG;
- }
- if (retval > (PJ_MAXLONG + 1UL) && is_negative) {
- *value = PJ_MINLONG;
- return PJ_ETOOSMALL;
- }
- if (is_negative && retval == PJ_MAXLONG + 1UL) {
- *value = PJ_MINLONG;
- return PJ_SUCCESS;
- }
- *value = is_negative ? -(long)retval : retval;
- return PJ_SUCCESS;
- }
- PJ_DEF(unsigned long) pj_strtoul(const pj_str_t *str)
- {
- unsigned long value;
- unsigned i;
- PJ_CHECK_STACK();
- pj_assert(str->slen >= 0);
- value = 0;
- for (i=0; i<(unsigned)str->slen; ++i) {
- if (!pj_isdigit(str->ptr[i]))
- break;
- value = value * 10 + (str->ptr[i] - '0');
- }
- return value;
- }
- PJ_DEF(unsigned long) pj_strtoul2(const pj_str_t *str, pj_str_t *endptr,
- unsigned base)
- {
- unsigned long value;
- unsigned i;
- PJ_CHECK_STACK();
- pj_assert(str->slen >= 0);
- value = 0;
- if (base <= 10) {
- for (i=0; i<(unsigned)str->slen; ++i) {
- unsigned c = (str->ptr[i] - '0');
- if (c >= base)
- break;
- value = value * base + c;
- }
- } else if (base == 16) {
- for (i=0; i<(unsigned)str->slen; ++i) {
- if (!pj_isxdigit(str->ptr[i]))
- break;
- value = value * 16 + pj_hex_digit_to_val(str->ptr[i]);
- }
- } else {
- pj_assert(!"Unsupported base");
- i = 0;
- value = 0xFFFFFFFFUL;
- }
- if (endptr) {
- endptr->ptr = str->ptr + i;
- endptr->slen = (str->slen < 0)? 0: (str->slen - i);
- }
- return value;
- }
- PJ_DEF(pj_status_t) pj_strtoul3(const pj_str_t *str, unsigned long *value,
- unsigned base)
- {
- pj_str_t s;
- unsigned i;
- PJ_CHECK_STACK();
- if (!str || !value) {
- return PJ_EINVAL;
- }
- PJ_ASSERT_RETURN(str->slen >= 0, PJ_EINVAL);
-
- s = *str;
- pj_strltrim(&s);
- if (s.slen == 0 || s.ptr[0] < '0' ||
- (base <= 10 && (unsigned)s.ptr[0] > ('0' - 1) + base) ||
- (base == 16 && !pj_isxdigit(s.ptr[0])))
- {
- return PJ_EINVAL;
- }
- *value = 0;
- if (base <= 10) {
- for (i=0; i<(unsigned)s.slen; ++i) {
- unsigned c = s.ptr[i] - '0';
- if (s.ptr[i] < '0' || (unsigned)s.ptr[i] > ('0' - 1) + base) {
- break;
- }
- if (*value > PJ_MAXULONG / base) {
- *value = PJ_MAXULONG;
- return PJ_ETOOBIG;
- }
- *value *= base;
- if ((PJ_MAXULONG - *value) < c) {
- *value = PJ_MAXULONG;
- return PJ_ETOOBIG;
- }
- *value += c;
- }
- } else if (base == 16) {
- for (i=0; i<(unsigned)s.slen; ++i) {
- unsigned c = pj_hex_digit_to_val(s.ptr[i]);
- if (!pj_isxdigit(s.ptr[i]))
- break;
- if (*value > PJ_MAXULONG / base) {
- *value = PJ_MAXULONG;
- return PJ_ETOOBIG;
- }
- *value *= base;
- if ((PJ_MAXULONG - *value) < c) {
- *value = PJ_MAXULONG;
- return PJ_ETOOBIG;
- }
- *value += c;
- }
- } else {
- pj_assert(!"Unsupported base");
- return PJ_EINVAL;
- }
- return PJ_SUCCESS;
- }
- PJ_DEF(pj_status_t) pj_strtoul4(const pj_str_t *str, pj_uint_t *value,
- unsigned base)
- {
- pj_str_t s;
- unsigned i;
- PJ_CHECK_STACK();
- if (!str || !value) {
- return PJ_EINVAL;
- }
- PJ_ASSERT_RETURN(str->slen >= 0, PJ_EINVAL);
- s = *str;
- pj_strltrim(&s);
- if (s.slen == 0 || s.ptr[0] < '0' ||
- (base <= 10 && (unsigned)s.ptr[0] > ('0' - 1) + base) ||
- (base == 16 && !pj_isxdigit(s.ptr[0])))
- {
- return PJ_EINVAL;
- }
- *value = 0;
- if (base <= 10) {
- for (i=0; i<(unsigned)s.slen; ++i) {
- unsigned c = s.ptr[i] - '0';
- if (s.ptr[i] < '0' || (unsigned)s.ptr[i] > ('0' - 1) + base) {
- break;
- }
- if (*value > PJ_MAXUINT / base) {
- *value = PJ_MAXUINT;
- return PJ_ETOOBIG;
- }
- *value *= base;
- if ((PJ_MAXUINT - *value) < c) {
- *value = PJ_MAXUINT;
- return PJ_ETOOBIG;
- }
- *value += c;
- }
- } else if (base == 16) {
- for (i=0; i<(unsigned)s.slen; ++i) {
- unsigned c = pj_hex_digit_to_val(s.ptr[i]);
- if (!pj_isxdigit(s.ptr[i]))
- break;
- if (*value > PJ_MAXUINT / base) {
- *value = PJ_MAXUINT;
- return PJ_ETOOBIG;
- }
- *value *= base;
- if ((PJ_MAXUINT - *value) < c) {
- *value = PJ_MAXUINT;
- return PJ_ETOOBIG;
- }
- *value += c;
- }
- } else {
- pj_assert(!"Unsupported base");
- return PJ_EINVAL;
- }
- return PJ_SUCCESS;
- }
- PJ_DEF(float) pj_strtof(const pj_str_t *str)
- {
- pj_str_t part;
- char *pdot;
- float val;
- pj_assert(str->slen >= 0);
- if (str->slen <= 0)
- return 0;
- pdot = (char*)pj_memchr(str->ptr, '.', str->slen);
- part.ptr = str->ptr;
- part.slen = pdot ? pdot - str->ptr : str->slen;
- if (part.slen)
- val = (float)pj_strtol(&part);
- else
- val = 0;
- if (pdot) {
- part.ptr = pdot + 1;
- part.slen = (str->ptr + str->slen - pdot - 1);
- if (part.slen) {
- pj_str_t endptr;
- float fpart, fdiv;
- int i;
- fpart = (float)pj_strtoul2(&part, &endptr, 10);
- fdiv = 1.0;
- for (i=0; i<(part.slen - endptr.slen); ++i)
- fdiv = fdiv * 10;
- if (val >= 0)
- val += (fpart / fdiv);
- else
- val -= (fpart / fdiv);
- }
- }
- return val;
- }
- PJ_DEF(int) pj_utoa(unsigned long val, char *buf)
- {
- return pj_utoa_pad(val, buf, 0, 0);
- }
- PJ_DEF(int) pj_utoa_pad( unsigned long val, char *buf, int min_dig, int pad)
- {
- char *p;
- int len;
- PJ_CHECK_STACK();
- p = buf;
- do {
- unsigned long digval = (unsigned long) (val % 10);
- val /= 10;
- *p++ = (char) (digval + '0');
- } while (val > 0);
- len = (int)(p-buf);
- while (len < min_dig) {
- *p++ = (char)pad;
- ++len;
- }
- *p-- = '\0';
- do {
- char temp = *p;
- *p = *buf;
- *buf = temp;
- --p;
- ++buf;
- } while (buf < p);
- return len;
- }
- PJ_DEF(int) pj_utoa2(pj_uint_t val, char *buf)
- {
- return pj_utoa_pad2(val, buf, 0, 0);
- }
- PJ_DEF(int) pj_utoa_pad2(pj_uint_t val, char *buf, int min_dig, int pad)
- {
- char *p;
- int len;
- PJ_CHECK_STACK();
- p = buf;
- do {
- pj_uint_t digval = (pj_uint_t) (val % 10);
- val /= 10;
- *p++ = (char) (digval + '0');
- } while (val > 0);
- len = (int)(p-buf);
- while (len < min_dig) {
- *p++ = (char)pad;
- ++len;
- }
- *p-- = '\0';
- do {
- char temp = *p;
- *p = *buf;
- *buf = temp;
- --p;
- ++buf;
- } while (buf < p);
- return len;
- }
- PJ_DEF(int) pj_ansi_strxcpy(char *dst, const char *src,
- pj_size_t dst_size)
- {
- char *odst = dst;
- PJ_ASSERT_RETURN(dst && src, -PJ_EINVAL);
- if (dst_size==0)
- return -PJ_ETOOBIG;
- while (--dst_size && (*dst=*src) != 0) {
- ++dst;
- ++src;
- }
- if (!*dst && !*src) {
- return dst-odst;
- } else {
- *dst = '\0';
- return *src? -PJ_ETOOBIG : dst-odst;
- }
- }
- PJ_DEF(int) pj_ansi_strxcpy2(char *dst, const pj_str_t *src,
- pj_size_t dst_size)
- {
- char *odst = dst;
- const char *ssrc, *esrc;
- PJ_ASSERT_RETURN(dst && src && src->slen >= 0, -PJ_EINVAL);
- if (dst_size==0)
- return -PJ_ETOOBIG;
- ssrc = src->ptr;
- esrc = ssrc + src->slen;
- while (ssrc < esrc && --dst_size && (*dst = *ssrc)!= 0) {
- dst++;
- ssrc++;
- }
- *dst = '\0';
- if (ssrc==esrc || !*ssrc) {
- return dst-odst;
- } else {
- return -PJ_ETOOBIG;
- }
- }
- PJ_DEF(int) pj_ansi_strxcat(char *dst, const char *src, pj_size_t dst_size)
- {
- pj_size_t dst_len;
- PJ_ASSERT_RETURN(dst && src, -PJ_EINVAL);
- if (dst_size==0)
- return -PJ_ETOOBIG;
- dst_len = pj_ansi_strlen(dst);
- if (dst_len < dst_size) {
- int rc = pj_ansi_strxcpy(dst+dst_len, src, dst_size-dst_len);
- if (rc < 0)
- return rc;
- return dst_len + rc;
- } else
- return -PJ_ETOOBIG;
- }
|