uncrustify eina.
[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         while (*s++)
235            ;
236      }
237
238    return(s - src - 1); /* count does not include NUL */
239 #endif
240 }
241
242 /**
243  * @brief Append a c-string.
244  *
245  * @param dst The destination string.
246  * @param src The source string.
247  * @param siz The size of the destination string.
248  * @return The length of the source string plus MIN(siz, strlen(initial dst))
249  *
250  * This function appends @p src to @p dst of size @p siz (unlike
251  * strncat, @p siz is the full size of @p dst, not space left).  At
252  * most @p siz - 1 characters will be copied.  Always NUL terminates
253  * (unless @p siz <= strlen(dst)). This function returns strlen(src) +
254  * MIN(siz, strlen(initial dst)). If the returned value is greater or
255  * equal than @p siz, truncation occurred.
256  */
257 EAPI size_t
258 eina_strlcat(char *dst, const char *src, size_t siz)
259 {
260    char *d = dst;
261    const char *s = src;
262    size_t n = siz;
263    size_t dlen;
264
265    /* Find the end of dst and adjust bytes left but don't go past end */
266    while (n-- != 0 && *d != '\0')
267       d++;
268    dlen = d - dst;
269    n = siz - dlen;
270
271    if (n == 0)
272       return(dlen + strlen(s));
273
274    while (*s != '\0') {
275         if (n != 1)
276           {
277              *d++ = *s;
278              n--;
279           }
280
281         s++;
282      }
283    *d = '\0';
284
285    return(dlen + (s - src)); /* count does not include NUL */
286 }
287
288 /**
289  * @brief Check if the given string has the given prefix.
290  *
291  * @param str The string to work with.
292  * @param prefix The prefix to check for.
293  * @return #EINA_TRUE if the string has the given prefix, #EINA_FALSE otherwise.
294  *
295  * This function returns #EINA_TRUE if @p str has the prefix
296  * @p prefix, #EINA_FALSE otherwise. If the length of @p prefix is
297  * greater than @p str, #EINA_FALSE is returned.
298  */
299 EAPI Eina_Bool
300 eina_str_has_prefix(const char *str, const char *prefix)
301 {
302    size_t str_len;
303    size_t prefix_len;
304
305    str_len = strlen(str);
306    prefix_len = eina_strlen_bounded(prefix, str_len);
307    if (prefix_len == (size_t)-1)
308       return EINA_FALSE;
309
310    return (strncmp(str, prefix, prefix_len) == 0);
311 }
312
313 /**
314  * @brief Check if the given string has the given suffix.
315  *
316  * @param str The string to work with.
317  * @param suffix The suffix to check for.
318  * @return #EINA_TRUE if the string has the given suffix, #EINA_FALSE otherwise.
319  *
320  * This function returns #EINA_TRUE if @p str has the suffix
321  * @p suffix, #EINA_FALSE otherwise. If the length of @p suffix is
322  * greater than @p str, #EINA_FALSE is returned.
323  */
324 /**
325  * @param str the string to work with
326  * @param suffix the suffix to check for
327  * @return true if str has the given suffix
328  * @brief checks if the string has the given suffix
329  */
330 EAPI Eina_Bool
331 eina_str_has_suffix(const char *str, const char *suffix)
332 {
333    return eina_str_has_suffix_helper(str, suffix, strcmp);
334 }
335
336 /**
337  * @brief Check if the given string has the given suffix.
338  *
339  * @param str The string to work with.
340  * @param ext The  extension to check for.
341  * @return #EINA_TRUE if the string has the given extension, #EINA_FALSE otherwise.
342  *
343  * This function does the same like eina_str_has_suffix(), but with a
344  * case insensitive compare.
345  */
346 EAPI Eina_Bool
347 eina_str_has_extension(const char *str, const char *ext)
348 {
349    return eina_str_has_suffix_helper(str, ext, strcasecmp);
350 }
351
352 /**
353  * @brief Split a string using a delimiter and returns number of elements.
354  *
355  * @param str The string to split.
356  * @param delim The string which specifies the places at which to split the string.
357  * @param max_tokens The maximum number of strings to split string into.
358  * @param elements Where to return the number of elements in returned
359  *        array (not counting the terminating @c NULL). May be @c NULL.
360  * @return A newly-allocated NULL-terminated array of strings or NULL if it
361  * fails to allocate the array.
362  *
363  * This functin splits @p str into a maximum of @p max_tokens pieces,
364  * using the given delimiter @p delim. @p delim is not included in any
365  * of the resulting strings, unless @p max_tokens is reached. If
366  * @p max_tokens is less than @c 1, the string is splitted completely. If
367  * @p max_tokens is reached, the last string in the returned string
368  * array contains the remainder of string. The returned value is a
369  * newly allocated NULL-terminated array of strings or NULL if it fails to
370  * allocate the array. To free it, free the first element of the array and the
371  * array itself.
372  *
373  * @see eina_str_split()
374  */
375 EAPI char **
376 eina_str_split_full(const char *str,
377                     const char *delim,
378                     int max_tokens,
379                     unsigned int *elements)
380 {
381    return eina_str_split_full_helper(str, delim, max_tokens, elements);
382 }
383
384
385 /**
386  * @brief Split a string using a delimiter.
387  *
388  * @param str The string to split.
389  * @param delim The string which specifies the places at which to split the string.
390  * @param max_tokens The maximum number of strings to split string into.
391  * @return A newly-allocated NULL-terminated array of strings or NULL if it
392  * fails to allocate the array.
393  *
394  * This functin splits @p str into a maximum of @p max_tokens pieces,
395  * using the given delimiter @p delim. @p delim is not included in any
396  * of the resulting strings, unless @p max_tokens is reached. If
397  * @p max_tokens is less than @c 1, the string is splitted completely. If
398  * @p max_tokens is reached, the last string in the returned string
399  * array contains the remainder of string. The returned value is a
400  * newly allocated NULL-terminated array of strings or NULL if it fails to
401  * allocate the array. To free it, free the first element of the array and the
402  * array itself.
403  */
404 EAPI char **
405 eina_str_split(const char *str, const char *delim, int max_tokens)
406 {
407    return eina_str_split_full_helper(str, delim, max_tokens, NULL);
408 }
409
410 /**
411  * @brief Join two strings of known length.
412  *
413  * @param dst The buffer to store the result.
414  * @param size Size (in byte) of the buffer.
415  * @param sep The separator character to use.
416  * @param a First string to use, before @p sep.
417  * @param a_len length of @p a.
418  * @param b Second string to use, after @p sep.
419  * @param b_len length of @p b.
420  * @return The number of characters printed.
421  *
422  * This function joins the strings @p a and @p b (in that order) and
423  * separate them with @p sep. The result is stored in the buffer
424  * @p dst and at most @p size - 1 characters will be written and the
425  * string is NULL-terminated. @p a_len is the length of @p a (not
426  * including '\\0') and @p b_len is the length of @p b (not including
427  * '\\0'). This function returns the number of characters printed (not
428  * including the trailing '\\0' used to end output to strings). Just
429  * like snprintf(), it will not write more than @p size bytes, thus a
430  * returned value of @p size or more means that the output was
431  * truncated.
432  *
433  * @see eina_str_join()
434  * @see eina_str_join_static()
435  */
436 EAPI size_t
437 eina_str_join_len(char *dst,
438                   size_t size,
439                   char sep,
440                   const char *a,
441                   size_t a_len,
442                   const char *b,
443                   size_t b_len)
444 {
445    size_t ret = a_len + b_len + 1;
446    size_t off;
447
448    if (size < 1)
449       return ret;
450
451    if (size <= a_len)
452      {
453         memcpy(dst, a, size - 1);
454         dst[size - 1] = '\0';
455         return ret;
456      }
457
458         memcpy(dst, a, a_len);
459    off = a_len;
460
461    if (size <= off + 1)
462      {
463         dst[size - 1] = '\0';
464         return ret;
465      }
466
467    dst[off] = sep;
468    off++;
469
470    if (size <= off + b_len + 1)
471      {
472         memcpy(dst + off, b, size - off - 1);
473         dst[size - 1] = '\0';
474         return ret;
475      }
476
477         memcpy(dst + off, b, b_len);
478    dst[off + b_len] = '\0';
479    return ret;
480 }
481
482 /**
483  * @brief Use iconv to convert a text string from one encoding to another
484  *
485  * @param enc_from encoding to convert from
486  * @param enc_to   encoding to convert to
487  * @param text     text to convert
488  *
489  */
490 #ifdef HAVE_ICONV
491 EAPI char *
492 eina_str_convert(const char *enc_from, const char *enc_to, const char *text)
493 {
494    iconv_t ic;
495    char *new_txt, *inp, *outp;
496    size_t inb, outb, outlen, tob, outalloc;
497
498    if (!text)
499       return NULL;
500
501    ic = iconv_open(enc_to, enc_from);
502    if (ic == (iconv_t)(-1))
503       return NULL;
504
505    new_txt = malloc(64);
506    inb = strlen(text);
507    outb = 64;
508    inp = (char *)text;
509    outp = new_txt;
510    outalloc = 64;
511    outlen = 0;
512
513    for (;; )
514      {
515         size_t count;
516
517         tob = outb;
518         count = iconv(ic, &inp, &inb, &outp, &outb);
519         outlen += tob - outb;
520         if (count == (size_t)(-1))
521           {
522              if (errno == E2BIG)
523                {
524                   new_txt = realloc(new_txt, outalloc + 64);
525                   outp = new_txt + outlen;
526                   outalloc += 64;
527                   outb += 64;
528                }
529              else if (errno == EILSEQ)
530                {
531                   if (new_txt)
532                      free(new_txt);
533
534                   new_txt = NULL;
535                   break;
536                }
537              else if (errno == EINVAL)
538                {
539                   if (new_txt)
540                      free(new_txt);
541
542                   new_txt = NULL;
543                   break;
544                }
545              else
546                {
547                   if (new_txt)
548                      free(new_txt);
549
550                   new_txt = NULL;
551                   break;
552                }
553           }
554
555         if (inb == 0)
556           {
557              if (outalloc == outlen)
558                 new_txt = realloc(new_txt, outalloc + 1);
559
560              new_txt[outlen] = 0;
561              break;
562           }
563      }
564    iconv_close(ic);
565    return new_txt;
566 }
567 #else
568 EAPI char *
569 eina_str_convert(const char *enc_from __UNUSED__,
570                  const char *enc_to __UNUSED__,
571                  const char *text __UNUSED__)
572 {
573    return NULL;
574 }
575 #endif
576
577 /**
578  * @brief Put a \ before and Space( ), \ or ' in a string.
579  *
580  * @param str the string to escape
581  *
582  * A newly allocated string is returned.
583  */
584 EAPI char *
585 eina_str_escape(const char *str)
586 {
587    char *s2, *d;
588    const char *s;
589
590    s2 = malloc((strlen(str) * 2) + 1);
591    if (!s2)
592       return NULL;
593
594    for (s = str, d = s2; *s != 0; s++, d++)
595      {
596         if ((*s == ' ') || (*s == '\\') || (*s == '\''))
597           {
598              *d = '\\';
599              d++;
600           }
601
602         *d = *s;
603      }
604    *d = 0;
605    return s2;
606 }
607
608 /**
609  * @brief Lowercase all the characters in range [A-Z] in the given string.
610  *
611  * @param str the string to lowercase
612  *
613  * This modifies the original string, changing all characters in [A-Z] to lowercase.
614  */
615 EAPI void
616 eina_str_tolower(char **str)
617 {
618    char *p;
619    if ((!str) || (!(*str)))
620       return;
621
622    for (p = *str; (*p); p++)
623       *p = tolower(*p);
624 }
625
626 /**
627  * @brief Uppercase all the characters in range [a-z] in the given string.
628  *
629  * @param str the string to uppercase
630  *
631  * This modifies the original string, changing all characters in [a-z] to uppercase.
632  */
633 EAPI void
634 eina_str_toupper(char **str)
635 {
636    char *p;
637    if ((!str) || (!(*str)))
638       return;
639
640    for (p = *str; (*p); p++)
641       *p = toupper(*p);
642 }
643
644
645 /**
646  * @}
647  */