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