Coverage Report

Created: 2026-10-14 08:19

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