Coverage Report

Created: 2025-08-28 06:43

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