X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=eglib%2Fsrc%2Fgstr.c;h=305f9480e26867fb19f6bcbcef8b34cb25e15df9;hb=8ef4e4703172fd32ada3f74b22df5203b4683493;hp=2ac93f6059a4383fe76cf76c5c8ebebce122f10b;hpb=098d73cf256d8298fca6a3e14d09dd688b798028;p=mono.git diff --git a/eglib/src/gstr.c b/eglib/src/gstr.c index 2ac93f6059a..305f9480e26 100644 --- a/eglib/src/gstr.c +++ b/eglib/src/gstr.c @@ -26,7 +26,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#define _GNU_SOURCE +#include #include #include #include @@ -36,7 +36,18 @@ gchar * g_strndup (const gchar *str, gsize n) { +#ifdef HAVE_STRNDUP return strndup (str, n); +#else + if (str) { + char *retval = g_malloc(n+1); + if (retval) { + strncpy(retval, str, n)[n] = 0; + } + return retval; + } + return NULL; +#endif } void @@ -64,8 +75,8 @@ g_strv_length(gchar **str_array) gboolean g_str_has_suffix(const gchar *str, const gchar *suffix) { - gint str_length; - gint suffix_length; + size_t str_length; + size_t suffix_length; g_return_val_if_fail(str != NULL, FALSE); g_return_val_if_fail(suffix != NULL, FALSE); @@ -81,8 +92,8 @@ g_str_has_suffix(const gchar *str, const gchar *suffix) gboolean g_str_has_prefix(const gchar *str, const gchar *prefix) { - gint str_length; - gint prefix_length; + size_t str_length; + size_t prefix_length; g_return_val_if_fail(str != NULL, FALSE); g_return_val_if_fail(prefix != NULL, FALSE); @@ -133,10 +144,10 @@ g_strerror (gint errnum) gchar * g_strconcat (const gchar *first, ...) { - g_return_val_if_fail (first != NULL, NULL); va_list args; - int total = 0; + size_t total = 0; char *s, *ret; + g_return_val_if_fail (first != NULL, NULL); total += strlen (first); va_start (args, first); @@ -160,66 +171,169 @@ g_strconcat (const gchar *first, ...) return ret; } +static void +add_to_vector (gchar ***vector, int size, gchar *token) +{ + *vector = *vector == NULL ? + (gchar **)g_malloc(2 * sizeof(*vector)) : + (gchar **)g_realloc(*vector, (size + 1) * sizeof(*vector)); + + (*vector)[size - 1] = token; +} + gchar ** g_strsplit (const gchar *string, const gchar *delimiter, gint max_tokens) { - gchar *string_c; - gchar *strtok_save, **vector; - gchar *token, *token_c; + const gchar *c; + gchar *token, **vector; gint size = 1; - gint token_length; + + g_return_val_if_fail (string != NULL, NULL); + g_return_val_if_fail (delimiter != NULL, NULL); + g_return_val_if_fail (delimiter[0] != 0, NULL); + + if (strncmp (string, delimiter, strlen (delimiter)) == 0) { + vector = (gchar **)g_malloc (2 * sizeof(vector)); + vector[0] = g_strdup (""); + size++; + string += strlen (delimiter); + } else { + vector = NULL; + } + + while (*string && !(max_tokens > 0 && size >= max_tokens)) { + c = string; + if (strncmp (string, delimiter, strlen (delimiter)) == 0) { + token = g_strdup (""); + string += strlen (delimiter); + } else { + while (*string && strncmp (string, delimiter, strlen (delimiter)) != 0) { + string++; + } + + if (*string) { + gsize toklen = (string - c); + token = g_strndup (c, toklen); + + /* Need to leave a trailing empty + * token if the delimiter is the last + * part of the string + */ + if (strcmp (string, delimiter) != 0) { + string += strlen (delimiter); + } + } else { + token = g_strdup (c); + } + } + + add_to_vector (&vector, size, token); + size++; + } - g_return_val_if_fail(string != NULL, NULL); - g_return_val_if_fail(delimiter != NULL, NULL); - g_return_val_if_fail(delimiter[0] != 0, NULL); + if (*string) { + /* Add the rest of the string as the last element */ + add_to_vector (&vector, size, g_strdup (string)); + size++; + } + + if (vector == NULL) { + vector = (gchar **) g_malloc (2 * sizeof (vector)); + vector [0] = NULL; + } else if (size > 0) { + vector[size - 1] = NULL; + } + + return vector; +} + +static gboolean +charcmp (gchar testchar, const gchar *compare) +{ + while(*compare) { + if (*compare == testchar) { + return TRUE; + } + compare++; + } - token_length = strlen(string); - string_c = (gchar *)g_malloc(token_length + 1); - memcpy(string_c, string, token_length); - string_c[token_length] = 0; + return FALSE; +} + +gchar ** +g_strsplit_set (const gchar *string, const gchar *delimiter, gint max_tokens) +{ + const gchar *c; + gchar *token, **vector; + gint size = 1; - vector = NULL; - token = (gchar *)strtok_r(string_c, delimiter, &strtok_save); - - while(token != NULL) { - token_length = strlen(token); - token_c = (gchar *)g_malloc(token_length + 1); - memcpy(token_c, token, token_length); - token_c[token_length] = 0; - - vector = vector == NULL ? - (gchar **)g_malloc(2 * sizeof(vector)) : - (gchar **)g_realloc(vector, (size + 1) * sizeof(vector)); + g_return_val_if_fail (string != NULL, NULL); + g_return_val_if_fail (delimiter != NULL, NULL); + g_return_val_if_fail (delimiter[0] != 0, NULL); - vector[size - 1] = token_c; + if (charcmp (*string, delimiter)) { + vector = (gchar **)g_malloc (2 * sizeof(vector)); + vector[0] = g_strdup (""); size++; + string++; + } else { + vector = NULL; + } - if(max_tokens > 0 && size >= max_tokens) { - if(size > max_tokens) { - break; + c = string; + while (*string && !(max_tokens > 0 && size >= max_tokens)) { + if (charcmp (*string, delimiter)) { + gsize toklen = (string - c); + if (toklen == 0) { + token = g_strdup (""); + } else { + token = g_strndup (c, toklen); } + + c = string + 1; + + add_to_vector (&vector, size, token); + size++; + } - token = strtok_save; + string++; + } + + if (max_tokens > 0 && size >= max_tokens) { + if (*string) { + /* Add the rest of the string as the last element */ + add_to_vector (&vector, size, g_strdup (string)); + size++; + } + } else { + if (*c) { + /* Fill in the trailing last token */ + add_to_vector (&vector, size, g_strdup (c)); + size++; } else { - token = (gchar *)strtok_r(NULL, delimiter, &strtok_save); + /* Need to leave a trailing empty token if the + * delimiter is the last part of the string + */ + add_to_vector (&vector, size, g_strdup ("")); + size++; } } - - if(vector != NULL && size > 0) { + + if (vector == NULL) { + vector = (gchar **) g_malloc (2 * sizeof (vector)); + vector [0] = NULL; + } else if (size > 0) { vector[size - 1] = NULL; } - g_free(string_c); - string_c = NULL; - return vector; } gchar * g_strreverse (gchar *str) { - guint len, half; - gint i; + size_t len, half; + size_t i; gchar c; if (str == NULL) @@ -241,7 +355,7 @@ g_strjoin (const gchar *separator, ...) { va_list args; char *res, *s; - int len, slen; + size_t len, slen; if (separator != NULL) slen = strlen (separator); @@ -275,10 +389,41 @@ g_strjoin (const gchar *separator, ...) return res; } +gchar * +g_strjoinv (const gchar *separator, gchar **str_array) +{ + char *res; + size_t slen, len, i; + + if (separator != NULL) + slen = strlen (separator); + else + slen = 0; + + len = 0; + for (i = 0; str_array [i] != NULL; i++){ + len += strlen (str_array [i]); + len += slen; + } + if (len == 0) + return g_strdup (""); + if (slen > 0 && len > 0) + len -= slen; + len++; + res = g_malloc (len); + strcpy (res, str_array [0]); + for (i = 1; str_array [i] != NULL; i++){ + if (separator != NULL) + strcat (res, separator); + strcat (res, str_array [i]); + } + return res; +} + gchar * g_strchug (gchar *str) { - gint len; + size_t len; gchar *tmp; if (str == NULL) @@ -359,7 +504,7 @@ g_snprintf(gchar *string, gulong n, gchar const *format, ...) return ret; } -static const char const hx [] = { '0', '1', '2', '3', '4', '5', '6', '7', +static const char hx [] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; static gboolean @@ -371,7 +516,7 @@ char_needs_encoding (char c) if ((c >= '@' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '&' && c < 0x3b) || - (c == '!') || (c == '$') || (c == '_') || c == '=') + (c == '!') || (c == '$') || (c == '_') || (c == '=') || (c == '~')) return FALSE; return TRUE; } @@ -379,32 +524,49 @@ char_needs_encoding (char c) gchar * g_filename_to_uri (const gchar *filename, const gchar *hostname, GError **error) { - int n; + size_t n; char *ret, *rp; const char *p; +#ifdef G_OS_WIN32 + const char *uriPrefix = "file:///"; +#else + const char *uriPrefix = "file://"; +#endif g_return_val_if_fail (filename != NULL, NULL); if (hostname != NULL) - g_warning ("g_filename_to_uri: hostname and error not handled"); + g_warning ("%s", "eglib: g_filename_to_uri: hostname not handled"); - if (*filename != '/'){ + if (!g_path_is_absolute (filename)){ if (error != NULL) *error = g_error_new (NULL, 2, "Not an absolute filename"); return NULL; } - n = strlen ("file://") + 1; + n = strlen (uriPrefix) + 1; for (p = filename; *p; p++){ +#ifdef G_OS_WIN32 + if (*p == '\\') { + n++; + continue; + } +#endif if (char_needs_encoding (*p)) n += 3; else n++; } ret = g_malloc (n); - strcpy (ret, "file://"); + strcpy (ret, uriPrefix); for (p = filename, rp = ret + strlen (ret); *p; p++){ +#ifdef G_OS_WIN32 + if (*p == '\\') { + *rp++ = '/'; + continue; + } +#endif if (char_needs_encoding (*p)){ *rp++ = '%'; *rp++ = hx [((unsigned char)(*p)) >> 4]; @@ -415,3 +577,261 @@ g_filename_to_uri (const gchar *filename, const gchar *hostname, GError **error) *rp = 0; return ret; } + +static int +decode (char p) +{ + if (p >= '0' && p <= '9') + return p - '0'; + if (p >= 'A' && p <= 'F') + return p - 'A'; + if (p >= 'a' && p <= 'f') + return p - 'a'; + g_assert_not_reached (); + return 0; +} + +gchar * +g_filename_from_uri (const gchar *uri, gchar **hostname, GError **error) +{ + const char *p; + char *r, *result; + int flen = 0; + + g_return_val_if_fail (uri != NULL, NULL); + + if (hostname != NULL) + g_warning ("%s", "eglib: g_filename_from_uri: hostname not handled"); + + if (strncmp (uri, "file:///", 8) != 0){ + if (error != NULL) + *error = g_error_new (NULL, 2, "URI does not start with the file: scheme"); + return NULL; + } + + for (p = uri + 8; *p; p++){ + if (*p == '%'){ + if (p [1] && p [2] && isxdigit (p [1]) && isxdigit (p [2])){ + p += 2; + } else { + if (error != NULL) + *error = g_error_new (NULL, 2, "URI contains an invalid escape sequence"); + return NULL; + } + } + flen++; + } +#ifndef G_OS_WIN32 + flen++; +#endif + + result = g_malloc (flen + 1); + result [flen] = 0; + +#ifndef G_OS_WIN32 + *result = '/'; + r = result + 1; +#else + r = result; +#endif + + for (p = uri + 8; *p; p++){ + if (*p == '%'){ + *r++ = (char)((decode (p [1]) << 4) | decode (p [2])); + p += 2; + } else + *r++ = *p; + flen++; + } + return result; +} + +void +g_strdown (gchar *string) +{ + g_return_if_fail (string != NULL); + + while (*string){ + *string = (gchar)tolower (*string); + string++; + } +} + +gchar +g_ascii_tolower (gchar c) +{ + return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c; +} + +gchar * +g_ascii_strdown (const gchar *str, gssize len) +{ + char *ret; + int i; + + g_return_val_if_fail (str != NULL, NULL); + + if (len == -1) + len = strlen (str); + + ret = g_malloc (len + 1); + for (i = 0; i < len; i++) + ret [i] = (guchar) g_ascii_tolower (str [i]); + ret [i] = 0; + + return ret; +} + +gint +g_ascii_strncasecmp (const gchar *s1, const gchar *s2, gsize n) +{ + gsize i; + + g_return_val_if_fail (s1 != NULL, 0); + g_return_val_if_fail (s2 != NULL, 0); + + for (i = 0; i < n; i++){ + gchar c1 = g_ascii_tolower (*s1++); + gchar c2 = g_ascii_tolower (*s2++); + + if (c1 == c2) + continue; + + if (c1 == 0) + return -1; + if (c2 == 0) + return 1; + return c1-c2; + } + return 0; +} + +gchar * +g_strdelimit (gchar *string, const gchar *delimiters, gchar new_delimiter) +{ + gchar *ptr; + + g_return_val_if_fail (string != NULL, NULL); + + if (delimiters == NULL) + delimiters = G_STR_DELIMITERS; + + for (ptr = string; *ptr; ptr++) { + if (strchr (delimiters, *ptr)) + *ptr = new_delimiter; + } + + return string; +} + +gsize +g_strlcpy (gchar *dest, const gchar *src, gsize dest_size) +{ +#ifdef HAVE_STRLCPY + return strlcpy (dest, src, dest_size); +#else + gchar *d; + const gchar *s; + gchar c; + gsize len; + + g_return_val_if_fail (src != NULL, 0); + g_return_val_if_fail (dest != NULL, 0); + + len = dest_size; + if (len == 0) + return 0; + + s = src; + d = dest; + while (--len) { + c = *s++; + *d++ = c; + if (c == '\0') + return (dest_size - len - 1); + } + + /* len is 0 i we get here */ + *d = '\0'; + /* we need to return the length of src here */ + while (*s++) ; /* instead of a plain strlen, we use 's' */ + return s - src - 1; +#endif +} + +static const gchar escaped_dflt [256] = { + 1, 1, 1, 1, 1, 1, 1, 1, 'b', 't', 'n', 1, 'f', 'r', 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\', 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +gchar * +g_strescape (const gchar *source, const gchar *exceptions) +{ + gchar escaped [256]; + const gchar *ptr; + gchar c; + gchar op; + gchar *result; + gchar *res_ptr; + + g_return_val_if_fail (source != NULL, NULL); + + memcpy (escaped, escaped_dflt, 256); + if (exceptions != NULL) { + for (ptr = exceptions; *ptr; ptr++) + escaped [(int) *ptr] = 0; + } + result = g_malloc (strlen (source) * 4 + 1); /* Worst case: everything octal. */ + res_ptr = result; + for (ptr = source; *ptr; ptr++) { + c = *ptr; + op = escaped [(int) c]; + if (op == 0) { + *res_ptr++ = c; + } else { + *res_ptr++ = '\\'; + if (op != 1) { + *res_ptr++ = op; + } else { + *res_ptr++ = '0' + ((c >> 6) & 3); + *res_ptr++ = '0' + ((c >> 3) & 7); + *res_ptr++ = '0' + (c & 7); + } + } + } + *res_ptr = '\0'; + return result; +} + +gint +g_ascii_xdigit_value (gchar c) +{ + return ((isxdigit (c) == 0) ? -1 : + ((c >= '0' && c <= '9') ? (c - '0') : + ((c >= 'a' && c <= 'f') ? (c - 'a' + 10) : + (c - 'A' + 10)))); +} + +gchar * +g_strnfill (gsize length, gchar fill_char) +{ + gchar *ret = g_new (gchar, length + 1); + + memset (ret, fill_char, length); + ret [length] = 0; + return ret; +}