File: | glib-utils.c |
Warning: | line 382, column 14 Out of bound memory access (access exceeds upper limit of memory block) |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ | |||
2 | ||||
3 | /* | |||
4 | * Grapa | |||
5 | * | |||
6 | * Copyright (C) 2005 Free Software Foundation, Inc. | |||
7 | * | |||
8 | * This program is free software; you can redistribute it and/or modify | |||
9 | * it under the terms of the GNU General Public License as published by | |||
10 | * the Free Software Foundation; either version 2 of the License, or | |||
11 | * (at your option) any later version. | |||
12 | * | |||
13 | * This program is distributed in the hope that it will be useful, | |||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
16 | * GNU General Public License for more details. | |||
17 | * | |||
18 | * You should have received a copy of the GNU General Public License | |||
19 | * along with this program; if not, write to the Free Software | |||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |||
21 | */ | |||
22 | ||||
23 | #include <config.h> | |||
24 | #include <string.h> | |||
25 | #include <stdio.h> | |||
26 | #include <glib.h> | |||
27 | #include <glib/gi18n.h> | |||
28 | #include <glib/gprintf.h> | |||
29 | #include <glib-object.h> | |||
30 | #include "glib-utils.h" | |||
31 | ||||
32 | ||||
33 | #define MAX_PATTERNS128 128 | |||
34 | ||||
35 | ||||
36 | /* gobject utils*/ | |||
37 | ||||
38 | ||||
39 | void | |||
40 | _g_object_unref (gpointer object) | |||
41 | { | |||
42 | if (object != NULL((void*)0)) | |||
43 | g_object_unref (object); | |||
44 | } | |||
45 | ||||
46 | ||||
47 | /* string utils */ | |||
48 | ||||
49 | gboolean | |||
50 | strchrs (const char *str, | |||
51 | const char *chars) | |||
52 | { | |||
53 | const char *c; | |||
54 | for (c = chars; *c != '\0'; c++) | |||
55 | if (strchr (str, *c) != NULL((void*)0)) | |||
56 | return TRUE(!(0)); | |||
57 | return FALSE(0); | |||
58 | } | |||
59 | ||||
60 | ||||
61 | char * | |||
62 | str_substitute (const char *str, | |||
63 | const char *from_str, | |||
64 | const char *to_str) | |||
65 | { | |||
66 | char **tokens; | |||
67 | int i; | |||
68 | GString *gstr; | |||
69 | ||||
70 | if (str == NULL((void*)0)) | |||
71 | return NULL((void*)0); | |||
72 | ||||
73 | if (from_str == NULL((void*)0)) | |||
74 | return g_strdup (str)g_strdup_inline (str); | |||
75 | ||||
76 | if (strcmp (str, from_str) == 0) | |||
77 | return g_strdup (to_str)g_strdup_inline (to_str); | |||
78 | ||||
79 | tokens = g_strsplit (str, from_str, -1); | |||
80 | ||||
81 | gstr = g_string_new (NULL((void*)0)); | |||
82 | for (i = 0; tokens[i] != NULL((void*)0); i++) { | |||
83 | gstr = g_string_append (gstr, tokens[i])(__builtin_constant_p (tokens[i]) ? __extension__ ({ const char * const __val = (tokens[i]); g_string_append_len_inline (gstr , __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + ! (__val))) : (gssize) -1); }) : g_string_append_len_inline (gstr , tokens[i], (gssize) -1)); | |||
84 | if ((to_str != NULL((void*)0)) && (tokens[i+1] != NULL((void*)0))) | |||
85 | gstr = g_string_append (gstr, to_str)(__builtin_constant_p (to_str) ? __extension__ ({ const char * const __val = (to_str); g_string_append_len_inline (gstr, __val , (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val ))) : (gssize) -1); }) : g_string_append_len_inline (gstr, to_str , (gssize) -1)); | |||
86 | } | |||
87 | ||||
88 | g_strfreev (tokens); | |||
89 | ||||
90 | return g_string_free (gstr, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((gstr ), ((0))) : g_string_free_and_steal (gstr)) : (g_string_free) ((gstr), ((0)))); | |||
91 | } | |||
92 | ||||
93 | ||||
94 | int | |||
95 | strcmp_null_tolerant (const char *s1, const char *s2) | |||
96 | { | |||
97 | if ((s1 == NULL((void*)0)) && (s2 == NULL((void*)0))) | |||
98 | return 0; | |||
99 | else if ((s1 != NULL((void*)0)) && (s2 == NULL((void*)0))) | |||
100 | return 1; | |||
101 | else if ((s1 == NULL((void*)0)) && (s2 != NULL((void*)0))) | |||
102 | return -1; | |||
103 | else | |||
104 | return strcmp (s1, s2); | |||
105 | } | |||
106 | ||||
107 | ||||
108 | /* counts how many characters to escape in @str. */ | |||
109 | static int | |||
110 | count_chars_to_escape (const char *str, | |||
111 | const char *meta_chars) | |||
112 | { | |||
113 | int meta_chars_n = strlen (meta_chars); | |||
114 | const char *s; | |||
115 | int n = 0; | |||
116 | ||||
117 | for (s = str; *s != 0; s++) { | |||
118 | int i; | |||
119 | for (i = 0; i < meta_chars_n; i++) | |||
120 | if (*s == meta_chars[i]) { | |||
121 | n++; | |||
122 | break; | |||
123 | } | |||
124 | } | |||
125 | return n; | |||
126 | } | |||
127 | ||||
128 | ||||
129 | char* | |||
130 | escape_str_common (const char *str, | |||
131 | const char *meta_chars, | |||
132 | const char prefix, | |||
133 | const char postfix) | |||
134 | { | |||
135 | int meta_chars_n = strlen (meta_chars); | |||
136 | char *escaped; | |||
137 | int i, new_l, extra_chars = 0; | |||
138 | const char *s; | |||
139 | char *t; | |||
140 | ||||
141 | if (str == NULL((void*)0)) | |||
142 | return NULL((void*)0); | |||
143 | ||||
144 | if (prefix) | |||
145 | extra_chars++; | |||
146 | if (postfix) | |||
147 | extra_chars++; | |||
148 | ||||
149 | new_l = strlen (str) + (count_chars_to_escape (str, meta_chars) * extra_chars); | |||
150 | escaped = g_malloc (new_l + 1); | |||
151 | ||||
152 | s = str; | |||
153 | t = escaped; | |||
154 | while (*s) { | |||
155 | gboolean is_bad = FALSE(0); | |||
156 | for (i = 0; (i < meta_chars_n) && !is_bad; i++) | |||
157 | is_bad = (*s == meta_chars[i]); | |||
158 | if (is_bad && prefix) | |||
159 | *t++ = prefix; | |||
160 | *t++ = *s++; | |||
161 | if (is_bad && postfix) | |||
162 | *t++ = postfix; | |||
163 | } | |||
164 | *t = 0; | |||
165 | ||||
166 | return escaped; | |||
167 | } | |||
168 | ||||
169 | ||||
170 | /* escape with backslash the string @str. */ | |||
171 | char* | |||
172 | escape_str (const char *str, | |||
173 | const char *meta_chars) | |||
174 | { | |||
175 | return escape_str_common (str, meta_chars, '\\', 0); | |||
176 | } | |||
177 | ||||
178 | ||||
179 | static const char * | |||
180 | g_utf8_strstr (const char *haystack, const char *needle) | |||
181 | { | |||
182 | const char *s; | |||
183 | gsize i; | |||
184 | gsize haystack_len = g_utf8_strlen (haystack, -1); | |||
185 | gsize needle_len = g_utf8_strlen (needle, -1); | |||
186 | int needle_size = strlen (needle); | |||
187 | ||||
188 | s = haystack; | |||
189 | for (i = 0; i <= haystack_len - needle_len; i++) { | |||
190 | if (strncmp (s, needle, needle_size) == 0) | |||
191 | return s; | |||
192 | s = g_utf8_next_char(s)(char *)((s) + g_utf8_skip[*(const guchar *)(s)]); | |||
193 | } | |||
194 | ||||
195 | return NULL((void*)0); | |||
196 | } | |||
197 | ||||
198 | ||||
199 | static char** | |||
200 | g_utf8_strsplit (const char *string, | |||
201 | const char *delimiter, | |||
202 | int max_tokens) | |||
203 | { | |||
204 | GSList *string_list = NULL((void*)0), *slist; | |||
205 | char **str_array; | |||
206 | const char *s; | |||
207 | guint n = 0; | |||
208 | const char *remainder; | |||
209 | ||||
210 | g_return_val_if_fail (string != NULL, NULL)do { if ((string != ((void*)0))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "string != NULL") ; return (((void*)0)); } } while (0); | |||
211 | g_return_val_if_fail (delimiter != NULL, NULL)do { if ((delimiter != ((void*)0))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "delimiter != NULL" ); return (((void*)0)); } } while (0); | |||
212 | g_return_val_if_fail (delimiter[0] != '\0', NULL)do { if ((delimiter[0] != '\0')) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "delimiter[0] != '\\0'" ); return (((void*)0)); } } while (0); | |||
213 | ||||
214 | if (max_tokens < 1) | |||
215 | max_tokens = G_MAXINT2147483647; | |||
216 | ||||
217 | remainder = string; | |||
218 | s = g_utf8_strstr (remainder, delimiter); | |||
219 | if (s != NULL((void*)0)) { | |||
220 | gsize delimiter_size = strlen (delimiter); | |||
221 | ||||
222 | while (--max_tokens && (s != NULL((void*)0))) { | |||
223 | gsize size = s - remainder; | |||
224 | char *new_string; | |||
225 | ||||
226 | new_string = g_new (char, size + 1)((char *) g_malloc_n ((size + 1), sizeof (char))); | |||
227 | strncpy (new_string, remainder, size); | |||
228 | new_string[size] = 0; | |||
229 | ||||
230 | string_list = g_slist_prepend (string_list, new_string); | |||
231 | n++; | |||
232 | remainder = s + delimiter_size; | |||
233 | s = g_utf8_strstr (remainder, delimiter); | |||
234 | } | |||
235 | } | |||
236 | if (*string) { | |||
237 | n++; | |||
238 | string_list = g_slist_prepend (string_list, g_strdup (remainder)g_strdup_inline (remainder)); | |||
239 | } | |||
240 | ||||
241 | str_array = g_new (char*, n + 1)((char* *) g_malloc_n ((n + 1), sizeof (char*))); | |||
242 | ||||
243 | str_array[n--] = NULL((void*)0); | |||
244 | for (slist = string_list; slist; slist = slist->next) | |||
245 | str_array[n--] = slist->data; | |||
246 | ||||
247 | g_slist_free (string_list); | |||
248 | ||||
249 | return str_array; | |||
250 | } | |||
251 | ||||
252 | ||||
253 | static char* | |||
254 | g_utf8_strchug (char *string) | |||
255 | { | |||
256 | char *scan; | |||
257 | gunichar c; | |||
258 | ||||
259 | g_return_val_if_fail (string != NULL, NULL)do { if ((string != ((void*)0))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "string != NULL") ; return (((void*)0)); } } while (0); | |||
260 | ||||
261 | scan = string; | |||
262 | c = g_utf8_get_char (scan); | |||
263 | while (g_unichar_isspace (c)) { | |||
264 | scan = g_utf8_next_char (scan)(char *)((scan) + g_utf8_skip[*(const guchar *)(scan)]); | |||
265 | c = g_utf8_get_char (scan); | |||
266 | } | |||
267 | ||||
268 | memmove (string, scan, strlen (scan) + 1); | |||
269 | ||||
270 | return string; | |||
271 | } | |||
272 | ||||
273 | ||||
274 | static char* | |||
275 | g_utf8_strchomp (char *string) | |||
276 | { | |||
277 | char *scan; | |||
278 | gsize len; | |||
279 | ||||
280 | g_return_val_if_fail (string != NULL, NULL)do { if ((string != ((void*)0))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "string != NULL") ; return (((void*)0)); } } while (0); | |||
281 | ||||
282 | len = g_utf8_strlen (string, -1); | |||
283 | ||||
284 | if (len == 0) | |||
285 | return string; | |||
286 | ||||
287 | scan = g_utf8_offset_to_pointer (string, len - 1); | |||
288 | ||||
289 | while (len--) { | |||
290 | gunichar c = g_utf8_get_char (scan); | |||
291 | if (g_unichar_isspace (c)) | |||
292 | *scan = '\0'; | |||
293 | else | |||
294 | break; | |||
295 | scan = g_utf8_find_prev_char (string, scan); | |||
296 | } | |||
297 | ||||
298 | return string; | |||
299 | } | |||
300 | ||||
301 | ||||
302 | #define g_utf8_strstrip(string)g_utf8_strchomp (g_utf8_strchug (string)) g_utf8_strchomp (g_utf8_strchug (string)) | |||
303 | ||||
304 | ||||
305 | gboolean | |||
306 | match_regexps (GRegex **regexps, | |||
307 | const char *string, | |||
308 | GRegexMatchFlags match_options) | |||
309 | { | |||
310 | gboolean matched; | |||
311 | int i; | |||
312 | ||||
313 | if ((regexps == NULL((void*)0)) || (regexps[0] == NULL((void*)0))) | |||
314 | return TRUE(!(0)); | |||
315 | ||||
316 | if (string == NULL((void*)0)) | |||
317 | return FALSE(0); | |||
318 | ||||
319 | matched = FALSE(0); | |||
320 | for (i = 0; regexps[i] != NULL((void*)0); i++) | |||
321 | if (g_regex_match (regexps[i], string, match_options, NULL((void*)0))) { | |||
322 | matched = TRUE(!(0)); | |||
323 | break; | |||
324 | } | |||
325 | ||||
326 | return matched; | |||
327 | } | |||
328 | ||||
329 | ||||
330 | void | |||
331 | free_regexps (GRegex **regexps) | |||
332 | { | |||
333 | int i; | |||
334 | ||||
335 | if (regexps == NULL((void*)0)) | |||
336 | return; | |||
337 | ||||
338 | for (i = 0; regexps[i] != NULL((void*)0); i++) | |||
339 | g_regex_unref (regexps[i]); | |||
340 | g_free (regexps); | |||
341 | } | |||
342 | ||||
343 | ||||
344 | char ** | |||
345 | search_util_get_patterns (const char *pattern_string) | |||
346 | { | |||
347 | char **patterns; | |||
348 | int i; | |||
349 | ||||
350 | if (pattern_string == NULL((void*)0)) | |||
351 | return NULL((void*)0); | |||
352 | ||||
353 | patterns = g_utf8_strsplit (pattern_string, ";", MAX_PATTERNS128); | |||
354 | for (i = 0; patterns[i] != NULL((void*)0); i++) { | |||
355 | char *p1, *p2; | |||
356 | ||||
357 | p1 = g_utf8_strstrip (patterns[i])g_utf8_strchomp (g_utf8_strchug (patterns[i])); | |||
358 | p2 = str_substitute (p1, ".", "\\."); | |||
359 | patterns[i] = str_substitute (p2, "*", ".*"); | |||
360 | ||||
361 | g_free (p2); | |||
362 | g_free (p1); | |||
363 | } | |||
364 | ||||
365 | return patterns; | |||
366 | } | |||
367 | ||||
368 | ||||
369 | GRegex ** | |||
370 | search_util_get_regexps (const char *pattern_string, | |||
371 | GRegexCompileFlags compile_options) | |||
372 | { | |||
373 | char **patterns; | |||
374 | GRegex **regexps; | |||
375 | int i; | |||
376 | ||||
377 | patterns = search_util_get_patterns (pattern_string); | |||
378 | if (patterns
| |||
| ||||
379 | return NULL((void*)0); | |||
380 | ||||
381 | regexps = g_new0 (GRegex*, n_fields (patterns) + 1)((GRegex* *) g_malloc0_n ((n_fields (patterns) + 1), sizeof ( GRegex*))); | |||
382 | for (i = 0; patterns[i] != NULL((void*)0); i++) | |||
| ||||
383 | regexps[i] = g_regex_new (patterns[i], | |||
384 | G_REGEX_OPTIMIZE | compile_options, | |||
385 | G_REGEX_MATCH_NOTEMPTY, | |||
386 | NULL((void*)0)); | |||
387 | g_strfreev (patterns); | |||
388 | ||||
389 | return regexps; | |||
390 | } | |||
391 | ||||
392 | ||||
393 | const char * | |||
394 | eat_spaces (const char *line) | |||
395 | { | |||
396 | if (line == NULL((void*)0)) | |||
397 | return NULL((void*)0); | |||
398 | while ((*line == ' ') && (*line != 0)) | |||
399 | line++; | |||
400 | return line; | |||
401 | } | |||
402 | ||||
403 | ||||
404 | char ** | |||
405 | split_line (const char *line, | |||
406 | int n_fields) | |||
407 | { | |||
408 | char **fields; | |||
409 | const char *scan, *field_end; | |||
410 | int i; | |||
411 | ||||
412 | fields = g_new0 (char *, n_fields + 1)((char * *) g_malloc0_n ((n_fields + 1), sizeof (char *))); | |||
413 | fields[n_fields] = NULL((void*)0); | |||
414 | ||||
415 | scan = eat_spaces (line); | |||
416 | for (i = 0; i < n_fields; i++) { | |||
417 | if (scan == NULL((void*)0)) { | |||
418 | fields[i] = NULL((void*)0); | |||
419 | continue; | |||
420 | } | |||
421 | field_end = strchr (scan, ' '); | |||
422 | if (field_end != NULL((void*)0)) { | |||
423 | fields[i] = g_strndup (scan, field_end - scan); | |||
424 | scan = eat_spaces (field_end); | |||
425 | } | |||
426 | else if (i == n_fields - 1) | |||
427 | { | |||
428 | fields[i] = g_strdup (scan)g_strdup_inline (scan); | |||
429 | } | |||
430 | } | |||
431 | ||||
432 | return fields; | |||
433 | } | |||
434 | ||||
435 | ||||
436 | const char * | |||
437 | get_last_field (const char *line, | |||
438 | int last_field) | |||
439 | { | |||
440 | const char *field; | |||
441 | int i; | |||
442 | ||||
443 | if (line == NULL((void*)0)) | |||
444 | return NULL((void*)0); | |||
445 | ||||
446 | last_field--; | |||
447 | field = eat_spaces (line); | |||
448 | for (i = 0; i < last_field; i++) { | |||
449 | if (field == NULL((void*)0)) | |||
450 | return NULL((void*)0); | |||
451 | field = strchr (field, ' '); | |||
452 | field = eat_spaces (field); | |||
453 | } | |||
454 | ||||
455 | return field; | |||
456 | } | |||
457 | ||||
458 | ||||
459 | int | |||
460 | n_fields (char **str_array) | |||
461 | { | |||
462 | int i; | |||
463 | ||||
464 | if (str_array == NULL((void*)0)) | |||
465 | return 0; | |||
466 | ||||
467 | i = 0; | |||
468 | while (str_array[i] != NULL((void*)0)) | |||
469 | i++; | |||
470 | return i; | |||
471 | } | |||
472 | ||||
473 | ||||
474 | void | |||
475 | debug (const char *file, | |||
476 | int line, | |||
477 | const char *function, | |||
478 | const char *format, ...) | |||
479 | { | |||
480 | #ifdef CAFE_ENABLE_DEBUG | |||
481 | va_list args; | |||
482 | char *str; | |||
483 | ||||
484 | g_return_if_fail (format != NULL)do { if ((format != ((void*)0))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "format != NULL") ; return; } } while (0); | |||
485 | ||||
486 | va_start (args, format)__builtin_va_start(args, format); | |||
487 | str = g_strdup_vprintf (format, args); | |||
488 | va_end (args)__builtin_va_end(args); | |||
489 | ||||
490 | g_fprintf (stderrstderr, "[FR] %s:%d (%s):\n\t%s\n", file, line, function, str); | |||
491 | ||||
492 | g_free (str); | |||
493 | #else /* ! DEBUG */ | |||
494 | #endif | |||
495 | } | |||
496 | ||||
497 | ||||
498 | void | |||
499 | g_ptr_array_free_full (GPtrArray *array, | |||
500 | GFunc free_func, | |||
501 | gpointer user_data) | |||
502 | { | |||
503 | g_ptr_array_foreach (array, free_func, user_data); | |||
504 | g_ptr_array_free (array, TRUE(!(0))); | |||
505 | } | |||
506 | ||||
507 | ||||
508 | GHashTable *static_strings = NULL((void*)0); | |||
509 | ||||
510 | ||||
511 | const char * | |||
512 | get_static_string (const char *s) | |||
513 | { | |||
514 | const char *result; | |||
515 | ||||
516 | if (s == NULL((void*)0)) | |||
517 | return NULL((void*)0); | |||
518 | ||||
519 | if (static_strings == NULL((void*)0)) | |||
520 | static_strings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL((void*)0)); | |||
521 | ||||
522 | if (! g_hash_table_lookup_extended (static_strings, s, (gpointer*) &result, NULL((void*)0))) { | |||
523 | result = g_strdup (s)g_strdup_inline (s); | |||
524 | g_hash_table_insert (static_strings, | |||
525 | (gpointer) result, | |||
526 | GINT_TO_POINTER (1)((gpointer) (glong) (1))); | |||
527 | } | |||
528 | ||||
529 | return result; | |||
530 | } | |||
531 | ||||
532 | ||||
533 | char* | |||
534 | g_uri_display_basename (const char *uri) | |||
535 | { | |||
536 | char *e_name, *name; | |||
537 | ||||
538 | e_name = g_filename_display_basename (uri); | |||
539 | name = g_uri_unescape_string (e_name, ""); | |||
540 | g_free (e_name); | |||
541 | ||||
542 | return name; | |||
543 | } | |||
544 | ||||
545 | ||||
546 | const gchar * | |||
547 | _g_path_get_file_name (const gchar *file_name) | |||
548 | { | |||
549 | register char *base; | |||
550 | register gssize last_char; | |||
551 | ||||
552 | if (file_name == NULL((void*)0)) | |||
553 | return NULL((void*)0); | |||
554 | ||||
555 | if (file_name[0] == '\0') | |||
556 | return ""; | |||
557 | ||||
558 | last_char = strlen (file_name) - 1; | |||
559 | ||||
560 | if (file_name [last_char] == G_DIR_SEPARATOR'/') | |||
561 | return ""; | |||
562 | ||||
563 | base = g_utf8_strrchr (file_name, -1, G_DIR_SEPARATOR'/'); | |||
564 | if (! base) | |||
565 | return file_name; | |||
566 | ||||
567 | return base + 1; | |||
568 | } | |||
569 | ||||
570 | ||||
571 | const char * | |||
572 | _g_path_get_base_name (const char *path, | |||
573 | const char *base_dir, | |||
574 | gboolean junk_paths) | |||
575 | { | |||
576 | size_t base_dir_len; | |||
577 | const char *base_path; | |||
578 | ||||
579 | if (junk_paths) | |||
580 | return _g_path_get_file_name (path); | |||
581 | ||||
582 | ||||
583 | if (base_dir == NULL((void*)0)) | |||
584 | return (path[0] == '/') ? path + 1 : path; | |||
585 | ||||
586 | base_dir_len = strlen (base_dir); | |||
587 | if (strlen (path) < base_dir_len) | |||
588 | return NULL((void*)0); | |||
589 | ||||
590 | base_path = path + base_dir_len; | |||
591 | if (path[0] != '/') | |||
592 | base_path -= 1; | |||
593 | ||||
594 | return base_path; | |||
595 | } | |||
596 |