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.
35 #include "vasprintf.h"
37 /* This is not a macro, because I dont want to put _GNU_SOURCE in the glib.h header */
39 g_strndup (const gchar *str, gsize n)
41 #if defined (HAVE_STRNDUP) && !defined (G_OVERRIDABLE_ALLOCATORS)
42 return strndup (str, n);
45 char *retval = g_malloc(n+1);
47 strncpy(retval, str, n)[n] = 0;
56 g_strfreev (gchar **str_array)
58 gchar **orig = str_array;
59 if (str_array == NULL)
61 while (*str_array != NULL){
69 g_strdupv (gchar **str_array)
78 length = g_strv_length(str_array);
79 ret = g_new0(gchar *, length + 1);
80 for (i = 0; str_array[i]; i++) {
81 ret[i] = g_strdup(str_array[i]);
88 g_strv_length(gchar **str_array)
91 g_return_val_if_fail(str_array != NULL, 0);
92 for(length = 0; str_array[length] != NULL; length++);
97 g_str_has_suffix(const gchar *str, const gchar *suffix)
100 size_t suffix_length;
102 g_return_val_if_fail(str != NULL, FALSE);
103 g_return_val_if_fail(suffix != NULL, FALSE);
105 str_length = strlen(str);
106 suffix_length = strlen(suffix);
108 return suffix_length <= str_length ?
109 strncmp(str + str_length - suffix_length, suffix, suffix_length) == 0 :
114 g_str_has_prefix(const gchar *str, const gchar *prefix)
117 size_t prefix_length;
119 g_return_val_if_fail(str != NULL, FALSE);
120 g_return_val_if_fail(prefix != NULL, FALSE);
122 str_length = strlen(str);
123 prefix_length = strlen(prefix);
125 return prefix_length <= str_length ?
126 strncmp(str, prefix, prefix_length) == 0 :
131 g_strdup_vprintf (const gchar *format, va_list args)
136 n = g_vasprintf (&ret, format, args);
144 g_strdup_printf (const gchar *format, ...)
150 va_start (args, format);
151 n = g_vasprintf (&ret, format, args);
160 g_strerror (gint errnum)
162 return strerror (errnum);
166 g_strconcat (const gchar *first, ...)
171 g_return_val_if_fail (first != NULL, NULL);
173 total += strlen (first);
174 va_start (args, first);
175 for (s = va_arg (args, char *); s != NULL; s = va_arg(args, char *)){
180 ret = g_malloc (total + 1);
186 va_start (args, first);
187 for (s = va_arg (args, char *); s != NULL; s = va_arg(args, char *)){
196 add_to_vector (gchar ***vector, int size, gchar *token)
198 *vector = *vector == NULL ?
199 (gchar **)g_malloc(2 * sizeof(*vector)) :
200 (gchar **)g_realloc(*vector, (size + 1) * sizeof(*vector));
202 (*vector)[size - 1] = token;
206 g_strsplit (const gchar *string, const gchar *delimiter, gint max_tokens)
209 gchar *token, **vector;
212 g_return_val_if_fail (string != NULL, NULL);
213 g_return_val_if_fail (delimiter != NULL, NULL);
214 g_return_val_if_fail (delimiter[0] != 0, NULL);
216 if (strncmp (string, delimiter, strlen (delimiter)) == 0) {
217 vector = (gchar **)g_malloc (2 * sizeof(vector));
218 vector[0] = g_strdup ("");
220 string += strlen (delimiter);
225 while (*string && !(max_tokens > 0 && size >= max_tokens)) {
227 if (strncmp (string, delimiter, strlen (delimiter)) == 0) {
228 token = g_strdup ("");
229 string += strlen (delimiter);
231 while (*string && strncmp (string, delimiter, strlen (delimiter)) != 0) {
236 gsize toklen = (string - c);
237 token = g_strndup (c, toklen);
239 /* Need to leave a trailing empty
240 * token if the delimiter is the last
243 if (strcmp (string, delimiter) != 0) {
244 string += strlen (delimiter);
247 token = g_strdup (c);
251 add_to_vector (&vector, size, token);
256 if (strcmp (string, delimiter) == 0)
257 add_to_vector (&vector, size, g_strdup (""));
259 /* Add the rest of the string as the last element */
260 add_to_vector (&vector, size, g_strdup (string));
265 if (vector == NULL) {
266 vector = (gchar **) g_malloc (2 * sizeof (vector));
268 } else if (size > 0) {
269 vector[size - 1] = NULL;
276 charcmp (gchar testchar, const gchar *compare)
279 if (*compare == testchar) {
289 g_strsplit_set (const gchar *string, const gchar *delimiter, gint max_tokens)
292 gchar *token, **vector;
295 g_return_val_if_fail (string != NULL, NULL);
296 g_return_val_if_fail (delimiter != NULL, NULL);
297 g_return_val_if_fail (delimiter[0] != 0, NULL);
299 if (charcmp (*string, delimiter)) {
300 vector = (gchar **)g_malloc (2 * sizeof(vector));
301 vector[0] = g_strdup ("");
309 while (*string && !(max_tokens > 0 && size >= max_tokens)) {
310 if (charcmp (*string, delimiter)) {
311 gsize toklen = (string - c);
313 token = g_strdup ("");
315 token = g_strndup (c, toklen);
320 add_to_vector (&vector, size, token);
327 if (max_tokens > 0 && size >= max_tokens) {
329 /* Add the rest of the string as the last element */
330 add_to_vector (&vector, size, g_strdup (string));
335 /* Fill in the trailing last token */
336 add_to_vector (&vector, size, g_strdup (c));
339 /* Need to leave a trailing empty token if the
340 * delimiter is the last part of the string
342 add_to_vector (&vector, size, g_strdup (""));
347 if (vector == NULL) {
348 vector = (gchar **) g_malloc (2 * sizeof (vector));
350 } else if (size > 0) {
351 vector[size - 1] = NULL;
358 g_strreverse (gchar *str)
369 for (i = 0, j = strlen (str) - 1; i < j; i++, j--) {
379 g_strjoin (const gchar *separator, ...)
385 if (separator != NULL)
386 slen = strlen (separator);
391 va_start (args, separator);
392 for (s = va_arg (args, char *); s != NULL; s = va_arg (args, char *)){
399 return g_strdup ("");
401 /* Remove the last separator */
402 if (slen > 0 && len > 0)
405 res = g_malloc (len + 1);
406 va_start (args, separator);
407 s = va_arg (args, char *);
408 r = g_stpcpy (res, s);
409 for (s = va_arg (args, char *); s != NULL; s = va_arg (args, char *)){
410 if (separator != NULL)
411 r = g_stpcpy (r, separator);
420 g_strjoinv (const gchar *separator, gchar **str_array)
425 if (separator != NULL)
426 slen = strlen (separator);
431 for (i = 0; str_array [i] != NULL; i++){
432 len += strlen (str_array [i]);
437 return g_strdup ("");
439 if (slen > 0 && len > 0)
442 res = g_malloc (len + 1);
443 r = g_stpcpy (res, str_array [0]);
444 for (i = 1; str_array [i] != NULL; i++){
445 if (separator != NULL)
446 r = g_stpcpy (r, separator);
447 r = g_stpcpy (r, str_array [i]);
454 g_strchug (gchar *str)
463 while (*tmp && isspace (*tmp)) tmp++;
465 len = strlen (str) - (tmp - str - 1);
466 memmove (str, tmp, len);
472 g_strchomp (gchar *str)
479 tmp = str + strlen (str) - 1;
480 while (*tmp && isspace (*tmp)) tmp--;
486 g_printf(gchar const *format, ...)
491 va_start(args, format);
492 ret = vprintf(format, args);
499 g_fprintf(FILE *file, gchar const *format, ...)
504 va_start(args, format);
505 ret = vfprintf(file, format, args);
512 g_sprintf(gchar *string, gchar const *format, ...)
517 va_start(args, format);
518 ret = vsprintf(string, format, args);
525 g_snprintf(gchar *string, gulong n, gchar const *format, ...)
530 va_start(args, format);
531 ret = vsnprintf(string, n, format, args);
537 static const char hx [] = { '0', '1', '2', '3', '4', '5', '6', '7',
538 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
541 char_needs_encoding (char c)
543 if (((unsigned char)c) >= 0x80)
546 if ((c >= '@' && c <= 'Z') ||
547 (c >= 'a' && c <= 'z') ||
548 (c >= '&' && c < 0x3b) ||
549 (c == '!') || (c == '$') || (c == '_') || (c == '=') || (c == '~'))
555 g_filename_to_uri (const gchar *filename, const gchar *hostname, GError **error)
561 const char *uriPrefix = "file:///";
563 const char *uriPrefix = "file://";
566 g_return_val_if_fail (filename != NULL, NULL);
568 if (hostname != NULL)
569 g_warning ("%s", "eglib: g_filename_to_uri: hostname not handled");
571 if (!g_path_is_absolute (filename)){
573 *error = g_error_new (NULL, 2, "Not an absolute filename");
578 n = strlen (uriPrefix) + 1;
579 for (p = filename; *p; p++){
586 if (char_needs_encoding (*p))
592 strcpy (ret, uriPrefix);
593 for (p = filename, rp = ret + strlen (ret); *p; p++){
600 if (char_needs_encoding (*p)){
602 *rp++ = hx [((unsigned char)(*p)) >> 4];
603 *rp++ = hx [((unsigned char)(*p)) & 0xf];
614 if (p >= '0' && p <= '9')
616 if (p >= 'A' && p <= 'F')
618 if (p >= 'a' && p <= 'f')
620 g_assert_not_reached ();
625 g_filename_from_uri (const gchar *uri, gchar **hostname, GError **error)
631 g_return_val_if_fail (uri != NULL, NULL);
633 if (hostname != NULL)
634 g_warning ("%s", "eglib: g_filename_from_uri: hostname not handled");
636 if (strncmp (uri, "file:///", 8) != 0){
638 *error = g_error_new (NULL, 2, "URI does not start with the file: scheme");
642 for (p = uri + 8; *p; p++){
644 if (p [1] && p [2] && isxdigit (p [1]) && isxdigit (p [2])){
648 *error = g_error_new (NULL, 2, "URI contains an invalid escape sequence");
658 result = g_malloc (flen + 1);
668 for (p = uri + 8; *p; p++){
670 *r++ = (char)((decode (p [1]) << 4) | decode (p [2]));
680 g_strdown (gchar *string)
682 g_return_if_fail (string != NULL);
685 *string = (gchar)tolower (*string);
691 g_ascii_tolower (gchar c)
693 return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c;
697 g_ascii_strdown (const gchar *str, gssize len)
702 g_return_val_if_fail (str != NULL, NULL);
707 ret = g_malloc (len + 1);
708 for (i = 0; i < len; i++)
709 ret [i] = (guchar) g_ascii_tolower (str [i]);
716 g_ascii_toupper (gchar c)
718 return c >= 'a' && c <= 'z' ? c + ('A' - 'a') : c;
722 g_ascii_strup (const gchar *str, gssize len)
727 g_return_val_if_fail (str != NULL, NULL);
732 ret = g_malloc (len + 1);
733 for (i = 0; i < len; i++)
734 ret [i] = (guchar) g_ascii_toupper (str [i]);
741 g_ascii_strncasecmp (const gchar *s1, const gchar *s2, gsize n)
745 g_return_val_if_fail (s1 != NULL, 0);
746 g_return_val_if_fail (s2 != NULL, 0);
748 for (i = 0; i < n; i++) {
749 gchar c1 = g_ascii_tolower (*s1++);
750 gchar c2 = g_ascii_tolower (*s2++);
760 g_ascii_strcasecmp (const gchar *s1, const gchar *s2)
762 const char *sp1 = s1;
763 const char *sp2 = s2;
765 g_return_val_if_fail (s1 != NULL, 0);
766 g_return_val_if_fail (s2 != NULL, 0);
768 while (*sp1 != '\0') {
769 char c1 = g_ascii_tolower (*sp1++);
770 char c2 = g_ascii_tolower (*sp2++);
776 return (*sp1) - (*sp2);
780 g_strdelimit (gchar *string, const gchar *delimiters, gchar new_delimiter)
784 g_return_val_if_fail (string != NULL, NULL);
786 if (delimiters == NULL)
787 delimiters = G_STR_DELIMITERS;
789 for (ptr = string; *ptr; ptr++) {
790 if (strchr (delimiters, *ptr))
791 *ptr = new_delimiter;
798 g_strlcpy (gchar *dest, const gchar *src, gsize dest_size)
801 return strlcpy (dest, src, dest_size);
808 g_return_val_if_fail (src != NULL, 0);
809 g_return_val_if_fail (dest != NULL, 0);
821 return (dest_size - len - 1);
824 /* len is 0 i we get here */
826 /* we need to return the length of src here */
827 while (*s++) ; /* instead of a plain strlen, we use 's' */
833 g_stpcpy (gchar *dest, const char *src)
835 g_return_val_if_fail (dest != NULL, dest);
836 g_return_val_if_fail (src != NULL, dest);
839 return stpcpy (dest, src);
850 static const gchar escaped_dflt [256] = {
851 1, 1, 1, 1, 1, 1, 1, 1, 'b', 't', 'n', 1, 'f', 'r', 1, 1,
852 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
853 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
854 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
855 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
856 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\', 0, 0, 0,
857 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
858 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
859 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
860 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
861 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
862 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
863 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
864 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
865 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
866 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
870 g_strescape (const gchar *source, const gchar *exceptions)
879 g_return_val_if_fail (source != NULL, NULL);
881 memcpy (escaped, escaped_dflt, 256);
882 if (exceptions != NULL) {
883 for (ptr = exceptions; *ptr; ptr++)
884 escaped [(int) *ptr] = 0;
886 result = g_malloc (strlen (source) * 4 + 1); /* Worst case: everything octal. */
888 for (ptr = source; *ptr; ptr++) {
890 op = escaped [(int) c];
898 *res_ptr++ = '0' + ((c >> 6) & 3);
899 *res_ptr++ = '0' + ((c >> 3) & 7);
900 *res_ptr++ = '0' + (c & 7);
909 g_ascii_xdigit_value (gchar c)
911 return ((isxdigit (c) == 0) ? -1 :
912 ((c >= '0' && c <= '9') ? (c - '0') :
913 ((c >= 'a' && c <= 'f') ? (c - 'a' + 10) :
918 g_strnfill (gsize length, gchar fill_char)
920 gchar *ret = g_new (gchar, length + 1);
922 memset (ret, fill_char, length);