PageRenderTime 79ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/suite/ecore/src/lib/eina_str.c

https://bitbucket.org/chittoor/gnutls
C | 594 lines | 304 code | 75 blank | 215 comment | 97 complexity | 38c2d7c70d5cd1884b9c36fe0d91e501 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.1, LGPL-2.0, LGPL-3.0
  1. /* Leave the OpenBSD version below so we can track upstream fixes */
  2. /* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */
  3. /*
  4. * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
  5. *
  6. * Permission to use, copy, modify, and distribute this software for any
  7. * purpose with or without fee is hereby granted, provided that the above
  8. * copyright notice and this permission notice appear in all copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. #ifdef HAVE_CONFIG_H
  19. #include "config.h"
  20. #endif
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <limits.h>
  25. #include <ctype.h>
  26. #ifdef HAVE_ICONV
  27. #include <errno.h>
  28. #include <iconv.h>
  29. #endif
  30. #include "eina_private.h"
  31. #include "eina_str.h"
  32. /*============================================================================*
  33. * Local *
  34. *============================================================================*/
  35. /**
  36. * @cond LOCAL
  37. */
  38. /*
  39. * Internal helper function used by eina_str_has_suffix() and
  40. * eina_str_has_extension()
  41. */
  42. static inline Eina_Bool
  43. eina_str_has_suffix_helper(const char *str,
  44. const char *suffix,
  45. int (*cmp) (const char *, const char *))
  46. {
  47. size_t str_len;
  48. size_t suffix_len;
  49. str_len = strlen(str);
  50. suffix_len = eina_strlen_bounded(suffix, str_len);
  51. if (suffix_len == (size_t) - 1)
  52. return EINA_FALSE;
  53. return cmp(str + str_len - suffix_len, suffix) == 0;
  54. }
  55. static inline char **eina_str_split_full_helper(const char *str,
  56. const char *delim,
  57. int max_tokens,
  58. unsigned int *elements)
  59. {
  60. char *s, **str_array;
  61. const char *src;
  62. size_t len, dlen;
  63. unsigned int tokens;
  64. dlen = strlen(delim);
  65. if (dlen == 0) {
  66. if (elements)
  67. *elements = 0;
  68. return NULL;
  69. }
  70. tokens = 0;
  71. src = str;
  72. /* count tokens and check strlen(str) */
  73. while (*src != '\0') {
  74. const char *d = delim, *d_end = d + dlen;
  75. const char *tmp = src;
  76. for (; (d < d_end) && (*tmp != '\0'); d++, tmp++) {
  77. if (EINA_LIKELY(*d != *tmp))
  78. break;
  79. }
  80. if (EINA_UNLIKELY(d == d_end)) {
  81. src = tmp;
  82. tokens++;
  83. } else
  84. src++;
  85. }
  86. len = src - str;
  87. if ((max_tokens > 0) && (tokens > (unsigned int) max_tokens))
  88. tokens = max_tokens;
  89. str_array = malloc(sizeof(char *) * (tokens + 2));
  90. if (!str_array) {
  91. if (elements)
  92. *elements = 0;
  93. return NULL;
  94. }
  95. s = malloc(len + 1);
  96. if (!s) {
  97. free(str_array);
  98. if (elements)
  99. *elements = 0;
  100. return NULL;
  101. }
  102. /* copy tokens and string */
  103. tokens = 0;
  104. str_array[0] = s;
  105. src = str;
  106. while (*src != '\0') {
  107. const char *d = delim, *d_end = d + dlen;
  108. const char *tmp = src;
  109. for (; (d < d_end) && (*tmp != '\0'); d++, tmp++) {
  110. if (EINA_LIKELY(*d != *tmp))
  111. break;
  112. }
  113. if (EINA_UNLIKELY(d == d_end)) {
  114. src = tmp;
  115. *s = '\0';
  116. s += dlen;
  117. tokens++;
  118. str_array[tokens] = s;
  119. } else {
  120. *s = *src;
  121. s++;
  122. src++;
  123. }
  124. }
  125. *s = '\0';
  126. str_array[tokens + 1] = NULL;
  127. if (elements)
  128. *elements = (tokens + 1);
  129. return str_array;
  130. }
  131. /**
  132. * @endcond
  133. */
  134. /*============================================================================*
  135. * Global *
  136. *============================================================================*/
  137. /*============================================================================*
  138. * API *
  139. *============================================================================*/
  140. /**
  141. * @addtogroup Eina_String_Group String
  142. *
  143. * @brief These functions provide useful C string management.
  144. *
  145. * @{
  146. */
  147. /**
  148. * @brief Copy a c-string to another.
  149. *
  150. * @param dst The destination string.
  151. * @param src The source string.
  152. * @param siz The size of the destination string.
  153. * @return The length of the source string.
  154. *
  155. * This function copies up to @p siz - 1 characters from the
  156. * NUL-terminated string @p src to @p dst, NUL-terminating the result
  157. * (unless @p siz is equal to 0). The returned value is the length of
  158. * @p src. If the returned value is greater than @p siz, truncation
  159. * occurred.
  160. */
  161. EAPI size_t eina_strlcpy(char *dst, const char *src, size_t siz)
  162. {
  163. #ifdef HAVE_STRLCPY
  164. return strlcpy(dst, src, siz);
  165. #else
  166. char *d = dst;
  167. const char *s = src;
  168. size_t n = siz;
  169. /* Copy as many bytes as will fit */
  170. if (n != 0)
  171. while (--n != 0) {
  172. if ((*d++ = *s++) == '\0')
  173. break;
  174. }
  175. /* Not enough room in dst, add NUL and traverse rest of src */
  176. if (n == 0) {
  177. if (siz != 0)
  178. *d = '\0'; /* NUL-terminate dst */
  179. while (*s++);
  180. }
  181. return (s - src - 1); /* count does not include NUL */
  182. #endif
  183. }
  184. /**
  185. * @brief Append a c-string.
  186. *
  187. * @param dst The destination string.
  188. * @param src The source string.
  189. * @param siz The size of the destination string.
  190. * @return The length of the source string plus MIN(siz, strlen(initial dst))
  191. *
  192. * This function appends @p src to @p dst of size @p siz (unlike
  193. * strncat, @p siz is the full size of @p dst, not space left). At
  194. * most @p siz - 1 characters will be copied. Always NUL terminates
  195. * (unless @p siz <= strlen(dst)). This function returns strlen(src) +
  196. * MIN(siz, strlen(initial dst)). If the returned value is greater or
  197. * equal than @p siz, truncation occurred.
  198. */
  199. EAPI size_t eina_strlcat(char *dst, const char *src, size_t siz)
  200. {
  201. char *d = dst;
  202. const char *s = src;
  203. size_t n = siz;
  204. size_t dlen;
  205. /* Find the end of dst and adjust bytes left but don't go past end */
  206. while (n-- != 0 && *d != '\0')
  207. d++;
  208. dlen = d - dst;
  209. n = siz - dlen;
  210. if (n == 0)
  211. return (dlen + strlen(s));
  212. while (*s != '\0') {
  213. if (n != 1) {
  214. *d++ = *s;
  215. n--;
  216. }
  217. s++;
  218. }
  219. *d = '\0';
  220. return (dlen + (s - src)); /* count does not include NUL */
  221. }
  222. /**
  223. * @brief Check if the given string has the given prefix.
  224. *
  225. * @param str The string to work with.
  226. * @param prefix The prefix to check for.
  227. * @return #EINA_TRUE if the string has the given prefix, #EINA_FALSE otherwise.
  228. *
  229. * This function returns #EINA_TRUE if @p str has the prefix
  230. * @p prefix, #EINA_FALSE otherwise. If the length of @p prefix is
  231. * greater than @p str, #EINA_FALSE is returned.
  232. */
  233. EAPI Eina_Bool eina_str_has_prefix(const char *str, const char *prefix)
  234. {
  235. size_t str_len;
  236. size_t prefix_len;
  237. str_len = strlen(str);
  238. prefix_len = eina_strlen_bounded(prefix, str_len);
  239. if (prefix_len == (size_t) - 1)
  240. return EINA_FALSE;
  241. return (strncmp(str, prefix, prefix_len) == 0);
  242. }
  243. /**
  244. * @brief Check if the given string has the given suffix.
  245. *
  246. * @param str The string to work with.
  247. * @param suffix The suffix to check for.
  248. * @return #EINA_TRUE if the string has the given suffix, #EINA_FALSE otherwise.
  249. *
  250. * This function returns #EINA_TRUE if @p str has the suffix
  251. * @p suffix, #EINA_FALSE otherwise. If the length of @p suffix is
  252. * greater than @p str, #EINA_FALSE is returned.
  253. */
  254. /**
  255. * @param str the string to work with
  256. * @param suffix the suffix to check for
  257. * @return true if str has the given suffix
  258. * @brief checks if the string has the given suffix
  259. */
  260. EAPI Eina_Bool eina_str_has_suffix(const char *str, const char *suffix)
  261. {
  262. return eina_str_has_suffix_helper(str, suffix, strcmp);
  263. }
  264. /**
  265. * @brief Check if the given string has the given suffix.
  266. *
  267. * @param str The string to work with.
  268. * @param ext The extension to check for.
  269. * @return #EINA_TRUE if the string has the given extension, #EINA_FALSE otherwise.
  270. *
  271. * This function does the same like eina_str_has_suffix(), but with a
  272. * case insensitive compare.
  273. */
  274. EAPI Eina_Bool eina_str_has_extension(const char *str, const char *ext)
  275. {
  276. return eina_str_has_suffix_helper(str, ext, strcasecmp);
  277. }
  278. /**
  279. * @brief Split a string using a delimiter and returns number of elements.
  280. *
  281. * @param str The string to split.
  282. * @param delim The string which specifies the places at which to split the string.
  283. * @param max_tokens The maximum number of strings to split string into.
  284. * @param elements Where to return the number of elements in returned
  285. * array (not counting the terminating @c NULL). May be @c NULL.
  286. * @return A newly-allocated NULL-terminated array of strings or NULL if it
  287. * fails to allocate the array.
  288. *
  289. * This functin splits @p str into a maximum of @p max_tokens pieces,
  290. * using the given delimiter @p delim. @p delim is not included in any
  291. * of the resulting strings, unless @p max_tokens is reached. If
  292. * @p max_tokens is less than @c 1, the string is splitted completely. If
  293. * @p max_tokens is reached, the last string in the returned string
  294. * array contains the remainder of string. The returned value is a
  295. * newly allocated NULL-terminated array of strings or NULL if it fails to
  296. * allocate the array. To free it, free the first element of the array and the
  297. * array itself.
  298. *
  299. * @see eina_str_split()
  300. */
  301. EAPI char **eina_str_split_full(const char *str,
  302. const char *delim,
  303. int max_tokens, unsigned int *elements)
  304. {
  305. return eina_str_split_full_helper(str, delim, max_tokens,
  306. elements);
  307. }
  308. /**
  309. * @brief Split a string using a delimiter.
  310. *
  311. * @param str The string to split.
  312. * @param delim The string which specifies the places at which to split the string.
  313. * @param max_tokens The maximum number of strings to split string into.
  314. * @return A newly-allocated NULL-terminated array of strings or NULL if it
  315. * fails to allocate the array.
  316. *
  317. * This functin splits @p str into a maximum of @p max_tokens pieces,
  318. * using the given delimiter @p delim. @p delim is not included in any
  319. * of the resulting strings, unless @p max_tokens is reached. If
  320. * @p max_tokens is less than @c 1, the string is splitted completely. If
  321. * @p max_tokens is reached, the last string in the returned string
  322. * array contains the remainder of string. The returned value is a
  323. * newly allocated NULL-terminated array of strings or NULL if it fails to
  324. * allocate the array. To free it, free the first element of the array and the
  325. * array itself.
  326. */
  327. EAPI char **eina_str_split(const char *str, const char *delim,
  328. int max_tokens)
  329. {
  330. return eina_str_split_full_helper(str, delim, max_tokens, NULL);
  331. }
  332. /**
  333. * @brief Join two strings of known length.
  334. *
  335. * @param dst The buffer to store the result.
  336. * @param size Size (in byte) of the buffer.
  337. * @param sep The separator character to use.
  338. * @param a First string to use, before @p sep.
  339. * @param a_len length of @p a.
  340. * @param b Second string to use, after @p sep.
  341. * @param b_len length of @p b.
  342. * @return The number of characters printed.
  343. *
  344. * This function joins the strings @p a and @p b (in that order) and
  345. * separate them with @p sep. The result is stored in the buffer
  346. * @p dst and at most @p size - 1 characters will be written and the
  347. * string is NULL-terminated. @p a_len is the length of @p a (not
  348. * including '\\0') and @p b_len is the length of @p b (not including
  349. * '\\0'). This function returns the number of characters printed (not
  350. * including the trailing '\\0' used to end output to strings). Just
  351. * like snprintf(), it will not write more than @p size bytes, thus a
  352. * returned value of @p size or more means that the output was
  353. * truncated.
  354. *
  355. * @see eina_str_join()
  356. * @see eina_str_join_static()
  357. */
  358. EAPI size_t
  359. eina_str_join_len(char *dst,
  360. size_t size,
  361. char sep,
  362. const char *a, size_t a_len, const char *b, size_t b_len)
  363. {
  364. size_t ret = a_len + b_len + 1;
  365. size_t off;
  366. if (size < 1)
  367. return ret;
  368. if (size <= a_len) {
  369. memcpy(dst, a, size - 1);
  370. dst[size - 1] = '\0';
  371. return ret;
  372. }
  373. memcpy(dst, a, a_len);
  374. off = a_len;
  375. if (size <= off + 1) {
  376. dst[size - 1] = '\0';
  377. return ret;
  378. }
  379. dst[off] = sep;
  380. off++;
  381. if (size <= off + b_len + 1) {
  382. memcpy(dst + off, b, size - off - 1);
  383. dst[size - 1] = '\0';
  384. return ret;
  385. }
  386. memcpy(dst + off, b, b_len);
  387. dst[off + b_len] = '\0';
  388. return ret;
  389. }
  390. /**
  391. * @brief Use iconv to convert a text string from one encoding to another
  392. *
  393. * @param enc_from encoding to convert from
  394. * @param enc_to encoding to convert to
  395. * @param text text to convert
  396. *
  397. */
  398. #ifdef HAVE_ICONV
  399. EAPI char *eina_str_convert(const char *enc_from, const char *enc_to,
  400. const char *text)
  401. {
  402. iconv_t ic;
  403. char *new_txt, *inp, *outp;
  404. size_t inb, outb, outlen, tob, outalloc;
  405. if (!text)
  406. return NULL;
  407. ic = iconv_open(enc_to, enc_from);
  408. if (ic == (iconv_t) (-1))
  409. return NULL;
  410. new_txt = malloc(64);
  411. inb = strlen(text);
  412. outb = 64;
  413. inp = (char *) text;
  414. outp = new_txt;
  415. outalloc = 64;
  416. outlen = 0;
  417. for (;;) {
  418. size_t count;
  419. tob = outb;
  420. count = iconv(ic, &inp, &inb, &outp, &outb);
  421. outlen += tob - outb;
  422. if (count == (size_t) (-1)) {
  423. if (errno == E2BIG) {
  424. new_txt = realloc(new_txt, outalloc + 64);
  425. outp = new_txt + outlen;
  426. outalloc += 64;
  427. outb += 64;
  428. } else if (errno == EILSEQ) {
  429. if (new_txt)
  430. free(new_txt);
  431. new_txt = NULL;
  432. break;
  433. } else if (errno == EINVAL) {
  434. if (new_txt)
  435. free(new_txt);
  436. new_txt = NULL;
  437. break;
  438. } else {
  439. if (new_txt)
  440. free(new_txt);
  441. new_txt = NULL;
  442. break;
  443. }
  444. }
  445. if (inb == 0) {
  446. if (outalloc == outlen)
  447. new_txt = realloc(new_txt, outalloc + 1);
  448. new_txt[outlen] = 0;
  449. break;
  450. }
  451. }
  452. iconv_close(ic);
  453. return new_txt;
  454. }
  455. #else
  456. EAPI char *eina_str_convert(const char *enc_from __UNUSED__,
  457. const char *enc_to __UNUSED__,
  458. const char *text __UNUSED__)
  459. {
  460. return NULL;
  461. }
  462. #endif
  463. /**
  464. * @brief Put a \ before and Space( ), \ or ' in a string.
  465. *
  466. * @param str the string to escape
  467. *
  468. * A newly allocated string is returned.
  469. */
  470. EAPI char *eina_str_escape(const char *str)
  471. {
  472. char *s2, *d;
  473. const char *s;
  474. s2 = malloc((strlen(str) * 2) + 1);
  475. if (!s2)
  476. return NULL;
  477. for (s = str, d = s2; *s != 0; s++, d++) {
  478. if ((*s == ' ') || (*s == '\\') || (*s == '\'')) {
  479. *d = '\\';
  480. d++;
  481. }
  482. *d = *s;
  483. }
  484. *d = 0;
  485. return s2;
  486. }
  487. /**
  488. * @brief Lowercase all the characters in range [A-Z] in the given string.
  489. *
  490. * @param str the string to lowercase
  491. *
  492. * This modifies the original string, changing all characters in [A-Z] to lowercase.
  493. */
  494. EAPI void eina_str_tolower(char **str)
  495. {
  496. char *p;
  497. if ((!str) || (!(*str)))
  498. return;
  499. for (p = *str; (*p); p++)
  500. *p = tolower((unsigned char) (*p));
  501. }
  502. /**
  503. * @brief Uppercase all the characters in range [a-z] in the given string.
  504. *
  505. * @param str the string to uppercase
  506. *
  507. * This modifies the original string, changing all characters in [a-z] to uppercase.
  508. */
  509. EAPI void eina_str_toupper(char **str)
  510. {
  511. char *p;
  512. if ((!str) || (!(*str)))
  513. return;
  514. for (p = *str; (*p); p++)
  515. *p = toupper((unsigned char) (*p));
  516. }
  517. /**
  518. * @}
  519. */