Coverage Report

Created: 2026-05-23 06:59

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