2006-10-08 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono/afaerber.git] / eglib / src / gstr.c
blob04666da134b89fdedd7fda1a001ee01292631ac5
1 /*
2 * gstr.c: String Utility Functions.
4 * Author:
5 * Miguel de Icaza (miguel@novell.com)
6 * Aaron Bockover (abockover@novell.com)
8 * (C) 2006 Novell, Inc.
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:
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
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.
29 #define _GNU_SOURCE
30 #include <stdio.h>
31 #include <string.h>
32 #include <ctype.h>
33 #include <glib.h>
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)
39 return strndup (str, n);
42 void
43 g_strfreev (gchar **str_array)
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++;
52 g_free (orig);
55 guint
56 g_strv_length(gchar **str_array)
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;
64 gboolean
65 g_str_has_suffix(const gchar *str, const gchar *suffix)
67 gint str_length;
68 gint suffix_length;
70 g_return_val_if_fail(str != NULL, FALSE);
71 g_return_val_if_fail(suffix != NULL, FALSE);
73 str_length = strlen(str);
74 suffix_length = strlen(suffix);
76 return suffix_length <= str_length ?
77 strncmp(str + str_length - suffix_length, suffix, suffix_length) == 0 :
78 FALSE;
81 gboolean
82 g_str_has_prefix(const gchar *str, const gchar *prefix)
84 gint str_length;
85 gint prefix_length;
87 g_return_val_if_fail(str != NULL, FALSE);
88 g_return_val_if_fail(prefix != NULL, FALSE);
90 str_length = strlen(str);
91 prefix_length = strlen(prefix);
93 return prefix_length <= str_length ?
94 strncmp(str, prefix, prefix_length) == 0 :
95 FALSE;
98 gchar *
99 g_strdup_vprintf (const gchar *format, va_list args)
101 int n;
102 char *ret;
104 n = vasprintf (&ret, format, args);
105 if (n == -1)
106 return NULL;
108 return ret;
111 gchar *
112 g_strdup_printf (const gchar *format, ...)
114 gchar *ret;
115 va_list args;
116 int n;
118 va_start (args, format);
119 n = vasprintf (&ret, format, args);
120 va_end (args);
121 if (n == -1)
122 return NULL;
124 return ret;
127 const gchar *
128 g_strerror (gint errnum)
130 return strerror (errnum);
133 gchar *
134 g_strconcat (const gchar *first, ...)
136 g_return_val_if_fail (first != NULL, NULL);
137 va_list args;
138 int total = 0;
139 char *s, *ret;
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);
146 va_end (args);
148 ret = g_malloc (total + 1);
149 if (ret == NULL)
150 return NULL;
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);
158 va_end (args);
160 return ret;
163 gchar **
164 g_strsplit (const gchar *string, const gchar *delimiter, gint max_tokens)
166 gchar *string_c;
167 gchar *strtok_save, **vector;
168 gchar *token, *token_c;
169 gint size = 1;
170 gint token_length;
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);
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;
181 vector = NULL;
182 token = (gchar *)strtok_r(string_c, delimiter, &strtok_save);
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;
190 vector = vector == NULL ?
191 (gchar **)g_malloc(2 * sizeof(vector)) :
192 (gchar **)g_realloc(vector, (size + 1) * sizeof(vector));
194 vector[size - 1] = token_c;
195 size++;
197 if(max_tokens > 0 && size >= max_tokens) {
198 if(size > max_tokens) {
199 break;
202 token = strtok_save;
203 } else {
204 token = (gchar *)strtok_r(NULL, delimiter, &strtok_save);
208 if(vector != NULL && size > 0) {
209 vector[size - 1] = NULL;
212 g_free(string_c);
213 string_c = NULL;
215 return vector;
218 gchar *
219 g_strreverse (gchar *str)
221 guint len, half;
222 gint i;
223 gchar c;
225 if (str == NULL)
226 return NULL;
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;
236 return str;
239 gchar *
240 g_strjoin (const gchar *separator, ...)
242 va_list args;
243 char *res, *s;
244 int len, slen;
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;
256 va_end (args);
257 if (len == 0)
258 return g_strdup ("");
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);
273 va_end (args);
275 return res;
278 gchar *
279 g_strchug (gchar *str)
281 gint len;
282 gchar *tmp;
284 if (str == NULL)
285 return NULL;
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);
293 return str;
296 gchar *
297 g_strchomp (gchar *str)
299 gchar *tmp;
301 if (str == NULL)
302 return NULL;
304 tmp = str + strlen (str) - 1;
305 while (*tmp && isspace (*tmp)) tmp--;
306 *(tmp + 1) = '\0';
307 return str;
310 gint
311 g_printf(gchar const *format, ...)
313 va_list args;
314 gint ret;
316 va_start(args, format);
317 ret = vprintf(format, args);
318 va_end(args);
320 return ret;
323 gint
324 g_fprintf(FILE *file, gchar const *format, ...)
326 va_list args;
327 gint ret;
329 va_start(args, format);
330 ret = vfprintf(file, format, args);
331 va_end(args);
333 return ret;
336 gint
337 g_sprintf(gchar *string, gchar const *format, ...)
339 va_list args;
340 gint ret;
342 va_start(args, format);
343 ret = vsprintf(string, format, args);
344 va_end(args);
346 return ret;
349 gint
350 g_snprintf(gchar *string, gulong n, gchar const *format, ...)
352 va_list args;
353 gint ret;
355 va_start(args, format);
356 ret = vsnprintf(string, n, format, args);
357 va_end(args);
359 return ret;
362 static const char const hx [] = { '0', '1', '2', '3', '4', '5', '6', '7',
363 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
365 static gboolean
366 char_needs_encoding (char c)
368 if (((unsigned char)c) >= 0x80)
369 return TRUE;
371 if ((c >= '@' && c <= 'Z') ||
372 (c >= 'a' && c <= 'z') ||
373 (c >= '&' && c < 0x3b) ||
374 (c == '!') || (c == '$') || (c == '_') || (c == '=') || (c == '~'))
375 return FALSE;
376 return TRUE;
379 gchar *
380 g_filename_to_uri (const gchar *filename, const gchar *hostname, GError **error)
382 int n;
383 char *ret, *rp;
384 const char *p;
386 g_return_val_if_fail (filename != NULL, NULL);
388 if (hostname != NULL)
389 g_warning ("eglib: g_filename_to_uri: hostname not handled");
391 if (*filename != '/'){
392 if (error != NULL)
393 *error = g_error_new (NULL, 2, "Not an absolute filename");
395 return NULL;
398 n = strlen ("file://") + 1;
399 for (p = filename; *p; p++){
400 if (char_needs_encoding (*p))
401 n += 3;
402 else
403 n++;
405 ret = g_malloc (n);
406 strcpy (ret, "file://");
407 for (p = filename, rp = ret + strlen (ret); *p; p++){
408 if (char_needs_encoding (*p)){
409 *rp++ = '%';
410 *rp++ = hx [((unsigned char)(*p)) >> 4];
411 *rp++ = hx [((unsigned char)(*p)) & 0xf];
412 } else
413 *rp++ = *p;
415 *rp = 0;
416 return ret;
419 static int
420 decode (char p)
422 if (p >= '0' && p <= '9')
423 return p - '0';
424 if (p >= 'A' && p <= 'F')
425 return p - 'A';
426 if (p >= 'a' && p <= 'f')
427 return p - 'a';
428 g_assert_not_reached ();
429 return 0;
432 gchar *
433 g_filename_from_uri (const gchar *uri, gchar **hostname, GError **error)
435 const char *p;
436 char *r, *result;
437 int flen = 0;
439 g_return_val_if_fail (uri != NULL, NULL);
441 if (hostname != NULL)
442 g_warning ("eglib: g_filename_from_uri: hostname not handled");
444 if (strncmp (uri, "file:///", 8) != 0){
445 if (error != NULL)
446 *error = g_error_new (NULL, 2, "URI does not start with the file: scheme");
447 return NULL;
450 for (p = uri + 8; *p; p++){
451 if (*p == '%'){
452 if (p [1] && p [2] && isxdigit (p [1]) && isxdigit (p [2])){
453 p += 2;
454 } else {
455 if (error != NULL)
456 *error = g_error_new (NULL, 2, "URI contains an invalid escape sequence");
457 return NULL;
460 flen++;
462 flen++;
464 result = g_malloc (flen + 1);
465 *result = '/';
466 result [flen] = 0;
468 for (p = uri + 8, r = result + 1; *p; p++){
469 if (*p == '%'){
470 *r++ = (decode (p [1]) << 4) | decode (p [2]);
471 p += 2;
472 } else
473 *r++ = *p;
474 flen++;
476 return result;
479 void
480 g_strdown (gchar *string)
482 g_return_if_fail (string != NULL);
484 while (*string){
485 *string = tolower (*string);
489 gchar *
490 g_ascii_strdown (const gchar *str, gssize len)
492 char *ret;
493 int i;
495 g_return_val_if_fail (str != NULL, NULL);
497 if (len == -1)
498 len = strlen (str);
500 ret = g_malloc (len + 1);
501 for (i = 0; i < len; i++){
502 guchar c = (guchar) str [i];
503 if (c >= 'A' && c <= 'Z')
504 c += 'a' - 'A';
505 ret [i] = c;
507 ret [i] = 0;
509 return ret;
513 gchar *
514 g_strdelimit (gchar *string, const gchar *delimiters, gchar new_delimiter)
516 gchar *ptr;
518 g_return_val_if_fail (string != NULL, NULL);
520 if (delimiters == NULL)
521 delimiters = G_STR_DELIMITERS;
523 for (ptr = string; *ptr; ptr++) {
524 if (strchr (delimiters, *ptr))
525 *ptr = new_delimiter;
528 return string;