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 = malloc(n);
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 g_strsplit (const gchar *string, const gchar *delimiter, gint max_tokens)
178 gchar *strtok_save, **vector;
179 gchar *token, *token_c;
183 g_return_val_if_fail(string != NULL, NULL);
184 g_return_val_if_fail(delimiter != NULL, NULL);
185 g_return_val_if_fail(delimiter[0] != 0, NULL);
187 token_length = strlen(string);
188 string_c = (gchar *)g_malloc(token_length + 1);
189 memcpy(string_c, string, token_length);
190 string_c[token_length] = 0;
192 if (strncmp (string_c, delimiter, strlen (delimiter)) == 0){
193 vector = (gchar **) g_malloc (2 * sizeof (vector));
194 vector [0] = g_strdup ("");
198 token = (gchar *)strtok_r(string_c, delimiter, &strtok_save);
200 if (!(max_tokens > 0 && size >= max_tokens)){
201 while(token != NULL) {
202 token_length = strlen(token);
203 token_c = (gchar *)g_malloc(token_length + 1);
204 memcpy(token_c, token, token_length);
205 token_c[token_length] = 0;
207 vector = vector == NULL ?
208 (gchar **)g_malloc(2 * sizeof(vector)) :
209 (gchar **)g_realloc(vector, (size + 1) * sizeof(vector));
211 vector[size - 1] = token_c;
214 if(max_tokens > 0 && size >= max_tokens) {
215 if(size > max_tokens) {
219 token = *strtok_save ? strtok_save : NULL;
221 token = (gchar *)strtok_r(NULL, delimiter, &strtok_save);
227 vector = (gchar **) g_malloc (2 * sizeof (vector));
229 } else if (size > 0){
230 vector[size - 1] = NULL;
240 g_strreverse (gchar *str)
252 for (i = 0; i < half; i++, len--) {
261 g_strjoin (const gchar *separator, ...)
267 if (separator != NULL)
268 slen = strlen (separator);
272 va_start (args, separator);
273 for (s = va_arg (args, char *); s != NULL; s = va_arg (args, char *)){
279 return g_strdup ("");
281 /* Remove the last separator */
282 if (slen > 0 && len > 0)
285 res = g_malloc (len);
286 va_start (args, separator);
287 s = va_arg (args, char *);
289 for (s = va_arg (args, char *); s != NULL; s = va_arg (args, char *)){
290 if (separator != NULL)
291 strcat (res, separator);
300 g_strjoinv (const gchar *separator, gchar **str_array)
305 if (separator != NULL)
306 slen = strlen (separator);
311 for (i = 0; str_array [i] != NULL; i++){
312 len += strlen (str_array [i]);
316 return g_strdup ("");
317 if (slen > 0 && len > 0)
320 res = g_malloc (len);
321 strcpy (res, str_array [0]);
322 for (i = 1; str_array [i] != NULL; i++){
323 if (separator != NULL)
324 strcat (res, separator);
325 strcat (res, str_array [i]);
331 g_strchug (gchar *str)
340 while (*tmp && isspace (*tmp)) tmp++;
342 len = strlen (str) - (tmp - str - 1);
343 memmove (str, tmp, len);
349 g_strchomp (gchar *str)
356 tmp = str + strlen (str) - 1;
357 while (*tmp && isspace (*tmp)) tmp--;
363 g_printf(gchar const *format, ...)
368 va_start(args, format);
369 ret = vprintf(format, args);
376 g_fprintf(FILE *file, gchar const *format, ...)
381 va_start(args, format);
382 ret = vfprintf(file, format, args);
389 g_sprintf(gchar *string, gchar const *format, ...)
394 va_start(args, format);
395 ret = vsprintf(string, format, args);
402 g_snprintf(gchar *string, gulong n, gchar const *format, ...)
407 va_start(args, format);
408 ret = vsnprintf(string, n, format, args);
414 static const char hx [] = { '0', '1', '2', '3', '4', '5', '6', '7',
415 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
418 char_needs_encoding (char c)
420 if (((unsigned char)c) >= 0x80)
423 if ((c >= '@' && c <= 'Z') ||
424 (c >= 'a' && c <= 'z') ||
425 (c >= '&' && c < 0x3b) ||
426 (c == '!') || (c == '$') || (c == '_') || (c == '=') || (c == '~'))
432 g_filename_to_uri (const gchar *filename, const gchar *hostname, GError **error)
438 g_return_val_if_fail (filename != NULL, NULL);
440 if (hostname != NULL)
441 g_warning ("%s", "eglib: g_filename_to_uri: hostname not handled");
443 if (*filename != '/'){
445 *error = g_error_new (NULL, 2, "Not an absolute filename");
450 n = strlen ("file://") + 1;
451 for (p = filename; *p; p++){
452 if (char_needs_encoding (*p))
458 strcpy (ret, "file://");
459 for (p = filename, rp = ret + strlen (ret); *p; p++){
460 if (char_needs_encoding (*p)){
462 *rp++ = hx [((unsigned char)(*p)) >> 4];
463 *rp++ = hx [((unsigned char)(*p)) & 0xf];
474 if (p >= '0' && p <= '9')
476 if (p >= 'A' && p <= 'F')
478 if (p >= 'a' && p <= 'f')
480 g_assert_not_reached ();
485 g_filename_from_uri (const gchar *uri, gchar **hostname, GError **error)
491 g_return_val_if_fail (uri != NULL, NULL);
493 if (hostname != NULL)
494 g_warning ("%s", "eglib: g_filename_from_uri: hostname not handled");
496 if (strncmp (uri, "file:///", 8) != 0){
498 *error = g_error_new (NULL, 2, "URI does not start with the file: scheme");
502 for (p = uri + 8; *p; p++){
504 if (p [1] && p [2] && isxdigit (p [1]) && isxdigit (p [2])){
508 *error = g_error_new (NULL, 2, "URI contains an invalid escape sequence");
516 result = g_malloc (flen + 1);
520 for (p = uri + 8, r = result + 1; *p; p++){
522 *r++ = (char)((decode (p [1]) << 4) | decode (p [2]));
532 g_strdown (gchar *string)
534 g_return_if_fail (string != NULL);
537 *string = (gchar)tolower (*string);
543 g_ascii_strdown (const gchar *str, gssize len)
548 g_return_val_if_fail (str != NULL, NULL);
553 ret = g_malloc (len + 1);
554 for (i = 0; i < len; i++){
555 guchar c = (guchar) str [i];
556 if (c >= 'A' && c <= 'Z')
566 g_ascii_strncasecmp (const gchar *s1, const gchar *s2, gsize n)
570 g_return_val_if_fail (s1 != NULL, 0);
571 g_return_val_if_fail (s2 != NULL, 0);
573 for (i = 0; i < n; i++){
590 g_strdelimit (gchar *string, const gchar *delimiters, gchar new_delimiter)
594 g_return_val_if_fail (string != NULL, NULL);
596 if (delimiters == NULL)
597 delimiters = G_STR_DELIMITERS;
599 for (ptr = string; *ptr; ptr++) {
600 if (strchr (delimiters, *ptr))
601 *ptr = new_delimiter;
608 g_strlcpy (gchar *dest, const gchar *src, gsize dest_size)
611 return strlcpy (dest, src, dest_size);
618 g_return_val_if_fail (src != NULL, 0);
619 g_return_val_if_fail (dest != NULL, 0);
631 return (dest_size - len - 1);
634 /* len is 0 i we get here */
636 /* we need to return the length of src here */
637 while (*s++) ; /* instead of a plain strlen, we use 's' */
642 static const gchar escaped_dflt [256] = {
643 1, 1, 1, 1, 1, 1, 1, 1, 'b', 't', 'n', 1, 'f', 'r', 1, 1,
644 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
645 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
646 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
647 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
648 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\', 0, 0, 0,
649 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
650 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
651 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
652 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
653 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
654 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
655 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
656 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
657 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
658 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
662 g_strescape (const gchar *source, const gchar *exceptions)
671 g_return_val_if_fail (source != NULL, NULL);
673 memcpy (escaped, escaped_dflt, 256);
674 if (exceptions != NULL) {
675 for (ptr = exceptions; *ptr; ptr++)
676 escaped [(int) *ptr] = 0;
678 result = g_malloc (strlen (source) * 4 + 1); /* Worst case: everything octal. */
680 for (ptr = source; *ptr; ptr++) {
682 op = escaped [(int) c];
690 *res_ptr++ = '0' + ((c >> 6) & 3);
691 *res_ptr++ = '0' + ((c >> 3) & 7);
692 *res_ptr++ = '0' + (c & 7);
701 g_strdup (const gchar *str)
710 g_ascii_xdigit_value (gchar c)
712 return ((isxdigit (c) == 0) ? -1 :
713 ((c >= '0' && c <= '9') ? (c - '0') :
714 ((c >= 'a' && c <= 'f') ? (c - 'a' + 10) :