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_strv_length(gchar
**str_array
)
70 g_return_val_if_fail(str_array
!= NULL
, 0);
71 for(length
= 0; str_array
[length
] != NULL
; length
++);
76 g_str_has_suffix(const gchar
*str
, const gchar
*suffix
)
81 g_return_val_if_fail(str
!= NULL
, FALSE
);
82 g_return_val_if_fail(suffix
!= NULL
, FALSE
);
84 str_length
= strlen(str
);
85 suffix_length
= strlen(suffix
);
87 return suffix_length
<= str_length
?
88 strncmp(str
+ str_length
- suffix_length
, suffix
, suffix_length
) == 0 :
93 g_str_has_prefix(const gchar
*str
, const gchar
*prefix
)
98 g_return_val_if_fail(str
!= NULL
, FALSE
);
99 g_return_val_if_fail(prefix
!= NULL
, FALSE
);
101 str_length
= strlen(str
);
102 prefix_length
= strlen(prefix
);
104 return prefix_length
<= str_length
?
105 strncmp(str
, prefix
, prefix_length
) == 0 :
110 g_strdup_vprintf (const gchar
*format
, va_list args
)
115 n
= vasprintf (&ret
, format
, args
);
123 g_strdup_printf (const gchar
*format
, ...)
129 va_start (args
, format
);
130 n
= vasprintf (&ret
, format
, args
);
139 g_strerror (gint errnum
)
141 return strerror (errnum
);
145 g_strconcat (const gchar
*first
, ...)
150 g_return_val_if_fail (first
!= NULL
, NULL
);
152 total
+= strlen (first
);
153 va_start (args
, first
);
154 for (s
= va_arg (args
, char *); s
!= NULL
; s
= va_arg(args
, char *)){
159 ret
= g_malloc (total
+ 1);
165 va_start (args
, first
);
166 for (s
= va_arg (args
, char *); s
!= NULL
; s
= va_arg(args
, char *)){
175 add_to_vector (gchar
***vector
, int size
, gchar
*token
)
177 *vector
= *vector
== NULL
?
178 (gchar
**)g_malloc(2 * sizeof(*vector
)) :
179 (gchar
**)g_realloc(*vector
, (size
+ 1) * sizeof(*vector
));
181 (*vector
)[size
- 1] = token
;
185 g_strsplit (const gchar
*string
, const gchar
*delimiter
, gint max_tokens
)
188 gchar
*token
, **vector
;
191 g_return_val_if_fail (string
!= NULL
, NULL
);
192 g_return_val_if_fail (delimiter
!= NULL
, NULL
);
193 g_return_val_if_fail (delimiter
[0] != 0, NULL
);
195 if (strncmp (string
, delimiter
, strlen (delimiter
)) == 0) {
196 vector
= (gchar
**)g_malloc (2 * sizeof(vector
));
197 vector
[0] = g_strdup ("");
199 string
+= strlen (delimiter
);
204 while (*string
&& !(max_tokens
> 0 && size
>= max_tokens
)) {
206 if (strncmp (string
, delimiter
, strlen (delimiter
)) == 0) {
207 token
= g_strdup ("");
208 string
+= strlen (delimiter
);
210 while (*string
&& strncmp (string
, delimiter
, strlen (delimiter
)) != 0) {
215 gsize toklen
= (string
- c
);
216 token
= g_strndup (c
, toklen
);
218 /* Need to leave a trailing empty
219 * token if the delimiter is the last
222 if (strcmp (string
, delimiter
) != 0) {
223 string
+= strlen (delimiter
);
226 token
= g_strdup (c
);
230 add_to_vector (&vector
, size
, token
);
235 /* Add the rest of the string as the last element */
236 add_to_vector (&vector
, size
, g_strdup (string
));
240 if (vector
== NULL
) {
241 vector
= (gchar
**) g_malloc (2 * sizeof (vector
));
243 } else if (size
> 0) {
244 vector
[size
- 1] = NULL
;
251 charcmp (gchar testchar
, const gchar
*compare
)
254 if (*compare
== testchar
) {
264 g_strsplit_set (const gchar
*string
, const gchar
*delimiter
, gint max_tokens
)
267 gchar
*token
, **vector
;
270 g_return_val_if_fail (string
!= NULL
, NULL
);
271 g_return_val_if_fail (delimiter
!= NULL
, NULL
);
272 g_return_val_if_fail (delimiter
[0] != 0, NULL
);
274 if (charcmp (*string
, delimiter
)) {
275 vector
= (gchar
**)g_malloc (2 * sizeof(vector
));
276 vector
[0] = g_strdup ("");
284 while (*string
&& !(max_tokens
> 0 && size
>= max_tokens
)) {
285 if (charcmp (*string
, delimiter
)) {
286 gsize toklen
= (string
- c
);
288 token
= g_strdup ("");
290 token
= g_strndup (c
, toklen
);
295 add_to_vector (&vector
, size
, token
);
302 if (max_tokens
> 0 && size
>= max_tokens
) {
304 /* Add the rest of the string as the last element */
305 add_to_vector (&vector
, size
, g_strdup (string
));
310 /* Fill in the trailing last token */
311 add_to_vector (&vector
, size
, g_strdup (c
));
314 /* Need to leave a trailing empty token if the
315 * delimiter is the last part of the string
317 add_to_vector (&vector
, size
, g_strdup (""));
322 if (vector
== NULL
) {
323 vector
= (gchar
**) g_malloc (2 * sizeof (vector
));
325 } else if (size
> 0) {
326 vector
[size
- 1] = NULL
;
333 g_strreverse (gchar
*str
)
345 for (i
= 0; i
< half
; i
++, len
--) {
354 g_strjoin (const gchar
*separator
, ...)
360 if (separator
!= NULL
)
361 slen
= strlen (separator
);
365 va_start (args
, separator
);
366 for (s
= va_arg (args
, char *); s
!= NULL
; s
= va_arg (args
, char *)){
372 return g_strdup ("");
374 /* Remove the last separator */
375 if (slen
> 0 && len
> 0)
378 res
= g_malloc (len
);
379 va_start (args
, separator
);
380 s
= va_arg (args
, char *);
382 for (s
= va_arg (args
, char *); s
!= NULL
; s
= va_arg (args
, char *)){
383 if (separator
!= NULL
)
384 strcat (res
, separator
);
393 g_strjoinv (const gchar
*separator
, gchar
**str_array
)
398 if (separator
!= NULL
)
399 slen
= strlen (separator
);
404 for (i
= 0; str_array
[i
] != NULL
; i
++){
405 len
+= strlen (str_array
[i
]);
409 return g_strdup ("");
410 if (slen
> 0 && len
> 0)
413 res
= g_malloc (len
);
414 strcpy (res
, str_array
[0]);
415 for (i
= 1; str_array
[i
] != NULL
; i
++){
416 if (separator
!= NULL
)
417 strcat (res
, separator
);
418 strcat (res
, str_array
[i
]);
424 g_strchug (gchar
*str
)
433 while (*tmp
&& isspace (*tmp
)) tmp
++;
435 len
= strlen (str
) - (tmp
- str
- 1);
436 memmove (str
, tmp
, len
);
442 g_strchomp (gchar
*str
)
449 tmp
= str
+ strlen (str
) - 1;
450 while (*tmp
&& isspace (*tmp
)) tmp
--;
456 g_printf(gchar
const *format
, ...)
461 va_start(args
, format
);
462 ret
= vprintf(format
, args
);
469 g_fprintf(FILE *file
, gchar
const *format
, ...)
474 va_start(args
, format
);
475 ret
= vfprintf(file
, format
, args
);
482 g_sprintf(gchar
*string
, gchar
const *format
, ...)
487 va_start(args
, format
);
488 ret
= vsprintf(string
, format
, args
);
495 g_snprintf(gchar
*string
, gulong n
, gchar
const *format
, ...)
500 va_start(args
, format
);
501 ret
= vsnprintf(string
, n
, format
, args
);
507 static const char hx
[] = { '0', '1', '2', '3', '4', '5', '6', '7',
508 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
511 char_needs_encoding (char c
)
513 if (((unsigned char)c
) >= 0x80)
516 if ((c
>= '@' && c
<= 'Z') ||
517 (c
>= 'a' && c
<= 'z') ||
518 (c
>= '&' && c
< 0x3b) ||
519 (c
== '!') || (c
== '$') || (c
== '_') || (c
== '=') || (c
== '~'))
525 g_filename_to_uri (const gchar
*filename
, const gchar
*hostname
, GError
**error
)
531 const char *uriPrefix
= "file:///";
533 const char *uriPrefix
= "file://";
536 g_return_val_if_fail (filename
!= NULL
, NULL
);
538 if (hostname
!= NULL
)
539 g_warning ("%s", "eglib: g_filename_to_uri: hostname not handled");
541 if (!g_path_is_absolute (filename
)){
543 *error
= g_error_new (NULL
, 2, "Not an absolute filename");
548 n
= strlen (uriPrefix
) + 1;
549 for (p
= filename
; *p
; p
++){
556 if (char_needs_encoding (*p
))
562 strcpy (ret
, uriPrefix
);
563 for (p
= filename
, rp
= ret
+ strlen (ret
); *p
; p
++){
570 if (char_needs_encoding (*p
)){
572 *rp
++ = hx
[((unsigned char)(*p
)) >> 4];
573 *rp
++ = hx
[((unsigned char)(*p
)) & 0xf];
584 if (p
>= '0' && p
<= '9')
586 if (p
>= 'A' && p
<= 'F')
588 if (p
>= 'a' && p
<= 'f')
590 g_assert_not_reached ();
595 g_filename_from_uri (const gchar
*uri
, gchar
**hostname
, GError
**error
)
601 g_return_val_if_fail (uri
!= NULL
, NULL
);
603 if (hostname
!= NULL
)
604 g_warning ("%s", "eglib: g_filename_from_uri: hostname not handled");
606 if (strncmp (uri
, "file:///", 8) != 0){
608 *error
= g_error_new (NULL
, 2, "URI does not start with the file: scheme");
612 for (p
= uri
+ 8; *p
; p
++){
614 if (p
[1] && p
[2] && isxdigit (p
[1]) && isxdigit (p
[2])){
618 *error
= g_error_new (NULL
, 2, "URI contains an invalid escape sequence");
628 result
= g_malloc (flen
+ 1);
638 for (p
= uri
+ 8; *p
; p
++){
640 *r
++ = (char)((decode (p
[1]) << 4) | decode (p
[2]));
650 g_strdown (gchar
*string
)
652 g_return_if_fail (string
!= NULL
);
655 *string
= (gchar
)tolower (*string
);
661 g_ascii_tolower (gchar c
)
663 return c
>= 'A' && c
<= 'Z' ? c
+ ('a' - 'A') : c
;
667 g_ascii_strdown (const gchar
*str
, gssize len
)
672 g_return_val_if_fail (str
!= NULL
, NULL
);
677 ret
= g_malloc (len
+ 1);
678 for (i
= 0; i
< len
; i
++)
679 ret
[i
] = (guchar
) g_ascii_tolower (str
[i
]);
686 g_ascii_strncasecmp (const gchar
*s1
, const gchar
*s2
, gsize n
)
690 g_return_val_if_fail (s1
!= NULL
, 0);
691 g_return_val_if_fail (s2
!= NULL
, 0);
693 for (i
= 0; i
< n
; i
++){
694 gchar c1
= g_ascii_tolower (*s1
++);
695 gchar c2
= g_ascii_tolower (*s2
++);
710 g_strdelimit (gchar
*string
, const gchar
*delimiters
, gchar new_delimiter
)
714 g_return_val_if_fail (string
!= NULL
, NULL
);
716 if (delimiters
== NULL
)
717 delimiters
= G_STR_DELIMITERS
;
719 for (ptr
= string
; *ptr
; ptr
++) {
720 if (strchr (delimiters
, *ptr
))
721 *ptr
= new_delimiter
;
728 g_strlcpy (gchar
*dest
, const gchar
*src
, gsize dest_size
)
731 return strlcpy (dest
, src
, dest_size
);
738 g_return_val_if_fail (src
!= NULL
, 0);
739 g_return_val_if_fail (dest
!= NULL
, 0);
751 return (dest_size
- len
- 1);
754 /* len is 0 i we get here */
756 /* we need to return the length of src here */
757 while (*s
++) ; /* instead of a plain strlen, we use 's' */
762 static const gchar escaped_dflt
[256] = {
763 1, 1, 1, 1, 1, 1, 1, 1, 'b', 't', 'n', 1, 'f', 'r', 1, 1,
764 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
765 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
766 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
767 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
768 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\', 0, 0, 0,
769 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
770 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
771 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
772 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
773 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
774 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
775 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
776 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
777 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
778 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
782 g_strescape (const gchar
*source
, const gchar
*exceptions
)
791 g_return_val_if_fail (source
!= NULL
, NULL
);
793 memcpy (escaped
, escaped_dflt
, 256);
794 if (exceptions
!= NULL
) {
795 for (ptr
= exceptions
; *ptr
; ptr
++)
796 escaped
[(int) *ptr
] = 0;
798 result
= g_malloc (strlen (source
) * 4 + 1); /* Worst case: everything octal. */
800 for (ptr
= source
; *ptr
; ptr
++) {
802 op
= escaped
[(int) c
];
810 *res_ptr
++ = '0' + ((c
>> 6) & 3);
811 *res_ptr
++ = '0' + ((c
>> 3) & 7);
812 *res_ptr
++ = '0' + (c
& 7);
821 g_ascii_xdigit_value (gchar c
)
823 return ((isxdigit (c
) == 0) ? -1 :
824 ((c
>= '0' && c
<= '9') ? (c
- '0') :
825 ((c
>= 'a' && c
<= 'f') ? (c
- 'a' + 10) :
830 g_strnfill (gsize length
, gchar fill_char
)
832 gchar
*ret
= g_new (gchar
, length
+ 1);
834 memset (ret
, fill_char
, length
);