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 /* This is not a macro, because I dont want to put _GNU_SOURCE in the glib.h header */
37 g_strndup (const gchar
*str
, gsize n
)
40 return strndup (str
, n
);
43 char *retval
= g_malloc(n
+1);
45 strncpy(retval
, str
, n
)[n
] = 0;
54 g_strfreev (gchar
**str_array
)
56 gchar
**orig
= str_array
;
57 if (str_array
== NULL
)
59 while (*str_array
!= NULL
){
67 g_strdupv (gchar
**str_array
)
76 length
= g_strv_length(str_array
);
77 ret
= g_new0(gchar
*, length
+ 1);
78 for (i
= 0; str_array
[i
]; i
++) {
79 ret
[i
] = g_strdup(str_array
[i
]);
86 g_strv_length(gchar
**str_array
)
89 g_return_val_if_fail(str_array
!= NULL
, 0);
90 for(length
= 0; str_array
[length
] != NULL
; length
++);
95 g_str_has_suffix(const gchar
*str
, const gchar
*suffix
)
100 g_return_val_if_fail(str
!= NULL
, FALSE
);
101 g_return_val_if_fail(suffix
!= NULL
, FALSE
);
103 str_length
= strlen(str
);
104 suffix_length
= strlen(suffix
);
106 return suffix_length
<= str_length
?
107 strncmp(str
+ str_length
- suffix_length
, suffix
, suffix_length
) == 0 :
112 g_str_has_prefix(const gchar
*str
, const gchar
*prefix
)
115 size_t prefix_length
;
117 g_return_val_if_fail(str
!= NULL
, FALSE
);
118 g_return_val_if_fail(prefix
!= NULL
, FALSE
);
120 str_length
= strlen(str
);
121 prefix_length
= strlen(prefix
);
123 return prefix_length
<= str_length
?
124 strncmp(str
, prefix
, prefix_length
) == 0 :
129 g_strdup_vprintf (const gchar
*format
, va_list args
)
134 n
= vasprintf (&ret
, format
, args
);
142 g_strdup_printf (const gchar
*format
, ...)
148 va_start (args
, format
);
149 n
= vasprintf (&ret
, format
, args
);
158 g_strerror (gint errnum
)
160 return strerror (errnum
);
164 g_strconcat (const gchar
*first
, ...)
169 g_return_val_if_fail (first
!= NULL
, NULL
);
171 total
+= strlen (first
);
172 va_start (args
, first
);
173 for (s
= va_arg (args
, char *); s
!= NULL
; s
= va_arg(args
, char *)){
178 ret
= g_malloc (total
+ 1);
184 va_start (args
, first
);
185 for (s
= va_arg (args
, char *); s
!= NULL
; s
= va_arg(args
, char *)){
194 add_to_vector (gchar
***vector
, int size
, gchar
*token
)
196 *vector
= *vector
== NULL
?
197 (gchar
**)g_malloc(2 * sizeof(*vector
)) :
198 (gchar
**)g_realloc(*vector
, (size
+ 1) * sizeof(*vector
));
200 (*vector
)[size
- 1] = token
;
204 g_strsplit (const gchar
*string
, const gchar
*delimiter
, gint max_tokens
)
207 gchar
*token
, **vector
;
210 g_return_val_if_fail (string
!= NULL
, NULL
);
211 g_return_val_if_fail (delimiter
!= NULL
, NULL
);
212 g_return_val_if_fail (delimiter
[0] != 0, NULL
);
214 if (strncmp (string
, delimiter
, strlen (delimiter
)) == 0) {
215 vector
= (gchar
**)g_malloc (2 * sizeof(vector
));
216 vector
[0] = g_strdup ("");
218 string
+= strlen (delimiter
);
223 while (*string
&& !(max_tokens
> 0 && size
>= max_tokens
)) {
225 if (strncmp (string
, delimiter
, strlen (delimiter
)) == 0) {
226 token
= g_strdup ("");
227 string
+= strlen (delimiter
);
229 while (*string
&& strncmp (string
, delimiter
, strlen (delimiter
)) != 0) {
234 gsize toklen
= (string
- c
);
235 token
= g_strndup (c
, toklen
);
237 /* Need to leave a trailing empty
238 * token if the delimiter is the last
241 if (strcmp (string
, delimiter
) != 0) {
242 string
+= strlen (delimiter
);
245 token
= g_strdup (c
);
249 add_to_vector (&vector
, size
, token
);
254 /* Add the rest of the string as the last element */
255 add_to_vector (&vector
, size
, g_strdup (string
));
259 if (vector
== NULL
) {
260 vector
= (gchar
**) g_malloc (2 * sizeof (vector
));
262 } else if (size
> 0) {
263 vector
[size
- 1] = NULL
;
270 charcmp (gchar testchar
, const gchar
*compare
)
273 if (*compare
== testchar
) {
283 g_strsplit_set (const gchar
*string
, const gchar
*delimiter
, gint max_tokens
)
286 gchar
*token
, **vector
;
289 g_return_val_if_fail (string
!= NULL
, NULL
);
290 g_return_val_if_fail (delimiter
!= NULL
, NULL
);
291 g_return_val_if_fail (delimiter
[0] != 0, NULL
);
293 if (charcmp (*string
, delimiter
)) {
294 vector
= (gchar
**)g_malloc (2 * sizeof(vector
));
295 vector
[0] = g_strdup ("");
303 while (*string
&& !(max_tokens
> 0 && size
>= max_tokens
)) {
304 if (charcmp (*string
, delimiter
)) {
305 gsize toklen
= (string
- c
);
307 token
= g_strdup ("");
309 token
= g_strndup (c
, toklen
);
314 add_to_vector (&vector
, size
, token
);
321 if (max_tokens
> 0 && size
>= max_tokens
) {
323 /* Add the rest of the string as the last element */
324 add_to_vector (&vector
, size
, g_strdup (string
));
329 /* Fill in the trailing last token */
330 add_to_vector (&vector
, size
, g_strdup (c
));
333 /* Need to leave a trailing empty token if the
334 * delimiter is the last part of the string
336 add_to_vector (&vector
, size
, g_strdup (""));
341 if (vector
== NULL
) {
342 vector
= (gchar
**) g_malloc (2 * sizeof (vector
));
344 } else if (size
> 0) {
345 vector
[size
- 1] = NULL
;
352 g_strreverse (gchar
*str
)
360 for (i
= 0, j
= strlen (str
) - 1; i
< j
; i
++, j
--) {
370 g_strjoin (const gchar
*separator
, ...)
376 if (separator
!= NULL
)
377 slen
= strlen (separator
);
382 va_start (args
, separator
);
383 for (s
= va_arg (args
, char *); s
!= NULL
; s
= va_arg (args
, char *)){
390 return g_strdup ("");
392 /* Remove the last separator */
393 if (slen
> 0 && len
> 0)
396 res
= g_malloc (len
+ 1);
397 va_start (args
, separator
);
398 s
= va_arg (args
, char *);
399 r
= g_stpcpy (res
, s
);
400 for (s
= va_arg (args
, char *); s
!= NULL
; s
= va_arg (args
, char *)){
401 if (separator
!= NULL
)
402 r
= g_stpcpy (r
, separator
);
411 g_strjoinv (const gchar
*separator
, gchar
**str_array
)
416 if (separator
!= NULL
)
417 slen
= strlen (separator
);
422 for (i
= 0; str_array
[i
] != NULL
; i
++){
423 len
+= strlen (str_array
[i
]);
428 return g_strdup ("");
430 if (slen
> 0 && len
> 0)
433 res
= g_malloc (len
+ 1);
434 r
= g_stpcpy (res
, str_array
[0]);
435 for (i
= 1; str_array
[i
] != NULL
; i
++){
436 if (separator
!= NULL
)
437 r
= g_stpcpy (r
, separator
);
438 r
= g_stpcpy (r
, str_array
[i
]);
445 g_strchug (gchar
*str
)
454 while (*tmp
&& isspace (*tmp
)) tmp
++;
456 len
= strlen (str
) - (tmp
- str
- 1);
457 memmove (str
, tmp
, len
);
463 g_strchomp (gchar
*str
)
470 tmp
= str
+ strlen (str
) - 1;
471 while (*tmp
&& isspace (*tmp
)) tmp
--;
477 g_printf(gchar
const *format
, ...)
482 va_start(args
, format
);
483 ret
= vprintf(format
, args
);
490 g_fprintf(FILE *file
, gchar
const *format
, ...)
495 va_start(args
, format
);
496 ret
= vfprintf(file
, format
, args
);
503 g_sprintf(gchar
*string
, gchar
const *format
, ...)
508 va_start(args
, format
);
509 ret
= vsprintf(string
, format
, args
);
516 g_snprintf(gchar
*string
, gulong n
, gchar
const *format
, ...)
521 va_start(args
, format
);
522 ret
= vsnprintf(string
, n
, format
, args
);
528 static const char hx
[] = { '0', '1', '2', '3', '4', '5', '6', '7',
529 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
532 char_needs_encoding (char c
)
534 if (((unsigned char)c
) >= 0x80)
537 if ((c
>= '@' && c
<= 'Z') ||
538 (c
>= 'a' && c
<= 'z') ||
539 (c
>= '&' && c
< 0x3b) ||
540 (c
== '!') || (c
== '$') || (c
== '_') || (c
== '=') || (c
== '~'))
546 g_filename_to_uri (const gchar
*filename
, const gchar
*hostname
, GError
**error
)
552 const char *uriPrefix
= "file:///";
554 const char *uriPrefix
= "file://";
557 g_return_val_if_fail (filename
!= NULL
, NULL
);
559 if (hostname
!= NULL
)
560 g_warning ("%s", "eglib: g_filename_to_uri: hostname not handled");
562 if (!g_path_is_absolute (filename
)){
564 *error
= g_error_new (NULL
, 2, "Not an absolute filename");
569 n
= strlen (uriPrefix
) + 1;
570 for (p
= filename
; *p
; p
++){
577 if (char_needs_encoding (*p
))
583 strcpy (ret
, uriPrefix
);
584 for (p
= filename
, rp
= ret
+ strlen (ret
); *p
; p
++){
591 if (char_needs_encoding (*p
)){
593 *rp
++ = hx
[((unsigned char)(*p
)) >> 4];
594 *rp
++ = hx
[((unsigned char)(*p
)) & 0xf];
605 if (p
>= '0' && p
<= '9')
607 if (p
>= 'A' && p
<= 'F')
609 if (p
>= 'a' && p
<= 'f')
611 g_assert_not_reached ();
616 g_filename_from_uri (const gchar
*uri
, gchar
**hostname
, GError
**error
)
622 g_return_val_if_fail (uri
!= NULL
, NULL
);
624 if (hostname
!= NULL
)
625 g_warning ("%s", "eglib: g_filename_from_uri: hostname not handled");
627 if (strncmp (uri
, "file:///", 8) != 0){
629 *error
= g_error_new (NULL
, 2, "URI does not start with the file: scheme");
633 for (p
= uri
+ 8; *p
; p
++){
635 if (p
[1] && p
[2] && isxdigit (p
[1]) && isxdigit (p
[2])){
639 *error
= g_error_new (NULL
, 2, "URI contains an invalid escape sequence");
649 result
= g_malloc (flen
+ 1);
659 for (p
= uri
+ 8; *p
; p
++){
661 *r
++ = (char)((decode (p
[1]) << 4) | decode (p
[2]));
671 g_strdown (gchar
*string
)
673 g_return_if_fail (string
!= NULL
);
676 *string
= (gchar
)tolower (*string
);
682 g_ascii_tolower (gchar c
)
684 return c
>= 'A' && c
<= 'Z' ? c
+ ('a' - 'A') : c
;
688 g_ascii_strdown (const gchar
*str
, gssize len
)
693 g_return_val_if_fail (str
!= NULL
, NULL
);
698 ret
= g_malloc (len
+ 1);
699 for (i
= 0; i
< len
; i
++)
700 ret
[i
] = (guchar
) g_ascii_tolower (str
[i
]);
707 g_ascii_toupper (gchar c
)
709 return c
>= 'a' && c
<= 'z' ? c
+ ('A' - 'a') : c
;
713 g_ascii_strup (const gchar
*str
, gssize len
)
718 g_return_val_if_fail (str
!= NULL
, NULL
);
723 ret
= g_malloc (len
+ 1);
724 for (i
= 0; i
< len
; i
++)
725 ret
[i
] = (guchar
) g_ascii_toupper (str
[i
]);
732 g_ascii_strncasecmp (const gchar
*s1
, const gchar
*s2
, gsize n
)
736 g_return_val_if_fail (s1
!= NULL
, 0);
737 g_return_val_if_fail (s2
!= NULL
, 0);
739 for (i
= 0; i
< n
; i
++) {
740 gchar c1
= g_ascii_tolower (*s1
++);
741 gchar c2
= g_ascii_tolower (*s2
++);
751 g_ascii_strcasecmp (const gchar
*s1
, const gchar
*s2
)
753 const char *sp1
= s1
;
754 const char *sp2
= s2
;
756 g_return_val_if_fail (s1
!= NULL
, 0);
757 g_return_val_if_fail (s2
!= NULL
, 0);
759 while (*sp1
!= '\0') {
760 char c1
= g_ascii_tolower (*sp1
++);
761 char c2
= g_ascii_tolower (*sp2
++);
767 return (*sp1
) - (*sp2
);
771 g_strdelimit (gchar
*string
, const gchar
*delimiters
, gchar new_delimiter
)
775 g_return_val_if_fail (string
!= NULL
, NULL
);
777 if (delimiters
== NULL
)
778 delimiters
= G_STR_DELIMITERS
;
780 for (ptr
= string
; *ptr
; ptr
++) {
781 if (strchr (delimiters
, *ptr
))
782 *ptr
= new_delimiter
;
789 g_strlcpy (gchar
*dest
, const gchar
*src
, gsize dest_size
)
792 return strlcpy (dest
, src
, dest_size
);
799 g_return_val_if_fail (src
!= NULL
, 0);
800 g_return_val_if_fail (dest
!= NULL
, 0);
812 return (dest_size
- len
- 1);
815 /* len is 0 i we get here */
817 /* we need to return the length of src here */
818 while (*s
++) ; /* instead of a plain strlen, we use 's' */
824 g_stpcpy (gchar
*dest
, const char *src
)
826 g_return_val_if_fail (dest
!= NULL
, dest
);
827 g_return_val_if_fail (src
!= NULL
, dest
);
830 return stpcpy (dest
, src
);
841 static const gchar escaped_dflt
[256] = {
842 1, 1, 1, 1, 1, 1, 1, 1, 'b', 't', 'n', 1, 'f', 'r', 1, 1,
843 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
844 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
845 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
846 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
847 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\', 0, 0, 0,
848 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
849 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
850 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
851 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
852 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
853 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
854 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
855 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
856 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
857 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
861 g_strescape (const gchar
*source
, const gchar
*exceptions
)
870 g_return_val_if_fail (source
!= NULL
, NULL
);
872 memcpy (escaped
, escaped_dflt
, 256);
873 if (exceptions
!= NULL
) {
874 for (ptr
= exceptions
; *ptr
; ptr
++)
875 escaped
[(int) *ptr
] = 0;
877 result
= g_malloc (strlen (source
) * 4 + 1); /* Worst case: everything octal. */
879 for (ptr
= source
; *ptr
; ptr
++) {
881 op
= escaped
[(int) c
];
889 *res_ptr
++ = '0' + ((c
>> 6) & 3);
890 *res_ptr
++ = '0' + ((c
>> 3) & 7);
891 *res_ptr
++ = '0' + (c
& 7);
900 g_ascii_xdigit_value (gchar c
)
902 return ((isxdigit (c
) == 0) ? -1 :
903 ((c
>= '0' && c
<= '9') ? (c
- '0') :
904 ((c
>= 'a' && c
<= 'f') ? (c
- 'a' + 10) :
909 g_strnfill (gsize length
, gchar fill_char
)
911 gchar
*ret
= g_new (gchar
, length
+ 1);
913 memset (ret
, fill_char
, length
);