Coverage Report

Created: 2026-10-28 06:22

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