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