X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gstrfuncs.c;h=792278abdc05e0c361d787884613c9fab595a7af;hb=07267bf096978a528a02bfa9d12aec2d6f5de541;hp=01816b3593d61a2aac21b6c41ae65ed6236a22a1;hpb=5900267cc7bfe0641709d43eaba28f6b0ff7ab0d;p=platform%2Fupstream%2Fglib.git diff --git a/gstrfuncs.c b/gstrfuncs.c index 01816b3..792278a 100644 --- a/gstrfuncs.c +++ b/gstrfuncs.c @@ -2,21 +2,32 @@ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public + * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. + * Lesser General Public License for more details. * - * You should have received a copy of the GNU Library General Public + * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ +/* + * Modified by the GLib Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GLib Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* + * MT safe + */ + #ifdef HAVE_CONFIG_H #include #endif @@ -27,7 +38,15 @@ #include #include #include /* For tolower() */ +#if !defined (HAVE_STRSIGNAL) || !defined(NO_SYS_SIGLIST_DECL) +#include +#endif #include "glib.h" + +#ifdef G_OS_WIN32 +#include +#endif + /* do not include in this place since it * inteferes with g_strsignal() on some OSes */ @@ -36,7 +55,7 @@ gchar* g_strdup (const gchar *str) { gchar *new_str; - + if (str) { new_str = g_new (char, strlen (str) + 1); @@ -44,7 +63,7 @@ g_strdup (const gchar *str) } else new_str = NULL; - + return new_str; } @@ -137,9 +156,9 @@ g_strconcat (const gchar *string1, ...) va_list args; gchar *s; gchar *concat; - + g_return_val_if_fail (string1 != NULL, NULL); - + l = 1 + strlen (string1); va_start (args, string1); s = va_arg (args, gchar*); @@ -149,10 +168,10 @@ g_strconcat (const gchar *string1, ...) s = va_arg (args, gchar*); } va_end (args); - + concat = g_new (gchar, l); concat[0] = 0; - + strcat (concat, string1); va_start (args, string1); s = va_arg (args, gchar*); @@ -162,7 +181,7 @@ g_strconcat (const gchar *string1, ...) s = va_arg (args, gchar*); } va_end (args); - + return concat; } @@ -174,23 +193,25 @@ g_strtod (const gchar *nptr, gchar *fail_pos_2; gdouble val_1; gdouble val_2 = 0; - + g_return_val_if_fail (nptr != NULL, 0); - + fail_pos_1 = NULL; fail_pos_2 = NULL; - + val_1 = strtod (nptr, &fail_pos_1); - + if (fail_pos_1 && fail_pos_1[0] != 0) { gchar *old_locale; - - old_locale = setlocale (LC_NUMERIC, "C"); + + old_locale = g_strdup (setlocale (LC_NUMERIC, NULL)); + setlocale (LC_NUMERIC, "C"); val_2 = strtod (nptr, &fail_pos_2); setlocale (LC_NUMERIC, old_locale); + g_free (old_locale); } - + if (!fail_pos_1 || fail_pos_1[0] == 0 || fail_pos_1 >= fail_pos_2) { if (endptr) @@ -208,8 +229,9 @@ g_strtod (const gchar *nptr, gchar* g_strerror (gint errnum) { - static char msg[64]; - + static GStaticPrivate msg_private = G_STATIC_PRIVATE_INIT; + char *msg; + #ifdef HAVE_STRERROR return strerror (errnum); #elif NO_SYS_ERRLIST @@ -630,22 +652,36 @@ g_strerror (gint errnum) #else /* NO_SYS_ERRLIST */ extern int sys_nerr; extern char *sys_errlist[]; - + if ((errnum > 0) && (errnum <= sys_nerr)) return sys_errlist [errnum]; #endif /* NO_SYS_ERRLIST */ - + + msg = g_static_private_get (&msg_private); + if (!msg) + { + msg = g_new (gchar, 64); + g_static_private_set (&msg_private, msg, g_free); + } + sprintf (msg, "unknown error (%d)", errnum); + return msg; } gchar* g_strsignal (gint signum) { - static char msg[64]; - + static GStaticPrivate msg_private = G_STATIC_PRIVATE_INIT; + char *msg; + #ifdef HAVE_STRSIGNAL +#ifdef G_OS_BEOS +extern const char * strsignal(int); +#else /* !G_OS_BEOS */ + /* this is declared differently (const) in string.h on BeOS */ extern char *strsignal (int sig); +#endif /* !G_OS_BEOS */ return strsignal (signum); #elif NO_SYS_SIGLIST switch (signum) @@ -745,199 +781,203 @@ g_strsignal (gint signum) #endif } #else /* NO_SYS_SIGLIST */ - extern char *sys_siglist[]; - return sys_siglist [signum]; + +#ifdef NO_SYS_SIGLIST_DECL + extern char *sys_siglist[]; /*(see Tue Jan 19 00:44:24 1999 in changelog)*/ +#endif + + return (char*) /* this function should return const --josh */ sys_siglist [signum]; #endif /* NO_SYS_SIGLIST */ - + + msg = g_static_private_get (&msg_private); + if (!msg) + { + msg = g_new (gchar, 64); + g_static_private_set (&msg_private, msg, g_free); + } + sprintf (msg, "unknown signal (%d)", signum); + return msg; } -guint -g_printf_string_upper_bound (const gchar* format, - va_list args) +/* Functions g_strlcpy and g_strlcat were originally developed by + * Todd C. Miller to simplify writing secure code. + * See ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3 + * for more information. + */ + +#ifdef HAVE_STRLCPY +/* Use the native ones, if available; they might be implemented in assembly */ +gsize +g_strlcpy (gchar *dest, + const gchar *src, + gsize dest_size) { - guint len = 1; + g_return_val_if_fail (dest != NULL, 0); + g_return_val_if_fail (src != NULL, 0); - while (*format) + return strlcpy (dest, src, dest_size); +} + +gsize +g_strlcat (gchar *dest, + const gchar *src, + gsize dest_size) +{ + g_return_val_if_fail (dest != NULL, 0); + g_return_val_if_fail (src != NULL, 0); + + return strlcat (dest, src, dest_size); +} + +#else /* ! HAVE_STRLCPY */ +/* g_strlcpy + * + * Copy string src to buffer dest (of buffer size dest_size). At most + * dest_size-1 characters will be copied. Always NUL terminates + * (unless dest_size == 0). This function does NOT allocate memory. + * Unlike strncpy, this function doesn't pad dest (so it's often faster). + * Returns size of attempted result, strlen(src), + * so if retval >= dest_size, truncation occurred. + */ +gsize +g_strlcpy (gchar *dest, + const gchar *src, + gsize dest_size) +{ + register gchar *d = dest; + register const gchar *s = src; + register gsize n = dest_size; + + g_return_val_if_fail (dest != NULL, 0); + g_return_val_if_fail (src != NULL, 0); + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) + do + { + register gchar c = *s++; + + *d++ = c; + if (c == 0) + break; + } + while (--n != 0); + + /* If not enough room in dest, add NUL and traverse rest of src */ + if (n == 0) + { + if (dest_size != 0) + *d = 0; + while (*s++) + ; + } + + return s - src - 1; /* count does not include NUL */ +} + +/* g_strlcat + * + * Appends string src to buffer dest (of buffer size dest_size). + * At most dest_size-1 characters will be copied. + * Unlike strncat, dest_size is the full size of dest, not the space left over. + * This function does NOT allocate memory. + * This always NUL terminates (unless siz == 0 or there were no NUL characters + * in the dest_size characters of dest to start with). + * Returns size of attempted result, which is + * MIN (dest_size, strlen (original dest)) + strlen (src), + * so if retval >= dest_size, truncation occurred. + */ +gsize +g_strlcat (gchar *dest, + const gchar *src, + gsize dest_size) +{ + register gchar *d = dest; + register const gchar *s = src; + register gsize bytes_left = dest_size; + gsize dlength; /* Logically, MIN (strlen (d), dest_size) */ + + g_return_val_if_fail (dest != NULL, 0); + g_return_val_if_fail (src != NULL, 0); + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (*d != 0 && bytes_left-- != 0) + d++; + dlength = d - dest; + bytes_left = dest_size - dlength; + + if (bytes_left == 0) + return dlength + strlen (s); + + while (*s != 0) { - gboolean long_int = FALSE; - gboolean extra_long = FALSE; - gchar c; - - c = *format++; - - if (c == '%') + if (bytes_left != 1) { - gboolean done = FALSE; - - while (*format && !done) - { - switch (*format++) - { - gchar *string_arg; - - case '*': - len += va_arg (args, int); - break; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - /* add specified format length, since it might exceed the - * size we assume it to have. - */ - format -= 1; - len += strtol (format, (char**) &format, 10); - break; - case 'h': - /* ignore short int flag, since all args have at least the - * same size as an int - */ - break; - case 'l': - if (long_int) - extra_long = TRUE; /* linux specific */ - else - long_int = TRUE; - break; - case 'q': - case 'L': - long_int = TRUE; - extra_long = TRUE; - break; - case 's': - string_arg = va_arg (args, char *); - if (string_arg) - len += strlen (string_arg); - else - { - /* add enough padding to hold "(null)" identifier */ - len += 16; - } - done = TRUE; - break; - case 'd': - case 'i': - case 'o': - case 'u': - case 'x': - case 'X': -#ifdef HAVE_GINT64 - if (extra_long) - (void) va_arg (args, gint64); - else -#endif /* HAVE_GINT64 */ - { - if (long_int) - (void) va_arg (args, long); - else - (void) va_arg (args, int); - } - len += extra_long ? 64 : 32; - done = TRUE; - break; - case 'D': - case 'O': - case 'U': - (void) va_arg (args, long); - len += 32; - done = TRUE; - break; - case 'e': - case 'E': - case 'f': - case 'g': -#ifdef HAVE_LONG_DOUBLE - if (extra_long) - (void) va_arg (args, long double); - else -#endif /* HAVE_LONG_DOUBLE */ - (void) va_arg (args, double); - len += extra_long ? 64 : 32; - done = TRUE; - break; - case 'c': - (void) va_arg (args, int); - len += 1; - done = TRUE; - break; - case 'p': - case 'n': - (void) va_arg (args, void*); - len += 32; - done = TRUE; - break; - case '%': - len += 1; - done = TRUE; - break; - default: - /* ignore unknow/invalid flags */ - break; - } - } + *d++ = *s; + bytes_left--; } - else - len += 1; + s++; } + *d = 0; - return len; + return dlength + (s - src); /* count does not include NUL */ } +#endif /* ! HAVE_STRLCPY */ -void -g_strdown (gchar *string) +gchar* +g_strdown (gchar *string) { - register gchar *s; + register guchar *s; - g_return_if_fail (string != NULL); + g_return_val_if_fail (string != NULL, NULL); - s = string; + s = (guchar *) string; while (*s) { *s = tolower (*s); s++; } + + return (gchar *) string; } -void -g_strup (gchar *string) +gchar* +g_strup (gchar *string) { - register gchar *s; - - g_return_if_fail (string != NULL); - - s = string; - + register guchar *s; + + g_return_val_if_fail (string != NULL, NULL); + + s = (guchar *) string; + while (*s) { *s = toupper (*s); s++; } + + return (gchar *) string; } -void -g_strreverse (gchar *string) +gchar* +g_strreverse (gchar *string) { - g_return_if_fail (string != NULL); - + g_return_val_if_fail (string != NULL, NULL); + if (*string) { register gchar *h, *t; - + h = string; t = string + strlen (string) - 1; - + while (h < t) { register gchar c; - + c = *h; *h = *t; h++; @@ -945,6 +985,8 @@ g_strreverse (gchar *string) t--; } } + + return string; } gint @@ -952,10 +994,13 @@ g_strcasecmp (const gchar *s1, const gchar *s2) { #ifdef HAVE_STRCASECMP + g_return_val_if_fail (s1 != NULL, 0); + g_return_val_if_fail (s2 != NULL, 0); + return strcasecmp (s1, s2); #else gint c1, c2; - + g_return_val_if_fail (s1 != NULL, 0); g_return_val_if_fail (s2 != NULL, 0); @@ -970,23 +1015,56 @@ g_strcasecmp (const gchar *s1, return (c1 - c2); s1++; s2++; } - + return (((gint)(guchar) *s1) - ((gint)(guchar) *s2)); #endif } +gint +g_strncasecmp (const gchar *s1, + const gchar *s2, + guint n) +{ +#ifdef HAVE_STRNCASECMP + return strncasecmp (s1, s2, n); +#else + gint c1, c2; + + g_return_val_if_fail (s1 != NULL, 0); + g_return_val_if_fail (s2 != NULL, 0); + + while (n && *s1 && *s2) + { + n -= 1; + /* According to A. Cox, some platforms have islower's that + * don't work right on non-uppercase + */ + c1 = isupper ((guchar)*s1) ? tolower ((guchar)*s1) : *s1; + c2 = isupper ((guchar)*s2) ? tolower ((guchar)*s2) : *s2; + if (c1 != c2) + return (c1 - c2); + s1++; s2++; + } + + if (n) + return (((gint) (guchar) *s1) - ((gint) (guchar) *s2)); + else + return 0; +#endif +} + gchar* g_strdelimit (gchar *string, const gchar *delimiters, gchar new_delim) { register gchar *c; - + g_return_val_if_fail (string != NULL, NULL); - + if (!delimiters) delimiters = G_STR_DELIMITERS; - + for (c = string; *c; c++) { if (strchr (delimiters, *c)) @@ -997,49 +1075,172 @@ g_strdelimit (gchar *string, } gchar* -g_strescape (gchar *string) +g_strcanon (gchar *string, + const gchar *valid_chars, + gchar subsitutor) { - gchar *q; - gchar *escaped; - guint backslashes = 0; - gchar *p = string; + register gchar *c; g_return_val_if_fail (string != NULL, NULL); + g_return_val_if_fail (valid_chars != NULL, NULL); - while (*p != '\000') - backslashes += (*p++ == '\\'); + for (c = string; *c; c++) + { + if (!strchr (valid_chars, *c)) + *c = subsitutor; + } + + return string; +} - if (!backslashes) - return g_strdup (string); +gchar* +g_strcompress (const gchar *source) +{ + const gchar *p = source, *octal; + gchar *dest = g_malloc (strlen (source) + 1); + gchar *q = dest; + + while (*p) + { + if (*p == '\\') + { + p++; + switch (*p) + { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': + *q = 0; + octal = p; + while ((p < octal + 3) && (*p >= '0') && (*p <= '7')) + { + *q = (*q * 8) + (*p - '0'); + p++; + } + q++; + p--; + break; + case 'b': + *q++ = '\b'; + break; + case 'f': + *q++ = '\f'; + break; + case 'n': + *q++ = '\n'; + break; + case 'r': + *q++ = '\r'; + break; + case 't': + *q++ = '\t'; + break; + default: /* Also handles \" and \\ */ + *q++ = *p; + break; + } + } + else + *q++ = *p; + p++; + } + *q = 0; + + return dest; +} - escaped = g_new (gchar, strlen (string) + backslashes + 1); +gchar * +g_strescape (const gchar *source, + const gchar *exceptions) +{ + const guchar *p; + gchar *dest; + gchar *q; + guchar excmap[256]; + + g_return_val_if_fail (source != NULL, NULL); - p = string; - q = escaped; + p = (guchar *) source; + /* Each source byte needs maximally four destination chars (\777) */ + q = dest = g_malloc (strlen (source) * 4 + 1); - while (*p != '\000') + memset (excmap, 0, 256); + if (exceptions) { - if (*p == '\\') - *q++ = '\\'; - *q++ = *p++; + guchar *e = (guchar *) exceptions; + + while (*e) + { + excmap[*e] = 1; + e++; + } } - *q = '\000'; - return escaped; + while (*p) + { + if (excmap[*p]) + *q++ = *p; + else + { + switch (*p) + { + case '\b': + *q++ = '\\'; + *q++ = 'b'; + break; + case '\f': + *q++ = '\\'; + *q++ = 'f'; + break; + case '\n': + *q++ = '\\'; + *q++ = 'n'; + break; + case '\r': + *q++ = '\\'; + *q++ = 'r'; + break; + case '\t': + *q++ = '\\'; + *q++ = 't'; + break; + case '\\': + *q++ = '\\'; + *q++ = '\\'; + break; + case '"': + *q++ = '\\'; + *q++ = '"'; + break; + default: + if ((*p < ' ') || (*p >= 0177)) + { + *q++ = '\\'; + *q++ = '0' + (((*p) >> 6) & 07); + *q++ = '0' + (((*p) >> 3) & 07); + *q++ = '0' + ((*p) & 07); + } + else + *q++ = *p; + break; + } + } + p++; + } + *q = 0; + return dest; } -/* blame Elliot for these next five routines */ gchar* g_strchug (gchar *string) { - gchar *start; + guchar *start; g_return_val_if_fail (string != NULL, NULL); - for (start = string; *start && isspace (*start); start++) + for (start = (guchar*) string; *start && isspace (*start); start++) ; - strcpy (string, start); + g_memmove (string, start, strlen ((gchar *) start) + 1); return string; } @@ -1054,7 +1255,8 @@ g_strchomp (gchar *string) if (!*string) return string; - for (s = string + strlen (string) - 1; s >= string && isspace (*s); s--) + for (s = string + strlen (string) - 1; s >= string && isspace ((guchar)*s); + s--) *s = '\0'; return string; @@ -1067,7 +1269,7 @@ g_strsplit (const gchar *string, { GSList *string_list = NULL, *slist; gchar **str_array, *s; - guint i, n = 1; + guint n = 1; g_return_val_if_fail (string != NULL, NULL); g_return_val_if_fail (delimiter != NULL, NULL); @@ -1079,12 +1281,12 @@ g_strsplit (const gchar *string, if (s) { guint delimiter_len = strlen (delimiter); - + do { guint len; gchar *new_string; - + len = s - string; new_string = g_new (gchar, len + 1); strncpy (new_string, string, len); @@ -1096,19 +1298,13 @@ g_strsplit (const gchar *string, } while (--max_tokens && s); } - if (*string) - { - n++; - string_list = g_slist_prepend (string_list, g_strdup (string)); - } - - str_array = g_new (gchar*, n); + string_list = g_slist_prepend (string_list, g_strdup (string)); - i = n - 1; + str_array = g_new (gchar*, n + 1); - str_array[i--] = NULL; + str_array[n--] = NULL; for (slist = string_list; slist; slist = slist->next) - str_array[i--] = slist->data; + str_array[n--] = slist->data; g_slist_free (string_list); @@ -1129,15 +1325,54 @@ g_strfreev (gchar **str_array) } } +/** + * g_strdupv: + * @str_array: %NULL-terminated array of strings + * + * Copies %NULL-terminated array of strings. The copy is a deep copy; + * the new array should be freed by first freeing each string, then + * the array itself. g_strfreev() does this for you. If called + * on a %NULL value, g_strdupv() simply returns %NULL. + * + * Return value: a new %NULL-terminated array of strings + **/ +gchar** +g_strdupv (gchar **str_array) +{ + if (str_array) + { + gint i; + gchar **retval; + + i = 0; + while (str_array[i]) + ++i; + + retval = g_new (gchar*, i + 1); + + i = 0; + while (str_array[i]) + { + retval[i] = g_strdup (str_array[i]); + ++i; + } + retval[i] = NULL; + + return retval; + } + else + return NULL; +} + gchar* g_strjoinv (const gchar *separator, gchar **str_array) { gchar *string; - + g_return_val_if_fail (str_array != NULL, NULL); - if(separator == NULL) + if (separator == NULL) separator = ""; if (*str_array) @@ -1149,7 +1384,7 @@ g_strjoinv (const gchar *separator, len = 1 + strlen (str_array[0]); for(i = 1; str_array[i] != NULL; i++) len += separator_len + strlen(str_array[i]); - + string = g_new (gchar, len); *string = 0; strcat (string, *str_array); @@ -1174,42 +1409,47 @@ g_strjoin (const gchar *separator, guint len; guint separator_len; - if(separator == NULL) + if (separator == NULL) separator = ""; separator_len = strlen (separator); - va_start(args, separator); + va_start (args, separator); - s = va_arg(args, gchar *); - - if(s) { - len = strlen(s) + 1; + s = va_arg (args, gchar*); - while((s = va_arg(args, gchar*))) - { - len += separator_len + strlen(s); - } - va_end(args); + if (s) + { + len = strlen (s); - string = g_new (gchar, len); + s = va_arg (args, gchar*); + while (s) + { + len += separator_len + strlen (s); + s = va_arg (args, gchar*); + } + va_end (args); - va_start(args, separator); + string = g_new (gchar, len + 1); + *string = 0; - *string = 0; - s = va_arg(args, gchar*); - strcat (string, s); + va_start (args, separator); - while((s = va_arg(args, gchar*))) - { - strcat(string, separator); - strcat(string, s); - } + s = va_arg (args, gchar*); + strcat (string, s); - } else - string = g_strdup(""); + s = va_arg (args, gchar*); + while (s) + { + strcat (string, separator); + strcat (string, s); + s = va_arg (args, gchar*); + } + } + else + string = g_strdup (""); - va_end(args); + va_end (args); return string; }