2006-08-21 Aaron Bockover <abockover@novell.com>
[mono.git] / eglib / src / gstr.c
1 /*
2  * gstr.c: String Utility Functions.
3  *
4  * Author:
5  *   Miguel de Icaza (miguel@novell.com)
6  *   Aaron Bockover (abockover@novell.com)
7  *
8  * (C) 2006 Novell, Inc.
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining
11  * a copy of this software and associated documentation files (the
12  * "Software"), to deal in the Software without restriction, including
13  * without limitation the rights to use, copy, modify, merge, publish,
14  * distribute, sublicense, and/or sell copies of the Software, and to
15  * permit persons to whom the Software is furnished to do so, subject to
16  * the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be
19  * included in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28  */
29 #define _GNU_SOURCE
30 #include <stdio.h>
31 #include <string.h>
32 #include <ctype.h>
33 #include <glib.h>
34
35 /* This is not a macro, because I dont want to put _GNU_SOURCE in the glib.h header */
36 gchar *
37 g_strndup (const gchar *str, gsize n)
38 {
39         return strndup (str, n);
40 }
41
42 void
43 g_strfreev (gchar **str_array)
44 {
45         gchar **orig = str_array;
46         if (str_array == NULL)
47                 return;
48         while (*str_array != NULL){
49                 g_free (*str_array);
50                 str_array++;
51         }
52         g_free (orig);
53 }
54
55 gint
56 g_strv_length(gchar **str_array)
57 {
58         gint length = 0;
59         g_return_val_if_fail(str_array != NULL, 0);
60         for(length = 0; str_array[length] != NULL; length++);
61         return length;
62 }
63
64 gboolean
65 g_str_has_suffix(const gchar *str, const gchar *suffix)
66 {
67         gint str_length;
68         gint suffix_length;
69         
70         g_return_val_if_fail(str != NULL, FALSE);
71         g_return_val_if_fail(suffix != NULL, FALSE);
72
73         str_length = strlen(str);
74         suffix_length = strlen(suffix);
75
76         return suffix_length <= str_length ?
77                 strncmp(str + str_length - suffix_length, suffix, suffix_length) == 0 :
78                 FALSE;
79 }
80
81 gboolean
82 g_str_has_prefix(const gchar *str, const gchar *prefix)
83 {
84         gint str_length;
85         gint prefix_length;
86         
87         g_return_val_if_fail(str != NULL, FALSE);
88         g_return_val_if_fail(prefix != NULL, FALSE);
89
90         str_length = strlen(str);
91         prefix_length = strlen(prefix);
92
93         return prefix_length <= str_length ?
94                 strncmp(str, prefix, prefix_length) == 0 :
95                 FALSE;
96 }
97
98 gchar *
99 g_strdup_vprintf (const gchar *format, va_list args)
100 {
101         int n;
102         char *ret;
103         
104         n = vasprintf (&ret, format, args);
105         if (n == -1)
106                 return NULL;
107
108         return ret;
109 }
110
111 gchar *
112 g_strdup_printf (const gchar *format, ...)
113 {
114         gchar *ret;
115         va_list args;
116         int n;
117
118         va_start (args, format);
119         n = vasprintf (&ret, format, args);
120         va_end (args);
121         if (n == -1)
122                 return NULL;
123
124         return ret;
125 }
126
127 const gchar *
128 g_strerror (gint errnum)
129 {
130         return strerror (errnum);
131 }
132
133 gchar *
134 g_strconcat (const gchar *first, ...)
135 {
136         g_return_val_if_fail (first != NULL, NULL);
137         va_list args;
138         int total = 0;
139         char *s, *ret;
140
141         total += strlen (first);
142         va_start (args, first);
143         for (s = va_arg (args, char *); s != NULL; s = va_arg(args, char *)){
144                 total += strlen (s);
145         }
146         va_end (args);
147         
148         ret = g_malloc (total + 1);
149         if (ret == NULL)
150                 return NULL;
151
152         ret [total] = 0;
153         strcpy (ret, first);
154         va_start (args, first);
155         for (s = va_arg (args, char *); s != NULL; s = va_arg(args, char *)){
156                 strcat (ret, s);
157         }
158         va_end (args);
159
160         return ret;
161 }
162
163 gchar ** 
164 g_strsplit (const gchar *string, const gchar *delimiter, gint max_tokens)
165 {
166         gchar *string_c;
167         gchar *strtok_save, **vector;
168         gchar *token, *token_c;
169         gint size = 1;
170         gint token_length;
171
172         g_return_val_if_fail(string != NULL, NULL);
173         g_return_val_if_fail(delimiter != NULL, NULL);
174         g_return_val_if_fail(delimiter[0] != 0, NULL);
175         
176         token_length = strlen(string);
177         string_c = (gchar *)g_malloc(token_length + 1);
178         memcpy(string_c, string, token_length);
179         string_c[token_length] = 0;
180         
181         vector = NULL;
182         token = (gchar *)strtok_r(string_c, delimiter, &strtok_save);
183
184         while(token != NULL) {
185                 token_length = strlen(token);
186                 token_c = (gchar *)g_malloc(token_length + 1);
187                 memcpy(token_c, token, token_length);
188                 token_c[token_length] = 0;
189
190                 vector = vector == NULL ? 
191                         (gchar **)g_malloc(2 * sizeof(vector)) :
192                         (gchar **)g_realloc(vector, (size + 1) * sizeof(vector));
193         
194                 vector[size - 1] = token_c;     
195                 size++;
196
197                 if(max_tokens > 0 && size >= max_tokens) {
198                         if(size > max_tokens) {
199                                 break;
200                         }
201
202                         token = strtok_save;
203                 } else {
204                         token = (gchar *)strtok_r(NULL, delimiter, &strtok_save);
205                 }
206         }
207
208         if(vector != NULL && size > 0) {
209                 vector[size - 1] = NULL;
210         }
211         
212         g_free(string_c);
213         string_c = NULL;
214
215         return vector;
216 }
217
218 gchar *
219 g_strreverse (gchar *str)
220 {
221         guint len, half;
222         gint i;
223         gchar c;
224
225         if (str == NULL)
226                 return NULL;
227
228         len = strlen (str);
229         half = len / 2;
230         len--;
231         for (i = 0; i < half; i++, len--) {
232                 c = str [i];
233                 str [i] = str [len];
234                 str [len] = c;
235         }
236         return str;
237 }
238
239 gchar *
240 g_strjoin (const gchar *separator, ...)
241 {
242         va_list args;
243         char *res, *s;
244         int len, slen;
245
246         if (separator != NULL)
247                 slen = strlen (separator);
248         else
249                 slen = 0;
250         len = 0;
251         va_start (args, separator);
252         for (s = va_arg (args, char *); s != NULL; s = va_arg (args, char *)){
253                 len += strlen (s);
254                 len += slen;
255         }
256         va_end (args);
257         if (len == 0)
258                 return g_strdup ("");
259         
260         /* Remove the last separator */
261         if (slen > 0 && len > 0)
262                 len -= slen;
263         len++;
264         res = g_malloc (len);
265         va_start (args, separator);
266         s = va_arg (args, char *);
267         strcpy (res, s);
268         for (s = va_arg (args, char *); s != NULL; s = va_arg (args, char *)){
269                 if (separator != NULL)
270                         strcat (res, separator);
271                 strcat (res, s);
272         }
273         va_end (args);
274
275         return res;
276 }
277
278 gchar *
279 g_strchug (gchar *str)
280 {
281         gint len;
282         gchar *tmp;
283
284         if (str == NULL)
285                 return NULL;
286
287         tmp = str;
288         while (*tmp && isspace (*tmp)) tmp++;
289         if (str != tmp) {
290                 len = strlen (str) - (tmp - str - 1);
291                 memmove (str, tmp, len);
292         }
293         return str;
294 }
295
296 gchar *
297 g_strchomp (gchar *str)
298 {
299         gchar *tmp;
300
301         if (str == NULL)
302                 return NULL;
303
304         tmp = str + strlen (str) - 1;
305         while (*tmp && isspace (*tmp)) tmp--;
306         *(tmp + 1) = '\0';
307         return str;
308 }
309
310 gint
311 g_printf(gchar const *format, ...)
312 {
313         va_list args;
314         gint ret;
315
316         va_start(args, format);
317         ret = vprintf(format, args);
318         va_end(args);
319
320         return ret;
321 }
322
323 gint
324 g_fprintf(FILE *file, gchar const *format, ...)
325 {
326         va_list args;
327         gint ret;
328
329         va_start(args, format);
330         ret = vfprintf(file, format, args);
331         va_end(args);
332
333         return ret;
334 }
335
336 gint
337 g_sprintf(gchar *string, gchar const *format, ...)
338 {
339         va_list args;
340         gint ret;
341
342         va_start(args, format);
343         ret = vsprintf(string, format, args);
344         va_end(args);
345
346         return ret;
347 }
348
349 gint
350 g_snprintf(gchar *string, gulong n, gchar const *format, ...)
351 {
352         va_list args;
353         gint ret;
354         
355         va_start(args, format);
356         ret = vsnprintf(string, n, format, args);
357         va_end(args);
358
359         return ret;
360 }
361
362