summaryrefslogtreecommitdiff
path: root/src/glib-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/glib-utils.c')
-rw-r--r--src/glib-utils.c645
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;
+}