Coverage Report

Created: 2025-07-23 08:13

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