2 * gstr.c: String Utility Functions.
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.
34 /* This is not a macro, because I dont want to put _GNU_SOURCE in the glib.h header */
36 g_strndup (const gchar *str, gsize n)
38 return strndup (str, n);
42 g_strfreev (gchar **str_array)
44 gchar **orig = str_array;
45 if (str_array == NULL)
47 while (*str_array != NULL){
55 g_strv_length(gchar **str_array)
58 g_return_val_if_fail(str_array != NULL, 0);
59 for(length = 0; str_array[length] != NULL; length++);
64 g_str_has_suffix(const gchar *str, const gchar *suffix)
69 g_return_val_if_fail(str != NULL, FALSE);
70 g_return_val_if_fail(suffix != NULL, FALSE);
72 str_length = strlen(str);
73 suffix_length = strlen(suffix);
75 return suffix_length <= str_length ?
76 strncmp(str + str_length - suffix_length, suffix, suffix_length) == 0 :
81 g_str_has_prefix(const gchar *str, const gchar *prefix)
86 g_return_val_if_fail(str != NULL, FALSE);
87 g_return_val_if_fail(prefix != NULL, FALSE);
89 str_length = strlen(str);
90 prefix_length = strlen(prefix);
92 return prefix_length <= str_length ?
93 strncmp(str, prefix, prefix_length) == 0 :
98 g_strdup_vprintf (const gchar *format, va_list args)
103 n = vasprintf (&ret, format, args);
111 g_strdup_printf (const gchar *format, ...)
117 va_start (args, format);
118 n = vasprintf (&ret, format, args);
127 g_strerror (gint errnum)
129 return strerror (errnum);
133 g_strconcat (const gchar *first, ...)
135 g_return_val_if_fail (first != NULL, NULL);
140 total += strlen (first);
141 va_start (args, first);
142 for (s = va_arg (args, char *); s != NULL; s = va_arg(args, char *)){
147 ret = g_malloc (total + 1);
153 va_start (args, first);
154 for (s = va_arg (args, char *); s != NULL; s = va_arg(args, char *)){
163 g_strsplit (const gchar *string, const gchar *delimiter, gint max_tokens)
166 gchar *strtok_save, **vector;
167 gchar *token, *token_c;
171 g_return_val_if_fail(string != NULL, NULL);
172 g_return_val_if_fail(delimiter != NULL, NULL);
173 g_return_val_if_fail(delimiter[0] != 0, NULL);
175 token_length = strlen(string);
176 string_c = (gchar *)g_malloc(token_length + 1);
177 memcpy(string_c, string, token_length);
178 string_c[token_length] = 0;
180 if (strncmp (string_c, delimiter, strlen (delimiter)) == 0){
181 vector = (gchar **) g_malloc (2 * sizeof (vector));
182 vector [0] = g_strdup ("");
186 token = (gchar *)strtok_r(string_c, delimiter, &strtok_save);
188 if (!(max_tokens > 0 && size >= max_tokens)){
189 while(token != NULL) {
190 token_length = strlen(token);
191 token_c = (gchar *)g_malloc(token_length + 1);
192 memcpy(token_c, token, token_length);
193 token_c[token_length] = 0;
195 vector = vector == NULL ?
196 (gchar **)g_malloc(2 * sizeof(vector)) :
197 (gchar **)g_realloc(vector, (size + 1) * sizeof(vector));
199 vector[size - 1] = token_c;
202 if(max_tokens > 0 && size >= max_tokens) {
203 if(size > max_tokens) {
207 token = *strtok_save ? strtok_save : NULL;
209 token = (gchar *)strtok_r(NULL, delimiter, &strtok_save);
215 vector = (gchar **) g_malloc (2 * sizeof (vector));
217 } else if (size > 0){
218 vector[size - 1] = NULL;
228 g_strreverse (gchar *str)
240 for (i = 0; i < half; i++, len--) {
249 g_strjoin (const gchar *separator, ...)
255 if (separator != NULL)
256 slen = strlen (separator);
260 va_start (args, separator);
261 for (s = va_arg (args, char *); s != NULL; s = va_arg (args, char *)){
267 return g_strdup ("");
269 /* Remove the last separator */
270 if (slen > 0 && len > 0)
273 res = g_malloc (len);
274 va_start (args, separator);
275 s = va_arg (args, char *);
277 for (s = va_arg (args, char *); s != NULL; s = va_arg (args, char *)){
278 if (separator != NULL)
279 strcat (res, separator);
288 g_strjoinv (const gchar *separator, gchar **str_array)
293 if (separator != NULL)
294 slen = strlen (separator);
299 for (i = 0; str_array [i] != NULL; i++){
300 len += strlen (str_array [i]);
304 return g_strdup ("");
305 if (slen > 0 && len > 0)
308 res = g_malloc (len);
309 strcpy (res, str_array [0]);
310 for (i = 1; str_array [i] != NULL; i++){
311 if (separator != NULL)
312 strcat (res, separator);
313 strcat (res, str_array [i]);
319 g_strchug (gchar *str)
328 while (*tmp && isspace (*tmp)) tmp++;
330 len = strlen (str) - (tmp - str - 1);
331 memmove (str, tmp, len);
337 g_strchomp (gchar *str)
344 tmp = str + strlen (str) - 1;
345 while (*tmp && isspace (*tmp)) tmp--;
351 g_printf(gchar const *format, ...)
356 va_start(args, format);
357 ret = vprintf(format, args);
364 g_fprintf(FILE *file, gchar const *format, ...)
369 va_start(args, format);
370 ret = vfprintf(file, format, args);
377 g_sprintf(gchar *string, gchar const *format, ...)
382 va_start(args, format);
383 ret = vsprintf(string, format, args);
390 g_snprintf(gchar *string, gulong n, gchar const *format, ...)
395 va_start(args, format);
396 ret = vsnprintf(string, n, format, args);
402 static const char const hx [] = { '0', '1', '2', '3', '4', '5', '6', '7',
403 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
406 char_needs_encoding (char c)
408 if (((unsigned char)c) >= 0x80)
411 if ((c >= '@' && c <= 'Z') ||
412 (c >= 'a' && c <= 'z') ||
413 (c >= '&' && c < 0x3b) ||
414 (c == '!') || (c == '$') || (c == '_') || (c == '=') || (c == '~'))
420 g_filename_to_uri (const gchar *filename, const gchar *hostname, GError **error)
426 g_return_val_if_fail (filename != NULL, NULL);
428 if (hostname != NULL)
429 g_warning ("eglib: g_filename_to_uri: hostname not handled");
431 if (*filename != '/'){
433 *error = g_error_new (NULL, 2, "Not an absolute filename");
438 n = strlen ("file://") + 1;
439 for (p = filename; *p; p++){
440 if (char_needs_encoding (*p))
446 strcpy (ret, "file://");
447 for (p = filename, rp = ret + strlen (ret); *p; p++){
448 if (char_needs_encoding (*p)){
450 *rp++ = hx [((unsigned char)(*p)) >> 4];
451 *rp++ = hx [((unsigned char)(*p)) & 0xf];
462 if (p >= '0' && p <= '9')
464 if (p >= 'A' && p <= 'F')
466 if (p >= 'a' && p <= 'f')
468 g_assert_not_reached ();
473 g_filename_from_uri (const gchar *uri, gchar **hostname, GError **error)
479 g_return_val_if_fail (uri != NULL, NULL);
481 if (hostname != NULL)
482 g_warning ("eglib: g_filename_from_uri: hostname not handled");
484 if (strncmp (uri, "file:///", 8) != 0){
486 *error = g_error_new (NULL, 2, "URI does not start with the file: scheme");
490 for (p = uri + 8; *p; p++){
492 if (p [1] && p [2] && isxdigit (p [1]) && isxdigit (p [2])){
496 *error = g_error_new (NULL, 2, "URI contains an invalid escape sequence");
504 result = g_malloc (flen + 1);
508 for (p = uri + 8, r = result + 1; *p; p++){
510 *r++ = (decode (p [1]) << 4) | decode (p [2]);
520 g_strdown (gchar *string)
522 g_return_if_fail (string != NULL);
525 *string = tolower (*string);
531 g_ascii_strdown (const gchar *str, gssize len)
536 g_return_val_if_fail (str != NULL, NULL);
541 ret = g_malloc (len + 1);
542 for (i = 0; i < len; i++){
543 guchar c = (guchar) str [i];
544 if (c >= 'A' && c <= 'Z')
554 g_ascii_strncasecmp (const gchar *s1, const gchar *s2, gsize n)
558 g_return_val_if_fail (s1 != NULL, 0);
559 g_return_val_if_fail (s2 != NULL, 0);
561 for (i = 0; i < n; i++){
578 g_strdelimit (gchar *string, const gchar *delimiters, gchar new_delimiter)
582 g_return_val_if_fail (string != NULL, NULL);
584 if (delimiters == NULL)
585 delimiters = G_STR_DELIMITERS;
587 for (ptr = string; *ptr; ptr++) {
588 if (strchr (delimiters, *ptr))
589 *ptr = new_delimiter;
597 g_strlcpy (gchar *dest, const gchar *src, gsize dest_size)
604 g_return_val_if_fail (src != NULL, 0);
605 g_return_val_if_fail (dest != NULL, 0);
617 return (dest_size - len - 1);
620 /* len is 0 i we get here */
622 /* we need to return the length of src here */
623 while (*s++) ; /* instead of a plain strlen, we use 's' */
628 static const gchar escaped_dflt [256] = {
629 1, 1, 1, 1, 1, 1, 1, 1, 'b', 't', 'n', 1, 'f', 'r', 1, 1,
630 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
631 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
632 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
633 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
634 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\', 0, 0, 0,
635 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
636 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
637 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
638 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
639 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
640 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
641 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
642 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
643 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
644 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
648 g_strescape (const gchar *source, const gchar *exceptions)
657 g_return_val_if_fail (source != NULL, NULL);
659 memcpy (escaped, escaped_dflt, 256);
660 if (exceptions != NULL) {
661 for (ptr = exceptions; *ptr; ptr++)
662 escaped [(int) *ptr] = 0;
664 result = g_malloc (strlen (source) * 4 + 1); /* Worst case: everything octal. */
666 for (ptr = source; *ptr; ptr++) {
668 op = escaped [(int) c];
676 *res_ptr++ = '0' + ((c >> 6) & 3);
677 *res_ptr++ = '0' + ((c >> 3) & 7);
678 *res_ptr++ = '0' + (c & 7);
687 g_strdup (const gchar *str)
696 g_ascii_xdigit_value (gchar c)
698 return ((isxdigit (c) == 0) ? -1 :
699 ((c >= '0' && c <= '9') ? (c - '0') :
700 ((c >= 'a' && c <= 'f') ? (c - 'a' + 10) :