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
)
39 return strndup (str
, n
);
43 g_strfreev (gchar
**str_array
)
45 gchar
**orig
= str_array
;
46 if (str_array
== NULL
)
48 while (*str_array
!= NULL
){
56 g_strv_length(gchar
**str_array
)
59 g_return_val_if_fail(str_array
!= NULL
, 0);
60 for(length
= 0; str_array
[length
] != NULL
; length
++);
65 g_str_has_suffix(const gchar
*str
, const gchar
*suffix
)
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 :
82 g_str_has_prefix(const gchar
*str
, const gchar
*prefix
)
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 :
99 g_strdup_vprintf (const gchar
*format
, va_list args
)
104 n
= vasprintf (&ret
, format
, args
);
112 g_strdup_printf (const gchar
*format
, ...)
118 va_start (args
, format
);
119 n
= vasprintf (&ret
, format
, args
);
128 g_strerror (gint errnum
)
130 return strerror (errnum
);
134 g_strconcat (const gchar
*first
, ...)
136 g_return_val_if_fail (first
!= NULL
, NULL
);
141 total
+= strlen (first
);
142 va_start (args
, first
);
143 for (s
= va_arg (args
, char *); s
!= NULL
; s
= va_arg(args
, char *)){
148 ret
= g_malloc (total
+ 1);
154 va_start (args
, first
);
155 for (s
= va_arg (args
, char *); s
!= NULL
; s
= va_arg(args
, char *)){
164 g_strsplit (const gchar
*string
, const gchar
*delimiter
, gint max_tokens
)
167 gchar
*strtok_save
, **vector
;
168 gchar
*token
, *token_c
;
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;
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
;
197 if(max_tokens
> 0 && size
>= max_tokens
) {
198 if(size
> max_tokens
) {
204 token
= (gchar
*)strtok_r(NULL
, delimiter
, &strtok_save
);
208 if(vector
!= NULL
&& size
> 0) {
209 vector
[size
- 1] = NULL
;
219 g_strreverse (gchar
*str
)
231 for (i
= 0; i
< half
; i
++, len
--) {
240 g_strjoin (const gchar
*separator
, ...)
246 if (separator
!= NULL
)
247 slen
= strlen (separator
);
251 va_start (args
, separator
);
252 for (s
= va_arg (args
, char *); s
!= NULL
; s
= va_arg (args
, char *)){
258 return g_strdup ("");
260 /* Remove the last separator */
261 if (slen
> 0 && len
> 0)
264 res
= g_malloc (len
);
265 va_start (args
, separator
);
266 s
= va_arg (args
, char *);
268 for (s
= va_arg (args
, char *); s
!= NULL
; s
= va_arg (args
, char *)){
269 if (separator
!= NULL
)
270 strcat (res
, separator
);
279 g_strchug (gchar
*str
)
288 while (*tmp
&& isspace (*tmp
)) tmp
++;
290 len
= strlen (str
) - (tmp
- str
- 1);
291 memmove (str
, tmp
, len
);
297 g_strchomp (gchar
*str
)
304 tmp
= str
+ strlen (str
) - 1;
305 while (*tmp
&& isspace (*tmp
)) tmp
--;
311 g_printf(gchar
const *format
, ...)
316 va_start(args
, format
);
317 ret
= vprintf(format
, args
);
324 g_fprintf(FILE *file
, gchar
const *format
, ...)
329 va_start(args
, format
);
330 ret
= vfprintf(file
, format
, args
);
337 g_sprintf(gchar
*string
, gchar
const *format
, ...)
342 va_start(args
, format
);
343 ret
= vsprintf(string
, format
, args
);
350 g_snprintf(gchar
*string
, gulong n
, gchar
const *format
, ...)
355 va_start(args
, format
);
356 ret
= vsnprintf(string
, n
, format
, args
);
362 static const char const hx
[] = { '0', '1', '2', '3', '4', '5', '6', '7',
363 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
366 char_needs_encoding (char c
)
368 if (((unsigned char)c
) >= 0x80)
371 if ((c
>= '@' && c
<= 'Z') ||
372 (c
>= 'a' && c
<= 'z') ||
373 (c
>= '&' && c
< 0x3b) ||
374 (c
== '!') || (c
== '$') || (c
== '_') || (c
== '=') || (c
== '~'))
380 g_filename_to_uri (const gchar
*filename
, const gchar
*hostname
, GError
**error
)
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
!= '/'){
393 *error
= g_error_new (NULL
, 2, "Not an absolute filename");
398 n
= strlen ("file://") + 1;
399 for (p
= filename
; *p
; p
++){
400 if (char_needs_encoding (*p
))
406 strcpy (ret
, "file://");
407 for (p
= filename
, rp
= ret
+ strlen (ret
); *p
; p
++){
408 if (char_needs_encoding (*p
)){
410 *rp
++ = hx
[((unsigned char)(*p
)) >> 4];
411 *rp
++ = hx
[((unsigned char)(*p
)) & 0xf];
422 if (p
>= '0' && p
<= '9')
424 if (p
>= 'A' && p
<= 'F')
426 if (p
>= 'a' && p
<= 'f')
428 g_assert_not_reached ();
433 g_filename_from_uri (const gchar
*uri
, gchar
**hostname
, GError
**error
)
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){
446 *error
= g_error_new (NULL
, 2, "URI does not start with the file: scheme");
450 for (p
= uri
+ 8; *p
; p
++){
452 if (p
[1] && p
[2] && isxdigit (p
[1]) && isxdigit (p
[2])){
456 *error
= g_error_new (NULL
, 2, "URI contains an invalid escape sequence");
464 result
= g_malloc (flen
+ 1);
468 for (p
= uri
+ 8, r
= result
+ 1; *p
; p
++){
470 *r
++ = (decode (p
[1]) << 4) | decode (p
[2]);
480 g_strdown (gchar
*string
)
482 g_return_if_fail (string
!= NULL
);
485 *string
= tolower (*string
);
490 g_ascii_strdown (const gchar
*str
, gssize len
)
495 g_return_val_if_fail (str
!= NULL
, NULL
);
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')
514 g_strdelimit (gchar
*string
, const gchar
*delimiters
, gchar new_delimiter
)
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
;