diff options
Diffstat (limited to 'src/glib-utils.c')
-rw-r--r-- | src/glib-utils.c | 645 |
1 files changed, 645 insertions, 0 deletions
diff --git a/src/glib-utils.c b/src/glib-utils.c new file mode 100644 index 0000000..7935f13 --- /dev/null +++ b/src/glib-utils.c @@ -0,0 +1,645 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/* + * File-Roller + * + * Copyright (C) 2005 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + */ + +#include <string.h> +#include <stdio.h> +#include <glib.h> +#include <glib/gi18n.h> +#include <glib/gprintf.h> +#include "glib-utils.h" + + +#define MAX_PATTERNS 128 + + +gboolean +strchrs (const char *str, + const char *chars) +{ + const char *c; + for (c = chars; *c != '\0'; c++) + if (strchr (str, *c) != NULL) + return TRUE; + return FALSE; +} + + +char * +str_substitute (const char *str, + const char *from_str, + const char *to_str) +{ + char **tokens; + int i; + GString *gstr; + + if (str == NULL) + return NULL; + + if (from_str == NULL) + return g_strdup (str); + + if (strcmp (str, from_str) == 0) + return g_strdup (to_str); + + tokens = g_strsplit (str, from_str, -1); + + gstr = g_string_new (NULL); + for (i = 0; tokens[i] != NULL; i++) { + gstr = g_string_append (gstr, tokens[i]); + if ((to_str != NULL) && (tokens[i+1] != NULL)) + gstr = g_string_append (gstr, to_str); + } + + return g_string_free (gstr, FALSE); +} + + +int +strcmp_null_tolerant (const char *s1, const char *s2) +{ + if ((s1 == NULL) && (s2 == NULL)) + return 0; + else if ((s1 != NULL) && (s2 == NULL)) + return 1; + else if ((s1 == NULL) && (s2 != NULL)) + return -1; + else + return strcmp (s1, s2); +} + + +/* counts how many characters to escape in @str. */ +static int +count_chars_to_escape (const char *str, + const char *meta_chars) +{ + int meta_chars_n = strlen (meta_chars); + const char *s; + int n = 0; + + for (s = str; *s != 0; s++) { + int i; + for (i = 0; i < meta_chars_n; i++) + if (*s == meta_chars[i]) { + n++; + break; + } + } + return n; +} + + +char* +escape_str_common (const char *str, + const char *meta_chars, + const char prefix, + const char postfix) +{ + int meta_chars_n = strlen (meta_chars); + char *escaped; + int i, new_l, extra_chars = 0; + const char *s; + char *t; + + if (str == NULL) + return NULL; + + if (prefix) + extra_chars++; + if (postfix) + extra_chars++; + + new_l = strlen (str) + (count_chars_to_escape (str, meta_chars) * extra_chars); + escaped = g_malloc (new_l + 1); + + s = str; + t = escaped; + while (*s) { + gboolean is_bad = FALSE; + for (i = 0; (i < meta_chars_n) && !is_bad; i++) + is_bad = (*s == meta_chars[i]); + if (is_bad && prefix) + *t++ = prefix; + *t++ = *s++; + if (is_bad && postfix) + *t++ = postfix; + } + *t = 0; + + return escaped; +} + + +/* escape with backslash the string @str. */ +char* +escape_str (const char *str, + const char *meta_chars) +{ + return escape_str_common (str, meta_chars, '\\', 0); +} + + +/* escape with backslash the file name. */ +char* +shell_escape (const char *filename) +{ + return escape_str (filename, "$'`\"\\!?* ()[]&|:;<>#"); +} + + +static const char * +g_utf8_strstr (const char *haystack, const char *needle) +{ + const char *s; + gsize i; + gsize haystack_len = g_utf8_strlen (haystack, -1); + gsize needle_len = g_utf8_strlen (needle, -1); + int needle_size = strlen (needle); + + s = haystack; + for (i = 0; i <= haystack_len - needle_len; i++) { + if (strncmp (s, needle, needle_size) == 0) + return s; + s = g_utf8_next_char(s); + } + + return NULL; +} + + +static char** +g_utf8_strsplit (const char *string, + const char *delimiter, + int max_tokens) +{ + GSList *string_list = NULL, *slist; + char **str_array; + const char *s; + guint n = 0; + const char *remainder; + + 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 (max_tokens < 1) + max_tokens = G_MAXINT; + + remainder = string; + s = g_utf8_strstr (remainder, delimiter); + if (s != NULL) { + gsize delimiter_size = strlen (delimiter); + + while (--max_tokens && (s != NULL)) { + gsize size = s - remainder; + char *new_string; + + new_string = g_new (char, size + 1); + strncpy (new_string, remainder, size); + new_string[size] = 0; + + string_list = g_slist_prepend (string_list, new_string); + n++; + remainder = s + delimiter_size; + s = g_utf8_strstr (remainder, delimiter); + } + } + if (*string) { + n++; + string_list = g_slist_prepend (string_list, g_strdup (remainder)); + } + + str_array = g_new (char*, n + 1); + + str_array[n--] = NULL; + for (slist = string_list; slist; slist = slist->next) + str_array[n--] = slist->data; + + g_slist_free (string_list); + + return str_array; +} + + +static char* +g_utf8_strchug (char *string) +{ + char *scan; + gunichar c; + + g_return_val_if_fail (string != NULL, NULL); + + scan = string; + c = g_utf8_get_char (scan); + while (g_unichar_isspace (c)) { + scan = g_utf8_next_char (scan); + c = g_utf8_get_char (scan); + } + + g_memmove (string, scan, strlen (scan) + 1); + + return string; +} + + +static char* +g_utf8_strchomp (char *string) +{ + char *scan; + gsize len; + + g_return_val_if_fail (string != NULL, NULL); + + len = g_utf8_strlen (string, -1); + + if (len == 0) + return string; + + scan = g_utf8_offset_to_pointer (string, len - 1); + + while (len--) { + gunichar c = g_utf8_get_char (scan); + if (g_unichar_isspace (c)) + *scan = '\0'; + else + break; + scan = g_utf8_find_prev_char (string, scan); + } + + return string; +} + + +#define g_utf8_strstrip(string) g_utf8_strchomp (g_utf8_strchug (string)) + + +gboolean +match_regexps (GRegex **regexps, + const char *string, + GRegexMatchFlags match_options) +{ + gboolean matched; + int i; + + if ((regexps == NULL) || (regexps[0] == NULL)) + return TRUE; + + if (string == NULL) + return FALSE; + + matched = FALSE; + for (i = 0; regexps[i] != NULL; i++) + if (g_regex_match (regexps[i], string, match_options, NULL)) { + matched = TRUE; + break; + } + + return matched; +} + + +void +free_regexps (GRegex **regexps) +{ + int i; + + if (regexps == NULL) + return; + + for (i = 0; regexps[i] != NULL; i++) + g_regex_unref (regexps[i]); + g_free (regexps); +} + + +char ** +search_util_get_patterns (const char *pattern_string) +{ + char **patterns; + int i; + + if (pattern_string == NULL) + return NULL; + + patterns = g_utf8_strsplit (pattern_string, ";", MAX_PATTERNS); + for (i = 0; patterns[i] != NULL; i++) { + char *p1, *p2; + + p1 = g_utf8_strstrip (patterns[i]); + p2 = str_substitute (p1, ".", "\\."); + patterns[i] = str_substitute (p2, "*", ".*"); + + g_free (p2); + g_free (p1); + } + + return patterns; +} + + +GRegex ** +search_util_get_regexps (const char *pattern_string, + GRegexCompileFlags compile_options) +{ + char **patterns; + GRegex **regexps; + int i; + + patterns = search_util_get_patterns (pattern_string); + if (patterns == NULL) + return NULL; + + regexps = g_new0 (GRegex*, n_fields (patterns) + 1); + for (i = 0; patterns[i] != NULL; i++) + regexps[i] = g_regex_new (patterns[i], + G_REGEX_OPTIMIZE | compile_options, + G_REGEX_MATCH_NOTEMPTY, + NULL); + g_strfreev (patterns); + + return regexps; +} + + +char * +_g_strdup_with_max_size (const char *s, + int max_size) +{ + char *result; + int l = strlen (s); + + if (l > max_size) { + char *first_half; + char *second_half; + int offset; + int half_max_size = max_size / 2 + 1; + + first_half = g_strndup (s, half_max_size); + offset = half_max_size + l - max_size; + second_half = g_strndup (s + offset, half_max_size); + + result = g_strconcat (first_half, "...", second_half, NULL); + + g_free (first_half); + g_free (second_half); + } else + result = g_strdup (s); + + return result; +} + + +const char * +eat_spaces (const char *line) +{ + if (line == NULL) + return NULL; + while ((*line == ' ') && (*line != 0)) + line++; + return line; +} + + +const char * +eat_void_chars (const char *line) +{ + if (line == NULL) + return NULL; + while (((*line == ' ') || (*line == '\t')) && (*line != 0)) + line++; + return line; +} + + +char ** +split_line (const char *line, + int n_fields) +{ + char **fields; + const char *scan, *field_end; + int i; + + fields = g_new0 (char *, n_fields + 1); + fields[n_fields] = NULL; + + scan = eat_spaces (line); + for (i = 0; i < n_fields; i++) { + if (scan == NULL) { + fields[i] = NULL; + continue; + } + field_end = strchr (scan, ' '); + if (field_end != NULL) { + fields[i] = g_strndup (scan, field_end - scan); + scan = eat_spaces (field_end); + } + } + + return fields; +} + + +const char * +get_last_field (const char *line, + int last_field) +{ + const char *field; + int i; + + if (line == NULL) + return NULL; + + last_field--; + field = eat_spaces (line); + for (i = 0; i < last_field; i++) { + if (field == NULL) + return NULL; + field = strchr (field, ' '); + field = eat_spaces (field); + } + + return field; +} + + +int +n_fields (char **str_array) +{ + int i; + + if (str_array == NULL) + return 0; + + i = 0; + while (str_array[i] != NULL) + i++; + return i; +} + + +void +debug (const char *file, + int line, + const char *function, + const char *format, ...) +{ +#ifdef DEBUG + va_list args; + char *str; + + g_return_if_fail (format != NULL); + + va_start (args, format); + str = g_strdup_vprintf (format, args); + va_end (args); + + g_fprintf (stderr, "[FR] %s:%d (%s):\n\t%s\n", file, line, function, str); + + g_free (str); +#else /* ! DEBUG */ +#endif +} + + +char * +get_time_string (time_t time) +{ + struct tm *tm; + char s_time[256]; + char *locale_format = NULL; + char *time_utf8; + + tm = localtime (&time); + /* This is the time format used in the "Date Modified" column and + * in the Properties dialog. See the man page of strftime for an + * explanation of the values. */ + locale_format = g_locale_from_utf8 (_("%d %B %Y, %H:%M"), -1, NULL, NULL, NULL); + strftime (s_time, sizeof (s_time) - 1, locale_format, tm); + g_free (locale_format); + time_utf8 = g_locale_to_utf8 (s_time, -1, NULL, NULL, NULL); + + return time_utf8; +} + + +GPtrArray * +g_ptr_array_copy (GPtrArray *array) +{ + GPtrArray *new_array; + + if (array == NULL) + return NULL; + + new_array = g_ptr_array_sized_new (array->len); + memcpy (new_array->pdata, array->pdata, array->len * sizeof (gpointer)); + new_array->len = array->len; + + return new_array; +} + + +void +g_ptr_array_free_full (GPtrArray *array, + GFunc free_func, + gpointer user_data) +{ + g_ptr_array_foreach (array, free_func, user_data); + g_ptr_array_free (array, TRUE); +} + + +void +g_ptr_array_reverse (GPtrArray *array) +{ + int i, j; + gpointer tmp; + + for (i = 0; i < array->len / 2; i++) { + j = array->len - i - 1; + tmp = g_ptr_array_index (array, i); + g_ptr_array_index (array, i) = g_ptr_array_index (array, j); + g_ptr_array_index (array, j) = tmp; + } +} + + +int +g_ptr_array_binary_search (GPtrArray *array, + gpointer value, + GCompareFunc func) +{ + int l, r, p, cmp = -1; + + l = 0; + r = array->len; + while (l < r) { + p = l + ((r - l) / 2); + cmp = func(value, &g_ptr_array_index (array, p)); + if (cmp == 0) + return p; + else if (cmp < 0) + r = p; + else + l = p + 1; + } + + return -1; +} + + +GHashTable *static_strings = NULL; + + +const char * +get_static_string (const char *s) +{ + const char *result; + + if (s == NULL) + return NULL; + + if (static_strings == NULL) + static_strings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + if (! g_hash_table_lookup_extended (static_strings, s, (gpointer*) &result, NULL)) { + result = g_strdup (s); + g_hash_table_insert (static_strings, + (gpointer) result, + GINT_TO_POINTER (1)); + } + + return result; +} + + +char* +g_uri_display_basename (const char *uri) +{ + char *e_name, *name; + + e_name = g_filename_display_basename (uri); + name = g_uri_unescape_string (e_name, ""); + g_free (e_name); + + return name; +} |