Coverage Report

Created: 2026-07-16 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/glib/glib/gkeyfile.c
Line
Count
Source
1
/* gkeyfile.c - key file parser
2
 *
3
 *  Copyright 2004  Red Hat, Inc.  
4
 *  Copyright 2009-2010  Collabora Ltd.
5
 *  Copyright 2009  Nokia Corporation
6
 *
7
 * Written by Ray Strode <rstrode@redhat.com>
8
 *            Matthias Clasen <mclasen@redhat.com>
9
 *
10
 * This library is free software; you can redistribute it and/or
11
 * modify it under the terms of the GNU Lesser General Public
12
 * License as published by the Free Software Foundation; either
13
 * version 2.1 of the License, or (at your option) any later version.
14
 *
15
 * This library is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
 * Lesser General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Lesser General Public License
21
 * along with this library; if not, see <http://www.gnu.org/licenses/>.
22
 */
23
24
#include "config.h"
25
26
#include "gkeyfile.h"
27
#include "gutils.h"
28
29
#include <errno.h>
30
#include <fcntl.h>
31
#include <locale.h>
32
#include <string.h>
33
#include <stdio.h>
34
#include <stdlib.h>
35
#include <sys/types.h>
36
#include <sys/stat.h>
37
#ifdef G_OS_UNIX
38
#include <unistd.h>
39
#endif
40
#ifdef G_OS_WIN32
41
#include <io.h>
42
43
#undef fstat
44
#define fstat(a,b) _fstati64(a,b)
45
#undef stat
46
#define stat _stati64
47
48
#ifndef S_ISREG
49
#define S_ISREG(mode) ((mode)&_S_IFREG)
50
#endif
51
52
#endif  /* G_OS_WIN23 */
53
54
#include "gconvert.h"
55
#include "gdataset.h"
56
#include "gerror.h"
57
#include "gfileutils.h"
58
#include "ghash.h"
59
#include "glibintl.h"
60
#include "glist.h"
61
#include "gslist.h"
62
#include "gmem.h"
63
#include "gmessages.h"
64
#include "gstdio.h"
65
#include "gstring.h"
66
#include "gstrfuncs.h"
67
#include "gutils.h"
68
69
70
/**
71
 * SECTION:keyfile
72
 * @title: Key-value file parser
73
 * @short_description: parses .ini-like config files
74
 *
75
 * #GKeyFile lets you parse, edit or create files containing groups of
76
 * key-value pairs, which we call "key files" for lack of a better name.
77
 * Several freedesktop.org specifications use key files now, e.g the
78
 * [Desktop Entry Specification](http://freedesktop.org/Standards/desktop-entry-spec)
79
 * and the
80
 * [Icon Theme Specification](http://freedesktop.org/Standards/icon-theme-spec).
81
 *
82
 * The syntax of key files is described in detail in the
83
 * [Desktop Entry Specification](http://freedesktop.org/Standards/desktop-entry-spec),
84
 * here is a quick summary: Key files
85
 * consists of groups of key-value pairs, interspersed with comments.
86
 *
87
 * |[
88
 * # this is just an example
89
 * # there can be comments before the first group
90
 *
91
 * [First Group]
92
 *
93
 * Name=Key File Example\tthis value shows\nescaping
94
 *
95
 * # localized strings are stored in multiple key-value pairs
96
 * Welcome=Hello
97
 * Welcome[de]=Hallo
98
 * Welcome[fr_FR]=Bonjour
99
 * Welcome[it]=Ciao
100
 * Welcome[be@latin]=Hello
101
 *
102
 * [Another Group]
103
 *
104
 * Numbers=2;20;-200;0
105
 *
106
 * Booleans=true;false;true;true
107
 * ]|
108
 *
109
 * Lines beginning with a '#' and blank lines are considered comments.
110
 *
111
 * Groups are started by a header line containing the group name enclosed
112
 * in '[' and ']', and ended implicitly by the start of the next group or
113
 * the end of the file. Each key-value pair must be contained in a group.
114
 *
115
 * Key-value pairs generally have the form `key=value`, with the
116
 * exception of localized strings, which have the form
117
 * `key[locale]=value`, with a locale identifier of the
118
 * form `lang_COUNTRY@MODIFIER` where `COUNTRY` and `MODIFIER`
119
 * are optional.
120
 * Space before and after the '=' character are ignored. Newline, tab,
121
 * carriage return and backslash characters in value are escaped as \n,
122
 * \t, \r, and \\\\, respectively. To preserve leading spaces in values,
123
 * these can also be escaped as \s.
124
 *
125
 * Key files can store strings (possibly with localized variants), integers,
126
 * booleans and lists of these. Lists are separated by a separator character,
127
 * typically ';' or ','. To use the list separator character in a value in
128
 * a list, it has to be escaped by prefixing it with a backslash.
129
 *
130
 * This syntax is obviously inspired by the .ini files commonly met
131
 * on Windows, but there are some important differences:
132
 *
133
 * - .ini files use the ';' character to begin comments,
134
 *   key files use the '#' character.
135
 *
136
 * - Key files do not allow for ungrouped keys meaning only
137
 *   comments can precede the first group.
138
 *
139
 * - Key files are always encoded in UTF-8.
140
 *
141
 * - Key and Group names are case-sensitive. For example, a group called
142
 *   [GROUP] is a different from [group].
143
 *
144
 * - .ini files don't have a strongly typed boolean entry type,
145
 *    they only have GetProfileInt(). In key files, only
146
 *    true and false (in lower case) are allowed.
147
 *
148
 * Note that in contrast to the
149
 * [Desktop Entry Specification](http://freedesktop.org/Standards/desktop-entry-spec),
150
 * groups in key files may contain the same
151
 * key multiple times; the last entry wins. Key files may also contain
152
 * multiple groups with the same name; they are merged together.
153
 * Another difference is that keys and group names in key files are not
154
 * restricted to ASCII characters.
155
 *
156
 * Here is an example of loading a key file and reading a value:
157
 * |[<!-- language="C" -->
158
 * g_autoptr(GError) error = NULL;
159
 * g_autoptr(GKeyFile) key_file = g_key_file_new ();
160
 *
161
 * if (!g_key_file_load_from_file (key_file, "key-file.ini", flags, &error))
162
 *   {
163
 *     if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
164
 *       g_warning ("Error loading key file: %s", error->message);
165
 *     return;
166
 *   }
167
 *
168
 * g_autofree gchar *val = g_key_file_get_string (key_file, "Group Name", "SomeKey", &error);
169
 * if (val == NULL &&
170
 *     !g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND))
171
 *   {
172
 *     g_warning ("Error finding key in key file: %s", error->message);
173
 *     return;
174
 *   }
175
 * else if (val == NULL)
176
 *   {
177
 *     // Fall back to a default value.
178
 *     val = g_strdup ("default-value");
179
 *   }
180
 * ]|
181
 *
182
 * Here is an example of creating and saving a key file:
183
 * |[<!-- language="C" -->
184
 * g_autoptr(GKeyFile) key_file = g_key_file_new ();
185
 * const gchar *val = …;
186
 * g_autoptr(GError) error = NULL;
187
 *
188
 * g_key_file_set_string (key_file, "Group Name", "SomeKey", val);
189
 *
190
 * // Save as a file.
191
 * if (!g_key_file_save_to_file (key_file, "key-file.ini", &error))
192
 *   {
193
 *     g_warning ("Error saving key file: %s", error->message);
194
 *     return;
195
 *   }
196
 *
197
 * // Or store to a GBytes for use elsewhere.
198
 * gsize data_len;
199
 * g_autofree guint8 *data = (guint8 *) g_key_file_to_data (key_file, &data_len, &error);
200
 * if (data == NULL)
201
 *   {
202
 *     g_warning ("Error saving key file: %s", error->message);
203
 *     return;
204
 *   }
205
 * g_autoptr(GBytes) bytes = g_bytes_new_take (g_steal_pointer (&data), data_len);
206
 * ]|
207
 */
208
209
/**
210
 * G_KEY_FILE_ERROR:
211
 *
212
 * Error domain for key file parsing. Errors in this domain will
213
 * be from the #GKeyFileError enumeration.
214
 *
215
 * See #GError for information on error domains.
216
 */
217
218
/**
219
 * GKeyFileError:
220
 * @G_KEY_FILE_ERROR_UNKNOWN_ENCODING: the text being parsed was in
221
 *     an unknown encoding
222
 * @G_KEY_FILE_ERROR_PARSE: document was ill-formed
223
 * @G_KEY_FILE_ERROR_NOT_FOUND: the file was not found
224
 * @G_KEY_FILE_ERROR_KEY_NOT_FOUND: a requested key was not found
225
 * @G_KEY_FILE_ERROR_GROUP_NOT_FOUND: a requested group was not found
226
 * @G_KEY_FILE_ERROR_INVALID_VALUE: a value could not be parsed
227
 *
228
 * Error codes returned by key file parsing.
229
 */
230
231
/**
232
 * GKeyFileFlags:
233
 * @G_KEY_FILE_NONE: No flags, default behaviour
234
 * @G_KEY_FILE_KEEP_COMMENTS: Use this flag if you plan to write the
235
 *     (possibly modified) contents of the key file back to a file;
236
 *     otherwise all comments will be lost when the key file is
237
 *     written back.
238
 * @G_KEY_FILE_KEEP_TRANSLATIONS: Use this flag if you plan to write the
239
 *     (possibly modified) contents of the key file back to a file;
240
 *     otherwise only the translations for the current language will be
241
 *     written back.
242
 *
243
 * Flags which influence the parsing.
244
 */
245
246
/**
247
 * G_KEY_FILE_DESKTOP_GROUP:
248
 *
249
 * The name of the main group of a desktop entry file, as defined in the
250
 * [Desktop Entry Specification](http://freedesktop.org/Standards/desktop-entry-spec).
251
 * Consult the specification for more
252
 * details about the meanings of the keys below.
253
 *
254
 * Since: 2.14
255
 */
256
257
/**
258
 * G_KEY_FILE_DESKTOP_KEY_TYPE:
259
 *
260
 * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a string
261
 * giving the type of the desktop entry. Usually
262
 * #G_KEY_FILE_DESKTOP_TYPE_APPLICATION,
263
 * #G_KEY_FILE_DESKTOP_TYPE_LINK, or
264
 * #G_KEY_FILE_DESKTOP_TYPE_DIRECTORY.
265
 *
266
 * Since: 2.14
267
 */
268
269
/**
270
 * G_KEY_FILE_DESKTOP_KEY_VERSION:
271
 *
272
 * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a string
273
 * giving the version of the Desktop Entry Specification used for
274
 * the desktop entry file.
275
 *
276
 * Since: 2.14
277
 */
278
279
/**
280
 * G_KEY_FILE_DESKTOP_KEY_NAME:
281
 *
282
 * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a localized
283
 * string giving the specific name of the desktop entry.
284
 *
285
 * Since: 2.14
286
 */
287
288
/**
289
 * G_KEY_FILE_DESKTOP_KEY_GENERIC_NAME:
290
 *
291
 * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a localized
292
 * string giving the generic name of the desktop entry.
293
 *
294
 * Since: 2.14
295
 */
296
297
/**
298
 * G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY:
299
 *
300
 * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a boolean
301
 * stating whether the desktop entry should be shown in menus.
302
 *
303
 * Since: 2.14
304
 */
305
306
/**
307
 * G_KEY_FILE_DESKTOP_KEY_COMMENT:
308
 *
309
 * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a localized
310
 * string giving the tooltip for the desktop entry.
311
 *
312
 * Since: 2.14
313
 */
314
315
/**
316
 * G_KEY_FILE_DESKTOP_KEY_ICON:
317
 *
318
 * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a localized
319
 * string giving the name of the icon to be displayed for the desktop
320
 * entry.
321
 *
322
 * Since: 2.14
323
 */
324
325
/**
326
 * G_KEY_FILE_DESKTOP_KEY_HIDDEN:
327
 *
328
 * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a boolean
329
 * stating whether the desktop entry has been deleted by the user.
330
 *
331
 * Since: 2.14
332
 */
333
334
/**
335
 * G_KEY_FILE_DESKTOP_KEY_ONLY_SHOW_IN:
336
 *
337
 * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a list of
338
 * strings identifying the environments that should display the
339
 * desktop entry.
340
 *
341
 * Since: 2.14
342
 */
343
344
/**
345
 * G_KEY_FILE_DESKTOP_KEY_NOT_SHOW_IN:
346
 *
347
 * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a list of
348
 * strings identifying the environments that should not display the
349
 * desktop entry.
350
 *
351
 * Since: 2.14
352
 */
353
354
/**
355
 * G_KEY_FILE_DESKTOP_KEY_TRY_EXEC:
356
 *
357
 * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a string
358
 * giving the file name of a binary on disk used to determine if the
359
 * program is actually installed. It is only valid for desktop entries
360
 * with the `Application` type.
361
 *
362
 * Since: 2.14
363
 */
364
365
/**
366
 * G_KEY_FILE_DESKTOP_KEY_EXEC:
367
 *
368
 * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a string
369
 * giving the command line to execute. It is only valid for desktop
370
 * entries with the `Application` type.
371
 *
372
 * Since: 2.14
373
 */
374
375
 /**
376
  * G_KEY_FILE_DESKTOP_KEY_PATH:
377
  *
378
  * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a string
379
  * containing the working directory to run the program in. It is only
380
  * valid for desktop entries with the `Application` type.
381
  *
382
  * Since: 2.14
383
  */
384
385
/**
386
 * G_KEY_FILE_DESKTOP_KEY_TERMINAL:
387
 *
388
 * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a boolean
389
 * stating whether the program should be run in a terminal window.
390
 * It is only valid for desktop entries with the
391
 * `Application` type.
392
 *
393
 * Since: 2.14
394
 */
395
396
/**
397
 * G_KEY_FILE_DESKTOP_KEY_MIME_TYPE:
398
 *
399
 * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a list
400
 * of strings giving the MIME types supported by this desktop entry.
401
 *
402
 * Since: 2.14
403
 */
404
405
/**
406
 * G_KEY_FILE_DESKTOP_KEY_CATEGORIES:
407
 *
408
 * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a list
409
 * of strings giving the categories in which the desktop entry
410
 * should be shown in a menu.
411
 *
412
 * Since: 2.14
413
 */
414
415
/**
416
 * G_KEY_FILE_DESKTOP_KEY_STARTUP_NOTIFY:
417
 *
418
 * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a boolean
419
 * stating whether the application supports the
420
 * [Startup Notification Protocol Specification](http://www.freedesktop.org/Standards/startup-notification-spec).
421
 *
422
 * Since: 2.14
423
 */
424
425
/**
426
 * G_KEY_FILE_DESKTOP_KEY_STARTUP_WM_CLASS:
427
 *
428
 * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is string
429
 * identifying the WM class or name hint of a window that the application
430
 * will create, which can be used to emulate Startup Notification with
431
 * older applications.
432
 *
433
 * Since: 2.14
434
 */
435
436
/**
437
 * G_KEY_FILE_DESKTOP_KEY_URL:
438
 *
439
 * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a string
440
 * giving the URL to access. It is only valid for desktop entries
441
 * with the `Link` type.
442
 *
443
 * Since: 2.14
444
 */
445
446
/**
447
 * G_KEY_FILE_DESKTOP_KEY_DBUS_ACTIVATABLE:
448
 *
449
 * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a boolean set to true
450
 * if the application is D-Bus activatable.
451
 *
452
 * Since: 2.38
453
 */
454
455
/**
456
 * G_KEY_FILE_DESKTOP_KEY_ACTIONS:
457
 *
458
 * A key under #G_KEY_FILE_DESKTOP_GROUP, whose value is a string list
459
 * giving the available application actions.
460
 *
461
 * Since: 2.38
462
 */
463
464
/**
465
 * G_KEY_FILE_DESKTOP_TYPE_APPLICATION:
466
 *
467
 * The value of the #G_KEY_FILE_DESKTOP_KEY_TYPE, key for desktop
468
 * entries representing applications.
469
 *
470
 * Since: 2.14
471
 */
472
473
/**
474
 * G_KEY_FILE_DESKTOP_TYPE_LINK:
475
 *
476
 * The value of the #G_KEY_FILE_DESKTOP_KEY_TYPE, key for desktop
477
 * entries representing links to documents.
478
 *
479
 * Since: 2.14
480
 */
481
482
/**
483
 * G_KEY_FILE_DESKTOP_TYPE_DIRECTORY:
484
 *
485
 * The value of the #G_KEY_FILE_DESKTOP_KEY_TYPE, key for desktop
486
 * entries representing directories.
487
 *
488
 * Since: 2.14
489
 */
490
491
typedef struct _GKeyFileGroup GKeyFileGroup;
492
493
/**
494
 * GKeyFile:
495
 *
496
 * The GKeyFile struct contains only private data
497
 * and should not be accessed directly.
498
 */
499
struct _GKeyFile
500
{
501
  GList *groups;
502
  GHashTable *group_hash;
503
504
  GKeyFileGroup *start_group;
505
  GKeyFileGroup *current_group;
506
507
  GString *parse_buffer; /* Holds up to one line of not-yet-parsed data */
508
509
  gchar list_separator;
510
511
  GKeyFileFlags flags;
512
513
  gboolean checked_locales;
514
  gchar **locales;
515
516
  gint ref_count;  /* (atomic) */
517
};
518
519
typedef struct _GKeyFileKeyValuePair GKeyFileKeyValuePair;
520
521
struct _GKeyFileGroup
522
{
523
  const gchar *name;  /* NULL for above first group (which will be comments) */
524
525
  GKeyFileKeyValuePair *comment; /* Special comment that is stuck to the top of a group */
526
527
  GList *key_value_pairs;
528
529
  /* Used in parallel with key_value_pairs for
530
   * increased lookup performance
531
   */
532
  GHashTable *lookup_map;
533
};
534
535
struct _GKeyFileKeyValuePair
536
{
537
  gchar *key;  /* NULL for comments */
538
  gchar *value;
539
};
540
541
static gint                  find_file_in_data_dirs            (const gchar            *file,
542
                const gchar           **data_dirs,
543
                gchar                 **output_file,
544
                GError                **error);
545
static gboolean              g_key_file_load_from_fd           (GKeyFile               *key_file,
546
                gint                    fd,
547
                GKeyFileFlags           flags,
548
                GError                **error);
549
static GList                *g_key_file_lookup_group_node      (GKeyFile               *key_file,
550
                                              const gchar            *group_name);
551
static GKeyFileGroup        *g_key_file_lookup_group           (GKeyFile               *key_file,
552
                const gchar            *group_name);
553
554
static GList                *g_key_file_lookup_key_value_pair_node  (GKeyFile       *key_file,
555
                                                   GKeyFileGroup  *group,
556
                                                                     const gchar    *key);
557
static GKeyFileKeyValuePair *g_key_file_lookup_key_value_pair       (GKeyFile       *key_file,
558
                                                                     GKeyFileGroup  *group,
559
                                                                     const gchar    *key);
560
561
static void                  g_key_file_remove_group_node          (GKeyFile      *key_file,
562
                      GList         *group_node);
563
static void                  g_key_file_remove_key_value_pair_node (GKeyFile      *key_file,
564
                                                                    GKeyFileGroup *group,
565
                                                                    GList         *pair_node);
566
567
static void                  g_key_file_add_key_value_pair     (GKeyFile               *key_file,
568
                                                                GKeyFileGroup          *group,
569
                                                                GKeyFileKeyValuePair   *pair);
570
static void                  g_key_file_add_key                (GKeyFile               *key_file,
571
                GKeyFileGroup          *group,
572
                const gchar            *key,
573
                const gchar            *value);
574
static void                  g_key_file_add_group              (GKeyFile               *key_file,
575
                const gchar            *group_name);
576
static gboolean              g_key_file_is_group_name          (const gchar *name);
577
static gboolean              g_key_file_is_key_name            (const gchar *name);
578
static void                  g_key_file_key_value_pair_free    (GKeyFileKeyValuePair   *pair);
579
static gboolean              g_key_file_line_is_comment        (const gchar            *line);
580
static gboolean              g_key_file_line_is_group          (const gchar            *line);
581
static gboolean              g_key_file_line_is_key_value_pair (const gchar            *line);
582
static gchar                *g_key_file_parse_value_as_string  (GKeyFile               *key_file,
583
                const gchar            *value,
584
                GSList                **separators,
585
                GError                **error);
586
static gchar                *g_key_file_parse_string_as_value  (GKeyFile               *key_file,
587
                const gchar            *string,
588
                gboolean                escape_separator);
589
static gint                  g_key_file_parse_value_as_integer (GKeyFile               *key_file,
590
                const gchar            *value,
591
                GError                **error);
592
static gchar                *g_key_file_parse_integer_as_value (GKeyFile               *key_file,
593
                gint                    value);
594
static gdouble               g_key_file_parse_value_as_double  (GKeyFile               *key_file,
595
                                                                const gchar            *value,
596
                                                                GError                **error);
597
static gboolean              g_key_file_parse_value_as_boolean (GKeyFile               *key_file,
598
                const gchar            *value,
599
                GError                **error);
600
static gchar                *g_key_file_parse_boolean_as_value (GKeyFile               *key_file,
601
                gboolean                value);
602
static gchar                *g_key_file_parse_value_as_comment (GKeyFile               *key_file,
603
                                                                const gchar            *value,
604
                                                                gboolean                is_final_line);
605
static gchar                *g_key_file_parse_comment_as_value (GKeyFile               *key_file,
606
                                                                const gchar            *comment);
607
static void                  g_key_file_parse_key_value_pair   (GKeyFile               *key_file,
608
                const gchar            *line,
609
                gsize                   length,
610
                GError                **error);
611
static void                  g_key_file_parse_comment          (GKeyFile               *key_file,
612
                const gchar            *line,
613
                gsize                   length,
614
                GError                **error);
615
static void                  g_key_file_parse_group            (GKeyFile               *key_file,
616
                const gchar            *line,
617
                gsize                   length,
618
                GError                **error);
619
static gchar                *key_get_locale                    (const gchar            *key);
620
static void                  g_key_file_parse_data             (GKeyFile               *key_file,
621
                const gchar            *data,
622
                gsize                   length,
623
                GError                **error);
624
static void                  g_key_file_flush_parse_buffer     (GKeyFile               *key_file,
625
                GError                **error);
626
627
G_DEFINE_QUARK (g-key-file-error-quark, g_key_file_error)
628
629
static void
630
g_key_file_init (GKeyFile *key_file)
631
0
{  
632
0
  key_file->current_group = g_slice_new0 (GKeyFileGroup);
633
0
  key_file->groups = g_list_prepend (NULL, key_file->current_group);
634
0
  key_file->group_hash = NULL;
635
0
  key_file->start_group = NULL;
636
0
  key_file->parse_buffer = NULL;
637
0
  key_file->list_separator = ';';
638
0
  key_file->flags = 0;
639
0
}
640
641
static void
642
g_key_file_clear (GKeyFile *key_file)
643
0
{
644
0
  GList *tmp, *group_node;
645
646
0
  if (key_file->locales) 
647
0
    {
648
0
      g_strfreev (key_file->locales);
649
0
      key_file->locales = NULL;
650
0
    }
651
0
  key_file->checked_locales = FALSE;
652
653
0
  if (key_file->parse_buffer)
654
0
    {
655
0
      g_string_free (key_file->parse_buffer, TRUE);
656
0
      key_file->parse_buffer = NULL;
657
0
    }
658
659
0
  tmp = key_file->groups;
660
0
  while (tmp != NULL)
661
0
    {
662
0
      group_node = tmp;
663
0
      tmp = tmp->next;
664
0
      g_key_file_remove_group_node (key_file, group_node);
665
0
    }
666
667
0
  if (key_file->group_hash != NULL)
668
0
    {
669
0
      g_hash_table_destroy (key_file->group_hash);
670
0
      key_file->group_hash = NULL;
671
0
    }
672
673
0
  g_warn_if_fail (key_file->groups == NULL);
674
0
}
675
676
677
/**
678
 * g_key_file_new:
679
 *
680
 * Creates a new empty #GKeyFile object. Use
681
 * g_key_file_load_from_file(), g_key_file_load_from_data(),
682
 * g_key_file_load_from_dirs() or g_key_file_load_from_data_dirs() to
683
 * read an existing key file.
684
 *
685
 * Returns: (transfer full): an empty #GKeyFile.
686
 *
687
 * Since: 2.6
688
 **/
689
GKeyFile *
690
g_key_file_new (void)
691
0
{
692
0
  GKeyFile *key_file;
693
694
0
  key_file = g_slice_new0 (GKeyFile);
695
0
  key_file->ref_count = 1;
696
0
  g_key_file_init (key_file);
697
698
0
  return key_file;
699
0
}
700
701
/**
702
 * g_key_file_set_list_separator:
703
 * @key_file: a #GKeyFile 
704
 * @separator: the separator
705
 *
706
 * Sets the character which is used to separate
707
 * values in lists. Typically ';' or ',' are used
708
 * as separators. The default list separator is ';'.
709
 *
710
 * Since: 2.6
711
 */
712
void
713
g_key_file_set_list_separator (GKeyFile *key_file,
714
             gchar     separator)
715
0
{
716
0
  g_return_if_fail (key_file != NULL);
717
718
0
  key_file->list_separator = separator;
719
0
}
720
721
722
/* Iterates through all the directories in *dirs trying to
723
 * open file.  When it successfully locates and opens a file it
724
 * returns the file descriptor to the open file.  It also
725
 * outputs the absolute path of the file in output_file.
726
 */
727
static gint
728
find_file_in_data_dirs (const gchar   *file,
729
                        const gchar  **dirs,
730
                        gchar        **output_file,
731
                        GError       **error)
732
0
{
733
0
  const gchar **data_dirs, *data_dir;
734
0
  gchar *path;
735
0
  gint fd;
736
737
0
  path = NULL;
738
0
  fd = -1;
739
740
0
  if (dirs == NULL)
741
0
    return fd;
742
743
0
  data_dirs = dirs;
744
745
0
  while (data_dirs && (data_dir = *data_dirs) && fd == -1)
746
0
    {
747
0
      gchar *candidate_file, *sub_dir;
748
749
0
      candidate_file = (gchar *) file;
750
0
      sub_dir = g_strdup ("");
751
0
      while (candidate_file != NULL && fd == -1)
752
0
        {
753
0
          gchar *p;
754
755
0
          path = g_build_filename (data_dir, sub_dir,
756
0
                                   candidate_file, NULL);
757
758
0
          fd = g_open (path, O_RDONLY, 0);
759
760
0
          if (fd == -1)
761
0
            {
762
0
              g_free (path);
763
0
              path = NULL;
764
0
            }
765
766
0
          candidate_file = strchr (candidate_file, '-');
767
768
0
          if (candidate_file == NULL)
769
0
            break;
770
771
0
          candidate_file++;
772
773
0
          g_free (sub_dir);
774
0
          sub_dir = g_strndup (file, candidate_file - file - 1);
775
776
0
          for (p = sub_dir; *p != '\0'; p++)
777
0
            {
778
0
              if (*p == '-')
779
0
                *p = G_DIR_SEPARATOR;
780
0
            }
781
0
        }
782
0
      g_free (sub_dir);
783
0
      data_dirs++;
784
0
    }
785
786
0
  if (fd == -1)
787
0
    {
788
0
      g_set_error_literal (error, G_KEY_FILE_ERROR,
789
0
                           G_KEY_FILE_ERROR_NOT_FOUND,
790
0
                           _("Valid key file could not be "
791
0
                             "found in search dirs"));
792
0
    }
793
794
0
  if (output_file != NULL && fd != -1)
795
0
    *output_file = g_strdup (path);
796
797
0
  g_free (path);
798
799
0
  return fd;
800
0
}
801
802
static gboolean
803
g_key_file_load_from_fd (GKeyFile       *key_file,
804
       gint            fd,
805
       GKeyFileFlags   flags,
806
       GError        **error)
807
0
{
808
0
  GError *key_file_error = NULL;
809
0
  gssize bytes_read;
810
0
  struct stat stat_buf;
811
0
  gchar read_buf[4096];
812
0
  gchar list_separator;
813
814
0
  if (fstat (fd, &stat_buf) < 0)
815
0
    {
816
0
      int errsv = errno;
817
0
      g_set_error_literal (error, G_FILE_ERROR,
818
0
                           g_file_error_from_errno (errsv),
819
0
                           g_strerror (errsv));
820
0
      return FALSE;
821
0
    }
822
823
0
  if (!S_ISREG (stat_buf.st_mode))
824
0
    {
825
0
      g_set_error_literal (error, G_KEY_FILE_ERROR,
826
0
                           G_KEY_FILE_ERROR_PARSE,
827
0
                           _("Not a regular file"));
828
0
      return FALSE;
829
0
    }
830
831
0
  list_separator = key_file->list_separator;
832
0
  g_key_file_clear (key_file);
833
0
  g_key_file_init (key_file);
834
0
  key_file->list_separator = list_separator;
835
0
  key_file->flags = flags;
836
837
0
  do
838
0
    {
839
0
      int errsv;
840
841
0
      bytes_read = read (fd, read_buf, 4096);
842
0
      errsv = errno;
843
844
0
      if (bytes_read == 0)  /* End of File */
845
0
        break;
846
847
0
      if (bytes_read < 0)
848
0
        {
849
0
          if (errsv == EINTR || errsv == EAGAIN)
850
0
            continue;
851
852
0
          g_set_error_literal (error, G_FILE_ERROR,
853
0
                               g_file_error_from_errno (errsv),
854
0
                               g_strerror (errsv));
855
0
          return FALSE;
856
0
        }
857
858
0
      g_key_file_parse_data (key_file,
859
0
           read_buf, bytes_read,
860
0
           &key_file_error);
861
0
    }
862
0
  while (!key_file_error);
863
864
0
  if (key_file_error)
865
0
    {
866
0
      g_propagate_error (error, key_file_error);
867
0
      return FALSE;
868
0
    }
869
870
0
  g_key_file_flush_parse_buffer (key_file, &key_file_error);
871
872
0
  if (key_file_error)
873
0
    {
874
0
      g_propagate_error (error, key_file_error);
875
0
      return FALSE;
876
0
    }
877
878
0
  return TRUE;
879
0
}
880
881
/**
882
 * g_key_file_load_from_file:
883
 * @key_file: an empty #GKeyFile struct
884
 * @file: (type filename): the path of a filename to load, in the GLib filename encoding
885
 * @flags: flags from #GKeyFileFlags
886
 * @error: return location for a #GError, or %NULL
887
 *
888
 * Loads a key file into an empty #GKeyFile structure.
889
 *
890
 * If the OS returns an error when opening or reading the file, a
891
 * %G_FILE_ERROR is returned. If there is a problem parsing the file, a
892
 * %G_KEY_FILE_ERROR is returned.
893
 *
894
 * This function will never return a %G_KEY_FILE_ERROR_NOT_FOUND error. If the
895
 * @file is not found, %G_FILE_ERROR_NOENT is returned.
896
 *
897
 * Returns: %TRUE if a key file could be loaded, %FALSE otherwise
898
 *
899
 * Since: 2.6
900
 **/
901
gboolean
902
g_key_file_load_from_file (GKeyFile       *key_file,
903
         const gchar    *file,
904
         GKeyFileFlags   flags,
905
         GError        **error)
906
0
{
907
0
  GError *key_file_error = NULL;
908
0
  gint fd;
909
0
  int errsv;
910
911
0
  g_return_val_if_fail (key_file != NULL, FALSE);
912
0
  g_return_val_if_fail (file != NULL, FALSE);
913
914
0
  fd = g_open (file, O_RDONLY, 0);
915
0
  errsv = errno;
916
917
0
  if (fd == -1)
918
0
    {
919
0
      g_set_error_literal (error, G_FILE_ERROR,
920
0
                           g_file_error_from_errno (errsv),
921
0
                           g_strerror (errsv));
922
0
      return FALSE;
923
0
    }
924
925
0
  g_key_file_load_from_fd (key_file, fd, flags, &key_file_error);
926
0
  close (fd);
927
928
0
  if (key_file_error)
929
0
    {
930
0
      g_propagate_error (error, key_file_error);
931
0
      return FALSE;
932
0
    }
933
934
0
  return TRUE;
935
0
}
936
937
/**
938
 * g_key_file_load_from_data:
939
 * @key_file: an empty #GKeyFile struct
940
 * @data: key file loaded in memory
941
 * @length: the length of @data in bytes (or (gsize)-1 if data is nul-terminated)
942
 * @flags: flags from #GKeyFileFlags
943
 * @error: return location for a #GError, or %NULL
944
 *
945
 * Loads a key file from memory into an empty #GKeyFile structure.  
946
 * If the object cannot be created then %error is set to a #GKeyFileError. 
947
 *
948
 * Returns: %TRUE if a key file could be loaded, %FALSE otherwise
949
 *
950
 * Since: 2.6
951
 **/
952
gboolean
953
g_key_file_load_from_data (GKeyFile       *key_file,
954
         const gchar    *data,
955
         gsize           length,
956
         GKeyFileFlags   flags,
957
         GError        **error)
958
0
{
959
0
  GError *key_file_error = NULL;
960
0
  gchar list_separator;
961
962
0
  g_return_val_if_fail (key_file != NULL, FALSE);
963
0
  g_return_val_if_fail (data != NULL || length == 0, FALSE);
964
965
0
  if (length == (gsize)-1)
966
0
    length = strlen (data);
967
968
0
  list_separator = key_file->list_separator;
969
0
  g_key_file_clear (key_file);
970
0
  g_key_file_init (key_file);
971
0
  key_file->list_separator = list_separator;
972
0
  key_file->flags = flags;
973
974
0
  g_key_file_parse_data (key_file, data, length, &key_file_error);
975
  
976
0
  if (key_file_error)
977
0
    {
978
0
      g_propagate_error (error, key_file_error);
979
0
      return FALSE;
980
0
    }
981
982
0
  g_key_file_flush_parse_buffer (key_file, &key_file_error);
983
  
984
0
  if (key_file_error)
985
0
    {
986
0
      g_propagate_error (error, key_file_error);
987
0
      return FALSE;
988
0
    }
989
990
0
  return TRUE;
991
0
}
992
993
/**
994
 * g_key_file_load_from_bytes:
995
 * @key_file: an empty #GKeyFile struct
996
 * @bytes: a #GBytes
997
 * @flags: flags from #GKeyFileFlags
998
 * @error: return location for a #GError, or %NULL
999
 *
1000
 * Loads a key file from the data in @bytes into an empty #GKeyFile structure.
1001
 * If the object cannot be created then %error is set to a #GKeyFileError.
1002
 *
1003
 * Returns: %TRUE if a key file could be loaded, %FALSE otherwise
1004
 *
1005
 * Since: 2.50
1006
 **/
1007
gboolean
1008
g_key_file_load_from_bytes (GKeyFile       *key_file,
1009
                            GBytes         *bytes,
1010
                            GKeyFileFlags   flags,
1011
                            GError        **error)
1012
0
{
1013
0
  const guchar *data;
1014
0
  gsize size;
1015
1016
0
  g_return_val_if_fail (key_file != NULL, FALSE);
1017
0
  g_return_val_if_fail (bytes != NULL, FALSE);
1018
1019
0
  data = g_bytes_get_data (bytes, &size);
1020
0
  return g_key_file_load_from_data (key_file, (const gchar *) data, size, flags, error);
1021
0
}
1022
1023
/**
1024
 * g_key_file_load_from_dirs:
1025
 * @key_file: an empty #GKeyFile struct
1026
 * @file: (type filename): a relative path to a filename to open and parse
1027
 * @search_dirs: (array zero-terminated=1) (element-type filename): %NULL-terminated array of directories to search
1028
 * @full_path: (out) (type filename) (optional): return location for a string containing the full path
1029
 *   of the file, or %NULL
1030
 * @flags: flags from #GKeyFileFlags
1031
 * @error: return location for a #GError, or %NULL
1032
 *
1033
 * This function looks for a key file named @file in the paths
1034
 * specified in @search_dirs, loads the file into @key_file and
1035
 * returns the file's full path in @full_path.
1036
 *
1037
 * If the file could not be found in any of the @search_dirs,
1038
 * %G_KEY_FILE_ERROR_NOT_FOUND is returned. If
1039
 * the file is found but the OS returns an error when opening or reading the
1040
 * file, a %G_FILE_ERROR is returned. If there is a problem parsing the file, a
1041
 * %G_KEY_FILE_ERROR is returned.
1042
 *
1043
 * Returns: %TRUE if a key file could be loaded, %FALSE otherwise
1044
 *
1045
 * Since: 2.14
1046
 **/
1047
gboolean
1048
g_key_file_load_from_dirs (GKeyFile       *key_file,
1049
                           const gchar    *file,
1050
                           const gchar   **search_dirs,
1051
                           gchar         **full_path,
1052
                           GKeyFileFlags   flags,
1053
                           GError        **error)
1054
0
{
1055
0
  GError *key_file_error = NULL;
1056
0
  const gchar **data_dirs;
1057
0
  gchar *output_path;
1058
0
  gint fd;
1059
0
  gboolean found_file;
1060
1061
0
  g_return_val_if_fail (key_file != NULL, FALSE);
1062
0
  g_return_val_if_fail (!g_path_is_absolute (file), FALSE);
1063
0
  g_return_val_if_fail (search_dirs != NULL, FALSE);
1064
1065
0
  found_file = FALSE;
1066
0
  data_dirs = search_dirs;
1067
0
  output_path = NULL;
1068
0
  while (*data_dirs != NULL && !found_file)
1069
0
    {
1070
0
      g_free (output_path);
1071
0
      output_path = NULL;
1072
1073
0
      fd = find_file_in_data_dirs (file, data_dirs, &output_path,
1074
0
                                   &key_file_error);
1075
1076
0
      if (fd == -1)
1077
0
        {
1078
0
          if (key_file_error)
1079
0
            g_propagate_error (error, key_file_error);
1080
0
    break;
1081
0
        }
1082
1083
0
      found_file = g_key_file_load_from_fd (key_file, fd, flags,
1084
0
                                      &key_file_error);
1085
0
      close (fd);
1086
1087
0
      if (key_file_error)
1088
0
        {
1089
0
    g_propagate_error (error, key_file_error);
1090
0
    break;
1091
0
        }
1092
0
    }
1093
1094
0
  if (found_file && full_path)
1095
0
    *full_path = output_path;
1096
0
  else
1097
0
    g_free (output_path);
1098
1099
0
  return found_file;
1100
0
}
1101
1102
/**
1103
 * g_key_file_load_from_data_dirs:
1104
 * @key_file: an empty #GKeyFile struct
1105
 * @file: (type filename): a relative path to a filename to open and parse
1106
 * @full_path: (out) (type filename) (optional): return location for a string containing the full path
1107
 *   of the file, or %NULL
1108
 * @flags: flags from #GKeyFileFlags 
1109
 * @error: return location for a #GError, or %NULL
1110
 *
1111
 * This function looks for a key file named @file in the paths 
1112
 * returned from g_get_user_data_dir() and g_get_system_data_dirs(), 
1113
 * loads the file into @key_file and returns the file's full path in 
1114
 * @full_path.  If the file could not be loaded then an %error is
1115
 * set to either a #GFileError or #GKeyFileError.
1116
 *
1117
 * Returns: %TRUE if a key file could be loaded, %FALSE otherwise
1118
 * Since: 2.6
1119
 **/
1120
gboolean
1121
g_key_file_load_from_data_dirs (GKeyFile       *key_file,
1122
        const gchar    *file,
1123
        gchar         **full_path,
1124
        GKeyFileFlags   flags,
1125
        GError        **error)
1126
0
{
1127
0
  gchar **all_data_dirs;
1128
0
  const gchar * user_data_dir;
1129
0
  const gchar * const * system_data_dirs;
1130
0
  gsize i, j;
1131
0
  gboolean found_file;
1132
1133
0
  g_return_val_if_fail (key_file != NULL, FALSE);
1134
0
  g_return_val_if_fail (!g_path_is_absolute (file), FALSE);
1135
1136
0
  user_data_dir = g_get_user_data_dir ();
1137
0
  system_data_dirs = g_get_system_data_dirs ();
1138
0
  all_data_dirs = g_new (gchar *, g_strv_length ((gchar **)system_data_dirs) + 2);
1139
1140
0
  i = 0;
1141
0
  all_data_dirs[i++] = g_strdup (user_data_dir);
1142
1143
0
  j = 0;
1144
0
  while (system_data_dirs[j] != NULL)
1145
0
    all_data_dirs[i++] = g_strdup (system_data_dirs[j++]);
1146
0
  all_data_dirs[i] = NULL;
1147
1148
0
  found_file = g_key_file_load_from_dirs (key_file,
1149
0
                                          file,
1150
0
                                          (const gchar **)all_data_dirs,
1151
0
                                          full_path,
1152
0
                                          flags,
1153
0
                                          error);
1154
1155
0
  g_strfreev (all_data_dirs);
1156
1157
0
  return found_file;
1158
0
}
1159
1160
/**
1161
 * g_key_file_ref: (skip)
1162
 * @key_file: a #GKeyFile
1163
 *
1164
 * Increases the reference count of @key_file.
1165
 *
1166
 * Returns: the same @key_file.
1167
 *
1168
 * Since: 2.32
1169
 **/
1170
GKeyFile *
1171
g_key_file_ref (GKeyFile *key_file)
1172
0
{
1173
0
  g_return_val_if_fail (key_file != NULL, NULL);
1174
1175
0
  g_atomic_int_inc (&key_file->ref_count);
1176
1177
0
  return key_file;
1178
0
}
1179
1180
/**
1181
 * g_key_file_free: (skip)
1182
 * @key_file: a #GKeyFile
1183
 *
1184
 * Clears all keys and groups from @key_file, and decreases the
1185
 * reference count by 1. If the reference count reaches zero,
1186
 * frees the key file and all its allocated memory.
1187
 *
1188
 * Since: 2.6
1189
 **/
1190
void
1191
g_key_file_free (GKeyFile *key_file)
1192
0
{
1193
0
  g_return_if_fail (key_file != NULL);
1194
1195
0
  g_key_file_clear (key_file);
1196
1197
0
  if (g_atomic_int_dec_and_test (&key_file->ref_count))
1198
0
    g_slice_free (GKeyFile, key_file);
1199
0
  else
1200
0
    g_key_file_init (key_file);
1201
0
}
1202
1203
/**
1204
 * g_key_file_unref:
1205
 * @key_file: a #GKeyFile
1206
 *
1207
 * Decreases the reference count of @key_file by 1. If the reference count
1208
 * reaches zero, frees the key file and all its allocated memory.
1209
 *
1210
 * Since: 2.32
1211
 **/
1212
void
1213
g_key_file_unref (GKeyFile *key_file)
1214
0
{
1215
0
  g_return_if_fail (key_file != NULL);
1216
1217
0
  if (g_atomic_int_dec_and_test (&key_file->ref_count))
1218
0
    {
1219
0
      g_key_file_clear (key_file);
1220
0
      g_slice_free (GKeyFile, key_file);
1221
0
    }
1222
0
}
1223
1224
/* If G_KEY_FILE_KEEP_TRANSLATIONS is not set, only returns
1225
 * true for locales that match those in g_get_language_names().
1226
 */
1227
static gboolean
1228
g_key_file_locale_is_interesting (GKeyFile    *key_file,
1229
          const gchar *locale)
1230
0
{
1231
0
  gsize i;
1232
1233
0
  if (key_file->flags & G_KEY_FILE_KEEP_TRANSLATIONS)
1234
0
    return TRUE;
1235
1236
0
  if (!key_file->checked_locales)
1237
0
    {
1238
0
      key_file->locales = g_strdupv ((gchar **)g_get_language_names ());
1239
0
      key_file->checked_locales = TRUE;
1240
0
    }
1241
1242
0
  for (i = 0; key_file->locales[i] != NULL; i++)
1243
0
    {
1244
0
      if (g_ascii_strcasecmp (key_file->locales[i], locale) == 0)
1245
0
  return TRUE;
1246
0
    }
1247
1248
0
  return FALSE;
1249
0
}
1250
1251
static void
1252
g_key_file_parse_line (GKeyFile     *key_file,
1253
           const gchar  *line,
1254
           gsize         length,
1255
           GError      **error)
1256
0
{
1257
0
  GError *parse_error = NULL;
1258
0
  gchar *line_start;
1259
1260
0
  g_return_if_fail (key_file != NULL);
1261
0
  g_return_if_fail (line != NULL);
1262
1263
0
  line_start = (gchar *) line;
1264
0
  while (g_ascii_isspace (*line_start))
1265
0
    line_start++;
1266
1267
0
  if (g_key_file_line_is_comment (line_start))
1268
0
    g_key_file_parse_comment (key_file, line, length, &parse_error);
1269
0
  else if (g_key_file_line_is_group (line_start))
1270
0
    g_key_file_parse_group (key_file, line_start,
1271
0
          length - (line_start - line),
1272
0
          &parse_error);
1273
0
  else if (g_key_file_line_is_key_value_pair (line_start))
1274
0
    g_key_file_parse_key_value_pair (key_file, line_start,
1275
0
             length - (line_start - line),
1276
0
             &parse_error);
1277
0
  else
1278
0
    {
1279
0
      gchar *line_utf8 = g_utf8_make_valid (line, length);
1280
0
      g_set_error (error, G_KEY_FILE_ERROR,
1281
0
                   G_KEY_FILE_ERROR_PARSE,
1282
0
                   _("Key file contains line “%s” which is not "
1283
0
                     "a key-value pair, group, or comment"),
1284
0
                   line_utf8);
1285
0
      g_free (line_utf8);
1286
1287
0
      return;
1288
0
    }
1289
1290
0
  if (parse_error)
1291
0
    g_propagate_error (error, parse_error);
1292
0
}
1293
1294
static void
1295
g_key_file_parse_comment (GKeyFile     *key_file,
1296
        const gchar  *line,
1297
        gsize         length,
1298
        GError      **error)
1299
0
{
1300
0
  GKeyFileKeyValuePair *pair;
1301
  
1302
0
  if (!(key_file->flags & G_KEY_FILE_KEEP_COMMENTS))
1303
0
    return;
1304
  
1305
0
  g_warn_if_fail (key_file->current_group != NULL);
1306
1307
0
  pair = g_slice_new (GKeyFileKeyValuePair);
1308
0
  pair->key = NULL;
1309
0
  pair->value = g_strndup (line, length);
1310
  
1311
0
  key_file->current_group->key_value_pairs =
1312
0
    g_list_prepend (key_file->current_group->key_value_pairs, pair);
1313
0
}
1314
1315
static void
1316
g_key_file_parse_group (GKeyFile     *key_file,
1317
      const gchar  *line,
1318
      gsize         length,
1319
      GError      **error)
1320
0
{
1321
0
  gchar *group_name;
1322
0
  const gchar *group_name_start, *group_name_end;
1323
  
1324
  /* advance past opening '['
1325
   */
1326
0
  group_name_start = line + 1;
1327
0
  group_name_end = line + length - 1;
1328
  
1329
0
  while (*group_name_end != ']')
1330
0
    group_name_end--;
1331
1332
0
  group_name = g_strndup (group_name_start, 
1333
0
                          group_name_end - group_name_start);
1334
  
1335
0
  if (!g_key_file_is_group_name (group_name))
1336
0
    {
1337
0
      g_set_error (error, G_KEY_FILE_ERROR,
1338
0
       G_KEY_FILE_ERROR_PARSE,
1339
0
       _("Invalid group name: %s"), group_name);
1340
0
      g_free (group_name);
1341
0
      return;
1342
0
    }
1343
1344
0
  g_key_file_add_group (key_file, group_name);
1345
0
  g_free (group_name);
1346
0
}
1347
1348
static void
1349
g_key_file_parse_key_value_pair (GKeyFile     *key_file,
1350
         const gchar  *line,
1351
         gsize         length,
1352
         GError      **error)
1353
0
{
1354
0
  gchar *key, *value, *key_end, *value_start, *locale;
1355
0
  gsize key_len, value_len;
1356
1357
0
  if (key_file->current_group == NULL || key_file->current_group->name == NULL)
1358
0
    {
1359
0
      g_set_error_literal (error, G_KEY_FILE_ERROR,
1360
0
                           G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
1361
0
                           _("Key file does not start with a group"));
1362
0
      return;
1363
0
    }
1364
1365
0
  key_end = value_start = strchr (line, '=');
1366
1367
0
  g_warn_if_fail (key_end != NULL);
1368
1369
0
  key_end--;
1370
0
  value_start++;
1371
1372
  /* Pull the key name from the line (chomping trailing whitespace)
1373
   */
1374
0
  while (g_ascii_isspace (*key_end))
1375
0
    key_end--;
1376
1377
0
  key_len = key_end - line + 2;
1378
1379
0
  g_warn_if_fail (key_len <= length);
1380
1381
0
  key = g_strndup (line, key_len - 1);
1382
1383
0
  if (!g_key_file_is_key_name (key))
1384
0
    {
1385
0
      g_set_error (error, G_KEY_FILE_ERROR,
1386
0
                   G_KEY_FILE_ERROR_PARSE,
1387
0
                   _("Invalid key name: %s"), key);
1388
0
      g_free (key);
1389
0
      return; 
1390
0
    }
1391
1392
  /* Pull the value from the line (chugging leading whitespace)
1393
   */
1394
0
  while (g_ascii_isspace (*value_start))
1395
0
    value_start++;
1396
1397
0
  value_len = line + length - value_start + 1;
1398
1399
0
  value = g_strndup (value_start, value_len);
1400
1401
0
  g_warn_if_fail (key_file->start_group != NULL);
1402
1403
0
  if (key_file->current_group
1404
0
      && key_file->current_group->name
1405
0
      && strcmp (key_file->start_group->name,
1406
0
                 key_file->current_group->name) == 0
1407
0
      && strcmp (key, "Encoding") == 0)
1408
0
    {
1409
0
      if (g_ascii_strcasecmp (value, "UTF-8") != 0)
1410
0
        {
1411
0
    gchar *value_utf8 = g_utf8_make_valid (value, value_len);
1412
0
          g_set_error (error, G_KEY_FILE_ERROR,
1413
0
                       G_KEY_FILE_ERROR_UNKNOWN_ENCODING,
1414
0
                       _("Key file contains unsupported "
1415
0
       "encoding “%s”"), value_utf8);
1416
0
    g_free (value_utf8);
1417
1418
0
          g_free (key);
1419
0
          g_free (value);
1420
0
          return;
1421
0
        }
1422
0
    }
1423
1424
  /* Is this key a translation? If so, is it one that we care about?
1425
   */
1426
0
  locale = key_get_locale (key);
1427
1428
0
  if (locale == NULL || g_key_file_locale_is_interesting (key_file, locale))
1429
0
    {
1430
0
      GKeyFileKeyValuePair *pair;
1431
1432
0
      pair = g_slice_new (GKeyFileKeyValuePair);
1433
0
      pair->key = key;
1434
0
      pair->value = value;
1435
1436
0
      g_key_file_add_key_value_pair (key_file, key_file->current_group, pair);
1437
0
    }
1438
0
  else
1439
0
    {
1440
0
      g_free (key);
1441
0
      g_free (value);
1442
0
    }
1443
1444
0
  g_free (locale);
1445
0
}
1446
1447
static gchar *
1448
key_get_locale (const gchar *key)
1449
0
{
1450
0
  gchar *locale;
1451
1452
0
  locale = g_strrstr (key, "[");
1453
1454
0
  if (locale && strlen (locale) <= 2)
1455
0
    locale = NULL;
1456
1457
0
  if (locale)
1458
0
    locale = g_strndup (locale + 1, strlen (locale) - 2);
1459
1460
0
  return locale;
1461
0
}
1462
1463
static void
1464
g_key_file_parse_data (GKeyFile     *key_file,
1465
           const gchar  *data,
1466
           gsize         length,
1467
           GError      **error)
1468
0
{
1469
0
  GError *parse_error;
1470
0
  gsize i;
1471
1472
0
  g_return_if_fail (key_file != NULL);
1473
0
  g_return_if_fail (data != NULL || length == 0);
1474
1475
0
  parse_error = NULL;
1476
1477
0
  if (!key_file->parse_buffer)
1478
0
    key_file->parse_buffer = g_string_sized_new (128);
1479
1480
0
  i = 0;
1481
0
  while (i < length)
1482
0
    {
1483
0
      if (data[i] == '\n')
1484
0
        {
1485
0
    if (key_file->parse_buffer->len > 0
1486
0
        && (key_file->parse_buffer->str[key_file->parse_buffer->len - 1]
1487
0
      == '\r'))
1488
0
      g_string_erase (key_file->parse_buffer,
1489
0
          key_file->parse_buffer->len - 1,
1490
0
          1);
1491
      
1492
          /* When a newline is encountered flush the parse buffer so that the
1493
           * line can be parsed.  Note that completely blank lines won't show
1494
           * up in the parse buffer, so they get parsed directly.
1495
           */
1496
0
          if (key_file->parse_buffer->len > 0)
1497
0
            g_key_file_flush_parse_buffer (key_file, &parse_error);
1498
0
          else
1499
0
            g_key_file_parse_comment (key_file, "", 1, &parse_error);
1500
1501
0
          if (parse_error)
1502
0
            {
1503
0
              g_propagate_error (error, parse_error);
1504
0
              return;
1505
0
            }
1506
0
          i++;
1507
0
        }
1508
0
      else
1509
0
        {
1510
0
          const gchar *start_of_line;
1511
0
          const gchar *end_of_line;
1512
0
          gsize line_length;
1513
1514
0
          start_of_line = data + i;
1515
0
          end_of_line = memchr (start_of_line, '\n', length - i);
1516
1517
0
          if (end_of_line == NULL)
1518
0
            end_of_line = data + length;
1519
1520
0
          line_length = end_of_line - start_of_line;
1521
1522
0
          g_string_append_len (key_file->parse_buffer, start_of_line, line_length);
1523
0
          i += line_length;
1524
0
        }
1525
0
    }
1526
0
}
1527
1528
static void
1529
g_key_file_flush_parse_buffer (GKeyFile  *key_file,
1530
             GError   **error)
1531
0
{
1532
0
  GError *file_error = NULL;
1533
1534
0
  g_return_if_fail (key_file != NULL);
1535
1536
0
  if (!key_file->parse_buffer)
1537
0
    return;
1538
1539
0
  file_error = NULL;
1540
1541
0
  if (key_file->parse_buffer->len > 0)
1542
0
    {
1543
0
      g_key_file_parse_line (key_file, key_file->parse_buffer->str,
1544
0
           key_file->parse_buffer->len,
1545
0
           &file_error);
1546
0
      g_string_erase (key_file->parse_buffer, 0, -1);
1547
1548
0
      if (file_error)
1549
0
        {
1550
0
          g_propagate_error (error, file_error);
1551
0
          return;
1552
0
        }
1553
0
    }
1554
0
}
1555
1556
/**
1557
 * g_key_file_to_data:
1558
 * @key_file: a #GKeyFile
1559
 * @length: (out) (optional): return location for the length of the
1560
 *   returned string, or %NULL
1561
 * @error: return location for a #GError, or %NULL
1562
 *
1563
 * This function outputs @key_file as a string.  
1564
 *
1565
 * Note that this function never reports an error,
1566
 * so it is safe to pass %NULL as @error.
1567
 *
1568
 * Returns: a newly allocated string holding
1569
 *   the contents of the #GKeyFile 
1570
 *
1571
 * Since: 2.6
1572
 **/
1573
gchar *
1574
g_key_file_to_data (GKeyFile  *key_file,
1575
        gsize     *length,
1576
        GError   **error)
1577
0
{
1578
0
  GString *data_string;
1579
0
  GList *group_node, *key_file_node;
1580
1581
0
  g_return_val_if_fail (key_file != NULL, NULL);
1582
1583
0
  data_string = g_string_new (NULL);
1584
1585
0
  for (group_node = g_list_last (key_file->groups);
1586
0
       group_node != NULL;
1587
0
       group_node = group_node->prev)
1588
0
    {
1589
0
      GKeyFileGroup *group;
1590
1591
0
      group = (GKeyFileGroup *) group_node->data;
1592
1593
      /* separate groups by at least an empty line */
1594
0
      if (data_string->len >= 2 &&
1595
0
          data_string->str[data_string->len - 2] != '\n')
1596
0
        g_string_append_c (data_string, '\n');
1597
1598
0
      if (group->comment != NULL)
1599
0
        g_string_append_printf (data_string, "%s\n", group->comment->value);
1600
1601
0
      if (group->name != NULL)
1602
0
        g_string_append_printf (data_string, "[%s]\n", group->name);
1603
1604
0
      for (key_file_node = g_list_last (group->key_value_pairs);
1605
0
           key_file_node != NULL;
1606
0
           key_file_node = key_file_node->prev)
1607
0
        {
1608
0
          GKeyFileKeyValuePair *pair;
1609
1610
0
          pair = (GKeyFileKeyValuePair *) key_file_node->data;
1611
1612
0
          if (pair->key != NULL)
1613
0
            g_string_append_printf (data_string, "%s=%s\n", pair->key, pair->value);
1614
0
          else
1615
0
            g_string_append_printf (data_string, "%s\n", pair->value);
1616
0
        }
1617
0
    }
1618
1619
0
  if (length)
1620
0
    *length = data_string->len;
1621
1622
0
  return g_string_free (data_string, FALSE);
1623
0
}
1624
1625
/**
1626
 * g_key_file_get_keys:
1627
 * @key_file: a #GKeyFile
1628
 * @group_name: a group name
1629
 * @length: (out) (optional): return location for the number of keys returned, or %NULL
1630
 * @error: return location for a #GError, or %NULL
1631
 *
1632
 * Returns all keys for the group name @group_name.  The array of
1633
 * returned keys will be %NULL-terminated, so @length may
1634
 * optionally be %NULL. In the event that the @group_name cannot
1635
 * be found, %NULL is returned and @error is set to
1636
 * #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
1637
 *
1638
 * Returns: (array zero-terminated=1) (transfer full): a newly-allocated %NULL-terminated array of strings.
1639
 *     Use g_strfreev() to free it.
1640
 *
1641
 * Since: 2.6
1642
 **/
1643
gchar **
1644
g_key_file_get_keys (GKeyFile     *key_file,
1645
         const gchar  *group_name,
1646
         gsize        *length,
1647
         GError      **error)
1648
0
{
1649
0
  GKeyFileGroup *group;
1650
0
  GList *tmp;
1651
0
  gchar **keys;
1652
0
  gsize i, num_keys;
1653
  
1654
0
  g_return_val_if_fail (key_file != NULL, NULL);
1655
0
  g_return_val_if_fail (group_name != NULL, NULL);
1656
  
1657
0
  group = g_key_file_lookup_group (key_file, group_name);
1658
  
1659
0
  if (!group)
1660
0
    {
1661
0
      g_set_error (error, G_KEY_FILE_ERROR,
1662
0
                   G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
1663
0
                   _("Key file does not have group “%s”"),
1664
0
                   group_name);
1665
0
      return NULL;
1666
0
    }
1667
1668
0
  num_keys = 0;
1669
0
  for (tmp = group->key_value_pairs; tmp; tmp = tmp->next)
1670
0
    {
1671
0
      GKeyFileKeyValuePair *pair;
1672
1673
0
      pair = (GKeyFileKeyValuePair *) tmp->data;
1674
1675
0
      if (pair->key)
1676
0
  num_keys++;
1677
0
    }
1678
  
1679
0
  keys = g_new (gchar *, num_keys + 1);
1680
1681
0
  i = num_keys - 1;
1682
0
  for (tmp = group->key_value_pairs; tmp; tmp = tmp->next)
1683
0
    {
1684
0
      GKeyFileKeyValuePair *pair;
1685
1686
0
      pair = (GKeyFileKeyValuePair *) tmp->data;
1687
1688
0
      if (pair->key)
1689
0
  {
1690
0
    keys[i] = g_strdup (pair->key);
1691
0
    i--;
1692
0
  }
1693
0
    }
1694
1695
0
  keys[num_keys] = NULL;
1696
1697
0
  if (length)
1698
0
    *length = num_keys;
1699
1700
0
  return keys;
1701
0
}
1702
1703
/**
1704
 * g_key_file_get_start_group:
1705
 * @key_file: a #GKeyFile
1706
 *
1707
 * Returns the name of the start group of the file. 
1708
 *
1709
 * Returns: (nullable): The start group of the key file.
1710
 *
1711
 * Since: 2.6
1712
 **/
1713
gchar *
1714
g_key_file_get_start_group (GKeyFile *key_file)
1715
0
{
1716
0
  g_return_val_if_fail (key_file != NULL, NULL);
1717
1718
0
  if (key_file->start_group)
1719
0
    return g_strdup (key_file->start_group->name);
1720
1721
0
  return NULL;
1722
0
}
1723
1724
/**
1725
 * g_key_file_get_groups:
1726
 * @key_file: a #GKeyFile
1727
 * @length: (out) (optional): return location for the number of returned groups, or %NULL
1728
 *
1729
 * Returns all groups in the key file loaded with @key_file.  
1730
 * The array of returned groups will be %NULL-terminated, so 
1731
 * @length may optionally be %NULL.
1732
 *
1733
 * Returns: (array zero-terminated=1) (transfer full): a newly-allocated %NULL-terminated array of strings.
1734
 *   Use g_strfreev() to free it.
1735
 * Since: 2.6
1736
 **/
1737
gchar **
1738
g_key_file_get_groups (GKeyFile *key_file,
1739
           gsize    *length)
1740
0
{
1741
0
  GList *group_node;
1742
0
  gchar **groups;
1743
0
  gsize i, num_groups;
1744
1745
0
  g_return_val_if_fail (key_file != NULL, NULL);
1746
1747
0
  num_groups = g_list_length (key_file->groups);
1748
1749
0
  g_return_val_if_fail (num_groups > 0, NULL);
1750
1751
0
  group_node = g_list_last (key_file->groups);
1752
  
1753
0
  g_return_val_if_fail (((GKeyFileGroup *) group_node->data)->name == NULL, NULL);
1754
1755
  /* Only need num_groups instead of num_groups + 1
1756
   * because the first group of the file (last in the
1757
   * list) is always the comment group at the top,
1758
   * which we skip
1759
   */
1760
0
  groups = g_new (gchar *, num_groups);
1761
1762
1763
0
  i = 0;
1764
0
  for (group_node = group_node->prev;
1765
0
       group_node != NULL;
1766
0
       group_node = group_node->prev)
1767
0
    {
1768
0
      GKeyFileGroup *group;
1769
1770
0
      group = (GKeyFileGroup *) group_node->data;
1771
1772
0
      g_warn_if_fail (group->name != NULL);
1773
1774
0
      groups[i++] = g_strdup (group->name);
1775
0
    }
1776
0
  groups[i] = NULL;
1777
1778
0
  if (length)
1779
0
    *length = i;
1780
1781
0
  return groups;
1782
0
}
1783
1784
static void
1785
set_not_found_key_error (const char *group_name,
1786
                         const char *key,
1787
                         GError    **error)
1788
0
{
1789
0
  g_set_error (error, G_KEY_FILE_ERROR,
1790
0
               G_KEY_FILE_ERROR_KEY_NOT_FOUND,
1791
0
               _("Key file does not have key “%s” in group “%s”"),
1792
0
               key, group_name);
1793
0
}
1794
1795
/**
1796
 * g_key_file_get_value:
1797
 * @key_file: a #GKeyFile
1798
 * @group_name: a group name
1799
 * @key: a key
1800
 * @error: return location for a #GError, or %NULL
1801
 *
1802
 * Returns the raw value associated with @key under @group_name. 
1803
 * Use g_key_file_get_string() to retrieve an unescaped UTF-8 string. 
1804
 *
1805
 * In the event the key cannot be found, %NULL is returned and 
1806
 * @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND.  In the 
1807
 * event that the @group_name cannot be found, %NULL is returned 
1808
 * and @error is set to #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
1809
 *
1810
 *
1811
 * Returns: a newly allocated string or %NULL if the specified 
1812
 *  key cannot be found.
1813
 *
1814
 * Since: 2.6
1815
 **/
1816
gchar *
1817
g_key_file_get_value (GKeyFile     *key_file,
1818
          const gchar  *group_name,
1819
          const gchar  *key,
1820
          GError      **error)
1821
0
{
1822
0
  GKeyFileGroup *group;
1823
0
  GKeyFileKeyValuePair *pair;
1824
0
  gchar *value = NULL;
1825
1826
0
  g_return_val_if_fail (key_file != NULL, NULL);
1827
0
  g_return_val_if_fail (group_name != NULL, NULL);
1828
0
  g_return_val_if_fail (key != NULL, NULL);
1829
  
1830
0
  group = g_key_file_lookup_group (key_file, group_name);
1831
1832
0
  if (!group)
1833
0
    {
1834
0
      g_set_error (error, G_KEY_FILE_ERROR,
1835
0
                   G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
1836
0
                   _("Key file does not have group “%s”"),
1837
0
                   group_name);
1838
0
      return NULL;
1839
0
    }
1840
1841
0
  pair = g_key_file_lookup_key_value_pair (key_file, group, key);
1842
1843
0
  if (pair)
1844
0
    value = g_strdup (pair->value);
1845
0
  else
1846
0
    set_not_found_key_error (group_name, key, error);
1847
1848
0
  return value;
1849
0
}
1850
1851
/**
1852
 * g_key_file_set_value:
1853
 * @key_file: a #GKeyFile
1854
 * @group_name: a group name
1855
 * @key: a key
1856
 * @value: a string
1857
 *
1858
 * Associates a new value with @key under @group_name.  
1859
 *
1860
 * If @key cannot be found then it is created. If @group_name cannot 
1861
 * be found then it is created. To set an UTF-8 string which may contain 
1862
 * characters that need escaping (such as newlines or spaces), use 
1863
 * g_key_file_set_string().
1864
 *
1865
 * Since: 2.6
1866
 **/
1867
void
1868
g_key_file_set_value (GKeyFile    *key_file,
1869
          const gchar *group_name,
1870
          const gchar *key,
1871
          const gchar *value)
1872
0
{
1873
0
  GKeyFileGroup *group;
1874
0
  GKeyFileKeyValuePair *pair;
1875
1876
0
  g_return_if_fail (key_file != NULL);
1877
0
  g_return_if_fail (g_key_file_is_group_name (group_name));
1878
0
  g_return_if_fail (g_key_file_is_key_name (key));
1879
0
  g_return_if_fail (value != NULL);
1880
1881
0
  group = g_key_file_lookup_group (key_file, group_name);
1882
1883
0
  if (!group)
1884
0
    {
1885
0
      g_key_file_add_group (key_file, group_name);
1886
0
      group = (GKeyFileGroup *) key_file->groups->data;
1887
1888
0
      g_key_file_add_key (key_file, group, key, value);
1889
0
    }
1890
0
  else
1891
0
    {
1892
0
      pair = g_key_file_lookup_key_value_pair (key_file, group, key);
1893
1894
0
      if (!pair)
1895
0
        g_key_file_add_key (key_file, group, key, value);
1896
0
      else
1897
0
        {
1898
0
          g_free (pair->value);
1899
0
          pair->value = g_strdup (value);
1900
0
        }
1901
0
    }
1902
0
}
1903
1904
/**
1905
 * g_key_file_get_string:
1906
 * @key_file: a #GKeyFile
1907
 * @group_name: a group name
1908
 * @key: a key
1909
 * @error: return location for a #GError, or %NULL
1910
 *
1911
 * Returns the string value associated with @key under @group_name.
1912
 * Unlike g_key_file_get_value(), this function handles escape sequences
1913
 * like \s.
1914
 *
1915
 * In the event the key cannot be found, %NULL is returned and 
1916
 * @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND.  In the 
1917
 * event that the @group_name cannot be found, %NULL is returned 
1918
 * and @error is set to #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
1919
 *
1920
 * Returns: a newly allocated string or %NULL if the specified 
1921
 *   key cannot be found.
1922
 *
1923
 * Since: 2.6
1924
 **/
1925
gchar *
1926
g_key_file_get_string (GKeyFile     *key_file,
1927
           const gchar  *group_name,
1928
           const gchar  *key,
1929
           GError      **error)
1930
0
{
1931
0
  gchar *value, *string_value;
1932
0
  GError *key_file_error;
1933
1934
0
  g_return_val_if_fail (key_file != NULL, NULL);
1935
0
  g_return_val_if_fail (group_name != NULL, NULL);
1936
0
  g_return_val_if_fail (key != NULL, NULL);
1937
1938
0
  key_file_error = NULL;
1939
1940
0
  value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
1941
1942
0
  if (key_file_error)
1943
0
    {
1944
0
      g_propagate_error (error, key_file_error);
1945
0
      return NULL;
1946
0
    }
1947
1948
0
  if (!g_utf8_validate (value, -1, NULL))
1949
0
    {
1950
0
      gchar *value_utf8 = g_utf8_make_valid (value, -1);
1951
0
      g_set_error (error, G_KEY_FILE_ERROR,
1952
0
                   G_KEY_FILE_ERROR_UNKNOWN_ENCODING,
1953
0
                   _("Key file contains key “%s” with value “%s” "
1954
0
                     "which is not UTF-8"), key, value_utf8);
1955
0
      g_free (value_utf8);
1956
0
      g_free (value);
1957
1958
0
      return NULL;
1959
0
    }
1960
1961
0
  string_value = g_key_file_parse_value_as_string (key_file, value, NULL,
1962
0
               &key_file_error);
1963
0
  g_free (value);
1964
1965
0
  if (key_file_error)
1966
0
    {
1967
0
      if (g_error_matches (key_file_error,
1968
0
                           G_KEY_FILE_ERROR,
1969
0
                           G_KEY_FILE_ERROR_INVALID_VALUE))
1970
0
        {
1971
0
          g_set_error (error, G_KEY_FILE_ERROR,
1972
0
                       G_KEY_FILE_ERROR_INVALID_VALUE,
1973
0
                       _("Key file contains key “%s” "
1974
0
                         "which has a value that cannot be interpreted."),
1975
0
                       key);
1976
0
          g_error_free (key_file_error);
1977
0
        }
1978
0
      else
1979
0
        g_propagate_error (error, key_file_error);
1980
0
    }
1981
1982
0
  return string_value;
1983
0
}
1984
1985
/**
1986
 * g_key_file_set_string:
1987
 * @key_file: a #GKeyFile
1988
 * @group_name: a group name
1989
 * @key: a key
1990
 * @string: a string
1991
 *
1992
 * Associates a new string value with @key under @group_name.  
1993
 * If @key cannot be found then it is created.  
1994
 * If @group_name cannot be found then it is created.
1995
 * Unlike g_key_file_set_value(), this function handles characters
1996
 * that need escaping, such as newlines.
1997
 *
1998
 * Since: 2.6
1999
 **/
2000
void
2001
g_key_file_set_string (GKeyFile    *key_file,
2002
           const gchar *group_name,
2003
           const gchar *key,
2004
           const gchar *string)
2005
0
{
2006
0
  gchar *value;
2007
2008
0
  g_return_if_fail (key_file != NULL);
2009
0
  g_return_if_fail (string != NULL);
2010
2011
0
  value = g_key_file_parse_string_as_value (key_file, string, FALSE);
2012
0
  g_key_file_set_value (key_file, group_name, key, value);
2013
0
  g_free (value);
2014
0
}
2015
2016
/**
2017
 * g_key_file_get_string_list:
2018
 * @key_file: a #GKeyFile
2019
 * @group_name: a group name
2020
 * @key: a key
2021
 * @length: (out) (optional): return location for the number of returned strings, or %NULL
2022
 * @error: return location for a #GError, or %NULL
2023
 *
2024
 * Returns the values associated with @key under @group_name.
2025
 *
2026
 * In the event the key cannot be found, %NULL is returned and
2027
 * @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND.  In the
2028
 * event that the @group_name cannot be found, %NULL is returned
2029
 * and @error is set to #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
2030
 *
2031
 * Returns: (array zero-terminated=1 length=length) (element-type utf8) (transfer full): 
2032
 *  a %NULL-terminated string array or %NULL if the specified 
2033
 *  key cannot be found. The array should be freed with g_strfreev().
2034
 *
2035
 * Since: 2.6
2036
 **/
2037
gchar **
2038
g_key_file_get_string_list (GKeyFile     *key_file,
2039
          const gchar  *group_name,
2040
          const gchar  *key,
2041
          gsize        *length,
2042
          GError      **error)
2043
0
{
2044
0
  GError *key_file_error = NULL;
2045
0
  gchar *value, *string_value, **values;
2046
0
  gint i, len;
2047
0
  GSList *p, *pieces = NULL;
2048
2049
0
  g_return_val_if_fail (key_file != NULL, NULL);
2050
0
  g_return_val_if_fail (group_name != NULL, NULL);
2051
0
  g_return_val_if_fail (key != NULL, NULL);
2052
2053
0
  if (length)
2054
0
    *length = 0;
2055
2056
0
  value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
2057
2058
0
  if (key_file_error)
2059
0
    {
2060
0
      g_propagate_error (error, key_file_error);
2061
0
      return NULL;
2062
0
    }
2063
2064
0
  if (!g_utf8_validate (value, -1, NULL))
2065
0
    {
2066
0
      gchar *value_utf8 = g_utf8_make_valid (value, -1);
2067
0
      g_set_error (error, G_KEY_FILE_ERROR,
2068
0
                   G_KEY_FILE_ERROR_UNKNOWN_ENCODING,
2069
0
                   _("Key file contains key “%s” with value “%s” "
2070
0
                     "which is not UTF-8"), key, value_utf8);
2071
0
      g_free (value_utf8);
2072
0
      g_free (value);
2073
2074
0
      return NULL;
2075
0
    }
2076
2077
0
  string_value = g_key_file_parse_value_as_string (key_file, value, &pieces, &key_file_error);
2078
0
  g_free (value);
2079
0
  g_free (string_value);
2080
2081
0
  if (key_file_error)
2082
0
    {
2083
0
      if (g_error_matches (key_file_error,
2084
0
                           G_KEY_FILE_ERROR,
2085
0
                           G_KEY_FILE_ERROR_INVALID_VALUE))
2086
0
        {
2087
0
          g_set_error (error, G_KEY_FILE_ERROR,
2088
0
                       G_KEY_FILE_ERROR_INVALID_VALUE,
2089
0
                       _("Key file contains key “%s” "
2090
0
                         "which has a value that cannot be interpreted."),
2091
0
                       key);
2092
0
          g_error_free (key_file_error);
2093
0
        }
2094
0
      else
2095
0
        g_propagate_error (error, key_file_error);
2096
2097
0
      g_slist_free_full (pieces, g_free);
2098
0
      return NULL;
2099
0
    }
2100
2101
0
  len = g_slist_length (pieces);
2102
0
  values = g_new (gchar *, len + 1);
2103
0
  for (p = pieces, i = 0; p; p = p->next)
2104
0
    values[i++] = p->data;
2105
0
  values[len] = NULL;
2106
2107
0
  g_slist_free (pieces);
2108
2109
0
  if (length)
2110
0
    *length = len;
2111
2112
0
  return values;
2113
0
}
2114
2115
/**
2116
 * g_key_file_set_string_list:
2117
 * @key_file: a #GKeyFile
2118
 * @group_name: a group name
2119
 * @key: a key
2120
 * @list: (array zero-terminated=1 length=length) (element-type utf8): an array of string values
2121
 * @length: number of string values in @list
2122
 *
2123
 * Associates a list of string values for @key under @group_name.
2124
 * If @key cannot be found then it is created.
2125
 * If @group_name cannot be found then it is created.
2126
 *
2127
 * Since: 2.6
2128
 **/
2129
void
2130
g_key_file_set_string_list (GKeyFile            *key_file,
2131
          const gchar         *group_name,
2132
          const gchar         *key,
2133
          const gchar * const  list[],
2134
          gsize                length)
2135
0
{
2136
0
  GString *value_list;
2137
0
  gsize i;
2138
2139
0
  g_return_if_fail (key_file != NULL);
2140
0
  g_return_if_fail (list != NULL || length == 0);
2141
2142
0
  value_list = g_string_sized_new (length * 128);
2143
0
  for (i = 0; i < length && list[i] != NULL; i++)
2144
0
    {
2145
0
      gchar *value;
2146
2147
0
      value = g_key_file_parse_string_as_value (key_file, list[i], TRUE);
2148
0
      g_string_append (value_list, value);
2149
0
      g_string_append_c (value_list, key_file->list_separator);
2150
2151
0
      g_free (value);
2152
0
    }
2153
2154
0
  g_key_file_set_value (key_file, group_name, key, value_list->str);
2155
0
  g_string_free (value_list, TRUE);
2156
0
}
2157
2158
/**
2159
 * g_key_file_set_locale_string:
2160
 * @key_file: a #GKeyFile
2161
 * @group_name: a group name
2162
 * @key: a key
2163
 * @locale: a locale identifier
2164
 * @string: a string
2165
 *
2166
 * Associates a string value for @key and @locale under @group_name.
2167
 * If the translation for @key cannot be found then it is created.
2168
 *
2169
 * Since: 2.6
2170
 **/
2171
void
2172
g_key_file_set_locale_string (GKeyFile     *key_file,
2173
            const gchar  *group_name,
2174
            const gchar  *key,
2175
            const gchar  *locale,
2176
            const gchar  *string)
2177
0
{
2178
0
  gchar *full_key, *value;
2179
2180
0
  g_return_if_fail (key_file != NULL);
2181
0
  g_return_if_fail (key != NULL);
2182
0
  g_return_if_fail (locale != NULL);
2183
0
  g_return_if_fail (string != NULL);
2184
2185
0
  value = g_key_file_parse_string_as_value (key_file, string, FALSE);
2186
0
  full_key = g_strdup_printf ("%s[%s]", key, locale);
2187
0
  g_key_file_set_value (key_file, group_name, full_key, value);
2188
0
  g_free (full_key);
2189
0
  g_free (value);
2190
0
}
2191
2192
/**
2193
 * g_key_file_get_locale_string:
2194
 * @key_file: a #GKeyFile
2195
 * @group_name: a group name
2196
 * @key: a key
2197
 * @locale: (nullable): a locale identifier or %NULL
2198
 * @error: return location for a #GError, or %NULL
2199
 *
2200
 * Returns the value associated with @key under @group_name
2201
 * translated in the given @locale if available.  If @locale is
2202
 * %NULL then the current locale is assumed. 
2203
 *
2204
 * If @locale is to be non-%NULL, or if the current locale will change over
2205
 * the lifetime of the #GKeyFile, it must be loaded with
2206
 * %G_KEY_FILE_KEEP_TRANSLATIONS in order to load strings for all locales.
2207
 *
2208
 * If @key cannot be found then %NULL is returned and @error is set 
2209
 * to #G_KEY_FILE_ERROR_KEY_NOT_FOUND. If the value associated
2210
 * with @key cannot be interpreted or no suitable translation can
2211
 * be found then the untranslated value is returned.
2212
 *
2213
 * Returns: a newly allocated string or %NULL if the specified 
2214
 *   key cannot be found.
2215
 *
2216
 * Since: 2.6
2217
 **/
2218
gchar *
2219
g_key_file_get_locale_string (GKeyFile     *key_file,
2220
            const gchar  *group_name,
2221
            const gchar  *key,
2222
            const gchar  *locale,
2223
            GError      **error)
2224
0
{
2225
0
  gchar *candidate_key, *translated_value;
2226
0
  GError *key_file_error;
2227
0
  gchar **languages;
2228
0
  gboolean free_languages = FALSE;
2229
0
  gint i;
2230
2231
0
  g_return_val_if_fail (key_file != NULL, NULL);
2232
0
  g_return_val_if_fail (group_name != NULL, NULL);
2233
0
  g_return_val_if_fail (key != NULL, NULL);
2234
2235
0
  candidate_key = NULL;
2236
0
  translated_value = NULL;
2237
0
  key_file_error = NULL;
2238
2239
0
  if (locale)
2240
0
    {
2241
0
      languages = g_get_locale_variants (locale);
2242
0
      free_languages = TRUE;
2243
0
    }
2244
0
  else
2245
0
    {
2246
0
      languages = (gchar **) g_get_language_names ();
2247
0
      free_languages = FALSE;
2248
0
    }
2249
  
2250
0
  for (i = 0; languages[i]; i++)
2251
0
    {
2252
0
      candidate_key = g_strdup_printf ("%s[%s]", key, languages[i]);
2253
      
2254
0
      translated_value = g_key_file_get_string (key_file,
2255
0
            group_name,
2256
0
            candidate_key, NULL);
2257
0
      g_free (candidate_key);
2258
2259
0
      if (translated_value)
2260
0
  break;
2261
2262
0
      g_free (translated_value);
2263
0
      translated_value = NULL;
2264
0
   }
2265
2266
  /* Fallback to untranslated key
2267
   */
2268
0
  if (!translated_value)
2269
0
    {
2270
0
      translated_value = g_key_file_get_string (key_file, group_name, key,
2271
0
            &key_file_error);
2272
      
2273
0
      if (!translated_value)
2274
0
        g_propagate_error (error, key_file_error);
2275
0
    }
2276
2277
0
  if (free_languages)
2278
0
    g_strfreev (languages);
2279
2280
0
  return translated_value;
2281
0
}
2282
2283
/**
2284
 * g_key_file_get_locale_for_key:
2285
 * @key_file: a #GKeyFile
2286
 * @group_name: a group name
2287
 * @key: a key
2288
 * @locale: (nullable): a locale identifier or %NULL
2289
 *
2290
 * Returns the actual locale which the result of
2291
 * g_key_file_get_locale_string() or g_key_file_get_locale_string_list()
2292
 * came from.
2293
 *
2294
 * If calling g_key_file_get_locale_string() or
2295
 * g_key_file_get_locale_string_list() with exactly the same @key_file,
2296
 * @group_name, @key and @locale, the result of those functions will
2297
 * have originally been tagged with the locale that is the result of
2298
 * this function.
2299
 *
2300
 * Returns: (nullable): the locale from the file, or %NULL if the key was not
2301
 *   found or the entry in the file was was untranslated
2302
 *
2303
 * Since: 2.56
2304
 */
2305
gchar *
2306
g_key_file_get_locale_for_key (GKeyFile    *key_file,
2307
                               const gchar *group_name,
2308
                               const gchar *key,
2309
                               const gchar *locale)
2310
0
{
2311
0
  gchar **languages_allocated = NULL;
2312
0
  const gchar * const *languages;
2313
0
  gchar *result = NULL;
2314
0
  gsize i;
2315
2316
0
  g_return_val_if_fail (key_file != NULL, NULL);
2317
0
  g_return_val_if_fail (group_name != NULL, NULL);
2318
0
  g_return_val_if_fail (key != NULL, NULL);
2319
2320
0
  if (locale != NULL)
2321
0
    {
2322
0
      languages_allocated = g_get_locale_variants (locale);
2323
0
      languages = (const gchar * const *) languages_allocated;
2324
0
    }
2325
0
  else
2326
0
    languages = g_get_language_names ();
2327
2328
0
  for (i = 0; languages[i] != NULL; i++)
2329
0
    {
2330
0
      gchar *candidate_key, *translated_value;
2331
2332
0
      candidate_key = g_strdup_printf ("%s[%s]", key, languages[i]);
2333
0
      translated_value = g_key_file_get_string (key_file, group_name, candidate_key, NULL);
2334
0
      g_free (translated_value);
2335
0
      g_free (candidate_key);
2336
2337
0
      if (translated_value != NULL)
2338
0
        break;
2339
0
   }
2340
2341
0
  result = g_strdup (languages[i]);
2342
2343
0
  g_strfreev (languages_allocated);
2344
2345
0
  return result;
2346
0
}
2347
2348
/**
2349
 * g_key_file_get_locale_string_list:
2350
 * @key_file: a #GKeyFile
2351
 * @group_name: a group name
2352
 * @key: a key
2353
 * @locale: (nullable): a locale identifier or %NULL
2354
 * @length: (out) (optional): return location for the number of returned strings or %NULL
2355
 * @error: return location for a #GError or %NULL
2356
 *
2357
 * Returns the values associated with @key under @group_name
2358
 * translated in the given @locale if available.  If @locale is
2359
 * %NULL then the current locale is assumed.
2360
 *
2361
 * If @locale is to be non-%NULL, or if the current locale will change over
2362
 * the lifetime of the #GKeyFile, it must be loaded with
2363
 * %G_KEY_FILE_KEEP_TRANSLATIONS in order to load strings for all locales.
2364
 *
2365
 * If @key cannot be found then %NULL is returned and @error is set 
2366
 * to #G_KEY_FILE_ERROR_KEY_NOT_FOUND. If the values associated
2367
 * with @key cannot be interpreted or no suitable translations
2368
 * can be found then the untranslated values are returned. The 
2369
 * returned array is %NULL-terminated, so @length may optionally 
2370
 * be %NULL.
2371
 *
2372
 * Returns: (array zero-terminated=1 length=length) (element-type utf8) (transfer full): a newly allocated %NULL-terminated string array
2373
 *   or %NULL if the key isn't found. The string array should be freed
2374
 *   with g_strfreev().
2375
 *
2376
 * Since: 2.6
2377
 **/
2378
gchar **
2379
g_key_file_get_locale_string_list (GKeyFile     *key_file,
2380
           const gchar  *group_name,
2381
           const gchar  *key,
2382
           const gchar  *locale,
2383
           gsize        *length,
2384
           GError      **error)
2385
0
{
2386
0
  GError *key_file_error;
2387
0
  gchar **values, *value;
2388
0
  char list_separator[2];
2389
0
  gsize len;
2390
2391
0
  g_return_val_if_fail (key_file != NULL, NULL);
2392
0
  g_return_val_if_fail (group_name != NULL, NULL);
2393
0
  g_return_val_if_fail (key != NULL, NULL);
2394
2395
0
  key_file_error = NULL;
2396
2397
0
  value = g_key_file_get_locale_string (key_file, group_name, 
2398
0
          key, locale,
2399
0
          &key_file_error);
2400
  
2401
0
  if (key_file_error)
2402
0
    g_propagate_error (error, key_file_error);
2403
  
2404
0
  if (!value)
2405
0
    {
2406
0
      if (length)
2407
0
        *length = 0;
2408
0
      return NULL;
2409
0
    }
2410
2411
0
  len = strlen (value);
2412
0
  if (value[len - 1] == key_file->list_separator)
2413
0
    value[len - 1] = '\0';
2414
2415
0
  list_separator[0] = key_file->list_separator;
2416
0
  list_separator[1] = '\0';
2417
0
  values = g_strsplit (value, list_separator, 0);
2418
2419
0
  g_free (value);
2420
2421
0
  if (length)
2422
0
    *length = g_strv_length (values);
2423
2424
0
  return values;
2425
0
}
2426
2427
/**
2428
 * g_key_file_set_locale_string_list:
2429
 * @key_file: a #GKeyFile
2430
 * @group_name: a group name
2431
 * @key: a key
2432
 * @locale: a locale identifier
2433
 * @list: (array zero-terminated=1 length=length): a %NULL-terminated array of locale string values
2434
 * @length: the length of @list
2435
 *
2436
 * Associates a list of string values for @key and @locale under
2437
 * @group_name.  If the translation for @key cannot be found then
2438
 * it is created. 
2439
 *
2440
 * Since: 2.6
2441
 **/
2442
void
2443
g_key_file_set_locale_string_list (GKeyFile            *key_file,
2444
           const gchar         *group_name,
2445
           const gchar         *key,
2446
           const gchar         *locale,
2447
           const gchar * const  list[],
2448
           gsize                length)
2449
0
{
2450
0
  GString *value_list;
2451
0
  gchar *full_key;
2452
0
  gsize i;
2453
2454
0
  g_return_if_fail (key_file != NULL);
2455
0
  g_return_if_fail (key != NULL);
2456
0
  g_return_if_fail (locale != NULL);
2457
0
  g_return_if_fail (length != 0);
2458
2459
0
  value_list = g_string_sized_new (length * 128);
2460
0
  for (i = 0; i < length && list[i] != NULL; i++)
2461
0
    {
2462
0
      gchar *value;
2463
      
2464
0
      value = g_key_file_parse_string_as_value (key_file, list[i], TRUE);
2465
0
      g_string_append (value_list, value);
2466
0
      g_string_append_c (value_list, key_file->list_separator);
2467
2468
0
      g_free (value);
2469
0
    }
2470
2471
0
  full_key = g_strdup_printf ("%s[%s]", key, locale);
2472
0
  g_key_file_set_value (key_file, group_name, full_key, value_list->str);
2473
0
  g_free (full_key);
2474
0
  g_string_free (value_list, TRUE);
2475
0
}
2476
2477
/**
2478
 * g_key_file_get_boolean:
2479
 * @key_file: a #GKeyFile
2480
 * @group_name: a group name
2481
 * @key: a key
2482
 * @error: return location for a #GError
2483
 *
2484
 * Returns the value associated with @key under @group_name as a
2485
 * boolean. 
2486
 *
2487
 * If @key cannot be found then %FALSE is returned and @error is set
2488
 * to #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the value
2489
 * associated with @key cannot be interpreted as a boolean then %FALSE
2490
 * is returned and @error is set to #G_KEY_FILE_ERROR_INVALID_VALUE.
2491
 *
2492
 * Returns: the value associated with the key as a boolean, 
2493
 *    or %FALSE if the key was not found or could not be parsed.
2494
 *
2495
 * Since: 2.6
2496
 **/
2497
gboolean
2498
g_key_file_get_boolean (GKeyFile     *key_file,
2499
      const gchar  *group_name,
2500
      const gchar  *key,
2501
      GError      **error)
2502
0
{
2503
0
  GError *key_file_error = NULL;
2504
0
  gchar *value;
2505
0
  gboolean bool_value;
2506
2507
0
  g_return_val_if_fail (key_file != NULL, FALSE);
2508
0
  g_return_val_if_fail (group_name != NULL, FALSE);
2509
0
  g_return_val_if_fail (key != NULL, FALSE);
2510
2511
0
  value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
2512
2513
0
  if (!value)
2514
0
    {
2515
0
      g_propagate_error (error, key_file_error);
2516
0
      return FALSE;
2517
0
    }
2518
2519
0
  bool_value = g_key_file_parse_value_as_boolean (key_file, value,
2520
0
              &key_file_error);
2521
0
  g_free (value);
2522
2523
0
  if (key_file_error)
2524
0
    {
2525
0
      if (g_error_matches (key_file_error,
2526
0
                           G_KEY_FILE_ERROR,
2527
0
                           G_KEY_FILE_ERROR_INVALID_VALUE))
2528
0
        {
2529
0
          g_set_error (error, G_KEY_FILE_ERROR,
2530
0
                       G_KEY_FILE_ERROR_INVALID_VALUE,
2531
0
                       _("Key file contains key “%s” "
2532
0
                         "which has a value that cannot be interpreted."),
2533
0
                       key);
2534
0
          g_error_free (key_file_error);
2535
0
        }
2536
0
      else
2537
0
        g_propagate_error (error, key_file_error);
2538
0
    }
2539
2540
0
  return bool_value;
2541
0
}
2542
2543
/**
2544
 * g_key_file_set_boolean:
2545
 * @key_file: a #GKeyFile
2546
 * @group_name: a group name
2547
 * @key: a key
2548
 * @value: %TRUE or %FALSE
2549
 *
2550
 * Associates a new boolean value with @key under @group_name.
2551
 * If @key cannot be found then it is created. 
2552
 *
2553
 * Since: 2.6
2554
 **/
2555
void
2556
g_key_file_set_boolean (GKeyFile    *key_file,
2557
      const gchar *group_name,
2558
      const gchar *key,
2559
      gboolean     value)
2560
0
{
2561
0
  gchar *result;
2562
2563
0
  g_return_if_fail (key_file != NULL);
2564
2565
0
  result = g_key_file_parse_boolean_as_value (key_file, value);
2566
0
  g_key_file_set_value (key_file, group_name, key, result);
2567
0
  g_free (result);
2568
0
}
2569
2570
/**
2571
 * g_key_file_get_boolean_list:
2572
 * @key_file: a #GKeyFile
2573
 * @group_name: a group name
2574
 * @key: a key
2575
 * @length: (out): the number of booleans returned
2576
 * @error: return location for a #GError
2577
 *
2578
 * Returns the values associated with @key under @group_name as
2579
 * booleans. 
2580
 *
2581
 * If @key cannot be found then %NULL is returned and @error is set to
2582
 * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the values associated
2583
 * with @key cannot be interpreted as booleans then %NULL is returned
2584
 * and @error is set to #G_KEY_FILE_ERROR_INVALID_VALUE.
2585
 *
2586
 * Returns: (array length=length) (element-type gboolean) (transfer container):
2587
 *    the values associated with the key as a list of booleans, or %NULL if the
2588
 *    key was not found or could not be parsed. The returned list of booleans
2589
 *    should be freed with g_free() when no longer needed.
2590
 * 
2591
 * Since: 2.6
2592
 **/
2593
gboolean *
2594
g_key_file_get_boolean_list (GKeyFile     *key_file,
2595
           const gchar  *group_name,
2596
           const gchar  *key,
2597
           gsize        *length,
2598
           GError      **error)
2599
0
{
2600
0
  GError *key_file_error;
2601
0
  gchar **values;
2602
0
  gboolean *bool_values;
2603
0
  gsize i, num_bools;
2604
2605
0
  g_return_val_if_fail (key_file != NULL, NULL);
2606
0
  g_return_val_if_fail (group_name != NULL, NULL);
2607
0
  g_return_val_if_fail (key != NULL, NULL);
2608
2609
0
  if (length)
2610
0
    *length = 0;
2611
2612
0
  key_file_error = NULL;
2613
2614
0
  values = g_key_file_get_string_list (key_file, group_name, key,
2615
0
               &num_bools, &key_file_error);
2616
2617
0
  if (key_file_error)
2618
0
    g_propagate_error (error, key_file_error);
2619
2620
0
  if (!values)
2621
0
    return NULL;
2622
2623
0
  bool_values = g_new (gboolean, num_bools);
2624
2625
0
  for (i = 0; i < num_bools; i++)
2626
0
    {
2627
0
      bool_values[i] = g_key_file_parse_value_as_boolean (key_file,
2628
0
                values[i],
2629
0
                &key_file_error);
2630
2631
0
      if (key_file_error)
2632
0
        {
2633
0
          g_propagate_error (error, key_file_error);
2634
0
          g_strfreev (values);
2635
0
          g_free (bool_values);
2636
2637
0
          return NULL;
2638
0
        }
2639
0
    }
2640
0
  g_strfreev (values);
2641
2642
0
  if (length)
2643
0
    *length = num_bools;
2644
2645
0
  return bool_values;
2646
0
}
2647
2648
/**
2649
 * g_key_file_set_boolean_list:
2650
 * @key_file: a #GKeyFile
2651
 * @group_name: a group name
2652
 * @key: a key
2653
 * @list: (array length=length): an array of boolean values
2654
 * @length: length of @list
2655
 *
2656
 * Associates a list of boolean values with @key under @group_name.  
2657
 * If @key cannot be found then it is created.
2658
 * If @group_name is %NULL, the start_group is used.
2659
 *
2660
 * Since: 2.6
2661
 **/
2662
void
2663
g_key_file_set_boolean_list (GKeyFile    *key_file,
2664
           const gchar *group_name,
2665
           const gchar *key,
2666
           gboolean     list[],
2667
           gsize        length)
2668
0
{
2669
0
  GString *value_list;
2670
0
  gsize i;
2671
2672
0
  g_return_if_fail (key_file != NULL);
2673
0
  g_return_if_fail (list != NULL);
2674
2675
0
  value_list = g_string_sized_new (length * 8);
2676
0
  for (i = 0; i < length; i++)
2677
0
    {
2678
0
      gchar *value;
2679
2680
0
      value = g_key_file_parse_boolean_as_value (key_file, list[i]);
2681
2682
0
      g_string_append (value_list, value);
2683
0
      g_string_append_c (value_list, key_file->list_separator);
2684
2685
0
      g_free (value);
2686
0
    }
2687
2688
0
  g_key_file_set_value (key_file, group_name, key, value_list->str);
2689
0
  g_string_free (value_list, TRUE);
2690
0
}
2691
2692
/**
2693
 * g_key_file_get_integer:
2694
 * @key_file: a #GKeyFile
2695
 * @group_name: a group name
2696
 * @key: a key
2697
 * @error: return location for a #GError
2698
 *
2699
 * Returns the value associated with @key under @group_name as an
2700
 * integer. 
2701
 *
2702
 * If @key cannot be found then 0 is returned and @error is set to
2703
 * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the value associated
2704
 * with @key cannot be interpreted as an integer, or is out of range
2705
 * for a #gint, then 0 is returned
2706
 * and @error is set to #G_KEY_FILE_ERROR_INVALID_VALUE.
2707
 *
2708
 * Returns: the value associated with the key as an integer, or
2709
 *     0 if the key was not found or could not be parsed.
2710
 *
2711
 * Since: 2.6
2712
 **/
2713
gint
2714
g_key_file_get_integer (GKeyFile     *key_file,
2715
      const gchar  *group_name,
2716
      const gchar  *key,
2717
      GError      **error)
2718
0
{
2719
0
  GError *key_file_error;
2720
0
  gchar *value;
2721
0
  gint int_value;
2722
2723
0
  g_return_val_if_fail (key_file != NULL, -1);
2724
0
  g_return_val_if_fail (group_name != NULL, -1);
2725
0
  g_return_val_if_fail (key != NULL, -1);
2726
2727
0
  key_file_error = NULL;
2728
2729
0
  value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
2730
2731
0
  if (key_file_error)
2732
0
    {
2733
0
      g_propagate_error (error, key_file_error);
2734
0
      return 0;
2735
0
    }
2736
2737
0
  int_value = g_key_file_parse_value_as_integer (key_file, value,
2738
0
             &key_file_error);
2739
0
  g_free (value);
2740
2741
0
  if (key_file_error)
2742
0
    {
2743
0
      if (g_error_matches (key_file_error,
2744
0
                           G_KEY_FILE_ERROR,
2745
0
                           G_KEY_FILE_ERROR_INVALID_VALUE))
2746
0
        {
2747
0
          g_set_error (error, G_KEY_FILE_ERROR,
2748
0
                       G_KEY_FILE_ERROR_INVALID_VALUE,
2749
0
                       _("Key file contains key “%s” in group “%s” "
2750
0
                         "which has a value that cannot be interpreted."),
2751
0
                         key, group_name);
2752
0
          g_error_free (key_file_error);
2753
0
        }
2754
0
      else
2755
0
        g_propagate_error (error, key_file_error);
2756
0
    }
2757
2758
0
  return int_value;
2759
0
}
2760
2761
/**
2762
 * g_key_file_set_integer:
2763
 * @key_file: a #GKeyFile
2764
 * @group_name: a group name
2765
 * @key: a key
2766
 * @value: an integer value
2767
 *
2768
 * Associates a new integer value with @key under @group_name.
2769
 * If @key cannot be found then it is created.
2770
 *
2771
 * Since: 2.6
2772
 **/
2773
void
2774
g_key_file_set_integer (GKeyFile    *key_file,
2775
      const gchar *group_name,
2776
      const gchar *key,
2777
      gint         value)
2778
0
{
2779
0
  gchar *result;
2780
2781
0
  g_return_if_fail (key_file != NULL);
2782
2783
0
  result = g_key_file_parse_integer_as_value (key_file, value);
2784
0
  g_key_file_set_value (key_file, group_name, key, result);
2785
0
  g_free (result);
2786
0
}
2787
2788
/**
2789
 * g_key_file_get_int64:
2790
 * @key_file: a non-%NULL #GKeyFile
2791
 * @group_name: a non-%NULL group name
2792
 * @key: a non-%NULL key
2793
 * @error: return location for a #GError
2794
 *
2795
 * Returns the value associated with @key under @group_name as a signed
2796
 * 64-bit integer. This is similar to g_key_file_get_integer() but can return
2797
 * 64-bit results without truncation.
2798
 *
2799
 * Returns: the value associated with the key as a signed 64-bit integer, or
2800
 * 0 if the key was not found or could not be parsed.
2801
 *
2802
 * Since: 2.26
2803
 */
2804
gint64
2805
g_key_file_get_int64 (GKeyFile     *key_file,
2806
                      const gchar  *group_name,
2807
                      const gchar  *key,
2808
                      GError      **error)
2809
0
{
2810
0
  gchar *s, *end;
2811
0
  gint64 v;
2812
2813
0
  g_return_val_if_fail (key_file != NULL, -1);
2814
0
  g_return_val_if_fail (group_name != NULL, -1);
2815
0
  g_return_val_if_fail (key != NULL, -1);
2816
2817
0
  s = g_key_file_get_value (key_file, group_name, key, error);
2818
2819
0
  if (s == NULL)
2820
0
    return 0;
2821
2822
0
  v = g_ascii_strtoll (s, &end, 10);
2823
2824
0
  if (*s == '\0' || *end != '\0')
2825
0
    {
2826
0
      g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE,
2827
0
                   _("Key “%s” in group “%s” has value “%s” "
2828
0
                     "where %s was expected"),
2829
0
                   key, group_name, s, "int64");
2830
0
      g_free (s);
2831
0
      return 0;
2832
0
    }
2833
2834
0
  g_free (s);
2835
0
  return v;
2836
0
}
2837
2838
/**
2839
 * g_key_file_set_int64:
2840
 * @key_file: a #GKeyFile
2841
 * @group_name: a group name
2842
 * @key: a key
2843
 * @value: an integer value
2844
 *
2845
 * Associates a new integer value with @key under @group_name.
2846
 * If @key cannot be found then it is created.
2847
 *
2848
 * Since: 2.26
2849
 **/
2850
void
2851
g_key_file_set_int64 (GKeyFile    *key_file,
2852
                      const gchar *group_name,
2853
                      const gchar *key,
2854
                      gint64       value)
2855
0
{
2856
0
  gchar *result;
2857
2858
0
  g_return_if_fail (key_file != NULL);
2859
2860
0
  result = g_strdup_printf ("%" G_GINT64_FORMAT, value);
2861
0
  g_key_file_set_value (key_file, group_name, key, result);
2862
0
  g_free (result);
2863
0
}
2864
2865
/**
2866
 * g_key_file_get_uint64:
2867
 * @key_file: a non-%NULL #GKeyFile
2868
 * @group_name: a non-%NULL group name
2869
 * @key: a non-%NULL key
2870
 * @error: return location for a #GError
2871
 *
2872
 * Returns the value associated with @key under @group_name as an unsigned
2873
 * 64-bit integer. This is similar to g_key_file_get_integer() but can return
2874
 * large positive results without truncation.
2875
 *
2876
 * Returns: the value associated with the key as an unsigned 64-bit integer,
2877
 * or 0 if the key was not found or could not be parsed.
2878
 *
2879
 * Since: 2.26
2880
 */
2881
guint64
2882
g_key_file_get_uint64 (GKeyFile     *key_file,
2883
                       const gchar  *group_name,
2884
                       const gchar  *key,
2885
                       GError      **error)
2886
0
{
2887
0
  gchar *s, *end;
2888
0
  guint64 v;
2889
2890
0
  g_return_val_if_fail (key_file != NULL, -1);
2891
0
  g_return_val_if_fail (group_name != NULL, -1);
2892
0
  g_return_val_if_fail (key != NULL, -1);
2893
2894
0
  s = g_key_file_get_value (key_file, group_name, key, error);
2895
2896
0
  if (s == NULL)
2897
0
    return 0;
2898
2899
0
  v = g_ascii_strtoull (s, &end, 10);
2900
2901
0
  if (*s == '\0' || *end != '\0')
2902
0
    {
2903
0
      g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE,
2904
0
                   _("Key “%s” in group “%s” has value “%s” "
2905
0
                     "where %s was expected"),
2906
0
                   key, group_name, s, "uint64");
2907
0
      g_free (s);
2908
0
      return 0;
2909
0
    }
2910
2911
0
  g_free (s);
2912
0
  return v;
2913
0
}
2914
2915
/**
2916
 * g_key_file_set_uint64:
2917
 * @key_file: a #GKeyFile
2918
 * @group_name: a group name
2919
 * @key: a key
2920
 * @value: an integer value
2921
 *
2922
 * Associates a new integer value with @key under @group_name.
2923
 * If @key cannot be found then it is created.
2924
 *
2925
 * Since: 2.26
2926
 **/
2927
void
2928
g_key_file_set_uint64 (GKeyFile    *key_file,
2929
                       const gchar *group_name,
2930
                       const gchar *key,
2931
                       guint64      value)
2932
0
{
2933
0
  gchar *result;
2934
2935
0
  g_return_if_fail (key_file != NULL);
2936
2937
0
  result = g_strdup_printf ("%" G_GUINT64_FORMAT, value);
2938
0
  g_key_file_set_value (key_file, group_name, key, result);
2939
0
  g_free (result);
2940
0
}
2941
2942
/**
2943
 * g_key_file_get_integer_list:
2944
 * @key_file: a #GKeyFile
2945
 * @group_name: a group name
2946
 * @key: a key
2947
 * @length: (out): the number of integers returned
2948
 * @error: return location for a #GError
2949
 *
2950
 * Returns the values associated with @key under @group_name as
2951
 * integers. 
2952
 *
2953
 * If @key cannot be found then %NULL is returned and @error is set to
2954
 * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the values associated
2955
 * with @key cannot be interpreted as integers, or are out of range for
2956
 * #gint, then %NULL is returned
2957
 * and @error is set to #G_KEY_FILE_ERROR_INVALID_VALUE.
2958
 *
2959
 * Returns: (array length=length) (element-type gint) (transfer container):
2960
 *     the values associated with the key as a list of integers, or %NULL if
2961
 *     the key was not found or could not be parsed. The returned list of
2962
 *     integers should be freed with g_free() when no longer needed.
2963
 *
2964
 * Since: 2.6
2965
 **/
2966
gint *
2967
g_key_file_get_integer_list (GKeyFile     *key_file,
2968
           const gchar  *group_name,
2969
           const gchar  *key,
2970
           gsize        *length,
2971
           GError      **error)
2972
0
{
2973
0
  GError *key_file_error = NULL;
2974
0
  gchar **values;
2975
0
  gint *int_values;
2976
0
  gsize i, num_ints;
2977
2978
0
  g_return_val_if_fail (key_file != NULL, NULL);
2979
0
  g_return_val_if_fail (group_name != NULL, NULL);
2980
0
  g_return_val_if_fail (key != NULL, NULL);
2981
2982
0
  if (length)
2983
0
    *length = 0;
2984
2985
0
  values = g_key_file_get_string_list (key_file, group_name, key,
2986
0
               &num_ints, &key_file_error);
2987
2988
0
  if (key_file_error)
2989
0
    g_propagate_error (error, key_file_error);
2990
2991
0
  if (!values)
2992
0
    return NULL;
2993
2994
0
  int_values = g_new (gint, num_ints);
2995
2996
0
  for (i = 0; i < num_ints; i++)
2997
0
    {
2998
0
      int_values[i] = g_key_file_parse_value_as_integer (key_file,
2999
0
               values[i],
3000
0
               &key_file_error);
3001
3002
0
      if (key_file_error)
3003
0
        {
3004
0
          g_propagate_error (error, key_file_error);
3005
0
          g_strfreev (values);
3006
0
          g_free (int_values);
3007
3008
0
          return NULL;
3009
0
        }
3010
0
    }
3011
0
  g_strfreev (values);
3012
3013
0
  if (length)
3014
0
    *length = num_ints;
3015
3016
0
  return int_values;
3017
0
}
3018
3019
/**
3020
 * g_key_file_set_integer_list:
3021
 * @key_file: a #GKeyFile
3022
 * @group_name: a group name
3023
 * @key: a key
3024
 * @list: (array length=length): an array of integer values
3025
 * @length: number of integer values in @list
3026
 *
3027
 * Associates a list of integer values with @key under @group_name.  
3028
 * If @key cannot be found then it is created.
3029
 *
3030
 * Since: 2.6
3031
 **/
3032
void
3033
g_key_file_set_integer_list (GKeyFile    *key_file,
3034
           const gchar *group_name,
3035
           const gchar *key,
3036
           gint         list[],
3037
           gsize        length)
3038
0
{
3039
0
  GString *values;
3040
0
  gsize i;
3041
3042
0
  g_return_if_fail (key_file != NULL);
3043
0
  g_return_if_fail (list != NULL);
3044
3045
0
  values = g_string_sized_new (length * 16);
3046
0
  for (i = 0; i < length; i++)
3047
0
    {
3048
0
      gchar *value;
3049
3050
0
      value = g_key_file_parse_integer_as_value (key_file, list[i]);
3051
3052
0
      g_string_append (values, value);
3053
0
      g_string_append_c (values, key_file->list_separator);
3054
3055
0
      g_free (value);
3056
0
    }
3057
3058
0
  g_key_file_set_value (key_file, group_name, key, values->str);
3059
0
  g_string_free (values, TRUE);
3060
0
}
3061
3062
/**
3063
 * g_key_file_get_double:
3064
 * @key_file: a #GKeyFile
3065
 * @group_name: a group name
3066
 * @key: a key
3067
 * @error: return location for a #GError
3068
 *
3069
 * Returns the value associated with @key under @group_name as a
3070
 * double. If @group_name is %NULL, the start_group is used.
3071
 *
3072
 * If @key cannot be found then 0.0 is returned and @error is set to
3073
 * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the value associated
3074
 * with @key cannot be interpreted as a double then 0.0 is returned
3075
 * and @error is set to #G_KEY_FILE_ERROR_INVALID_VALUE.
3076
 *
3077
 * Returns: the value associated with the key as a double, or
3078
 *     0.0 if the key was not found or could not be parsed.
3079
 *
3080
 * Since: 2.12
3081
 **/
3082
gdouble
3083
g_key_file_get_double  (GKeyFile     *key_file,
3084
                        const gchar  *group_name,
3085
                        const gchar  *key,
3086
                        GError      **error)
3087
0
{
3088
0
  GError *key_file_error;
3089
0
  gchar *value;
3090
0
  gdouble double_value;
3091
3092
0
  g_return_val_if_fail (key_file != NULL, -1);
3093
0
  g_return_val_if_fail (group_name != NULL, -1);
3094
0
  g_return_val_if_fail (key != NULL, -1);
3095
3096
0
  key_file_error = NULL;
3097
3098
0
  value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
3099
3100
0
  if (key_file_error)
3101
0
    {
3102
0
      g_propagate_error (error, key_file_error);
3103
0
      return 0;
3104
0
    }
3105
3106
0
  double_value = g_key_file_parse_value_as_double (key_file, value,
3107
0
                                                  &key_file_error);
3108
0
  g_free (value);
3109
3110
0
  if (key_file_error)
3111
0
    {
3112
0
      if (g_error_matches (key_file_error,
3113
0
                           G_KEY_FILE_ERROR,
3114
0
                           G_KEY_FILE_ERROR_INVALID_VALUE))
3115
0
        {
3116
0
          g_set_error (error, G_KEY_FILE_ERROR,
3117
0
                       G_KEY_FILE_ERROR_INVALID_VALUE,
3118
0
                       _("Key file contains key “%s” in group “%s” "
3119
0
                         "which has a value that cannot be interpreted."),
3120
0
                       key, group_name);
3121
0
          g_error_free (key_file_error);
3122
0
        }
3123
0
      else
3124
0
        g_propagate_error (error, key_file_error);
3125
0
    }
3126
3127
0
  return double_value;
3128
0
}
3129
3130
/**
3131
 * g_key_file_set_double:
3132
 * @key_file: a #GKeyFile
3133
 * @group_name: a group name
3134
 * @key: a key
3135
 * @value: a double value
3136
 *
3137
 * Associates a new double value with @key under @group_name.
3138
 * If @key cannot be found then it is created. 
3139
 *
3140
 * Since: 2.12
3141
 **/
3142
void
3143
g_key_file_set_double  (GKeyFile    *key_file,
3144
                        const gchar *group_name,
3145
                        const gchar *key,
3146
                        gdouble      value)
3147
0
{
3148
0
  gchar result[G_ASCII_DTOSTR_BUF_SIZE];
3149
3150
0
  g_return_if_fail (key_file != NULL);
3151
3152
0
  g_ascii_dtostr (result, sizeof (result), value);
3153
0
  g_key_file_set_value (key_file, group_name, key, result);
3154
0
}
3155
3156
/**
3157
 * g_key_file_get_double_list:
3158
 * @key_file: a #GKeyFile
3159
 * @group_name: a group name
3160
 * @key: a key
3161
 * @length: (out): the number of doubles returned
3162
 * @error: return location for a #GError
3163
 *
3164
 * Returns the values associated with @key under @group_name as
3165
 * doubles. 
3166
 *
3167
 * If @key cannot be found then %NULL is returned and @error is set to
3168
 * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the values associated
3169
 * with @key cannot be interpreted as doubles then %NULL is returned
3170
 * and @error is set to #G_KEY_FILE_ERROR_INVALID_VALUE.
3171
 *
3172
 * Returns: (array length=length) (element-type gdouble) (transfer container):
3173
 *     the values associated with the key as a list of doubles, or %NULL if the
3174
 *     key was not found or could not be parsed. The returned list of doubles
3175
 *     should be freed with g_free() when no longer needed.
3176
 *
3177
 * Since: 2.12
3178
 **/
3179
gdouble *
3180
g_key_file_get_double_list  (GKeyFile     *key_file,
3181
                             const gchar  *group_name,
3182
                             const gchar  *key,
3183
                             gsize        *length,
3184
                             GError      **error)
3185
0
{
3186
0
  GError *key_file_error = NULL;
3187
0
  gchar **values;
3188
0
  gdouble *double_values;
3189
0
  gsize i, num_doubles;
3190
3191
0
  g_return_val_if_fail (key_file != NULL, NULL);
3192
0
  g_return_val_if_fail (group_name != NULL, NULL);
3193
0
  g_return_val_if_fail (key != NULL, NULL);
3194
3195
0
  if (length)
3196
0
    *length = 0;
3197
3198
0
  values = g_key_file_get_string_list (key_file, group_name, key,
3199
0
                                       &num_doubles, &key_file_error);
3200
3201
0
  if (key_file_error)
3202
0
    g_propagate_error (error, key_file_error);
3203
3204
0
  if (!values)
3205
0
    return NULL;
3206
3207
0
  double_values = g_new (gdouble, num_doubles);
3208
3209
0
  for (i = 0; i < num_doubles; i++)
3210
0
    {
3211
0
      double_values[i] = g_key_file_parse_value_as_double (key_file,
3212
0
                 values[i],
3213
0
                 &key_file_error);
3214
3215
0
      if (key_file_error)
3216
0
        {
3217
0
          g_propagate_error (error, key_file_error);
3218
0
          g_strfreev (values);
3219
0
          g_free (double_values);
3220
3221
0
          return NULL;
3222
0
        }
3223
0
    }
3224
0
  g_strfreev (values);
3225
3226
0
  if (length)
3227
0
    *length = num_doubles;
3228
3229
0
  return double_values;
3230
0
}
3231
3232
/**
3233
 * g_key_file_set_double_list:
3234
 * @key_file: a #GKeyFile
3235
 * @group_name: a group name
3236
 * @key: a key
3237
 * @list: (array length=length): an array of double values
3238
 * @length: number of double values in @list
3239
 *
3240
 * Associates a list of double values with @key under
3241
 * @group_name.  If @key cannot be found then it is created.
3242
 *
3243
 * Since: 2.12
3244
 **/
3245
void
3246
g_key_file_set_double_list (GKeyFile    *key_file,
3247
          const gchar *group_name,
3248
          const gchar *key,
3249
          gdouble      list[],
3250
          gsize        length)
3251
0
{
3252
0
  GString *values;
3253
0
  gsize i;
3254
3255
0
  g_return_if_fail (key_file != NULL);
3256
0
  g_return_if_fail (list != NULL);
3257
3258
0
  values = g_string_sized_new (length * 16);
3259
0
  for (i = 0; i < length; i++)
3260
0
    {
3261
0
      gchar result[G_ASCII_DTOSTR_BUF_SIZE];
3262
3263
0
      g_ascii_dtostr( result, sizeof (result), list[i] );
3264
3265
0
      g_string_append (values, result);
3266
0
      g_string_append_c (values, key_file->list_separator);
3267
0
    }
3268
3269
0
  g_key_file_set_value (key_file, group_name, key, values->str);
3270
0
  g_string_free (values, TRUE);
3271
0
}
3272
3273
static gboolean
3274
g_key_file_set_key_comment (GKeyFile     *key_file,
3275
                            const gchar  *group_name,
3276
                            const gchar  *key,
3277
                            const gchar  *comment,
3278
                            GError      **error)
3279
0
{
3280
0
  GKeyFileGroup *group;
3281
0
  GKeyFileKeyValuePair *pair;
3282
0
  GList *key_node, *comment_node, *tmp;
3283
  
3284
0
  group = g_key_file_lookup_group (key_file, group_name);
3285
0
  if (!group)
3286
0
    {
3287
0
      g_set_error (error, G_KEY_FILE_ERROR,
3288
0
                   G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
3289
0
                   _("Key file does not have group “%s”"),
3290
0
                   group_name ? group_name : "(null)");
3291
3292
0
      return FALSE;
3293
0
    }
3294
3295
  /* First find the key the comments are supposed to be
3296
   * associated with
3297
   */
3298
0
  key_node = g_key_file_lookup_key_value_pair_node (key_file, group, key);
3299
3300
0
  if (key_node == NULL)
3301
0
    {
3302
0
      set_not_found_key_error (group->name, key, error);
3303
0
      return FALSE;
3304
0
    }
3305
3306
  /* Then find all the comments already associated with the
3307
   * key and free them
3308
   */
3309
0
  tmp = key_node->next;
3310
0
  while (tmp != NULL)
3311
0
    {
3312
0
      pair = (GKeyFileKeyValuePair *) tmp->data;
3313
3314
0
      if (pair->key != NULL)
3315
0
        break;
3316
3317
0
      comment_node = tmp;
3318
0
      tmp = tmp->next;
3319
0
      g_key_file_remove_key_value_pair_node (key_file, group,
3320
0
                                             comment_node); 
3321
0
    }
3322
3323
0
  if (comment == NULL)
3324
0
    return TRUE;
3325
3326
  /* Now we can add our new comment
3327
   */
3328
0
  pair = g_slice_new (GKeyFileKeyValuePair);
3329
0
  pair->key = NULL;
3330
0
  pair->value = g_key_file_parse_comment_as_value (key_file, comment);
3331
  
3332
0
  key_node = g_list_insert (key_node, pair, 1);
3333
0
  (void) key_node;
3334
3335
0
  return TRUE;
3336
0
}
3337
3338
static gboolean
3339
g_key_file_set_group_comment (GKeyFile     *key_file,
3340
                              const gchar  *group_name,
3341
                              const gchar  *comment,
3342
                              GError      **error)
3343
0
{
3344
0
  GKeyFileGroup *group;
3345
  
3346
0
  g_return_val_if_fail (g_key_file_is_group_name (group_name), FALSE);
3347
3348
0
  group = g_key_file_lookup_group (key_file, group_name);
3349
0
  if (!group)
3350
0
    {
3351
0
      g_set_error (error, G_KEY_FILE_ERROR,
3352
0
                   G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
3353
0
                   _("Key file does not have group “%s”"),
3354
0
                   group_name ? group_name : "(null)");
3355
3356
0
      return FALSE;
3357
0
    }
3358
3359
  /* First remove any existing comment
3360
   */
3361
0
  if (group->comment)
3362
0
    {
3363
0
      g_key_file_key_value_pair_free (group->comment);
3364
0
      group->comment = NULL;
3365
0
    }
3366
3367
0
  if (comment == NULL)
3368
0
    return TRUE;
3369
3370
  /* Now we can add our new comment
3371
   */
3372
0
  group->comment = g_slice_new (GKeyFileKeyValuePair);
3373
0
  group->comment->key = NULL;
3374
0
  group->comment->value = g_key_file_parse_comment_as_value (key_file, comment);
3375
3376
0
  return TRUE;
3377
0
}
3378
3379
static gboolean
3380
g_key_file_set_top_comment (GKeyFile     *key_file,
3381
                            const gchar  *comment,
3382
                            GError      **error)
3383
0
{
3384
0
  GList *group_node;
3385
0
  GKeyFileGroup *group;
3386
0
  GKeyFileKeyValuePair *pair;
3387
3388
  /* The last group in the list should be the top (comments only)
3389
   * group in the file
3390
   */
3391
0
  g_warn_if_fail (key_file->groups != NULL);
3392
0
  group_node = g_list_last (key_file->groups);
3393
0
  group = (GKeyFileGroup *) group_node->data;
3394
0
  g_warn_if_fail (group->name == NULL);
3395
3396
  /* Note all keys must be comments at the top of
3397
   * the file, so we can just free it all.
3398
   */
3399
0
  g_list_free_full (group->key_value_pairs, (GDestroyNotify) g_key_file_key_value_pair_free);
3400
0
  group->key_value_pairs = NULL;
3401
3402
0
  if (comment == NULL)
3403
0
     return TRUE;
3404
3405
0
  pair = g_slice_new (GKeyFileKeyValuePair);
3406
0
  pair->key = NULL;
3407
0
  pair->value = g_key_file_parse_comment_as_value (key_file, comment);
3408
  
3409
0
  group->key_value_pairs =
3410
0
    g_list_prepend (group->key_value_pairs, pair);
3411
3412
0
  return TRUE;
3413
0
}
3414
3415
/**
3416
 * g_key_file_set_comment:
3417
 * @key_file: a #GKeyFile
3418
 * @group_name: (nullable): a group name, or %NULL
3419
 * @key: (nullable): a key
3420
 * @comment: a comment
3421
 * @error: return location for a #GError
3422
 *
3423
 * Places a comment above @key from @group_name.
3424
 *
3425
 * If @key is %NULL then @comment will be written above @group_name.
3426
 * If both @key and @group_name  are %NULL, then @comment will be
3427
 * written above the first group in the file.
3428
 *
3429
 * Note that this function prepends a '#' comment marker to
3430
 * each line of @comment.
3431
 *
3432
 * Returns: %TRUE if the comment was written, %FALSE otherwise
3433
 *
3434
 * Since: 2.6
3435
 **/
3436
gboolean
3437
g_key_file_set_comment (GKeyFile     *key_file,
3438
                        const gchar  *group_name,
3439
                        const gchar  *key,
3440
                        const gchar  *comment,
3441
                        GError      **error)
3442
0
{
3443
0
  g_return_val_if_fail (key_file != NULL, FALSE);
3444
3445
0
  if (group_name != NULL && key != NULL) 
3446
0
    {
3447
0
      if (!g_key_file_set_key_comment (key_file, group_name, key, comment, error))
3448
0
        return FALSE;
3449
0
    } 
3450
0
  else if (group_name != NULL) 
3451
0
    {
3452
0
      if (!g_key_file_set_group_comment (key_file, group_name, comment, error))
3453
0
        return FALSE;
3454
0
    } 
3455
0
  else 
3456
0
    {
3457
0
      if (!g_key_file_set_top_comment (key_file, comment, error))
3458
0
        return FALSE;
3459
0
    }
3460
3461
0
  return TRUE;
3462
0
}
3463
3464
static gchar *
3465
g_key_file_get_key_comment (GKeyFile     *key_file,
3466
                            const gchar  *group_name,
3467
                            const gchar  *key,
3468
                            GError      **error)
3469
0
{
3470
0
  GKeyFileGroup *group;
3471
0
  GKeyFileKeyValuePair *pair;
3472
0
  GList *key_node, *tmp;
3473
0
  GString *string;
3474
0
  gchar *comment;
3475
3476
0
  g_return_val_if_fail (g_key_file_is_group_name (group_name), NULL);
3477
3478
0
  group = g_key_file_lookup_group (key_file, group_name);
3479
0
  if (!group)
3480
0
    {
3481
0
      g_set_error (error, G_KEY_FILE_ERROR,
3482
0
                   G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
3483
0
                   _("Key file does not have group “%s”"),
3484
0
                   group_name ? group_name : "(null)");
3485
3486
0
      return NULL;
3487
0
    }
3488
3489
  /* First find the key the comments are supposed to be
3490
   * associated with
3491
   */
3492
0
  key_node = g_key_file_lookup_key_value_pair_node (key_file, group, key);
3493
3494
0
  if (key_node == NULL)
3495
0
    {
3496
0
      set_not_found_key_error (group->name, key, error);
3497
0
      return NULL;
3498
0
    }
3499
3500
0
  string = NULL;
3501
3502
  /* Then find all the comments already associated with the
3503
   * key and concatenate them.
3504
   */
3505
0
  tmp = key_node->next;
3506
0
  if (!key_node->next)
3507
0
    return NULL;
3508
3509
0
  pair = (GKeyFileKeyValuePair *) tmp->data;
3510
0
  if (pair->key != NULL)
3511
0
    return NULL;
3512
3513
0
  while (tmp->next)
3514
0
    {
3515
0
      pair = (GKeyFileKeyValuePair *) tmp->next->data;
3516
      
3517
0
      if (pair->key != NULL)
3518
0
        break;
3519
3520
0
      tmp = tmp->next;
3521
0
    }
3522
3523
0
  while (tmp != key_node)
3524
0
    {
3525
0
      pair = (GKeyFileKeyValuePair *) tmp->data;
3526
      
3527
0
      if (string == NULL)
3528
0
  string = g_string_sized_new (512);
3529
3530
0
      comment = g_key_file_parse_value_as_comment (key_file, pair->value,
3531
0
                                                   (tmp->prev == key_node));
3532
0
      g_string_append (string, comment);
3533
0
      g_free (comment);
3534
      
3535
0
      tmp = tmp->prev;
3536
0
    }
3537
3538
0
  if (string != NULL)
3539
0
    {
3540
0
      comment = string->str;
3541
0
      g_string_free (string, FALSE);
3542
0
    }
3543
0
  else
3544
0
    comment = NULL;
3545
3546
0
  return comment;
3547
0
}
3548
3549
static gchar *
3550
get_group_comment (GKeyFile       *key_file,
3551
       GKeyFileGroup  *group,
3552
       GError        **error)
3553
0
{
3554
0
  GString *string;
3555
0
  GList *tmp;
3556
0
  gchar *comment;
3557
3558
0
  string = NULL;
3559
3560
0
  tmp = group->key_value_pairs;
3561
0
  while (tmp)
3562
0
    {
3563
0
      GKeyFileKeyValuePair *pair;
3564
3565
0
      pair = (GKeyFileKeyValuePair *) tmp->data;
3566
3567
0
      if (pair->key != NULL)
3568
0
  {
3569
0
    tmp = tmp->prev;
3570
0
    break;
3571
0
  }
3572
3573
0
      if (tmp->next == NULL)
3574
0
  break;
3575
3576
0
      tmp = tmp->next;
3577
0
    }
3578
  
3579
0
  while (tmp != NULL)
3580
0
    {
3581
0
      GKeyFileKeyValuePair *pair;
3582
3583
0
      pair = (GKeyFileKeyValuePair *) tmp->data;
3584
3585
0
      if (string == NULL)
3586
0
        string = g_string_sized_new (512);
3587
3588
0
      comment = g_key_file_parse_value_as_comment (key_file, pair->value,
3589
0
                                                   (tmp->prev == NULL));
3590
0
      g_string_append (string, comment);
3591
0
      g_free (comment);
3592
3593
0
      tmp = tmp->prev;
3594
0
    }
3595
3596
0
  if (string != NULL)
3597
0
    return g_string_free (string, FALSE);
3598
3599
0
  return NULL;
3600
0
}
3601
3602
static gchar *
3603
g_key_file_get_group_comment (GKeyFile     *key_file,
3604
                              const gchar  *group_name,
3605
                              GError      **error)
3606
0
{
3607
0
  GList *group_node;
3608
0
  GKeyFileGroup *group;
3609
  
3610
0
  group = g_key_file_lookup_group (key_file, group_name);
3611
0
  if (!group)
3612
0
    {
3613
0
      g_set_error (error, G_KEY_FILE_ERROR,
3614
0
                   G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
3615
0
                   _("Key file does not have group “%s”"),
3616
0
                   group_name ? group_name : "(null)");
3617
3618
0
      return NULL;
3619
0
    }
3620
3621
0
  if (group->comment)
3622
0
    return g_strdup (group->comment->value);
3623
  
3624
0
  group_node = g_key_file_lookup_group_node (key_file, group_name);
3625
0
  group_node = group_node->next;
3626
0
  group = (GKeyFileGroup *)group_node->data;  
3627
0
  return get_group_comment (key_file, group, error);
3628
0
}
3629
3630
static gchar *
3631
g_key_file_get_top_comment (GKeyFile  *key_file,
3632
                            GError   **error)
3633
0
{
3634
0
  GList *group_node;
3635
0
  GKeyFileGroup *group;
3636
3637
  /* The last group in the list should be the top (comments only)
3638
   * group in the file
3639
   */
3640
0
  g_warn_if_fail (key_file->groups != NULL);
3641
0
  group_node = g_list_last (key_file->groups);
3642
0
  group = (GKeyFileGroup *) group_node->data;
3643
0
  g_warn_if_fail (group->name == NULL);
3644
3645
0
  return get_group_comment (key_file, group, error);
3646
0
}
3647
3648
/**
3649
 * g_key_file_get_comment:
3650
 * @key_file: a #GKeyFile
3651
 * @group_name: (nullable): a group name, or %NULL
3652
 * @key: (nullable): a key
3653
 * @error: return location for a #GError
3654
 *
3655
 * Retrieves a comment above @key from @group_name.
3656
 * If @key is %NULL then @comment will be read from above
3657
 * @group_name. If both @key and @group_name are %NULL, then
3658
 * @comment will be read from above the first group in the file.
3659
 *
3660
 * Note that the returned string does not include the '#' comment markers,
3661
 * but does include any whitespace after them (on each line). It includes
3662
 * the line breaks between lines, but does not include the final line break.
3663
 *
3664
 * Returns: a comment that should be freed with g_free()
3665
 *
3666
 * Since: 2.6
3667
 **/
3668
gchar * 
3669
g_key_file_get_comment (GKeyFile     *key_file,
3670
                        const gchar  *group_name,
3671
                        const gchar  *key,
3672
                        GError      **error)
3673
0
{
3674
0
  g_return_val_if_fail (key_file != NULL, NULL);
3675
3676
0
  if (group_name != NULL && key != NULL)
3677
0
    return g_key_file_get_key_comment (key_file, group_name, key, error);
3678
0
  else if (group_name != NULL)
3679
0
    return g_key_file_get_group_comment (key_file, group_name, error);
3680
0
  else
3681
0
    return g_key_file_get_top_comment (key_file, error);
3682
0
}
3683
3684
/**
3685
 * g_key_file_remove_comment:
3686
 * @key_file: a #GKeyFile
3687
 * @group_name: (nullable): a group name, or %NULL
3688
 * @key: (nullable): a key
3689
 * @error: return location for a #GError
3690
 *
3691
 * Removes a comment above @key from @group_name.
3692
 * If @key is %NULL then @comment will be removed above @group_name. 
3693
 * If both @key and @group_name are %NULL, then @comment will
3694
 * be removed above the first group in the file.
3695
 *
3696
 * Returns: %TRUE if the comment was removed, %FALSE otherwise
3697
 *
3698
 * Since: 2.6
3699
 **/
3700
3701
gboolean
3702
g_key_file_remove_comment (GKeyFile     *key_file,
3703
                           const gchar  *group_name,
3704
                           const gchar  *key,
3705
                           GError      **error)
3706
0
{
3707
0
  g_return_val_if_fail (key_file != NULL, FALSE);
3708
3709
0
  if (group_name != NULL && key != NULL)
3710
0
    return g_key_file_set_key_comment (key_file, group_name, key, NULL, error);
3711
0
  else if (group_name != NULL)
3712
0
    return g_key_file_set_group_comment (key_file, group_name, NULL, error);
3713
0
  else
3714
0
    return g_key_file_set_top_comment (key_file, NULL, error);
3715
0
}
3716
3717
/**
3718
 * g_key_file_has_group:
3719
 * @key_file: a #GKeyFile
3720
 * @group_name: a group name
3721
 *
3722
 * Looks whether the key file has the group @group_name.
3723
 *
3724
 * Returns: %TRUE if @group_name is a part of @key_file, %FALSE
3725
 * otherwise.
3726
 * Since: 2.6
3727
 **/
3728
gboolean
3729
g_key_file_has_group (GKeyFile    *key_file,
3730
          const gchar *group_name)
3731
0
{
3732
0
  g_return_val_if_fail (key_file != NULL, FALSE);
3733
0
  g_return_val_if_fail (group_name != NULL, FALSE);
3734
3735
0
  return g_key_file_lookup_group (key_file, group_name) != NULL;
3736
0
}
3737
3738
/* This code remains from a historical attempt to add a new public API
3739
 * which respects the GError rules.
3740
 */
3741
static gboolean
3742
g_key_file_has_key_full (GKeyFile     *key_file,
3743
       const gchar  *group_name,
3744
       const gchar  *key,
3745
       gboolean     *has_key,
3746
       GError      **error)
3747
0
{
3748
0
  GKeyFileKeyValuePair *pair;
3749
0
  GKeyFileGroup *group;
3750
3751
0
  g_return_val_if_fail (key_file != NULL, FALSE);
3752
0
  g_return_val_if_fail (group_name != NULL, FALSE);
3753
0
  g_return_val_if_fail (key != NULL, FALSE);
3754
3755
0
  group = g_key_file_lookup_group (key_file, group_name);
3756
3757
0
  if (!group)
3758
0
    {
3759
0
      g_set_error (error, G_KEY_FILE_ERROR,
3760
0
                   G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
3761
0
                   _("Key file does not have group “%s”"),
3762
0
                   group_name);
3763
3764
0
      return FALSE;
3765
0
    }
3766
3767
0
  pair = g_key_file_lookup_key_value_pair (key_file, group, key);
3768
3769
0
  if (has_key)
3770
0
    *has_key = pair != NULL;
3771
0
  return TRUE;
3772
0
}
3773
3774
/**
3775
 * g_key_file_has_key: (skip)
3776
 * @key_file: a #GKeyFile
3777
 * @group_name: a group name
3778
 * @key: a key name
3779
 * @error: return location for a #GError
3780
 *
3781
 * Looks whether the key file has the key @key in the group
3782
 * @group_name.
3783
 *
3784
 * Note that this function does not follow the rules for #GError strictly;
3785
 * the return value both carries meaning and signals an error.  To use
3786
 * this function, you must pass a #GError pointer in @error, and check
3787
 * whether it is not %NULL to see if an error occurred.
3788
 *
3789
 * Language bindings should use g_key_file_get_value() to test whether
3790
 * or not a key exists.
3791
 *
3792
 * Returns: %TRUE if @key is a part of @group_name, %FALSE otherwise
3793
 *
3794
 * Since: 2.6
3795
 **/
3796
gboolean
3797
g_key_file_has_key (GKeyFile     *key_file,
3798
        const gchar  *group_name,
3799
        const gchar  *key,
3800
        GError      **error)
3801
0
{
3802
0
  GError *temp_error = NULL;
3803
0
  gboolean has_key;
3804
3805
0
  if (g_key_file_has_key_full (key_file, group_name, key, &has_key, &temp_error))
3806
0
    {
3807
0
      return has_key;
3808
0
    }
3809
0
  else
3810
0
    {
3811
0
      g_propagate_error (error, temp_error);
3812
0
      return FALSE;
3813
0
    }
3814
0
}
3815
3816
static void
3817
g_key_file_add_group (GKeyFile    *key_file,
3818
          const gchar *group_name)
3819
0
{
3820
0
  GKeyFileGroup *group;
3821
3822
0
  g_return_if_fail (key_file != NULL);
3823
0
  g_return_if_fail (g_key_file_is_group_name (group_name));
3824
3825
0
  group = g_key_file_lookup_group (key_file, group_name);
3826
0
  if (group != NULL)
3827
0
    {
3828
0
      key_file->current_group = group;
3829
0
      return;
3830
0
    }
3831
3832
0
  group = g_slice_new0 (GKeyFileGroup);
3833
0
  group->name = g_strdup (group_name);
3834
0
  group->lookup_map = g_hash_table_new (g_str_hash, g_str_equal);
3835
0
  key_file->groups = g_list_prepend (key_file->groups, group);
3836
0
  key_file->current_group = group;
3837
3838
0
  if (key_file->start_group == NULL)
3839
0
    key_file->start_group = group;
3840
3841
0
  if (!key_file->group_hash)
3842
0
    key_file->group_hash = g_hash_table_new (g_str_hash, g_str_equal);
3843
3844
0
  g_hash_table_insert (key_file->group_hash, (gpointer)group->name, group);
3845
0
}
3846
3847
static void
3848
g_key_file_key_value_pair_free (GKeyFileKeyValuePair *pair)
3849
0
{
3850
0
  if (pair != NULL)
3851
0
    {
3852
0
      g_free (pair->key);
3853
0
      g_free (pair->value);
3854
0
      g_slice_free (GKeyFileKeyValuePair, pair);
3855
0
    }
3856
0
}
3857
3858
/* Be careful not to call this function on a node with data in the
3859
 * lookup map without removing it from the lookup map, first.
3860
 *
3861
 * Some current cases where this warning is not a concern are
3862
 * when:
3863
 *   - the node being removed is a comment node
3864
 *   - the entire lookup map is getting destroyed soon after
3865
 *     anyway.
3866
 */ 
3867
static void
3868
g_key_file_remove_key_value_pair_node (GKeyFile      *key_file,
3869
                                       GKeyFileGroup *group,
3870
                     GList         *pair_node)
3871
0
{
3872
3873
0
  GKeyFileKeyValuePair *pair;
3874
3875
0
  pair = (GKeyFileKeyValuePair *) pair_node->data;
3876
3877
0
  group->key_value_pairs = g_list_remove_link (group->key_value_pairs, pair_node);
3878
3879
0
  g_warn_if_fail (pair->value != NULL);
3880
3881
0
  g_key_file_key_value_pair_free (pair);
3882
3883
0
  g_list_free_1 (pair_node);
3884
0
}
3885
3886
static void
3887
g_key_file_remove_group_node (GKeyFile *key_file,
3888
            GList    *group_node)
3889
0
{
3890
0
  GKeyFileGroup *group;
3891
0
  GList *tmp;
3892
3893
0
  group = (GKeyFileGroup *) group_node->data;
3894
3895
0
  if (group->name)
3896
0
    {
3897
0
      g_assert (key_file->group_hash);
3898
0
      g_hash_table_remove (key_file->group_hash, group->name);
3899
0
    }
3900
3901
  /* If the current group gets deleted make the current group the last
3902
   * added group.
3903
   */
3904
0
  if (key_file->current_group == group)
3905
0
    {
3906
      /* groups should always contain at least the top comment group,
3907
       * unless g_key_file_clear has been called
3908
       */
3909
0
      if (key_file->groups)
3910
0
        key_file->current_group = (GKeyFileGroup *) key_file->groups->data;
3911
0
      else
3912
0
        key_file->current_group = NULL;
3913
0
    }
3914
3915
  /* If the start group gets deleted make the start group the first
3916
   * added group.
3917
   */
3918
0
  if (key_file->start_group == group)
3919
0
    {
3920
0
      tmp = g_list_last (key_file->groups);
3921
0
      while (tmp != NULL)
3922
0
  {
3923
0
    if (tmp != group_node &&
3924
0
        ((GKeyFileGroup *) tmp->data)->name != NULL)
3925
0
      break;
3926
3927
0
    tmp = tmp->prev;
3928
0
  }
3929
3930
0
      if (tmp)
3931
0
        key_file->start_group = (GKeyFileGroup *) tmp->data;
3932
0
      else
3933
0
        key_file->start_group = NULL;
3934
0
    }
3935
3936
0
  key_file->groups = g_list_remove_link (key_file->groups, group_node);
3937
3938
0
  tmp = group->key_value_pairs;
3939
0
  while (tmp != NULL)
3940
0
    {
3941
0
      GList *pair_node;
3942
3943
0
      pair_node = tmp;
3944
0
      tmp = tmp->next;
3945
0
      g_key_file_remove_key_value_pair_node (key_file, group, pair_node);
3946
0
    }
3947
3948
0
  g_warn_if_fail (group->key_value_pairs == NULL);
3949
3950
0
  if (group->comment)
3951
0
    {
3952
0
      g_key_file_key_value_pair_free (group->comment);
3953
0
      group->comment = NULL;
3954
0
    }
3955
3956
0
  if (group->lookup_map)
3957
0
    {
3958
0
      g_hash_table_destroy (group->lookup_map);
3959
0
      group->lookup_map = NULL;
3960
0
    }
3961
3962
0
  g_free ((gchar *) group->name);
3963
0
  g_slice_free (GKeyFileGroup, group);
3964
0
  g_list_free_1 (group_node);
3965
0
}
3966
3967
/**
3968
 * g_key_file_remove_group:
3969
 * @key_file: a #GKeyFile
3970
 * @group_name: a group name
3971
 * @error: return location for a #GError or %NULL
3972
 *
3973
 * Removes the specified group, @group_name, 
3974
 * from the key file. 
3975
 *
3976
 * Returns: %TRUE if the group was removed, %FALSE otherwise
3977
 *
3978
 * Since: 2.6
3979
 **/
3980
gboolean
3981
g_key_file_remove_group (GKeyFile     *key_file,
3982
       const gchar  *group_name,
3983
       GError      **error)
3984
0
{
3985
0
  GList *group_node;
3986
3987
0
  g_return_val_if_fail (key_file != NULL, FALSE);
3988
0
  g_return_val_if_fail (group_name != NULL, FALSE);
3989
3990
0
  group_node = g_key_file_lookup_group_node (key_file, group_name);
3991
3992
0
  if (!group_node)
3993
0
    {
3994
0
      g_set_error (error, G_KEY_FILE_ERROR,
3995
0
       G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
3996
0
       _("Key file does not have group “%s”"),
3997
0
       group_name);
3998
0
      return FALSE;
3999
0
    }
4000
4001
0
  g_key_file_remove_group_node (key_file, group_node);
4002
4003
0
  return TRUE;  
4004
0
}
4005
4006
static void
4007
g_key_file_add_key_value_pair (GKeyFile             *key_file,
4008
                               GKeyFileGroup        *group,
4009
                               GKeyFileKeyValuePair *pair)
4010
0
{
4011
0
  g_hash_table_replace (group->lookup_map, pair->key, pair);
4012
0
  group->key_value_pairs = g_list_prepend (group->key_value_pairs, pair);
4013
0
}
4014
4015
static void
4016
g_key_file_add_key (GKeyFile      *key_file,
4017
        GKeyFileGroup *group,
4018
        const gchar   *key,
4019
        const gchar   *value)
4020
0
{
4021
0
  GKeyFileKeyValuePair *pair;
4022
4023
0
  pair = g_slice_new (GKeyFileKeyValuePair);
4024
0
  pair->key = g_strdup (key);
4025
0
  pair->value = g_strdup (value);
4026
4027
0
  g_key_file_add_key_value_pair (key_file, group, pair);
4028
0
}
4029
4030
/**
4031
 * g_key_file_remove_key:
4032
 * @key_file: a #GKeyFile
4033
 * @group_name: a group name
4034
 * @key: a key name to remove
4035
 * @error: return location for a #GError or %NULL
4036
 *
4037
 * Removes @key in @group_name from the key file. 
4038
 *
4039
 * Returns: %TRUE if the key was removed, %FALSE otherwise
4040
 *
4041
 * Since: 2.6
4042
 **/
4043
gboolean
4044
g_key_file_remove_key (GKeyFile     *key_file,
4045
           const gchar  *group_name,
4046
           const gchar  *key,
4047
           GError      **error)
4048
0
{
4049
0
  GKeyFileGroup *group;
4050
0
  GKeyFileKeyValuePair *pair;
4051
4052
0
  g_return_val_if_fail (key_file != NULL, FALSE);
4053
0
  g_return_val_if_fail (group_name != NULL, FALSE);
4054
0
  g_return_val_if_fail (key != NULL, FALSE);
4055
4056
0
  pair = NULL;
4057
4058
0
  group = g_key_file_lookup_group (key_file, group_name);
4059
0
  if (!group)
4060
0
    {
4061
0
      g_set_error (error, G_KEY_FILE_ERROR,
4062
0
                   G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
4063
0
                   _("Key file does not have group “%s”"),
4064
0
                   group_name);
4065
0
      return FALSE;
4066
0
    }
4067
4068
0
  pair = g_key_file_lookup_key_value_pair (key_file, group, key);
4069
4070
0
  if (!pair)
4071
0
    {
4072
0
      set_not_found_key_error (group->name, key, error);
4073
0
      return FALSE;
4074
0
    }
4075
4076
0
  group->key_value_pairs = g_list_remove (group->key_value_pairs, pair);
4077
0
  g_hash_table_remove (group->lookup_map, pair->key);
4078
0
  g_key_file_key_value_pair_free (pair);
4079
4080
0
  return TRUE;
4081
0
}
4082
4083
static GList *
4084
g_key_file_lookup_group_node (GKeyFile    *key_file,
4085
            const gchar *group_name)
4086
0
{
4087
0
  GKeyFileGroup *group;
4088
0
  GList *tmp;
4089
4090
0
  for (tmp = key_file->groups; tmp != NULL; tmp = tmp->next)
4091
0
    {
4092
0
      group = (GKeyFileGroup *) tmp->data;
4093
4094
0
      if (group && group->name && strcmp (group->name, group_name) == 0)
4095
0
        break;
4096
0
    }
4097
4098
0
  return tmp;
4099
0
}
4100
4101
static GKeyFileGroup *
4102
g_key_file_lookup_group (GKeyFile    *key_file,
4103
       const gchar *group_name)
4104
0
{
4105
0
  if (!key_file->group_hash)
4106
0
    return NULL;
4107
4108
0
  return (GKeyFileGroup *)g_hash_table_lookup (key_file->group_hash, group_name);
4109
0
}
4110
4111
static GList *
4112
g_key_file_lookup_key_value_pair_node (GKeyFile       *key_file,
4113
                     GKeyFileGroup  *group,
4114
                                       const gchar    *key)
4115
0
{
4116
0
  GList *key_node;
4117
4118
0
  for (key_node = group->key_value_pairs;
4119
0
       key_node != NULL;
4120
0
       key_node = key_node->next)
4121
0
    {
4122
0
      GKeyFileKeyValuePair *pair;
4123
4124
0
      pair = (GKeyFileKeyValuePair *) key_node->data; 
4125
4126
0
      if (pair->key && strcmp (pair->key, key) == 0)
4127
0
        break;
4128
0
    }
4129
4130
0
  return key_node;
4131
0
}
4132
4133
static GKeyFileKeyValuePair *
4134
g_key_file_lookup_key_value_pair (GKeyFile      *key_file,
4135
          GKeyFileGroup *group,
4136
          const gchar   *key)
4137
0
{
4138
0
  return (GKeyFileKeyValuePair *) g_hash_table_lookup (group->lookup_map, key);
4139
0
}
4140
4141
/* Lines starting with # or consisting entirely of whitespace are merely
4142
 * recorded, not parsed. This function assumes all leading whitespace
4143
 * has been stripped.
4144
 */
4145
static gboolean
4146
g_key_file_line_is_comment (const gchar *line)
4147
0
{
4148
0
  return (*line == '#' || *line == '\0' || *line == '\n');
4149
0
}
4150
4151
static gboolean 
4152
g_key_file_is_group_name (const gchar *name)
4153
0
{
4154
0
  gchar *p, *q;
4155
4156
0
  if (name == NULL)
4157
0
    return FALSE;
4158
4159
0
  p = q = (gchar *) name;
4160
0
  while (*q && *q != ']' && *q != '[' && !g_ascii_iscntrl (*q))
4161
0
    q = g_utf8_find_next_char (q, NULL);
4162
  
4163
0
  if (*q != '\0' || q == p)
4164
0
    return FALSE;
4165
4166
0
  return TRUE;
4167
0
}
4168
4169
static gboolean
4170
g_key_file_is_key_name (const gchar *name)
4171
0
{
4172
0
  gchar *p, *q;
4173
4174
0
  if (name == NULL)
4175
0
    return FALSE;
4176
4177
0
  p = q = (gchar *) name;
4178
  /* We accept a little more than the desktop entry spec says,
4179
   * since gnome-vfs uses mime-types as keys in its cache.
4180
   */
4181
0
  while (*q && *q != '=' && *q != '[' && *q != ']')
4182
0
    q = g_utf8_find_next_char (q, NULL);
4183
  
4184
  /* No empty keys, please */
4185
0
  if (q == p)
4186
0
    return FALSE;
4187
4188
  /* We accept spaces in the middle of keys to not break
4189
   * existing apps, but we don't tolerate initial or final
4190
   * spaces, which would lead to silent corruption when
4191
   * rereading the file.
4192
   */
4193
0
  if (*p == ' ' || q[-1] == ' ')
4194
0
    return FALSE;
4195
4196
0
  if (*q == '[')
4197
0
    {
4198
0
      q++;
4199
0
      while (*q && (g_unichar_isalnum (g_utf8_get_char_validated (q, -1)) || *q == '-' || *q == '_' || *q == '.' || *q == '@'))
4200
0
        q = g_utf8_find_next_char (q, NULL);
4201
4202
0
      if (*q != ']')
4203
0
        return FALSE;     
4204
4205
0
      q++;
4206
0
    }
4207
4208
0
  if (*q != '\0')
4209
0
    return FALSE;
4210
4211
0
  return TRUE;
4212
0
}
4213
4214
/* A group in a key file is made up of a starting '[' followed by one
4215
 * or more letters making up the group name followed by ']'.
4216
 */
4217
static gboolean
4218
g_key_file_line_is_group (const gchar *line)
4219
0
{
4220
0
  gchar *p;
4221
4222
0
  p = (gchar *) line;
4223
0
  if (*p != '[')
4224
0
    return FALSE;
4225
4226
0
  p++;
4227
4228
0
  while (*p && *p != ']')
4229
0
    p = g_utf8_find_next_char (p, NULL);
4230
4231
0
  if (*p != ']')
4232
0
    return FALSE;
4233
 
4234
  /* silently accept whitespace after the ] */
4235
0
  p = g_utf8_find_next_char (p, NULL);
4236
0
  while (*p == ' ' || *p == '\t')
4237
0
    p = g_utf8_find_next_char (p, NULL);
4238
     
4239
0
  if (*p)
4240
0
    return FALSE;
4241
4242
0
  return TRUE;
4243
0
}
4244
4245
static gboolean
4246
g_key_file_line_is_key_value_pair (const gchar *line)
4247
0
{
4248
0
  gchar *p;
4249
4250
0
  p = (gchar *) g_utf8_strchr (line, -1, '=');
4251
4252
0
  if (!p)
4253
0
    return FALSE;
4254
4255
  /* Key must be non-empty
4256
   */
4257
0
  if (*p == line[0])
4258
0
    return FALSE;
4259
4260
0
  return TRUE;
4261
0
}
4262
4263
static gchar *
4264
g_key_file_parse_value_as_string (GKeyFile     *key_file,
4265
          const gchar  *value,
4266
          GSList      **pieces,
4267
          GError      **error)
4268
0
{
4269
0
  gchar *string_value, *p, *q0, *q;
4270
4271
0
  string_value = g_new (gchar, strlen (value) + 1);
4272
4273
0
  p = (gchar *) value;
4274
0
  q0 = q = string_value;
4275
0
  while (*p)
4276
0
    {
4277
0
      if (*p == '\\')
4278
0
        {
4279
0
          p++;
4280
4281
0
          switch (*p)
4282
0
            {
4283
0
            case 's':
4284
0
              *q = ' ';
4285
0
              break;
4286
4287
0
            case 'n':
4288
0
              *q = '\n';
4289
0
              break;
4290
4291
0
            case 't':
4292
0
              *q = '\t';
4293
0
              break;
4294
4295
0
            case 'r':
4296
0
              *q = '\r';
4297
0
              break;
4298
4299
0
            case '\\':
4300
0
              *q = '\\';
4301
0
              break;
4302
4303
0
      case '\0':
4304
0
        g_set_error_literal (error, G_KEY_FILE_ERROR,
4305
0
                                   G_KEY_FILE_ERROR_INVALID_VALUE,
4306
0
                                   _("Key file contains escape character "
4307
0
                                     "at end of line"));
4308
0
        break;
4309
4310
0
            default:
4311
0
        if (pieces && *p == key_file->list_separator)
4312
0
    *q = key_file->list_separator;
4313
0
        else
4314
0
    {
4315
0
      *q++ = '\\';
4316
0
      *q = *p;
4317
      
4318
0
      if (*error == NULL)
4319
0
        {
4320
0
          gchar sequence[3];
4321
          
4322
0
          sequence[0] = '\\';
4323
0
          sequence[1] = *p;
4324
0
          sequence[2] = '\0';
4325
          
4326
0
          g_set_error (error, G_KEY_FILE_ERROR,
4327
0
           G_KEY_FILE_ERROR_INVALID_VALUE,
4328
0
           _("Key file contains invalid escape "
4329
0
             "sequence “%s”"), sequence);
4330
0
        }
4331
0
    }
4332
0
              break;
4333
0
            }
4334
0
        }
4335
0
      else
4336
0
  {
4337
0
    *q = *p;
4338
0
    if (pieces && (*p == key_file->list_separator))
4339
0
      {
4340
0
        *pieces = g_slist_prepend (*pieces, g_strndup (q0, q - q0));
4341
0
        q0 = q + 1; 
4342
0
      }
4343
0
  }
4344
4345
0
      if (*p == '\0')
4346
0
  break;
4347
4348
0
      q++;
4349
0
      p++;
4350
0
    }
4351
4352
0
  *q = '\0';
4353
0
  if (pieces)
4354
0
  {
4355
0
    if (q0 < q)
4356
0
      *pieces = g_slist_prepend (*pieces, g_strndup (q0, q - q0));
4357
0
    *pieces = g_slist_reverse (*pieces);
4358
0
  }
4359
4360
0
  return string_value;
4361
0
}
4362
4363
static gchar *
4364
g_key_file_parse_string_as_value (GKeyFile    *key_file,
4365
          const gchar *string,
4366
          gboolean     escape_separator)
4367
0
{
4368
0
  gchar *value, *p, *q;
4369
0
  gsize length;
4370
0
  gboolean parsing_leading_space;
4371
4372
0
  length = strlen (string) + 1;
4373
4374
  /* Worst case would be that every character needs to be escaped.
4375
   * In other words every character turns to two characters
4376
   */
4377
0
  value = g_new (gchar, 2 * length);
4378
4379
0
  p = (gchar *) string;
4380
0
  q = value;
4381
0
  parsing_leading_space = TRUE;
4382
0
  while (p < (string + length - 1))
4383
0
    {
4384
0
      gchar escaped_character[3] = { '\\', 0, 0 };
4385
4386
0
      switch (*p)
4387
0
        {
4388
0
        case ' ':
4389
0
          if (parsing_leading_space)
4390
0
            {
4391
0
              escaped_character[1] = 's';
4392
0
              strcpy (q, escaped_character);
4393
0
              q += 2;
4394
0
            }
4395
0
          else
4396
0
            {
4397
0
        *q = *p;
4398
0
        q++;
4399
0
            }
4400
0
          break;
4401
0
        case '\t':
4402
0
          if (parsing_leading_space)
4403
0
            {
4404
0
              escaped_character[1] = 't';
4405
0
              strcpy (q, escaped_character);
4406
0
              q += 2;
4407
0
            }
4408
0
          else
4409
0
            {
4410
0
        *q = *p;
4411
0
        q++;
4412
0
            }
4413
0
          break;
4414
0
        case '\n':
4415
0
          escaped_character[1] = 'n';
4416
0
          strcpy (q, escaped_character);
4417
0
          q += 2;
4418
0
          break;
4419
0
        case '\r':
4420
0
          escaped_character[1] = 'r';
4421
0
          strcpy (q, escaped_character);
4422
0
          q += 2;
4423
0
          break;
4424
0
        case '\\':
4425
0
          escaped_character[1] = '\\';
4426
0
          strcpy (q, escaped_character);
4427
0
          q += 2;
4428
0
          parsing_leading_space = FALSE;
4429
0
          break;
4430
0
        default:
4431
0
    if (escape_separator && *p == key_file->list_separator)
4432
0
      {
4433
0
        escaped_character[1] = key_file->list_separator;
4434
0
        strcpy (q, escaped_character);
4435
0
        q += 2;
4436
0
              parsing_leading_space = TRUE;
4437
0
      }
4438
0
    else 
4439
0
      {
4440
0
        *q = *p;
4441
0
        q++;
4442
0
              parsing_leading_space = FALSE;
4443
0
      }
4444
0
          break;
4445
0
        }
4446
0
      p++;
4447
0
    }
4448
0
  *q = '\0';
4449
4450
0
  return value;
4451
0
}
4452
4453
static gint
4454
g_key_file_parse_value_as_integer (GKeyFile     *key_file,
4455
           const gchar  *value,
4456
           GError      **error)
4457
0
{
4458
0
  gchar *eof_int;
4459
0
  glong long_value;
4460
0
  gint int_value;
4461
0
  int errsv;
4462
4463
0
  errno = 0;
4464
0
  long_value = strtol (value, &eof_int, 10);
4465
0
  errsv = errno;
4466
4467
0
  if (*value == '\0' || (*eof_int != '\0' && !g_ascii_isspace(*eof_int)))
4468
0
    {
4469
0
      gchar *value_utf8 = g_utf8_make_valid (value, -1);
4470
0
      g_set_error (error, G_KEY_FILE_ERROR,
4471
0
       G_KEY_FILE_ERROR_INVALID_VALUE,
4472
0
       _("Value “%s” cannot be interpreted "
4473
0
         "as a number."), value_utf8);
4474
0
      g_free (value_utf8);
4475
4476
0
      return 0;
4477
0
    }
4478
4479
0
  int_value = long_value;
4480
0
  if (int_value != long_value || errsv == ERANGE)
4481
0
    {
4482
0
      gchar *value_utf8 = g_utf8_make_valid (value, -1);
4483
0
      g_set_error (error,
4484
0
       G_KEY_FILE_ERROR, 
4485
0
       G_KEY_FILE_ERROR_INVALID_VALUE,
4486
0
       _("Integer value “%s” out of range"), 
4487
0
       value_utf8);
4488
0
      g_free (value_utf8);
4489
4490
0
      return 0;
4491
0
    }
4492
  
4493
0
  return int_value;
4494
0
}
4495
4496
static gchar *
4497
g_key_file_parse_integer_as_value (GKeyFile *key_file,
4498
           gint      value)
4499
4500
0
{
4501
0
  return g_strdup_printf ("%d", value);
4502
0
}
4503
4504
static gdouble
4505
g_key_file_parse_value_as_double  (GKeyFile     *key_file,
4506
                                   const gchar  *value,
4507
                                   GError      **error)
4508
0
{
4509
0
  gchar *end_of_valid_d;
4510
0
  gdouble double_value = 0;
4511
4512
0
  double_value = g_ascii_strtod (value, &end_of_valid_d);
4513
4514
0
  if (*end_of_valid_d != '\0' || end_of_valid_d == value)
4515
0
    {
4516
0
      gchar *value_utf8 = g_utf8_make_valid (value, -1);
4517
0
      g_set_error (error, G_KEY_FILE_ERROR,
4518
0
       G_KEY_FILE_ERROR_INVALID_VALUE,
4519
0
       _("Value “%s” cannot be interpreted "
4520
0
         "as a float number."), 
4521
0
       value_utf8);
4522
0
      g_free (value_utf8);
4523
4524
0
      double_value = 0;
4525
0
    }
4526
4527
0
  return double_value;
4528
0
}
4529
4530
static gint
4531
strcmp_sized (const gchar *s1, size_t len1, const gchar *s2)
4532
0
{
4533
0
  size_t len2 = strlen (s2);
4534
0
  return strncmp (s1, s2, MAX (len1, len2));
4535
0
}
4536
4537
static gboolean
4538
g_key_file_parse_value_as_boolean (GKeyFile     *key_file,
4539
           const gchar  *value,
4540
           GError      **error)
4541
0
{
4542
0
  gchar *value_utf8;
4543
0
  gint i, length = 0;
4544
4545
  /* Count the number of non-whitespace characters */
4546
0
  for (i = 0; value[i]; i++)
4547
0
    if (!g_ascii_isspace (value[i]))
4548
0
      length = i + 1;
4549
4550
0
  if (strcmp_sized (value, length, "true") == 0 || strcmp_sized (value, length, "1") == 0)
4551
0
    return TRUE;
4552
0
  else if (strcmp_sized (value, length, "false") == 0 || strcmp_sized (value, length, "0") == 0)
4553
0
    return FALSE;
4554
4555
0
  value_utf8 = g_utf8_make_valid (value, -1);
4556
0
  g_set_error (error, G_KEY_FILE_ERROR,
4557
0
               G_KEY_FILE_ERROR_INVALID_VALUE,
4558
0
               _("Value “%s” cannot be interpreted "
4559
0
     "as a boolean."), value_utf8);
4560
0
  g_free (value_utf8);
4561
4562
0
  return FALSE;
4563
0
}
4564
4565
static gchar *
4566
g_key_file_parse_boolean_as_value (GKeyFile *key_file,
4567
           gboolean  value)
4568
0
{
4569
0
  if (value)
4570
0
    return g_strdup ("true");
4571
0
  else
4572
0
    return g_strdup ("false");
4573
0
}
4574
4575
static gchar *
4576
g_key_file_parse_value_as_comment (GKeyFile    *key_file,
4577
                                   const gchar *value,
4578
                                   gboolean     is_final_line)
4579
0
{
4580
0
  GString *string;
4581
0
  gchar **lines;
4582
0
  gsize i;
4583
4584
0
  string = g_string_sized_new (512);
4585
4586
0
  lines = g_strsplit (value, "\n", 0);
4587
4588
0
  for (i = 0; lines[i] != NULL; i++)
4589
0
    {
4590
0
      const gchar *line = lines[i];
4591
4592
0
      if (i != 0)
4593
0
        g_string_append_c (string, '\n');
4594
4595
0
      if (line[0] == '#')
4596
0
        line++;
4597
0
      g_string_append (string, line);
4598
0
    }
4599
0
  g_strfreev (lines);
4600
4601
  /* This function gets called once per line of a comment, but we don’t want
4602
   * to add a trailing newline. */
4603
0
  if (!is_final_line)
4604
0
    g_string_append_c (string, '\n');
4605
4606
0
  return g_string_free (string, FALSE);
4607
0
}
4608
4609
static gchar *
4610
g_key_file_parse_comment_as_value (GKeyFile      *key_file,
4611
                                   const gchar   *comment)
4612
0
{
4613
0
  GString *string;
4614
0
  gchar **lines;
4615
0
  gsize i;
4616
4617
0
  string = g_string_sized_new (512);
4618
4619
0
  lines = g_strsplit (comment, "\n", 0);
4620
4621
0
  for (i = 0; lines[i] != NULL; i++)
4622
0
    g_string_append_printf (string, "#%s%s", lines[i], 
4623
0
                            lines[i + 1] == NULL? "" : "\n");
4624
0
  g_strfreev (lines);
4625
4626
0
  return g_string_free (string, FALSE);
4627
0
}
4628
4629
/**
4630
 * g_key_file_save_to_file:
4631
 * @key_file: a #GKeyFile
4632
 * @filename: the name of the file to write to
4633
 * @error: a pointer to a %NULL #GError, or %NULL
4634
 *
4635
 * Writes the contents of @key_file to @filename using
4636
 * g_file_set_contents(). If you need stricter guarantees about durability of
4637
 * the written file than are provided by g_file_set_contents(), use
4638
 * g_file_set_contents_full() with the return value of g_key_file_to_data().
4639
 *
4640
 * This function can fail for any of the reasons that
4641
 * g_file_set_contents() may fail.
4642
 *
4643
 * Returns: %TRUE if successful, else %FALSE with @error set
4644
 *
4645
 * Since: 2.40
4646
 */
4647
gboolean
4648
g_key_file_save_to_file (GKeyFile     *key_file,
4649
                         const gchar  *filename,
4650
                         GError      **error)
4651
0
{
4652
0
  gchar *contents;
4653
0
  gboolean success;
4654
0
  gsize length;
4655
4656
0
  g_return_val_if_fail (key_file != NULL, FALSE);
4657
0
  g_return_val_if_fail (filename != NULL, FALSE);
4658
0
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
4659
4660
0
  contents = g_key_file_to_data (key_file, &length, NULL);
4661
0
  g_assert (contents != NULL);
4662
4663
0
  success = g_file_set_contents (filename, contents, length, error);
4664
0
  g_free (contents);
4665
4666
0
  return success;
4667
0
}