Coverage Report

Created: 2025-08-08 06:10

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