string.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. /*
  2. * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
  3. * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. */
  19. #include <pj/string.h>
  20. #include <pj/assert.h>
  21. #include <pj/pool.h>
  22. #include <pj/ctype.h>
  23. #include <pj/rand.h>
  24. #include <pj/os.h>
  25. #include <pj/errno.h>
  26. #include <pj/limits.h>
  27. #if PJ_FUNCTIONS_ARE_INLINED==0
  28. # include <pj/string_i.h>
  29. #endif
  30. PJ_DEF(pj_ssize_t) pj_strspn(const pj_str_t *str, const pj_str_t *set_char)
  31. {
  32. pj_ssize_t i, j, count = 0;
  33. for (i = 0; i < str->slen; i++) {
  34. if (count != i)
  35. break;
  36. for (j = 0; j < set_char->slen; j++) {
  37. if (str->ptr[i] == set_char->ptr[j])
  38. count++;
  39. }
  40. }
  41. return count;
  42. }
  43. PJ_DEF(pj_ssize_t) pj_strspn2(const pj_str_t *str, const char *set_char)
  44. {
  45. pj_ssize_t i, j, count = 0;
  46. for (i = 0; i < str->slen; i++) {
  47. if (count != i)
  48. break;
  49. for (j = 0; set_char[j] != 0; j++) {
  50. if (str->ptr[i] == set_char[j])
  51. count++;
  52. }
  53. }
  54. return count;
  55. }
  56. PJ_DEF(pj_ssize_t) pj_strcspn(const pj_str_t *str, const pj_str_t *set_char)
  57. {
  58. pj_ssize_t i, j;
  59. for (i = 0; i < str->slen; i++) {
  60. for (j = 0; j < set_char->slen; j++) {
  61. if (str->ptr[i] == set_char->ptr[j])
  62. return i;
  63. }
  64. }
  65. return i;
  66. }
  67. PJ_DEF(pj_ssize_t) pj_strcspn2(const pj_str_t *str, const char *set_char)
  68. {
  69. pj_ssize_t i, j;
  70. for (i = 0; i < str->slen; i++) {
  71. for (j = 0; set_char[j] != 0; j++) {
  72. if (str->ptr[i] == set_char[j])
  73. return i;
  74. }
  75. }
  76. return i;
  77. }
  78. PJ_DEF(pj_ssize_t) pj_strtok(const pj_str_t *str, const pj_str_t *delim,
  79. pj_str_t *tok, pj_size_t start_idx)
  80. {
  81. pj_ssize_t str_idx;
  82. pj_assert(str->slen >= 0);
  83. pj_assert(delim->slen >= 0);
  84. tok->slen = 0;
  85. if ((str->slen <= 0) || ((pj_size_t)str->slen < start_idx)) {
  86. return str->slen;
  87. }
  88. tok->ptr = str->ptr + start_idx;
  89. tok->slen = str->slen - start_idx;
  90. str_idx = pj_strspn(tok, delim);
  91. if (start_idx+str_idx == (pj_size_t)str->slen) {
  92. return str->slen;
  93. }
  94. tok->ptr += str_idx;
  95. tok->slen -= str_idx;
  96. tok->slen = pj_strcspn(tok, delim);
  97. return start_idx + str_idx;
  98. }
  99. PJ_DEF(pj_ssize_t) pj_strtok2(const pj_str_t *str, const char *delim,
  100. pj_str_t *tok, pj_size_t start_idx)
  101. {
  102. pj_ssize_t str_idx;
  103. pj_assert(str->slen >= 0);
  104. tok->slen = 0;
  105. if ((str->slen <= 0) || ((pj_size_t)str->slen < start_idx)) {
  106. return str->slen;
  107. }
  108. tok->ptr = str->ptr + start_idx;
  109. tok->slen = str->slen - start_idx;
  110. str_idx = pj_strspn2(tok, delim);
  111. if (start_idx + str_idx == (pj_size_t)str->slen) {
  112. return str->slen;
  113. }
  114. tok->ptr += str_idx;
  115. tok->slen -= str_idx;
  116. tok->slen = pj_strcspn2(tok, delim);
  117. return start_idx + str_idx;
  118. }
  119. PJ_DEF(char*) pj_strstr(const pj_str_t *str, const pj_str_t *substr)
  120. {
  121. const char *s, *ends;
  122. PJ_ASSERT_RETURN(str->slen >= 0 && substr->slen >= 0, NULL);
  123. /* Check if the string is empty */
  124. if (str->slen <= 0)
  125. return NULL;
  126. /* Special case when substr is empty */
  127. if (substr->slen <= 0) {
  128. return (char*)str->ptr;
  129. }
  130. s = str->ptr;
  131. ends = str->ptr + str->slen - substr->slen;
  132. for (; s<=ends; ++s) {
  133. if (pj_ansi_strncmp(s, substr->ptr, substr->slen)==0)
  134. return (char*)s;
  135. }
  136. return NULL;
  137. }
  138. PJ_DEF(char*) pj_stristr(const pj_str_t *str, const pj_str_t *substr)
  139. {
  140. const char *s, *ends;
  141. PJ_ASSERT_RETURN(str->slen >= 0 && substr->slen >= 0, NULL);
  142. /* Check if the string is empty */
  143. if (str->slen <= 0)
  144. return NULL;
  145. /* Special case when substr is empty */
  146. if (substr->slen == 0) {
  147. return (char*)str->ptr;
  148. }
  149. s = str->ptr;
  150. ends = str->ptr + str->slen - substr->slen;
  151. for (; s<=ends; ++s) {
  152. if (pj_ansi_strnicmp(s, substr->ptr, substr->slen)==0)
  153. return (char*)s;
  154. }
  155. return NULL;
  156. }
  157. PJ_DEF(pj_str_t*) pj_strltrim( pj_str_t *str )
  158. {
  159. char *end = str->ptr + str->slen;
  160. register char *p = str->ptr;
  161. pj_assert(str->slen >= 0);
  162. while (p < end && pj_isspace(*p))
  163. ++p;
  164. str->slen -= (p - str->ptr);
  165. str->ptr = p;
  166. return str;
  167. }
  168. PJ_DEF(pj_str_t*) pj_strrtrim( pj_str_t *str )
  169. {
  170. char *end = str->ptr + str->slen;
  171. register char *p = end - 1;
  172. pj_assert(str->slen >= 0);
  173. while (p >= str->ptr && pj_isspace(*p))
  174. --p;
  175. str->slen -= ((end - p) - 1);
  176. return str;
  177. }
  178. PJ_DEF(char*) pj_create_random_string(char *str, pj_size_t len)
  179. {
  180. unsigned i;
  181. char *p = str;
  182. PJ_CHECK_STACK();
  183. for (i=0; i<len/8; ++i) {
  184. pj_uint32_t val = pj_rand();
  185. pj_val_to_hex_digit( (val & 0xFF000000) >> 24, p+0 );
  186. pj_val_to_hex_digit( (val & 0x00FF0000) >> 16, p+2 );
  187. pj_val_to_hex_digit( (val & 0x0000FF00) >> 8, p+4 );
  188. pj_val_to_hex_digit( (val & 0x000000FF) >> 0, p+6 );
  189. p += 8;
  190. }
  191. for (i=i * 8; i<len; ++i) {
  192. *p++ = pj_hex_digits[ pj_rand() & 0x0F ];
  193. }
  194. return str;
  195. }
  196. PJ_DEF(long) pj_strtol(const pj_str_t *str)
  197. {
  198. pj_bool_t is_negative = PJ_FALSE;
  199. unsigned long uval;
  200. long val;
  201. PJ_CHECK_STACK();
  202. if (str->slen > 0 && (str->ptr[0] == '+' || str->ptr[0] == '-')) {
  203. pj_str_t s;
  204. s.ptr = str->ptr + 1;
  205. s.slen = str->slen - 1;
  206. uval = pj_strtoul(&s);
  207. is_negative = (str->ptr[0] == '-');
  208. } else
  209. uval = pj_strtoul(str);
  210. if (is_negative)
  211. val = uval > PJ_MAXLONG ? PJ_MINLONG : -(long)uval;
  212. else
  213. val = uval > PJ_MAXLONG ? PJ_MAXLONG : uval;
  214. return val;
  215. }
  216. PJ_DEF(pj_status_t) pj_strtol2(const pj_str_t *str, long *value)
  217. {
  218. pj_str_t s;
  219. unsigned long retval = 0;
  220. pj_bool_t is_negative = PJ_FALSE;
  221. int rc = 0;
  222. PJ_CHECK_STACK();
  223. if (!str || !value) {
  224. return PJ_EINVAL;
  225. }
  226. PJ_ASSERT_RETURN(str->slen >= 0, PJ_EINVAL);
  227. s = *str;
  228. pj_strltrim(&s);
  229. if (s.slen == 0)
  230. return PJ_EINVAL;
  231. if (s.ptr[0] == '+' || s.ptr[0] == '-') {
  232. is_negative = (s.ptr[0] == '-');
  233. s.ptr += 1;
  234. s.slen -= 1;
  235. }
  236. rc = pj_strtoul3(&s, &retval, 10);
  237. if (rc == PJ_EINVAL) {
  238. return rc;
  239. } else if (rc != PJ_SUCCESS) {
  240. *value = is_negative ? PJ_MINLONG : PJ_MAXLONG;
  241. return is_negative ? PJ_ETOOSMALL : PJ_ETOOBIG;
  242. }
  243. if (retval > PJ_MAXLONG && !is_negative) {
  244. *value = PJ_MAXLONG;
  245. return PJ_ETOOBIG;
  246. }
  247. if (retval > (PJ_MAXLONG + 1UL) && is_negative) {
  248. *value = PJ_MINLONG;
  249. return PJ_ETOOSMALL;
  250. }
  251. if (is_negative && retval == PJ_MAXLONG + 1UL) {
  252. *value = PJ_MINLONG;
  253. return PJ_SUCCESS;
  254. }
  255. *value = is_negative ? -(long)retval : retval;
  256. return PJ_SUCCESS;
  257. }
  258. PJ_DEF(unsigned long) pj_strtoul(const pj_str_t *str)
  259. {
  260. unsigned long value;
  261. unsigned i;
  262. PJ_CHECK_STACK();
  263. pj_assert(str->slen >= 0);
  264. value = 0;
  265. for (i=0; i<(unsigned)str->slen; ++i) {
  266. if (!pj_isdigit(str->ptr[i]))
  267. break;
  268. value = value * 10 + (str->ptr[i] - '0');
  269. }
  270. return value;
  271. }
  272. PJ_DEF(unsigned long) pj_strtoul2(const pj_str_t *str, pj_str_t *endptr,
  273. unsigned base)
  274. {
  275. unsigned long value;
  276. unsigned i;
  277. PJ_CHECK_STACK();
  278. pj_assert(str->slen >= 0);
  279. value = 0;
  280. if (base <= 10) {
  281. for (i=0; i<(unsigned)str->slen; ++i) {
  282. unsigned c = (str->ptr[i] - '0');
  283. if (c >= base)
  284. break;
  285. value = value * base + c;
  286. }
  287. } else if (base == 16) {
  288. for (i=0; i<(unsigned)str->slen; ++i) {
  289. if (!pj_isxdigit(str->ptr[i]))
  290. break;
  291. value = value * 16 + pj_hex_digit_to_val(str->ptr[i]);
  292. }
  293. } else {
  294. pj_assert(!"Unsupported base");
  295. i = 0;
  296. value = 0xFFFFFFFFUL;
  297. }
  298. if (endptr) {
  299. endptr->ptr = str->ptr + i;
  300. endptr->slen = (str->slen < 0)? 0: (str->slen - i);
  301. }
  302. return value;
  303. }
  304. PJ_DEF(pj_status_t) pj_strtoul3(const pj_str_t *str, unsigned long *value,
  305. unsigned base)
  306. {
  307. pj_str_t s;
  308. unsigned i;
  309. PJ_CHECK_STACK();
  310. if (!str || !value) {
  311. return PJ_EINVAL;
  312. }
  313. PJ_ASSERT_RETURN(str->slen >= 0, PJ_EINVAL);
  314. s = *str;
  315. pj_strltrim(&s);
  316. if (s.slen == 0 || s.ptr[0] < '0' ||
  317. (base <= 10 && (unsigned)s.ptr[0] > ('0' - 1) + base) ||
  318. (base == 16 && !pj_isxdigit(s.ptr[0])))
  319. {
  320. return PJ_EINVAL;
  321. }
  322. *value = 0;
  323. if (base <= 10) {
  324. for (i=0; i<(unsigned)s.slen; ++i) {
  325. unsigned c = s.ptr[i] - '0';
  326. if (s.ptr[i] < '0' || (unsigned)s.ptr[i] > ('0' - 1) + base) {
  327. break;
  328. }
  329. if (*value > PJ_MAXULONG / base) {
  330. *value = PJ_MAXULONG;
  331. return PJ_ETOOBIG;
  332. }
  333. *value *= base;
  334. if ((PJ_MAXULONG - *value) < c) {
  335. *value = PJ_MAXULONG;
  336. return PJ_ETOOBIG;
  337. }
  338. *value += c;
  339. }
  340. } else if (base == 16) {
  341. for (i=0; i<(unsigned)s.slen; ++i) {
  342. unsigned c = pj_hex_digit_to_val(s.ptr[i]);
  343. if (!pj_isxdigit(s.ptr[i]))
  344. break;
  345. if (*value > PJ_MAXULONG / base) {
  346. *value = PJ_MAXULONG;
  347. return PJ_ETOOBIG;
  348. }
  349. *value *= base;
  350. if ((PJ_MAXULONG - *value) < c) {
  351. *value = PJ_MAXULONG;
  352. return PJ_ETOOBIG;
  353. }
  354. *value += c;
  355. }
  356. } else {
  357. pj_assert(!"Unsupported base");
  358. return PJ_EINVAL;
  359. }
  360. return PJ_SUCCESS;
  361. }
  362. PJ_DEF(pj_status_t) pj_strtoul4(const pj_str_t *str, pj_uint_t *value,
  363. unsigned base)
  364. {
  365. pj_str_t s;
  366. unsigned i;
  367. PJ_CHECK_STACK();
  368. if (!str || !value) {
  369. return PJ_EINVAL;
  370. }
  371. PJ_ASSERT_RETURN(str->slen >= 0, PJ_EINVAL);
  372. s = *str;
  373. pj_strltrim(&s);
  374. if (s.slen == 0 || s.ptr[0] < '0' ||
  375. (base <= 10 && (unsigned)s.ptr[0] > ('0' - 1) + base) ||
  376. (base == 16 && !pj_isxdigit(s.ptr[0])))
  377. {
  378. return PJ_EINVAL;
  379. }
  380. *value = 0;
  381. if (base <= 10) {
  382. for (i=0; i<(unsigned)s.slen; ++i) {
  383. unsigned c = s.ptr[i] - '0';
  384. if (s.ptr[i] < '0' || (unsigned)s.ptr[i] > ('0' - 1) + base) {
  385. break;
  386. }
  387. if (*value > PJ_MAXUINT / base) {
  388. *value = PJ_MAXUINT;
  389. return PJ_ETOOBIG;
  390. }
  391. *value *= base;
  392. if ((PJ_MAXUINT - *value) < c) {
  393. *value = PJ_MAXUINT;
  394. return PJ_ETOOBIG;
  395. }
  396. *value += c;
  397. }
  398. } else if (base == 16) {
  399. for (i=0; i<(unsigned)s.slen; ++i) {
  400. unsigned c = pj_hex_digit_to_val(s.ptr[i]);
  401. if (!pj_isxdigit(s.ptr[i]))
  402. break;
  403. if (*value > PJ_MAXUINT / base) {
  404. *value = PJ_MAXUINT;
  405. return PJ_ETOOBIG;
  406. }
  407. *value *= base;
  408. if ((PJ_MAXUINT - *value) < c) {
  409. *value = PJ_MAXUINT;
  410. return PJ_ETOOBIG;
  411. }
  412. *value += c;
  413. }
  414. } else {
  415. pj_assert(!"Unsupported base");
  416. return PJ_EINVAL;
  417. }
  418. return PJ_SUCCESS;
  419. }
  420. PJ_DEF(float) pj_strtof(const pj_str_t *str)
  421. {
  422. pj_str_t part;
  423. char *pdot;
  424. float val;
  425. pj_assert(str->slen >= 0);
  426. if (str->slen <= 0)
  427. return 0;
  428. pdot = (char*)pj_memchr(str->ptr, '.', str->slen);
  429. part.ptr = str->ptr;
  430. part.slen = pdot ? pdot - str->ptr : str->slen;
  431. if (part.slen)
  432. val = (float)pj_strtol(&part);
  433. else
  434. val = 0;
  435. if (pdot) {
  436. part.ptr = pdot + 1;
  437. part.slen = (str->ptr + str->slen - pdot - 1);
  438. if (part.slen) {
  439. pj_str_t endptr;
  440. float fpart, fdiv;
  441. int i;
  442. fpart = (float)pj_strtoul2(&part, &endptr, 10);
  443. fdiv = 1.0;
  444. for (i=0; i<(part.slen - endptr.slen); ++i)
  445. fdiv = fdiv * 10;
  446. if (val >= 0)
  447. val += (fpart / fdiv);
  448. else
  449. val -= (fpart / fdiv);
  450. }
  451. }
  452. return val;
  453. }
  454. PJ_DEF(int) pj_utoa(unsigned long val, char *buf)
  455. {
  456. return pj_utoa_pad(val, buf, 0, 0);
  457. }
  458. PJ_DEF(int) pj_utoa_pad( unsigned long val, char *buf, int min_dig, int pad)
  459. {
  460. char *p;
  461. int len;
  462. PJ_CHECK_STACK();
  463. p = buf;
  464. do {
  465. unsigned long digval = (unsigned long) (val % 10);
  466. val /= 10;
  467. *p++ = (char) (digval + '0');
  468. } while (val > 0);
  469. len = (int)(p-buf);
  470. while (len < min_dig) {
  471. *p++ = (char)pad;
  472. ++len;
  473. }
  474. *p-- = '\0';
  475. do {
  476. char temp = *p;
  477. *p = *buf;
  478. *buf = temp;
  479. --p;
  480. ++buf;
  481. } while (buf < p);
  482. return len;
  483. }
  484. PJ_DEF(int) pj_utoa2(pj_uint_t val, char *buf)
  485. {
  486. return pj_utoa_pad2(val, buf, 0, 0);
  487. }
  488. PJ_DEF(int) pj_utoa_pad2(pj_uint_t val, char *buf, int min_dig, int pad)
  489. {
  490. char *p;
  491. int len;
  492. PJ_CHECK_STACK();
  493. p = buf;
  494. do {
  495. pj_uint_t digval = (pj_uint_t) (val % 10);
  496. val /= 10;
  497. *p++ = (char) (digval + '0');
  498. } while (val > 0);
  499. len = (int)(p-buf);
  500. while (len < min_dig) {
  501. *p++ = (char)pad;
  502. ++len;
  503. }
  504. *p-- = '\0';
  505. do {
  506. char temp = *p;
  507. *p = *buf;
  508. *buf = temp;
  509. --p;
  510. ++buf;
  511. } while (buf < p);
  512. return len;
  513. }
  514. PJ_DEF(int) pj_ansi_strxcpy(char *dst, const char *src,
  515. pj_size_t dst_size)
  516. {
  517. char *odst = dst;
  518. PJ_ASSERT_RETURN(dst && src, -PJ_EINVAL);
  519. if (dst_size==0)
  520. return -PJ_ETOOBIG;
  521. while (--dst_size && (*dst=*src) != 0) {
  522. ++dst;
  523. ++src;
  524. }
  525. if (!*dst && !*src) {
  526. return dst-odst;
  527. } else {
  528. *dst = '\0';
  529. return *src? -PJ_ETOOBIG : dst-odst;
  530. }
  531. }
  532. PJ_DEF(int) pj_ansi_strxcpy2(char *dst, const pj_str_t *src,
  533. pj_size_t dst_size)
  534. {
  535. char *odst = dst;
  536. const char *ssrc, *esrc;
  537. PJ_ASSERT_RETURN(dst && src && src->slen >= 0, -PJ_EINVAL);
  538. if (dst_size==0)
  539. return -PJ_ETOOBIG;
  540. ssrc = src->ptr;
  541. esrc = ssrc + src->slen;
  542. while (ssrc < esrc && --dst_size && (*dst = *ssrc)!= 0) {
  543. dst++;
  544. ssrc++;
  545. }
  546. *dst = '\0';
  547. if (ssrc==esrc || !*ssrc) {
  548. return dst-odst;
  549. } else {
  550. return -PJ_ETOOBIG;
  551. }
  552. }
  553. PJ_DEF(int) pj_ansi_strxcat(char *dst, const char *src, pj_size_t dst_size)
  554. {
  555. pj_size_t dst_len;
  556. PJ_ASSERT_RETURN(dst && src, -PJ_EINVAL);
  557. if (dst_size==0)
  558. return -PJ_ETOOBIG;
  559. dst_len = pj_ansi_strlen(dst);
  560. if (dst_len < dst_size) {
  561. int rc = pj_ansi_strxcpy(dst+dst_len, src, dst_size-dst_len);
  562. if (rc < 0)
  563. return rc;
  564. return dst_len + rc;
  565. } else
  566. return -PJ_ETOOBIG;
  567. }