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