Tizen 2.1 base
[framework/uifw/ecore.git] / src / lib / ecore / ecore_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 #include <sys/types.h>
21 #include <string.h>
22
23 #include "ecore_private.h"
24 #include "Ecore_Str.h"
25
26 static int ecore_str_has_suffix_helper(const char *str, const char *suffix, 
27                 int (*cmp)(const char *, const char *));
28 /**
29  * @param dst the destination
30  * @param src the source
31  * @param siz the size of the destination
32  * @return the length of the source string
33  * @brief copy a c-string
34  *
35  * Copy src to string dst of size siz.  At most siz-1 characters
36  * will be copied.  Always NUL terminates (unless siz == 0).
37  * Returns strlen(src); if retval >= siz, truncation occurred.
38  */
39 size_t
40 ecore_strlcpy(char *dst, const char *src, size_t siz)
41 {
42 #ifdef HAVE_STRLCPY
43    return strlcpy(dst, src, siz);
44 #else
45    char *d = dst;
46    const char *s = src;
47    size_t n = siz;
48
49    /* Copy as many bytes as will fit */
50    if (n != 0)
51      {
52         while (--n != 0)
53           {
54              if ((*d++ = *s++) == '\0')
55                break;
56           }
57      }
58
59    /* Not enough room in dst, add NUL and traverse rest of src */
60    if (n == 0)
61      {
62         if (siz != 0)
63           *d = '\0';                /* NUL-terminate dst */
64         while (*s++)
65           ;
66      }
67
68    return(s - src - 1);        /* count does not include NUL */
69 #endif
70 }
71
72 /**
73  * @param dst the destination
74  * @param src the source
75  * @param siz the size of the destination
76  * @return the length of the source string plus MIN(siz, strlen(initial dst)) 
77  * @brief append a c-string
78  *
79  * Appends src to string dst of size siz (unlike strncat, siz is the
80  * full size of dst, not space left).  At most siz-1 characters
81  * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
82  * Returns strlen(src) + MIN(siz, strlen(initial dst)).
83  * If retval >= siz, truncation occurred.
84  */
85 size_t
86 ecore_strlcat(char *dst, const char *src, size_t siz)
87 {
88         char *d = dst;
89         const char *s = src;
90         size_t n = siz;
91         size_t dlen;
92
93         /* Find the end of dst and adjust bytes left but don't go past end */
94         while (n-- != 0 && *d != '\0')
95                 d++;
96         dlen = d - dst;
97         n = siz - dlen;
98
99         if (n == 0)
100                 return(dlen + strlen(s));
101         while (*s != '\0') {
102                 if (n != 1) {
103                         *d++ = *s;
104                         n--;
105                 }
106                 s++;
107         }
108         *d = '\0';
109
110         return(dlen + (s - src));        /* count does not include NUL */
111 }
112
113 /**
114  * @param str the string to work with
115  * @param prefix the prefix to check for
116  * @return true if str has the given prefix
117  * @brief checks if the string has the given prefix
118  */
119 int
120 ecore_str_has_prefix(const char *str, const char *prefix)
121 {
122    size_t str_len;
123    size_t prefix_len;
124
125    CHECK_PARAM_POINTER_RETURN("str", str, 0);
126    CHECK_PARAM_POINTER_RETURN("prefix", prefix, 0);
127
128    str_len = strlen(str);
129    prefix_len = strlen(prefix);
130    if (prefix_len > str_len)
131      return 0;
132
133    return (strncmp(str, prefix, prefix_len) == 0);
134 }
135
136 /**
137  * @param str the string to work with
138  * @param suffix the suffix to check for
139  * @return true if str has the given suffix
140  * @brief checks if the string has the given suffix
141  */
142 int
143 ecore_str_has_suffix(const char *str, const char *suffix)
144 {
145    CHECK_PARAM_POINTER_RETURN("str", str, 0);
146    CHECK_PARAM_POINTER_RETURN("suffix", suffix, 0);
147    
148    return ecore_str_has_suffix_helper(str, suffix, strcmp);
149 }
150
151 /**
152  * This function does the same like ecore_str_has_suffix(), but with a
153  * case insensitive compare.
154  *
155  * @param str the string to work with
156  * @param ext the  extension to check for
157  * @return true if str has the given extension
158  * @brief checks if the string has the given extension
159  */
160 int
161 ecore_str_has_extension(const char *str, const char *ext)
162 {
163    CHECK_PARAM_POINTER_RETURN("str", str, 0);
164    CHECK_PARAM_POINTER_RETURN("ext", ext, 0);
165    
166    return ecore_str_has_suffix_helper(str, ext, strcasecmp);
167 }
168
169 /*
170  * Internal helper function used by ecore_str_has_suffix() and 
171  * ecore_str_has_extension()
172  */
173 static int
174 ecore_str_has_suffix_helper(const char *str, const char *suffix, 
175                 int (*cmp)(const char *, const char *))
176 {
177    size_t str_len;
178    size_t suffix_len;
179
180    str_len = strlen(str);
181    suffix_len = strlen(suffix);
182    if (suffix_len > str_len)
183      return 0;
184
185    return cmp(str + str_len - suffix_len, suffix) == 0;
186 }
187
188 /**
189  * Splits a string into a maximum of max_tokens pieces, using the given
190  * delimiter. If max_tokens is reached, the final string in the returned
191  * string array contains the remainder of string.
192  *
193  * @param str         A string to split.
194  * @param delim       A string which specifies the places at which to split the 
195  *                    string. The delimiter is not included in any of the 
196  *                    resulting strings, unless max_tokens is reached.
197  * @param max_tokens  The maximum number of strings to split string into. 
198  *                    If this is less than 1, the string is split completely.
199  * @return            A newly-allocated NULL-terminated array of strings.
200  *                    To free it: free the first element of the array
201  *                    and the array itself.
202  */
203 char **
204 ecore_str_split(const char *str, const char *delim, int max_tokens)
205 {
206    char *s, *sep, **str_array;
207    size_t len, dlen;
208    int i;
209
210    CHECK_PARAM_POINTER_RETURN("str", str, NULL);
211    CHECK_PARAM_POINTER_RETURN("delim", delim, NULL);
212
213    if (*delim == '\0')
214       return NULL;
215
216    max_tokens = ((max_tokens <= 0) ? (INT_MAX) : (max_tokens - 1));
217    len = strlen(str);
218    dlen = strlen(delim);
219    s = strdup(str);
220    str_array = malloc(sizeof(char *) * (len + 1));
221    for (i = 0; (i < max_tokens) && (sep = strstr(s, delim)); i++) 
222       {
223           str_array[i] = s;
224           s = sep + dlen;
225           *sep = 0;
226       }
227
228    str_array[i++] = s;
229    str_array = realloc(str_array, sizeof(char *) * (i + 1));
230    str_array[i] = NULL;
231  
232    return str_array;
233 }
234