~elementary-os/elementaryos/os-patch-file-roller-bionic-old

« back to all changes in this revision

Viewing changes to src/glib-utils.c

  • Committer: RabbitBot
  • Date: 2018-02-05 12:55:45 UTC
  • Revision ID: rabbitbot@elementary.io-20180205125545-nmwn0wosptxjg5ei
Initial import, version 3.26.2-3ubuntu1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 
2
 
 
3
/*
 
4
 *  File-Roller
 
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, see <http://www.gnu.org/licenses/>.
 
20
 */
 
21
 
 
22
#include <config.h>
 
23
#include <ctype.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
#if ENABLE_MAGIC
 
32
#  include <magic.h>
 
33
#endif
 
34
 
 
35
 
 
36
#define MAX_PATTERNS 128
 
37
 
 
38
 
 
39
/* gobject utils*/
 
40
 
 
41
 
 
42
gpointer
 
43
_g_object_ref (gpointer object)
 
44
{
 
45
        return (object != NULL) ? g_object_ref (object) : NULL;
 
46
}
 
47
 
 
48
 
 
49
void
 
50
_g_object_unref (gpointer object)
 
51
{
 
52
        if (object != NULL)
 
53
                g_object_unref (object);
 
54
}
 
55
 
 
56
 
 
57
void
 
58
_g_clear_object (gpointer p)
 
59
{
 
60
        g_clear_object ((GObject **) p);
 
61
}
 
62
 
 
63
 
 
64
GList *
 
65
_g_object_list_ref (GList *list)
 
66
{
 
67
        GList *new_list;
 
68
 
 
69
        if (list == NULL)
 
70
                return NULL;
 
71
 
 
72
        new_list = g_list_copy (list);
 
73
        g_list_foreach (new_list, (GFunc) g_object_ref, NULL);
 
74
 
 
75
        return new_list;
 
76
}
 
77
 
 
78
 
 
79
void
 
80
_g_object_list_unref (GList *list)
 
81
{
 
82
        g_list_foreach (list, (GFunc) g_object_unref, NULL);
 
83
        g_list_free (list);
 
84
}
 
85
 
 
86
/* enum */
 
87
 
 
88
 
 
89
GEnumValue *
 
90
_g_enum_type_get_value (GType enum_type,
 
91
                        int   value)
 
92
{
 
93
        GEnumClass *class;
 
94
        GEnumValue *enum_value;
 
95
 
 
96
        class = G_ENUM_CLASS (g_type_class_ref (enum_type));
 
97
        enum_value = g_enum_get_value (class, value);
 
98
        g_type_class_unref (class);
 
99
 
 
100
        return enum_value;
 
101
}
 
102
 
 
103
 
 
104
GEnumValue *
 
105
_g_enum_type_get_value_by_nick (GType       enum_type,
 
106
                                const char *nick)
 
107
{
 
108
        GEnumClass *class;
 
109
        GEnumValue *enum_value;
 
110
 
 
111
        class = G_ENUM_CLASS (g_type_class_ref (enum_type));
 
112
        enum_value = g_enum_get_value_by_nick (class, nick);
 
113
        g_type_class_unref (class);
 
114
 
 
115
        return enum_value;
 
116
}
 
117
 
 
118
 
 
119
/* error */
 
120
 
 
121
 
 
122
void
 
123
_g_error_free (GError *error)
 
124
{
 
125
        if (error != NULL)
 
126
                g_error_free (error);
 
127
}
 
128
 
 
129
 
 
130
/* string */
 
131
 
 
132
 
 
133
gboolean
 
134
_g_strchrs (const char *str,
 
135
            const char *chars)
 
136
{
 
137
        const char *c;
 
138
        for (c = chars; *c != '\0'; c++)
 
139
                if (strchr (str, *c) != NULL)
 
140
                        return TRUE;
 
141
        return FALSE;
 
142
}
 
143
 
 
144
 
 
145
char *
 
146
_g_str_substitute (const char *str,
 
147
                   const char *from_str,
 
148
                   const char *to_str)
 
149
{
 
150
        char    **tokens;
 
151
        int       i;
 
152
        GString  *gstr;
 
153
 
 
154
        if (str == NULL)
 
155
                return NULL;
 
156
 
 
157
        if (from_str == NULL)
 
158
                return g_strdup (str);
 
159
 
 
160
        if (strcmp (str, from_str) == 0)
 
161
                return g_strdup (to_str);
 
162
 
 
163
        tokens = g_strsplit (str, from_str, -1);
 
164
 
 
165
        gstr = g_string_new (NULL);
 
166
        for (i = 0; tokens[i] != NULL; i++) {
 
167
                gstr = g_string_append (gstr, tokens[i]);
 
168
                if ((to_str != NULL) && (tokens[i+1] != NULL))
 
169
                        gstr = g_string_append (gstr, to_str);
 
170
        }
 
171
 
 
172
        return g_string_free (gstr, FALSE);
 
173
}
 
174
 
 
175
 
 
176
gboolean
 
177
_g_str_equal (const char *s1,
 
178
              const char *s2)
 
179
{
 
180
        return g_strcmp0 (s1, s2) == 0;
 
181
}
 
182
 
 
183
 
 
184
/* -- _g_str_escape_full -- */
 
185
 
 
186
 
 
187
/* counts how many characters to escape in @str. */
 
188
static int
 
189
count_chars_to_escape (const char *str,
 
190
                       const char *meta_chars)
 
191
{
 
192
        int         meta_chars_n = strlen (meta_chars);
 
193
        const char *s;
 
194
        int         n = 0;
 
195
 
 
196
        for (s = str; *s != 0; s++) {
 
197
                int i;
 
198
                for (i = 0; i < meta_chars_n; i++)
 
199
                        if (*s == meta_chars[i]) {
 
200
                                n++;
 
201
                                break;
 
202
                        }
 
203
        }
 
204
 
 
205
        return n;
 
206
}
 
207
 
 
208
 
 
209
char *
 
210
_g_str_escape_full (const char *str,
 
211
                    const char *meta_chars,
 
212
                    const char  prefix,
 
213
                    const char  postfix)
 
214
{
 
215
        int         meta_chars_n = strlen (meta_chars);
 
216
        char       *escaped;
 
217
        int         i, new_l, extra_chars = 0;
 
218
        const char *s;
 
219
        char       *t;
 
220
 
 
221
        if (str == NULL)
 
222
                return NULL;
 
223
 
 
224
        if (prefix)
 
225
                extra_chars++;
 
226
        if (postfix)
 
227
                extra_chars++;
 
228
 
 
229
        new_l = strlen (str) + (count_chars_to_escape (str, meta_chars) * extra_chars);
 
230
        escaped = g_malloc (new_l + 1);
 
231
 
 
232
        s = str;
 
233
        t = escaped;
 
234
        while (*s) {
 
235
                gboolean is_bad = FALSE;
 
236
                for (i = 0; (i < meta_chars_n) && !is_bad; i++)
 
237
                        is_bad = (*s == meta_chars[i]);
 
238
                if (is_bad && prefix)
 
239
                        *t++ = prefix;
 
240
                *t++ = *s++;
 
241
                if (is_bad && postfix)
 
242
                        *t++ = postfix;
 
243
        }
 
244
        *t = 0;
 
245
 
 
246
        return escaped;
 
247
}
 
248
 
 
249
 
 
250
/* escape with backslash the string @str. */
 
251
char *
 
252
_g_str_escape (const char *str,
 
253
               const char *meta_chars)
 
254
{
 
255
        return _g_str_escape_full (str, meta_chars, '\\', 0);
 
256
}
 
257
 
 
258
 
 
259
/* escape with backslash the file name. */
 
260
char *
 
261
_g_str_shell_escape (const char *filename)
 
262
{
 
263
        return _g_str_escape (filename, "$'`\"\\!?* ()[]&|:;<>#");
 
264
}
 
265
 
 
266
 
 
267
char *
 
268
_g_strdup_with_max_size (const char *s,
 
269
                         int         max_size)
 
270
{
 
271
        char *result;
 
272
        int   l = strlen (s);
 
273
 
 
274
        if (l > max_size) {
 
275
                char *first_half;
 
276
                char *second_half;
 
277
                int   offset;
 
278
                int   half_max_size = max_size / 2 + 1;
 
279
 
 
280
                first_half = g_strndup (s, half_max_size);
 
281
                offset = half_max_size + l - max_size;
 
282
                second_half = g_strndup (s + offset, half_max_size);
 
283
 
 
284
                result = g_strconcat (first_half, "...", second_half, NULL);
 
285
 
 
286
                g_free (first_half);
 
287
                g_free (second_half);
 
288
        } else
 
289
                result = g_strdup (s);
 
290
 
 
291
        return result;
 
292
}
 
293
 
 
294
 
 
295
const char *
 
296
_g_str_eat_spaces (const char *line)
 
297
{
 
298
        if (line == NULL)
 
299
                return NULL;
 
300
        while ((*line == ' ') && (*line != 0))
 
301
                line++;
 
302
        return line;
 
303
}
 
304
 
 
305
 
 
306
const char *
 
307
_g_str_eat_void_chars (const char *line)
 
308
{
 
309
        if (line == NULL)
 
310
                return NULL;
 
311
        while (((*line == ' ') || (*line == '\t')) && (*line != 0))
 
312
                line++;
 
313
        return line;
 
314
}
 
315
 
 
316
 
 
317
char **
 
318
_g_str_split_line (const char *line,
 
319
                   int         n_fields)
 
320
{
 
321
        char       **fields;
 
322
        const char  *scan, *field_end;
 
323
        int          i;
 
324
 
 
325
        fields = g_new0 (char *, n_fields + 1);
 
326
        fields[n_fields] = NULL;
 
327
 
 
328
        scan = _g_str_eat_spaces (line);
 
329
        for (i = 0; i < n_fields; i++) {
 
330
                if (scan == NULL) {
 
331
                        fields[i] = NULL;
 
332
                        continue;
 
333
                }
 
334
                field_end = strchr (scan, ' ');
 
335
                if (field_end != NULL) {
 
336
                        fields[i] = g_strndup (scan, field_end - scan);
 
337
                        scan = _g_str_eat_spaces (field_end);
 
338
                }
 
339
        }
 
340
 
 
341
        return fields;
 
342
}
 
343
 
 
344
 
 
345
const char *
 
346
_g_str_get_last_field (const char *line,
 
347
                       int         last_field)
 
348
{
 
349
        const char *field;
 
350
        int         i;
 
351
 
 
352
        if (line == NULL)
 
353
                return NULL;
 
354
 
 
355
        last_field--;
 
356
        field = _g_str_eat_spaces (line);
 
357
        for (i = 0; i < last_field; i++) {
 
358
                if (field == NULL)
 
359
                        return NULL;
 
360
                field = strchr (field, ' ');
 
361
                field = _g_str_eat_spaces (field);
 
362
        }
 
363
 
 
364
        return field;
 
365
}
 
366
 
 
367
 
 
368
GHashTable *static_strings = NULL;
 
369
 
 
370
 
 
371
const char *
 
372
_g_str_get_static (const char *s)
 
373
{
 
374
        const char *result;
 
375
 
 
376
        if (s == NULL)
 
377
                return NULL;
 
378
 
 
379
        if (static_strings == NULL)
 
380
                static_strings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 
381
 
 
382
        if (! g_hash_table_lookup_extended (static_strings, s, (gpointer*) &result, NULL)) {
 
383
                result = g_strdup (s);
 
384
                g_hash_table_insert (static_strings,
 
385
                                     (gpointer) result,
 
386
                                     GINT_TO_POINTER (1));
 
387
        }
 
388
 
 
389
        return result;
 
390
}
 
391
 
 
392
 
 
393
/* string vector */
 
394
 
 
395
 
 
396
char **
 
397
_g_strv_prepend (char       **str_array,
 
398
                 const char  *str)
 
399
{
 
400
        char **result;
 
401
        int    i;
 
402
        int    j;
 
403
 
 
404
        result = g_new (char *, g_strv_length (str_array) + 1);
 
405
        i = 0;
 
406
        result[i++] = g_strdup (str);
 
407
        for (j = 0; str_array[j] != NULL; j++)
 
408
                result[i++] = g_strdup (str_array[j]);
 
409
        result[i] = NULL;
 
410
 
 
411
        return result;
 
412
}
 
413
 
 
414
 
 
415
gboolean
 
416
_g_strv_remove (char       **str_array,
 
417
                const char  *str)
 
418
{
 
419
        int i;
 
420
        int j;
 
421
 
 
422
        if (str == NULL)
 
423
                return FALSE;
 
424
 
 
425
        for (i = 0; str_array[i] != NULL; i++)
 
426
                if (strcmp (str_array[i], str) == 0)
 
427
                        break;
 
428
 
 
429
        if (str_array[i] == NULL)
 
430
                return FALSE;
 
431
 
 
432
        for (j = i; str_array[j] != NULL; j++)
 
433
                str_array[j] = str_array[j + 1];
 
434
 
 
435
        return TRUE;
 
436
}
 
437
 
 
438
 
 
439
/* string list */
 
440
 
 
441
 
 
442
void
 
443
_g_string_list_free (GList *path_list)
 
444
{
 
445
        if (path_list == NULL)
 
446
                return;
 
447
        g_list_foreach (path_list, (GFunc) g_free, NULL);
 
448
        g_list_free (path_list);
 
449
}
 
450
 
 
451
 
 
452
GList *
 
453
_g_string_list_dup (GList *path_list)
 
454
{
 
455
        GList *new_list = NULL;
 
456
        GList *scan;
 
457
 
 
458
        for (scan = path_list; scan; scan = scan->next)
 
459
                new_list = g_list_prepend (new_list, g_strdup (scan->data));
 
460
 
 
461
        return g_list_reverse (new_list);
 
462
}
 
463
 
 
464
 
 
465
/* GPtrArray */
 
466
 
 
467
 
 
468
GPtrArray *
 
469
_g_ptr_array_copy (GPtrArray *array)
 
470
{
 
471
        GPtrArray *new_array;
 
472
 
 
473
        if (array == NULL)
 
474
                return NULL;
 
475
 
 
476
        new_array = g_ptr_array_sized_new (array->len);
 
477
        memcpy (new_array->pdata, array->pdata, array->len * sizeof (gpointer));
 
478
        new_array->len = array->len;
 
479
 
 
480
        return new_array;
 
481
}
 
482
 
 
483
 
 
484
void
 
485
_g_ptr_array_free_full (GPtrArray *array,
 
486
                        GFunc      free_func,
 
487
                        gpointer   user_data)
 
488
{
 
489
        g_ptr_array_foreach (array, free_func, user_data);
 
490
        g_ptr_array_free (array, TRUE);
 
491
}
 
492
 
 
493
 
 
494
void
 
495
_g_ptr_array_reverse (GPtrArray *array)
 
496
{
 
497
        int      i, j;
 
498
        gpointer tmp;
 
499
 
 
500
        for (i = 0; i < array->len / 2; i++) {
 
501
                j = array->len - i - 1;
 
502
                tmp = g_ptr_array_index (array, i);
 
503
                g_ptr_array_index (array, i) = g_ptr_array_index (array, j);
 
504
                g_ptr_array_index (array, j) = tmp;
 
505
        }
 
506
}
 
507
 
 
508
 
 
509
int
 
510
_g_ptr_array_binary_search (GPtrArray    *array,
 
511
                           gpointer      value,
 
512
                           GCompareFunc  func)
 
513
{
 
514
        int l, r, p, cmp = -1;
 
515
 
 
516
        l = 0;
 
517
        r = array->len;
 
518
        while (l < r) {
 
519
                p = l + ((r - l) / 2);
 
520
                cmp = func(value, &g_ptr_array_index (array, p));
 
521
                if (cmp == 0)
 
522
                        return p;
 
523
                else if (cmp < 0)
 
524
                        r = p;
 
525
                else
 
526
                        l = p + 1;
 
527
        }
 
528
 
 
529
        return -1;
 
530
}
 
531
 
 
532
 
 
533
/* GRegex */
 
534
 
 
535
 
 
536
gboolean
 
537
_g_regexp_matchv (GRegex           **regexps,
 
538
                  const char        *string,
 
539
                  GRegexMatchFlags   match_options)
 
540
{
 
541
        gboolean matched;
 
542
        int      i;
 
543
 
 
544
        if ((regexps == NULL) || (regexps[0] == NULL))
 
545
                return TRUE;
 
546
 
 
547
        if (string == NULL)
 
548
                return FALSE;
 
549
 
 
550
        matched = FALSE;
 
551
        for (i = 0; regexps[i] != NULL; i++)
 
552
                if (g_regex_match (regexps[i], string, match_options, NULL)) {
 
553
                        matched = TRUE;
 
554
                        break;
 
555
                }
 
556
 
 
557
        return matched;
 
558
}
 
559
 
 
560
 
 
561
void
 
562
_g_regexp_freev (GRegex **regexps)
 
563
{
 
564
        int i;
 
565
 
 
566
        if (regexps == NULL)
 
567
                return;
 
568
 
 
569
        for (i = 0; regexps[i] != NULL; i++)
 
570
                g_regex_unref (regexps[i]);
 
571
        g_free (regexps);
 
572
}
 
573
 
 
574
 
 
575
/* -- _g_regexp_get_patternv -- */
 
576
 
 
577
 
 
578
static const char *
 
579
_g_utf8_strstr (const char *haystack,
 
580
                const char *needle)
 
581
{
 
582
        const char *s;
 
583
        gsize       i;
 
584
        gsize       haystack_len = g_utf8_strlen (haystack, -1);
 
585
        gsize       needle_len = g_utf8_strlen (needle, -1);
 
586
        int         needle_size = strlen (needle);
 
587
 
 
588
        s = haystack;
 
589
        for (i = 0; i <= haystack_len - needle_len; i++) {
 
590
                if (strncmp (s, needle, needle_size) == 0)
 
591
                        return s;
 
592
                s = g_utf8_next_char(s);
 
593
        }
 
594
 
 
595
        return NULL;
 
596
}
 
597
 
 
598
 
 
599
static char **
 
600
_g_utf8_strsplit (const char *string,
 
601
                  const char *delimiter,
 
602
                  int         max_tokens)
 
603
{
 
604
        GSList      *string_list = NULL, *slist;
 
605
        char       **str_array;
 
606
        const char  *s;
 
607
        guint        n = 0;
 
608
        const char  *remainder;
 
609
 
 
610
        g_return_val_if_fail (string != NULL, NULL);
 
611
        g_return_val_if_fail (delimiter != NULL, NULL);
 
612
        g_return_val_if_fail (delimiter[0] != '\0', NULL);
 
613
 
 
614
        if (max_tokens < 1)
 
615
                max_tokens = G_MAXINT;
 
616
 
 
617
        remainder = string;
 
618
        s = _g_utf8_strstr (remainder, delimiter);
 
619
        if (s != NULL) {
 
620
                gsize delimiter_size = strlen (delimiter);
 
621
 
 
622
                while (--max_tokens && (s != NULL)) {
 
623
                        gsize  size = s - remainder;
 
624
                        char  *new_string;
 
625
 
 
626
                        new_string = g_new (char, size + 1);
 
627
                        strncpy (new_string, remainder, size);
 
628
                        new_string[size] = 0;
 
629
 
 
630
                        string_list = g_slist_prepend (string_list, new_string);
 
631
                        n++;
 
632
                        remainder = s + delimiter_size;
 
633
                        s = _g_utf8_strstr (remainder, delimiter);
 
634
                }
 
635
        }
 
636
        if (*string) {
 
637
                n++;
 
638
                string_list = g_slist_prepend (string_list, g_strdup (remainder));
 
639
        }
 
640
 
 
641
        str_array = g_new (char*, n + 1);
 
642
 
 
643
        str_array[n--] = NULL;
 
644
        for (slist = string_list; slist; slist = slist->next)
 
645
                str_array[n--] = slist->data;
 
646
 
 
647
        g_slist_free (string_list);
 
648
 
 
649
        return str_array;
 
650
}
 
651
 
 
652
 
 
653
static char*
 
654
g_utf8_strchug (char *string)
 
655
{
 
656
        char     *scan;
 
657
        gunichar  c;
 
658
 
 
659
        g_return_val_if_fail (string != NULL, NULL);
 
660
 
 
661
        scan = string;
 
662
        c = g_utf8_get_char (scan);
 
663
        while (g_unichar_isspace (c)) {
 
664
                scan = g_utf8_next_char (scan);
 
665
                c = g_utf8_get_char (scan);
 
666
        }
 
667
 
 
668
        memmove (string, scan, strlen (scan) + 1);
 
669
 
 
670
        return string;
 
671
}
 
672
 
 
673
 
 
674
static char*
 
675
g_utf8_strchomp (char *string)
 
676
{
 
677
        char   *scan;
 
678
        gsize   len;
 
679
 
 
680
        g_return_val_if_fail (string != NULL, NULL);
 
681
 
 
682
        len = g_utf8_strlen (string, -1);
 
683
 
 
684
        if (len == 0)
 
685
                return string;
 
686
 
 
687
        scan = g_utf8_offset_to_pointer (string, len - 1);
 
688
 
 
689
        while (len--) {
 
690
                gunichar c = g_utf8_get_char (scan);
 
691
                if (g_unichar_isspace (c))
 
692
                        *scan = '\0';
 
693
                else
 
694
                        break;
 
695
                scan = g_utf8_find_prev_char (string, scan);
 
696
        }
 
697
 
 
698
        return string;
 
699
}
 
700
 
 
701
 
 
702
#define g_utf8_strstrip(string) g_utf8_strchomp (g_utf8_strchug (string))
 
703
 
 
704
 
 
705
char **
 
706
_g_regexp_get_patternv (const char *pattern_string)
 
707
{
 
708
        char **patterns;
 
709
        int    i;
 
710
 
 
711
        if (pattern_string == NULL)
 
712
                return NULL;
 
713
 
 
714
        patterns = _g_utf8_strsplit (pattern_string, ";", MAX_PATTERNS);
 
715
        for (i = 0; patterns[i] != NULL; i++) {
 
716
                char *p1, *p2;
 
717
 
 
718
                p1 = g_utf8_strstrip (patterns[i]);
 
719
                p2 = _g_str_substitute (p1, ".", "\\.");
 
720
                patterns[i] = _g_str_substitute (p2, "*", ".*");
 
721
 
 
722
                g_free (p2);
 
723
                g_free (p1);
 
724
        }
 
725
 
 
726
        return patterns;
 
727
}
 
728
 
 
729
 
 
730
GRegex **
 
731
_g_regexp_split_from_patterns (const char         *pattern_string,
 
732
                               GRegexCompileFlags  compile_options)
 
733
{
 
734
        char   **patterns;
 
735
        GRegex **regexps;
 
736
        int      i;
 
737
 
 
738
        patterns = _g_regexp_get_patternv (pattern_string);
 
739
        if (patterns == NULL)
 
740
                return NULL;
 
741
 
 
742
        regexps = g_new0 (GRegex*, g_strv_length (patterns) + 1);
 
743
        for (i = 0; patterns[i] != NULL; i++)
 
744
                regexps[i] = g_regex_new (patterns[i],
 
745
                                          G_REGEX_OPTIMIZE | compile_options,
 
746
                                          G_REGEX_MATCH_NOTEMPTY,
 
747
                                          NULL);
 
748
        g_strfreev (patterns);
 
749
 
 
750
        return regexps;
 
751
}
 
752
 
 
753
 
 
754
/* time */
 
755
 
 
756
 
 
757
char *
 
758
_g_time_to_string (time_t time)
 
759
{
 
760
        struct tm *tm;
 
761
        char       s_time[256];
 
762
        char      *locale_format = NULL;
 
763
        char      *time_utf8;
 
764
 
 
765
        tm = localtime (&time);
 
766
        /* This is the time format used in the "Date Modified" column and
 
767
         * in the Properties dialog.  See the man page of strftime for an
 
768
         * explanation of the values. */
 
769
        locale_format = g_locale_from_utf8 (_("%d %B %Y, %H:%M"), -1, NULL, NULL, NULL);
 
770
        strftime (s_time, sizeof (s_time) - 1, locale_format, tm);
 
771
        g_free (locale_format);
 
772
        time_utf8 = g_locale_to_utf8 (s_time, -1, NULL, NULL, NULL);
 
773
 
 
774
        return time_utf8;
 
775
}
 
776
 
 
777
 
 
778
/* uri/path/filename */
 
779
 
 
780
 
 
781
const char *
 
782
_g_uri_get_home (void)
 
783
{
 
784
        static char *home_uri = NULL;
 
785
        if (home_uri == NULL)
 
786
                home_uri = g_filename_to_uri (g_get_home_dir (), NULL, NULL);
 
787
        return home_uri;
 
788
}
 
789
 
 
790
 
 
791
char *
 
792
_g_uri_get_home_relative (const char *partial_uri)
 
793
{
 
794
        return g_strconcat (_g_uri_get_home (),
 
795
                            "/",
 
796
                            partial_uri,
 
797
                            NULL);
 
798
}
 
799
 
 
800
 
 
801
const char *
 
802
_g_uri_remove_host (const char *uri)
 
803
{
 
804
        const char *idx, *sep;
 
805
 
 
806
        if (uri == NULL)
 
807
                return NULL;
 
808
 
 
809
        idx = strstr (uri, "://");
 
810
        if (idx == NULL)
 
811
                return uri;
 
812
        idx += 3;
 
813
        if (*idx == '\0')
 
814
                return "/";
 
815
        sep = strstr (idx, "/");
 
816
        if (sep == NULL)
 
817
                return idx;
 
818
        return sep;
 
819
}
 
820
 
 
821
 
 
822
char *
 
823
_g_uri_get_host (const char *uri)
 
824
{
 
825
        const char *idx;
 
826
 
 
827
        idx = strstr (uri, "://");
 
828
        if (idx == NULL)
 
829
                return NULL;
 
830
        idx = strstr (idx + 3, "/");
 
831
        if (idx == NULL)
 
832
                return NULL;
 
833
        return g_strndup (uri, (idx - uri));
 
834
}
 
835
 
 
836
 
 
837
char *
 
838
_g_uri_get_root (const char *uri)
 
839
{
 
840
        char *host;
 
841
        char *root;
 
842
 
 
843
        host = _g_uri_get_host (uri);
 
844
        if (host == NULL)
 
845
                return NULL;
 
846
        root = g_strconcat (host, "/", NULL);
 
847
        g_free (host);
 
848
 
 
849
        return root;
 
850
}
 
851
 
 
852
 
 
853
int
 
854
_g_uri_cmp (const char *uri1,
 
855
            const char *uri2)
 
856
{
 
857
        return g_strcmp0 (uri1, uri2);
 
858
}
 
859
 
 
860
 
 
861
/* like g_path_get_basename but does not warn about NULL and does not
 
862
 * alloc a new string. */
 
863
const gchar *
 
864
_g_path_get_basename (const gchar *file_name)
 
865
{
 
866
        register char   *base;
 
867
        register gssize  last_char;
 
868
 
 
869
        if (file_name == NULL)
 
870
                return NULL;
 
871
 
 
872
        if (file_name[0] == '\0')
 
873
                return "";
 
874
 
 
875
        last_char = strlen (file_name) - 1;
 
876
 
 
877
        if (file_name [last_char] == G_DIR_SEPARATOR)
 
878
                return "";
 
879
 
 
880
        base = g_utf8_strrchr (file_name, -1, G_DIR_SEPARATOR);
 
881
        if (! base)
 
882
                return file_name;
 
883
 
 
884
        return base + 1;
 
885
}
 
886
 
 
887
 
 
888
char *
 
889
_g_path_get_dir_name (const gchar *path)
 
890
{
 
891
        register gssize base;
 
892
        register gssize last_char;
 
893
 
 
894
        if (path == NULL)
 
895
                return NULL;
 
896
 
 
897
        if (path[0] == '\0')
 
898
                return g_strdup ("");
 
899
 
 
900
        last_char = strlen (path) - 1;
 
901
        if (path[last_char] == G_DIR_SEPARATOR)
 
902
                last_char--;
 
903
 
 
904
        base = last_char;
 
905
        while ((base >= 0) && (path[base] != G_DIR_SEPARATOR))
 
906
                base--;
 
907
 
 
908
        return g_strndup (path + base + 1, last_char - base);
 
909
}
 
910
 
 
911
 
 
912
gchar *
 
913
_g_path_remove_level (const gchar *path)
 
914
{
 
915
        int         p;
 
916
        const char *ptr = path;
 
917
        char       *new_path;
 
918
 
 
919
        if (path == NULL)
 
920
                return NULL;
 
921
 
 
922
        p = strlen (path) - 1;
 
923
        if (p < 0)
 
924
                return NULL;
 
925
 
 
926
        /* ignore the first slash if it's the last character,
 
927
         * this way /a/b/ is treated as /a/b */
 
928
 
 
929
        if ((ptr[p] == '/') && (p > 0))
 
930
                p--;
 
931
 
 
932
        while ((p > 0) && (ptr[p] != '/'))
 
933
                p--;
 
934
        if ((p == 0) && (ptr[p] == '/'))
 
935
                p++;
 
936
        new_path = g_strndup (path, (guint)p);
 
937
 
 
938
        return new_path;
 
939
}
 
940
 
 
941
 
 
942
char *
 
943
_g_path_remove_ending_separator (const char *path)
 
944
{
 
945
        gint len, copy_len;
 
946
 
 
947
        if (path == NULL)
 
948
                return NULL;
 
949
 
 
950
        copy_len = len = strlen (path);
 
951
        if ((len > 1) && (path[len - 1] == '/'))
 
952
                copy_len--;
 
953
 
 
954
        return g_strndup (path, copy_len);
 
955
}
 
956
 
 
957
 
 
958
char *
 
959
_g_path_remove_extension (const gchar *path)
 
960
{
 
961
        const char *ext;
 
962
 
 
963
        if (path == NULL)
 
964
                return NULL;
 
965
 
 
966
        ext = _g_filename_get_extension (path);
 
967
        if (ext == NULL)
 
968
                return g_strdup (path);
 
969
        else
 
970
                return g_strndup (path, strlen (path) - strlen (ext));
 
971
}
 
972
 
 
973
 
 
974
char *
 
975
_g_path_remove_first_extension (const gchar *path)
 
976
{
 
977
        const char *ext;
 
978
 
 
979
        if (path == NULL)
 
980
                return NULL;
 
981
 
 
982
        ext = strrchr (path, '.');
 
983
        if (ext == NULL)
 
984
                return g_strdup (path);
 
985
        else
 
986
                return g_strndup (path, strlen (path) - strlen (ext));
 
987
}
 
988
 
 
989
 
 
990
/* Check whether the dirname is contained in filename */
 
991
gboolean
 
992
_g_path_is_parent_of (const char *dirname,
 
993
                      const char *filename)
 
994
{
 
995
        int dirname_l, filename_l, separator_position;
 
996
 
 
997
        if ((dirname == NULL) || (filename == NULL))
 
998
                return FALSE;
 
999
 
 
1000
        dirname_l = strlen (dirname);
 
1001
        filename_l = strlen (filename);
 
1002
 
 
1003
        if ((dirname_l == filename_l + 1)
 
1004
             && (dirname[dirname_l - 1] == '/'))
 
1005
                return FALSE;
 
1006
 
 
1007
        if ((filename_l == dirname_l + 1)
 
1008
             && (filename[filename_l - 1] == '/'))
 
1009
                return FALSE;
 
1010
 
 
1011
        if (dirname[dirname_l - 1] == '/')
 
1012
                separator_position = dirname_l - 1;
 
1013
        else
 
1014
                separator_position = dirname_l;
 
1015
 
 
1016
        return ((filename_l > dirname_l)
 
1017
                && (strncmp (dirname, filename, dirname_l) == 0)
 
1018
                && (filename[separator_position] == '/'));
 
1019
}
 
1020
 
 
1021
 
 
1022
const char *
 
1023
_g_path_get_relative_basename (const char *path,
 
1024
                               const char *base_dir,
 
1025
                               gboolean    junk_paths)
 
1026
{
 
1027
        int         base_dir_len;
 
1028
        const char *base_path;
 
1029
 
 
1030
        if (junk_paths)
 
1031
                return _g_path_get_basename (path);
 
1032
 
 
1033
        if (base_dir == NULL)
 
1034
                return (path[0] == '/') ? path + 1 : path;
 
1035
 
 
1036
        base_dir_len = strlen (base_dir);
 
1037
        if (strlen (path) < base_dir_len)
 
1038
                return NULL;
 
1039
 
 
1040
        base_path = path + base_dir_len;
 
1041
        if (path[0] != '/')
 
1042
                base_path -= 1;
 
1043
 
 
1044
        return base_path;
 
1045
}
 
1046
 
 
1047
 
 
1048
#define ISDOT(c) ((c) == '.')
 
1049
#define ISSLASH(c) ((c) == '/')
 
1050
 
 
1051
 
 
1052
static const char *
 
1053
sanitize_filename (const char *file_name)
 
1054
{
 
1055
        size_t      prefix_len;
 
1056
        char const *p;
 
1057
 
 
1058
        if (file_name == NULL)
 
1059
                return NULL;
 
1060
 
 
1061
        prefix_len = 0;
 
1062
        for (p = file_name; *p; ) {
 
1063
                if (ISDOT (p[0]) && ISDOT (p[1]) && (ISSLASH (p[2]) || !p[2]))
 
1064
                        prefix_len = p + 2 - file_name;
 
1065
 
 
1066
                do {
 
1067
                        char c = *p++;
 
1068
                        if (ISSLASH (c))
 
1069
                                break;
 
1070
                }
 
1071
                while (*p);
 
1072
        }
 
1073
 
 
1074
        p = file_name + prefix_len;
 
1075
        while (ISSLASH (*p))
 
1076
                p++;
 
1077
 
 
1078
        return p;
 
1079
}
 
1080
 
 
1081
 
 
1082
const char *
 
1083
_g_path_get_relative_basename_safe (const char *path,
 
1084
                                    const char *base_dir,
 
1085
                                    gboolean    junk_paths)
 
1086
{
 
1087
        return sanitize_filename (_g_path_get_relative_basename (path, base_dir, junk_paths));
 
1088
}
 
1089
 
 
1090
 
 
1091
gboolean
 
1092
_g_filename_is_hidden (const gchar *name)
 
1093
{
 
1094
        if (name[0] != '.') return FALSE;
 
1095
        if (name[1] == '\0') return FALSE;
 
1096
        if ((name[1] == '.') && (name[2] == '\0')) return FALSE;
 
1097
 
 
1098
        return TRUE;
 
1099
}
 
1100
 
 
1101
 
 
1102
const char *
 
1103
_g_filename_get_extension (const char *filename)
 
1104
{
 
1105
        const char *ptr = filename;
 
1106
        int         len;
 
1107
        int         p;
 
1108
        const char *ext;
 
1109
 
 
1110
        if (filename == NULL)
 
1111
                return NULL;
 
1112
 
 
1113
        len = strlen (filename);
 
1114
        if (len <= 1)
 
1115
                return NULL;
 
1116
 
 
1117
        p = len - 1;
 
1118
        while ((p >= 0) && (ptr[p] != '.'))
 
1119
                p--;
 
1120
        if (p < 0)
 
1121
                return NULL;
 
1122
 
 
1123
        ext = filename + p;
 
1124
        if (ext - 4 > filename) {
 
1125
                const char *test = ext - 4;
 
1126
                /* .tar.rz cannot be uncompressed in one step */
 
1127
                if ((strncmp (test, ".tar", 4) == 0) && (strncmp (ext, ".rz", 2) != 0))
 
1128
                        ext = ext - 4;
 
1129
        }
 
1130
        return ext;
 
1131
}
 
1132
 
 
1133
 
 
1134
gboolean
 
1135
_g_filename_has_extension (const char *filename,
 
1136
                   const char *ext)
 
1137
{
 
1138
        int filename_l, ext_l;
 
1139
 
 
1140
        filename_l = strlen (filename);
 
1141
        ext_l = strlen (ext);
 
1142
 
 
1143
        if (filename_l < ext_l)
 
1144
                return FALSE;
 
1145
        return strcasecmp (filename + filename_l - ext_l, ext) == 0;
 
1146
}
 
1147
 
 
1148
 
 
1149
char *
 
1150
_g_filename_get_random (int         random_part_len,
 
1151
                        const char *suffix)
 
1152
{
 
1153
        const char *letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
 
1154
        const int   n_letters = strlen (letters);
 
1155
        int         suffix_len;
 
1156
        char       *result, *c;
 
1157
        GRand      *rand;
 
1158
        int         i;
 
1159
 
 
1160
        suffix_len = suffix != NULL ? strlen (suffix) + 1 : 0;
 
1161
        result = g_new (char, suffix_len + random_part_len + 1);
 
1162
 
 
1163
        rand = g_rand_new ();
 
1164
        for (i = 0, c = result; i < random_part_len; i++, c++)
 
1165
                *c = letters[g_rand_int_range (rand, 0, n_letters)];
 
1166
        *c = '\0';
 
1167
        g_rand_free (rand);
 
1168
 
 
1169
        if (suffix != NULL) {
 
1170
                strcpy (c, ".");
 
1171
                strcpy (c + 1, suffix);
 
1172
        }
 
1173
 
 
1174
        return result;
 
1175
}
 
1176
 
 
1177
 
 
1178
gboolean
 
1179
_g_mime_type_matches (const char *mime_type,
 
1180
                      const char *pattern)
 
1181
{
 
1182
        return (strcasecmp (mime_type, pattern) == 0);
 
1183
}
 
1184
 
 
1185
 
 
1186
const char *
 
1187
_g_mime_type_get_from_content (char  *buffer,
 
1188
                               gsize  buffer_size)
 
1189
{
 
1190
#if ENABLE_MAGIC
 
1191
 
 
1192
        static magic_t magic = NULL;
 
1193
 
 
1194
        if (magic == NULL) {
 
1195
                magic = magic_open (MAGIC_MIME_TYPE);
 
1196
                if (magic != NULL)
 
1197
                        magic_load (magic, NULL);
 
1198
                else
 
1199
                        g_warning ("unable to open magic database");
 
1200
        }
 
1201
 
 
1202
        if (magic != NULL) {
 
1203
                const char * mime_type;
 
1204
 
 
1205
                mime_type = magic_buffer (magic, buffer, buffer_size);
 
1206
                if ((mime_type != NULL) && (strcmp (mime_type, "application/octet-stream") == 0))
 
1207
                        return NULL;
 
1208
 
 
1209
                if (mime_type != NULL)
 
1210
                        return mime_type;
 
1211
 
 
1212
                g_warning ("unable to detect filetype from magic: %s", magic_error (magic));
 
1213
        }
 
1214
 
 
1215
#else
 
1216
 
 
1217
        static const struct magic {
 
1218
                const unsigned int off;
 
1219
                const unsigned int len;
 
1220
                const char * const id;
 
1221
                const char * const mime_type;
 
1222
        }
 
1223
        magic_ids [] = {
 
1224
                /* magic ids taken from magic/Magdir/archive from the file-4.21 tarball */
 
1225
                { 0,  6, "7z\274\257\047\034",                   "application/x-7z-compressed" },
 
1226
                { 7,  7, "**ACE**",                              "application/x-ace"           },
 
1227
                { 0,  2, "\x60\xea",                             "application/x-arj"           },
 
1228
                { 0,  3, "BZh",                                  "application/x-bzip2"         },
 
1229
                { 0,  2, "\037\213",                             "application/x-gzip"          },
 
1230
                { 0,  4, "LZIP",                                 "application/x-lzip"          },
 
1231
                { 0,  9, "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a", "application/x-lzop",         },
 
1232
                { 0,  4, "Rar!",                                 "application/x-rar"           },
 
1233
                { 0,  4, "RZIP",                                 "application/x-rzip"          },
 
1234
                { 0,  6, "\3757zXZ\000",                         "application/x-xz"            },
 
1235
                { 20, 4, "\xdc\xa7\xc4\xfd",                     "application/x-zoo",          },
 
1236
                { 0,  4, "PK\003\004",                           "application/zip"             },
 
1237
                { 0,  8, "PK00PK\003\004",                       "application/zip"             },
 
1238
                { 0,  4, "LRZI",                                 "application/x-lrzip"         },
 
1239
        };
 
1240
 
 
1241
        int  i;
 
1242
 
 
1243
        for (i = 0; i < G_N_ELEMENTS (magic_ids); i++) {
 
1244
                const struct magic * const magic = &magic_ids[i];
 
1245
 
 
1246
                if ((magic->off + magic->len) > buffer_size)
 
1247
                        g_warning ("buffer underrun for mime-type '%s' magic", magic->mime_type);
 
1248
                else if (! memcmp (buffer + magic->off, magic->id, magic->len))
 
1249
                        return magic->mime_type;
 
1250
        }
 
1251
 
 
1252
#endif
 
1253
 
 
1254
        return NULL;
 
1255
}
 
1256
 
 
1257
 
 
1258
/* GFile */
 
1259
 
 
1260
 
 
1261
int
 
1262
_g_file_cmp_uris (GFile *a,
 
1263
                  GFile *b)
 
1264
{
 
1265
        char *uri_a;
 
1266
        char *uri_b;
 
1267
        int   result;
 
1268
 
 
1269
        uri_a = g_file_get_uri (a);
 
1270
        uri_b = g_file_get_uri (b);
 
1271
        result = g_strcmp0 (uri_a, uri_b);
 
1272
 
 
1273
        g_free (uri_b);
 
1274
        g_free (uri_a);
 
1275
 
 
1276
        return result;
 
1277
}
 
1278
 
 
1279
 
 
1280
gboolean
 
1281
_g_file_is_local (GFile *file)
 
1282
{
 
1283
        char     *scheme;
 
1284
        gboolean  is_local;
 
1285
 
 
1286
        scheme = g_file_get_uri_scheme (file);
 
1287
        is_local = strcmp (scheme, "file") == 0;
 
1288
 
 
1289
        g_free (scheme);
 
1290
 
 
1291
        return is_local;
 
1292
}
 
1293
 
 
1294
 
 
1295
GFile *
 
1296
_g_file_get_home (void)
 
1297
{
 
1298
        static GFile *file = NULL;
 
1299
 
 
1300
        if (file != NULL)
 
1301
                return file;
 
1302
 
 
1303
        file = g_file_new_for_path (g_get_home_dir ());
 
1304
 
 
1305
        return file;
 
1306
}
 
1307
 
 
1308
 
 
1309
char *
 
1310
_g_file_get_display_basename (GFile *file)
 
1311
{
 
1312
        char *uri, *e_name, *name;
 
1313
 
 
1314
        uri = g_file_get_uri (file);
 
1315
        e_name = g_filename_display_basename (uri);
 
1316
        name = g_uri_unescape_string (e_name, "");
 
1317
 
 
1318
        g_free (e_name);
 
1319
        g_free (uri);
 
1320
 
 
1321
        return name;
 
1322
}
 
1323
 
 
1324
 
 
1325
GFile *
 
1326
_g_file_new_home_relative (const char *partial_uri)
 
1327
{
 
1328
        GFile *file;
 
1329
        char  *uri;
 
1330
 
 
1331
        uri = g_strconcat (_g_uri_get_home (), "/", partial_uri, NULL);
 
1332
        file = g_file_new_for_uri (uri);
 
1333
        g_free (uri);
 
1334
 
 
1335
        return file;
 
1336
}
 
1337
 
 
1338
 
 
1339
GList *
 
1340
_g_file_list_dup (GList *l)
 
1341
{
 
1342
        GList *r = NULL, *scan;
 
1343
        for (scan = l; scan; scan = scan->next)
 
1344
                r = g_list_prepend (r, g_file_dup ((GFile*) scan->data));
 
1345
        return g_list_reverse (r);
 
1346
}
 
1347
 
 
1348
 
 
1349
void
 
1350
_g_file_list_free (GList *l)
 
1351
{
 
1352
        GList *scan;
 
1353
        for (scan = l; scan; scan = scan->next)
 
1354
                g_object_unref (scan->data);
 
1355
        g_list_free (l);
 
1356
}
 
1357
 
 
1358
 
 
1359
GList *
 
1360
_g_file_list_new_from_uri_list (GList *uris)
 
1361
{
 
1362
        GList *r = NULL, *scan;
 
1363
        for (scan = uris; scan; scan = scan->next)
 
1364
                r = g_list_prepend (r, g_file_new_for_uri ((char*)scan->data));
 
1365
        return g_list_reverse (r);
 
1366
}
 
1367
 
 
1368
 
 
1369
GFile *
 
1370
_g_file_append_path (GFile  *file,
 
1371
                     ...)
 
1372
{
 
1373
        char       *uri;
 
1374
        const char *path;
 
1375
        va_list     args;
 
1376
        GFile      *new_file;
 
1377
 
 
1378
        uri = g_file_get_uri (file);
 
1379
 
 
1380
        va_start (args, file);
 
1381
        while ((path = va_arg (args, const char *)) != NULL) {
 
1382
                char *escaped;
 
1383
                char *new_uri;
 
1384
 
 
1385
                escaped = g_uri_escape_string (path, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, FALSE);
 
1386
                new_uri = g_build_filename (uri, escaped, NULL);
 
1387
                g_free (uri);
 
1388
                uri = new_uri;
 
1389
 
 
1390
                g_free (escaped);
 
1391
        }
 
1392
        va_end (args);
 
1393
        new_file = g_file_new_for_uri (uri);
 
1394
 
 
1395
        g_free (uri);
 
1396
 
 
1397
        return new_file;
 
1398
}
 
1399
 
 
1400
 
 
1401
/* GKeyFile */
 
1402
 
 
1403
 
 
1404
GList *
 
1405
_g_key_file_get_string_list (GKeyFile    *key_file,
 
1406
                             const char  *group_name,
 
1407
                             const char  *key,
 
1408
                             GError    **error)
 
1409
{
 
1410
        char  **strv;
 
1411
        GList  *list;
 
1412
        int     i;
 
1413
 
 
1414
        strv = g_key_file_get_string_list (key_file, group_name, key, NULL, error);
 
1415
        if (strv == NULL)
 
1416
                return NULL;
 
1417
 
 
1418
        list = NULL;
 
1419
        for (i = 0; strv[i] != NULL; i++)
 
1420
                list = g_list_prepend (list, strv[i]);
 
1421
 
 
1422
        g_free (strv);
 
1423
 
 
1424
        return g_list_reverse (list);
 
1425
}
 
1426
 
 
1427
 
 
1428
/* GSettings utils */
 
1429
 
 
1430
 
 
1431
GSettings *
 
1432
_g_settings_new_if_schema_installed (const char *schema_id)
 
1433
{
 
1434
        GSettingsSchema *schema;
 
1435
 
 
1436
        schema = g_settings_schema_source_lookup (g_settings_schema_source_get_default (),
 
1437
                                                  schema_id,
 
1438
                                                  TRUE);
 
1439
        if (schema == NULL)
 
1440
                return NULL;
 
1441
 
 
1442
        g_settings_schema_unref (schema);
 
1443
 
 
1444
        return g_settings_new (schema_id);
 
1445
}
 
1446
 
 
1447
 
 
1448
/* line parser */
 
1449
 
 
1450
 
 
1451
gboolean
 
1452
_g_line_matches_pattern (const char *line,
 
1453
                         const char *pattern)
 
1454
{
 
1455
        const char *l = line, *p = pattern;
 
1456
 
 
1457
        for (/* void */; (*p != 0) && (*l != 0); p++, l++) {
 
1458
                if (*p != '%') {
 
1459
                        if (*p != *l)
 
1460
                                return FALSE;
 
1461
                }
 
1462
                else {
 
1463
                        p++;
 
1464
                        switch (*p) {
 
1465
                        case 'a':
 
1466
                                break;
 
1467
                        case 'n':
 
1468
                                if (!isdigit (*l))
 
1469
                                        return FALSE;
 
1470
                                break;
 
1471
                        case 'c':
 
1472
                                if (!isalpha (*l))
 
1473
                                        return FALSE;
 
1474
                                break;
 
1475
                        default:
 
1476
                                return FALSE;
 
1477
                        }
 
1478
                }
 
1479
        }
 
1480
 
 
1481
        return (*p == 0);
 
1482
}
 
1483
 
 
1484
 
 
1485
int
 
1486
_g_line_get_index_from_pattern (const char *line,
 
1487
                                const char *pattern)
 
1488
{
 
1489
        int         line_l, pattern_l;
 
1490
        const char *l;
 
1491
 
 
1492
        line_l = strlen (line);
 
1493
        pattern_l = strlen (pattern);
 
1494
 
 
1495
        if ((pattern_l == 0) || (line_l == 0))
 
1496
                return -1;
 
1497
 
 
1498
        for (l = line; *l != 0; l++)
 
1499
                if (_g_line_matches_pattern (l, pattern))
 
1500
                        return (l - line);
 
1501
 
 
1502
        return -1;
 
1503
}
 
1504
 
 
1505
 
 
1506
char*
 
1507
_g_line_get_next_field (const char *line,
 
1508
                        int         start_from,
 
1509
                        int         field_n)
 
1510
{
 
1511
        const char *f_start, *f_end;
 
1512
 
 
1513
        line = line + start_from;
 
1514
 
 
1515
        f_start = line;
 
1516
        while ((*f_start == ' ') && (*f_start != *line))
 
1517
                f_start++;
 
1518
        f_end = f_start;
 
1519
 
 
1520
        while ((field_n > 0) && (*f_end != 0)) {
 
1521
                if (*f_end == ' ') {
 
1522
                        field_n--;
 
1523
                        if (field_n != 0) {
 
1524
                                while ((*f_end == ' ') && (*f_end != *line))
 
1525
                                        f_end++;
 
1526
                                f_start = f_end;
 
1527
                        }
 
1528
                }
 
1529
                else
 
1530
                        f_end++;
 
1531
        }
 
1532
 
 
1533
        return g_strndup (f_start, f_end - f_start);
 
1534
}
 
1535
 
 
1536
 
 
1537
char*
 
1538
_g_line_get_prev_field (const char *line,
 
1539
                        int         start_from,
 
1540
                        int         field_n)
 
1541
{
 
1542
        const char *f_start, *f_end;
 
1543
 
 
1544
        f_start = line + start_from - 1;
 
1545
        while ((*f_start == ' ') && (*f_start != *line))
 
1546
                f_start--;
 
1547
        f_end = f_start;
 
1548
 
 
1549
        while ((field_n > 0) && (*f_start != *line)) {
 
1550
                if (*f_start == ' ') {
 
1551
                        field_n--;
 
1552
                        if (field_n != 0) {
 
1553
                                while ((*f_start == ' ') && (*f_start != *line))
 
1554
                                        f_start--;
 
1555
                                f_end = f_start;
 
1556
                        }
 
1557
                }
 
1558
                else
 
1559
                        f_start--;
 
1560
        }
 
1561
 
 
1562
        return g_strndup (f_start + 1, f_end - f_start);
 
1563
}
 
1564
 
 
1565
 
 
1566
/* debug */
 
1567
 
 
1568
void
 
1569
debug (const char *file,
 
1570
       int         line,
 
1571
       const char *function,
 
1572
       const char *format, ...)
 
1573
{
 
1574
#ifdef DEBUG
 
1575
        va_list  args;
 
1576
        char    *str;
 
1577
 
 
1578
        g_return_if_fail (format != NULL);
 
1579
 
 
1580
        va_start (args, format);
 
1581
        str = g_strdup_vprintf (format, args);
 
1582
        va_end (args);
 
1583
 
 
1584
        g_fprintf (stderr, "[FR] %s:%d (%s):\n\t%s\n", file, line, function, str);
 
1585
 
 
1586
        g_free (str);
 
1587
#else /* ! DEBUG */
 
1588
#endif
 
1589
}