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]);