remove tolower() from eina_str_tolower
[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, const char *delim, int max_tokens, unsigned int *elements)
75 {
76    char *s, **str_array;
77    const char *src;
78    size_t len, dlen;
79    unsigned int tokens;
80
81    dlen = strlen(delim);
82    if (dlen == 0)
83      {
84         if (elements) *elements = 0;
85         return NULL;
86      }
87
88    tokens = 0;
89    src = str;
90    /* count tokens and check strlen(str) */
91    while (*src != '\0')
92      {
93         const char *d = delim, *d_end = d + dlen;
94         const char *tmp = src;
95         for (; (d < d_end) && (*tmp != '\0'); d++, tmp++)
96           {
97              if (EINA_LIKELY(*d != *tmp))
98                break;
99           }
100         if (EINA_UNLIKELY(d == d_end))
101           {
102              src = tmp;
103              tokens++;
104           }
105         else
106           src++;
107      }
108    len = src - str;
109
110    if ((max_tokens > 0) && (tokens > (unsigned int)max_tokens))
111      tokens = max_tokens;
112
113    str_array = malloc(sizeof(char *) * (tokens + 2));
114    if (!str_array)
115      {
116         if (elements) *elements = 0;
117         return NULL;
118      }
119
120    s = malloc(len + 1);
121    if (!s)
122      {
123         free(str_array);
124         if (elements) *elements = 0;
125         return NULL;
126      }
127
128    /* copy tokens and string */
129    tokens = 0;
130    str_array[0] = s;
131    src = str;
132    while (*src != '\0')
133      {
134         const char *d = delim, *d_end = d + dlen;
135         const char *tmp = src;
136         for (; (d < d_end) && (*tmp != '\0'); d++, tmp++)
137           {
138              if (EINA_LIKELY(*d != *tmp))
139                break;
140           }
141         if (EINA_UNLIKELY(d == d_end))
142           {
143              src = tmp;
144              *s = '\0';
145              s += dlen;
146              tokens++;
147              str_array[tokens] = s;
148           }
149         else
150           {
151              *s = *src;
152              s++;
153              src++;
154           }
155      }
156    *s = '\0';
157    str_array[tokens + 1] = NULL;
158    if (elements) *elements = (tokens + 1);
159    return str_array;
160 }
161
162 /**
163  * @endcond
164  */
165
166 /*============================================================================*
167  *                                 Global                                     *
168  *============================================================================*/
169
170 /*============================================================================*
171  *                                   API                                      *
172  *============================================================================*/
173
174 /**
175  * @addtogroup Eina_String_Group String
176  *
177  * @brief These functions provide useful C string management.
178  *
179  * @{
180  */
181
182
183 /**
184  * @brief Copy a c-string to another.
185  *
186  * @param dst The destination string.
187  * @param src The source string.
188  * @param siz The size of the destination string.
189  * @return The length of the source string.
190  *
191  * This function copies up to @p siz - 1 characters from the
192  * NUL-terminated string @p src to @p dst, NUL-terminating the result
193  * (unless @p siz is equal to 0). The returned value is the length of
194  * @p src. If the returned value is greater than @p siz, truncation
195  * occured.
196  */
197 EAPI size_t
198 eina_strlcpy(char *dst, const char *src, size_t siz)
199 {
200 #ifdef HAVE_STRLCPY
201    return strlcpy(dst, src, siz);
202 #else
203    char *d = dst;
204    const char *s = src;
205    size_t n = siz;
206
207    /* Copy as many bytes as will fit */
208    if (n != 0)
209      {
210         while (--n != 0)
211           {
212              if ((*d++ = *s++) == '\0')
213                break;
214           }
215      }
216
217    /* Not enough room in dst, add NUL and traverse rest of src */
218    if (n == 0)
219      {
220         if (siz != 0)
221           *d = '\0';                /* NUL-terminate dst */
222         while (*s++)
223           ;
224      }
225
226    return(s - src - 1);        /* count does not include NUL */
227 #endif
228 }
229
230 /**
231  * @brief Append a c-string.
232  *
233  * @param dst The destination string.
234  * @param src The source string.
235  * @param siz The size of the destination string.
236  * @return The length of the source string plus MIN(siz, strlen(initial dst))
237  *
238  * This function appends @p src to @p dst of size @p siz (unlike
239  * strncat, @p siz is the full size of @p dst, not space left).  At
240  * most @p siz - 1 characters will be copied.  Always NUL terminates
241  * (unless @p siz <= strlen(dst)). This function returns strlen(src) +
242  * MIN(siz, strlen(initial dst)). If the returned value is greater or
243  * equal than @p siz, truncation occurred.
244  */
245 EAPI size_t
246 eina_strlcat(char *dst, const char *src, size_t siz)
247 {
248    char *d = dst;
249    const char *s = src;
250    size_t n = siz;
251    size_t dlen;
252
253    /* Find the end of dst and adjust bytes left but don't go past end */
254    while (n-- != 0 && *d != '\0')
255      d++;
256    dlen = d - dst;
257    n = siz - dlen;
258
259    if (n == 0)
260      return(dlen + strlen(s));
261    while (*s != '\0') {
262         if (n != 1) {
263              *d++ = *s;
264              n--;
265         }
266         s++;
267    }
268    *d = '\0';
269
270    return(dlen + (s - src));        /* count does not include NUL */
271 }
272
273 /**
274  * @brief Check if the given string has the given prefix.
275  *
276  * @param str The string to work with.
277  * @param prefix The prefix to check for.
278  * @return #EINA_TRUE if the string has the given prefix, #EINA_FALSE otherwise.
279  *
280  * This function returns #EINA_TRUE if @p str has the prefix
281  * @p prefix, #EINA_FALSE otherwise. If the length of @p prefix is
282  * greater than @p str, #EINA_FALSE is returned.
283  */
284 EAPI Eina_Bool
285 eina_str_has_prefix(const char *str, const char *prefix)
286 {
287    size_t str_len;
288    size_t prefix_len;
289
290    str_len = strlen(str);
291    prefix_len = eina_strlen_bounded(prefix, str_len);
292    if (prefix_len == (size_t)-1)
293      return EINA_FALSE;
294
295    return (strncmp(str, prefix, prefix_len) == 0);
296 }
297
298 /**
299  * @brief Check if the given string has the given suffix.
300  *
301  * @param str The string to work with.
302  * @param suffix The suffix to check for.
303  * @return #EINA_TRUE if the string has the given suffix, #EINA_FALSE otherwise.
304  *
305  * This function returns #EINA_TRUE if @p str has the suffix
306  * @p suffix, #EINA_FALSE otherwise. If the length of @p suffix is
307  * greater than @p str, #EINA_FALSE is returned.
308  */
309 /**
310  * @param str the string to work with
311  * @param suffix the suffix to check for
312  * @return true if str has the given suffix
313  * @brief checks if the string has the given suffix
314  */
315 EAPI Eina_Bool
316 eina_str_has_suffix(const char *str, const char *suffix)
317 {
318    return eina_str_has_suffix_helper(str, suffix, strcmp);
319 }
320
321 /**
322  * @brief Check if the given string has the given suffix.
323  *
324  * @param str The string to work with.
325  * @param ext The  extension to check for.
326  * @return #EINA_TRUE if the string has the given extension, #EINA_FALSE otherwise.
327  *
328  * This function does the same like eina_str_has_suffix(), but with a
329  * case insensitive compare.
330  */
331 EAPI Eina_Bool
332 eina_str_has_extension(const char *str, const char *ext)
333 {
334    return eina_str_has_suffix_helper(str, ext, strcasecmp);
335 }
336
337 /**
338  * @brief Split a string using a delimiter and returns number of elements.
339  *
340  * @param str The string to split.
341  * @param delim The string which specifies the places at which to split the string.
342  * @param max_tokens The maximum number of strings to split string into.
343  * @param elements Where to return the number of elements in returned
344  *        array (not counting the terminating @c NULL). May be @c NULL.
345  * @return A newly-allocated NULL-terminated array of strings or NULL if it
346  * fails to allocate the array.
347  *
348  * This functin splits @p str into a maximum of @p max_tokens pieces,
349  * using the given delimiter @p delim. @p delim is not included in any
350  * of the resulting strings, unless @p max_tokens is reached. If
351  * @p max_tokens is less than @c 1, the string is splitted completely. If
352  * @p max_tokens is reached, the last string in the returned string
353  * array contains the remainder of string. The returned value is a
354  * newly allocated NULL-terminated array of strings or NULL if it fails to
355  * allocate the array. To free it, free the first element of the array and the
356  * array itself.
357  *
358  * @see eina_str_split()
359  */
360 EAPI char **
361 eina_str_split_full(const char *str, const char *delim, int max_tokens, unsigned int *elements)
362 {
363    return eina_str_split_full_helper(str, delim, max_tokens, elements);
364 }
365
366
367 /**
368  * @brief Split a string using a delimiter.
369  *
370  * @param str The string to split.
371  * @param delim The string which specifies the places at which to split the string.
372  * @param max_tokens The maximum number of strings to split string into.
373  * @return A newly-allocated NULL-terminated array of strings or NULL if it
374  * fails to allocate the array.
375  *
376  * This functin splits @p str into a maximum of @p max_tokens pieces,
377  * using the given delimiter @p delim. @p delim is not included in any
378  * of the resulting strings, unless @p max_tokens is reached. If
379  * @p max_tokens is less than @c 1, the string is splitted completely. If
380  * @p max_tokens is reached, the last string in the returned string
381  * array contains the remainder of string. The returned value is a
382  * newly allocated NULL-terminated array of strings or NULL if it fails to
383  * allocate the array. To free it, free the first element of the array and the
384  * array itself.
385  */
386 EAPI char **
387 eina_str_split(const char *str, const char *delim, int max_tokens)
388 {
389    return eina_str_split_full_helper(str, delim, max_tokens, NULL);
390 }
391
392 /**
393  * @brief Join two strings of known length.
394  *
395  * @param dst The buffer to store the result.
396  * @param size Size (in byte) of the buffer.
397  * @param sep The separator character to use.
398  * @param a First string to use, before @p sep.
399  * @param a_len length of @p a.
400  * @param b Second string to use, after @p sep.
401  * @param b_len length of @p b.
402  * @return The number of characters printed.
403  *
404  * This function joins the strings @p a and @p b (in that order) and
405  * separate them with @p sep. The result is stored in the buffer
406  * @p dst and at most @p size - 1 characters will be written and the
407  * string is NULL-terminated. @p a_len is the length of @p a (not
408  * including '\\0') and @p b_len is the length of @p b (not including
409  * '\\0'). This function returns the number of characters printed (not
410  * including the trailing '\\0' used to end output to strings). Just
411  * like snprintf(), it will not write more than @p size bytes, thus a
412  * returned value of @p size or more means that the output was
413  * truncated.
414  *
415  * @see eina_str_join()
416  * @see eina_str_join_static()
417  */
418 EAPI size_t
419 eina_str_join_len(char *dst, size_t size, char sep, const char *a, size_t a_len, const char *b, size_t b_len)
420 {
421    size_t ret = a_len + b_len + 1;
422    size_t off;
423
424    if (size < 1) return ret;
425
426    if (size <= a_len)
427      {
428         memcpy(dst, a, size - 1);
429         dst[size - 1] = '\0';
430         return ret;
431      }
432
433    memcpy(dst, a, a_len);
434    off = a_len;
435
436    if (size <= off + 1)
437      {
438         dst[size - 1] = '\0';
439         return ret;
440      }
441
442    dst[off] = sep;
443    off++;
444
445    if (size <= off + b_len + 1)
446      {
447         memcpy(dst + off, b, size - off - 1);
448         dst[size - 1] = '\0';
449         return ret;
450      }
451
452    memcpy(dst + off, b, b_len);
453    dst[off + b_len] = '\0';
454    return ret;
455 }
456
457 /**
458  * @brief Use iconv to convert a text string from one encoding to another
459  *
460  * @param enc_from encoding to convert from
461  * @param enc_to   encoding to convert to
462  * @param text     text to convert
463  *
464  */
465 #ifdef HAVE_ICONV
466 EAPI char *
467 eina_str_convert(const char *enc_from, const char *enc_to, const char *text)
468 {
469    iconv_t ic;
470    char *new_txt, *inp, *outp;
471    size_t inb, outb, outlen, tob, outalloc;
472
473    if (!text) return NULL;
474    ic = iconv_open(enc_to, enc_from);
475    if (ic == (iconv_t)(-1)) return NULL;
476    new_txt  = malloc(64);
477    inb      = strlen(text);
478    outb     = 64;
479    inp      = (char*)text;
480    outp     = new_txt;
481    outalloc = 64;
482    outlen   = 0;
483
484    for (;;)
485      {
486         size_t count;
487
488         tob = outb;
489         count = iconv(ic, &inp, &inb, &outp, &outb);
490         outlen += tob - outb;
491         if (count == (size_t)(-1))
492           {
493              if (errno == E2BIG)
494                {
495                   new_txt = realloc(new_txt, outalloc + 64);
496                   outp = new_txt + outlen;
497                   outalloc += 64;
498                   outb += 64;
499                }
500              else if (errno == EILSEQ)
501                {
502                   if (new_txt) free(new_txt);
503                   new_txt = NULL;
504                   break;
505                }
506              else if (errno == EINVAL)
507                {
508                   if (new_txt) free(new_txt);
509                   new_txt = NULL;
510                   break;
511                }
512              else
513                {
514                   if (new_txt) free(new_txt);
515                   new_txt = NULL;
516                   break;
517                }
518           }
519         if (inb == 0)
520           {
521              if (outalloc == outlen) new_txt = realloc(new_txt, outalloc + 1);
522              new_txt[outlen] = 0;
523              break;
524           }
525      }
526    iconv_close(ic);
527    return new_txt;
528 }
529 #else
530 EAPI char *
531 eina_str_convert(const char *enc_from __UNUSED__, const char *enc_to __UNUSED__, const char *text __UNUSED__)
532 {
533    return NULL;
534 }
535 #endif
536
537 /**
538  * @brief Put a \ before and Space( ), \ or ' in a string.
539  *
540  * @param str the string to escape
541  *
542  * A newly allocated string is returned.
543  */
544 EAPI char *
545 eina_str_escape(const char *str)
546 {
547    char *s2, *d;
548    const char *s;
549
550    s2 = malloc((strlen(str) * 2) + 1);
551    if (!s2) return NULL;
552    for (s = str, d = s2; *s != 0; s++, d++)
553      {
554         if ((*s == ' ') || (*s == '\\') || (*s == '\''))
555           {
556              *d = '\\';
557              d++;
558           }
559         *d = *s;
560      }
561    *d = 0;
562    return s2;
563 }
564
565 /**
566  * @brief Lowercase all the characters in range [A-Z] in the given string.
567  *
568  * @param str the string to lowercase
569  *
570  * This modifies the original string, changing all characters in [A-Z] to lowercase.
571  */
572 EAPI void
573 eina_str_tolower(char **str)
574 {
575    char *p;
576    if ((!str) || (!(*str))) return;
577
578    for (p = *str; (*p); p++)
579      if ((*p >= 'A') && (*p <= 'Z'))
580        *p += 32;
581 }
582
583
584 /**
585  * @}
586  */