Imported Upstream version 2.74.3
[platform/upstream/glib.git] / glib / gkeyfile.c
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 {  
637   key_file->current_group = g_slice_new0 (GKeyFileGroup);
638   key_file->groups = g_list_prepend (NULL, key_file->current_group);
639   key_file->group_hash = NULL;
640   key_file->start_group = NULL;
641   key_file->parse_buffer = NULL;
642   key_file->list_separator = ';';
643   key_file->flags = 0;
644 }
645
646 static void
647 g_key_file_clear (GKeyFile *key_file)
648 {
649   GList *tmp, *group_node;
650
651   if (key_file->locales) 
652     {
653       g_strfreev (key_file->locales);
654       key_file->locales = NULL;
655     }
656   key_file->checked_locales = FALSE;
657
658   if (key_file->parse_buffer)
659     {
660       g_string_free (key_file->parse_buffer, TRUE);
661       key_file->parse_buffer = NULL;
662     }
663
664   tmp = key_file->groups;
665   while (tmp != NULL)
666     {
667       group_node = tmp;
668       tmp = tmp->next;
669       g_key_file_remove_group_node (key_file, group_node);
670     }
671
672   if (key_file->group_hash != NULL)
673     {
674       g_hash_table_destroy (key_file->group_hash);
675       key_file->group_hash = NULL;
676     }
677
678   g_warn_if_fail (key_file->groups == NULL);
679 }
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 {
697   GKeyFile *key_file;
698
699   key_file = g_slice_new0 (GKeyFile);
700   key_file->ref_count = 1;
701   g_key_file_init (key_file);
702
703   return key_file;
704 }
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 {
721   g_return_if_fail (key_file != NULL);
722
723   key_file->list_separator = separator;
724 }
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 {
738   const gchar **data_dirs, *data_dir;
739   gchar *path;
740   gint fd;
741
742   path = NULL;
743   fd = -1;
744
745   if (dirs == NULL)
746     return fd;
747
748   data_dirs = dirs;
749
750   while (data_dirs && (data_dir = *data_dirs) && fd == -1)
751     {
752       const gchar *candidate_file;
753       gchar *sub_dir;
754
755       candidate_file = file;
756       sub_dir = g_strdup ("");
757       while (candidate_file != NULL && fd == -1)
758         {
759           gchar *p;
760
761           path = g_build_filename (data_dir, sub_dir,
762                                    candidate_file, NULL);
763
764           fd = g_open (path, O_RDONLY, 0);
765
766           if (fd == -1)
767             {
768               g_free (path);
769               path = NULL;
770             }
771
772           candidate_file = strchr (candidate_file, '-');
773
774           if (candidate_file == NULL)
775             break;
776
777           candidate_file++;
778
779           g_free (sub_dir);
780           sub_dir = g_strndup (file, candidate_file - file - 1);
781
782           for (p = sub_dir; *p != '\0'; p++)
783             {
784               if (*p == '-')
785                 *p = G_DIR_SEPARATOR;
786             }
787         }
788       g_free (sub_dir);
789       data_dirs++;
790     }
791
792   if (fd == -1)
793     {
794       g_set_error_literal (error, G_KEY_FILE_ERROR,
795                            G_KEY_FILE_ERROR_NOT_FOUND,
796                            _("Valid key file could not be "
797                              "found in search dirs"));
798     }
799
800   if (output_file != NULL && fd != -1)
801     *output_file = g_strdup (path);
802
803   g_free (path);
804
805   return fd;
806 }
807
808 static gboolean
809 g_key_file_load_from_fd (GKeyFile       *key_file,
810                          gint            fd,
811                          GKeyFileFlags   flags,
812                          GError        **error)
813 {
814   GError *key_file_error = NULL;
815   gssize bytes_read;
816   struct stat stat_buf;
817   gchar read_buf[4096];
818   gchar list_separator;
819
820   if (fstat (fd, &stat_buf) < 0)
821     {
822       int errsv = errno;
823       g_set_error_literal (error, G_FILE_ERROR,
824                            g_file_error_from_errno (errsv),
825                            g_strerror (errsv));
826       return FALSE;
827     }
828
829   if (!S_ISREG (stat_buf.st_mode))
830     {
831       g_set_error_literal (error, G_KEY_FILE_ERROR,
832                            G_KEY_FILE_ERROR_PARSE,
833                            _("Not a regular file"));
834       return FALSE;
835     }
836
837   list_separator = key_file->list_separator;
838   g_key_file_clear (key_file);
839   g_key_file_init (key_file);
840   key_file->list_separator = list_separator;
841   key_file->flags = flags;
842
843   do
844     {
845       int errsv;
846
847       bytes_read = read (fd, read_buf, 4096);
848       errsv = errno;
849
850       if (bytes_read == 0)  /* End of File */
851         break;
852
853       if (bytes_read < 0)
854         {
855           if (errsv == EINTR || errsv == EAGAIN)
856             continue;
857
858           g_set_error_literal (error, G_FILE_ERROR,
859                                g_file_error_from_errno (errsv),
860                                g_strerror (errsv));
861           return FALSE;
862         }
863
864       g_key_file_parse_data (key_file,
865                              read_buf, bytes_read,
866                              &key_file_error);
867     }
868   while (!key_file_error);
869
870   if (key_file_error)
871     {
872       g_propagate_error (error, key_file_error);
873       return FALSE;
874     }
875
876   g_key_file_flush_parse_buffer (key_file, &key_file_error);
877
878   if (key_file_error)
879     {
880       g_propagate_error (error, key_file_error);
881       return FALSE;
882     }
883
884   return TRUE;
885 }
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 {
913   GError *key_file_error = NULL;
914   gint fd;
915   int errsv;
916
917   g_return_val_if_fail (key_file != NULL, FALSE);
918   g_return_val_if_fail (file != NULL, FALSE);
919
920   fd = g_open (file, O_RDONLY, 0);
921   errsv = errno;
922
923   if (fd == -1)
924     {
925       g_set_error_literal (error, G_FILE_ERROR,
926                            g_file_error_from_errno (errsv),
927                            g_strerror (errsv));
928       return FALSE;
929     }
930
931   g_key_file_load_from_fd (key_file, fd, flags, &key_file_error);
932   close (fd);
933
934   if (key_file_error)
935     {
936       g_propagate_error (error, key_file_error);
937       return FALSE;
938     }
939
940   return TRUE;
941 }
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 {
965   GError *key_file_error = NULL;
966   gchar list_separator;
967
968   g_return_val_if_fail (key_file != NULL, FALSE);
969   g_return_val_if_fail (data != NULL || length == 0, FALSE);
970
971   if (length == (gsize)-1)
972     length = strlen (data);
973
974   list_separator = key_file->list_separator;
975   g_key_file_clear (key_file);
976   g_key_file_init (key_file);
977   key_file->list_separator = list_separator;
978   key_file->flags = flags;
979
980   g_key_file_parse_data (key_file, data, length, &key_file_error);
981   
982   if (key_file_error)
983     {
984       g_propagate_error (error, key_file_error);
985       return FALSE;
986     }
987
988   g_key_file_flush_parse_buffer (key_file, &key_file_error);
989   
990   if (key_file_error)
991     {
992       g_propagate_error (error, key_file_error);
993       return FALSE;
994     }
995
996   return TRUE;
997 }
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 {
1019   const guchar *data;
1020   gsize size;
1021
1022   g_return_val_if_fail (key_file != NULL, FALSE);
1023   g_return_val_if_fail (bytes != NULL, FALSE);
1024
1025   data = g_bytes_get_data (bytes, &size);
1026   return g_key_file_load_from_data (key_file, (const gchar *) data, size, flags, error);
1027 }
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 {
1061   GError *key_file_error = NULL;
1062   const gchar **data_dirs;
1063   gchar *output_path;
1064   gint fd;
1065   gboolean found_file;
1066
1067   g_return_val_if_fail (key_file != NULL, FALSE);
1068   g_return_val_if_fail (!g_path_is_absolute (file), FALSE);
1069   g_return_val_if_fail (search_dirs != NULL, FALSE);
1070
1071   found_file = FALSE;
1072   data_dirs = search_dirs;
1073   output_path = NULL;
1074   while (*data_dirs != NULL && !found_file)
1075     {
1076       g_free (output_path);
1077       output_path = NULL;
1078
1079       fd = find_file_in_data_dirs (file, data_dirs, &output_path,
1080                                    &key_file_error);
1081
1082       if (fd == -1)
1083         {
1084           if (key_file_error)
1085             g_propagate_error (error, key_file_error);
1086           break;
1087         }
1088
1089       found_file = g_key_file_load_from_fd (key_file, fd, flags,
1090                                             &key_file_error);
1091       close (fd);
1092
1093       if (key_file_error)
1094         {
1095           g_propagate_error (error, key_file_error);
1096           break;
1097         }
1098     }
1099
1100   if (found_file && full_path)
1101     *full_path = output_path;
1102   else
1103     g_free (output_path);
1104
1105   return found_file;
1106 }
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 {
1133   gchar **all_data_dirs;
1134   const gchar * user_data_dir;
1135   const gchar * const * system_data_dirs;
1136   gsize i, j;
1137   gboolean found_file;
1138
1139   g_return_val_if_fail (key_file != NULL, FALSE);
1140   g_return_val_if_fail (!g_path_is_absolute (file), FALSE);
1141
1142   user_data_dir = g_get_user_data_dir ();
1143   system_data_dirs = g_get_system_data_dirs ();
1144   all_data_dirs = g_new (gchar *, g_strv_length ((gchar **)system_data_dirs) + 2);
1145
1146   i = 0;
1147   all_data_dirs[i++] = g_strdup (user_data_dir);
1148
1149   j = 0;
1150   while (system_data_dirs[j] != NULL)
1151     all_data_dirs[i++] = g_strdup (system_data_dirs[j++]);
1152   all_data_dirs[i] = NULL;
1153
1154   found_file = g_key_file_load_from_dirs (key_file,
1155                                           file,
1156                                           (const gchar **)all_data_dirs,
1157                                           full_path,
1158                                           flags,
1159                                           error);
1160
1161   g_strfreev (all_data_dirs);
1162
1163   return found_file;
1164 }
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 {
1179   g_return_val_if_fail (key_file != NULL, NULL);
1180
1181   g_atomic_int_inc (&key_file->ref_count);
1182
1183   return key_file;
1184 }
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 {
1199   g_return_if_fail (key_file != NULL);
1200
1201   g_key_file_clear (key_file);
1202
1203   if (g_atomic_int_dec_and_test (&key_file->ref_count))
1204     g_slice_free (GKeyFile, key_file);
1205   else
1206     g_key_file_init (key_file);
1207 }
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 {
1221   g_return_if_fail (key_file != NULL);
1222
1223   if (g_atomic_int_dec_and_test (&key_file->ref_count))
1224     {
1225       g_key_file_clear (key_file);
1226       g_slice_free (GKeyFile, key_file);
1227     }
1228 }
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 {
1238   gsize i;
1239
1240   if (key_file->flags & G_KEY_FILE_KEEP_TRANSLATIONS)
1241     return TRUE;
1242
1243   if (!key_file->checked_locales)
1244     {
1245       g_assert (key_file->locales == NULL);
1246       key_file->locales = g_strdupv ((gchar **)g_get_language_names ());
1247       key_file->checked_locales = TRUE;
1248     }
1249
1250   for (i = 0; key_file->locales[i] != NULL; i++)
1251     {
1252       if (g_ascii_strncasecmp (key_file->locales[i], locale, locale_len) == 0 &&
1253           key_file->locales[i][locale_len] == '\0')
1254         return TRUE;
1255     }
1256
1257   return FALSE;
1258 }
1259
1260 static void
1261 g_key_file_parse_line (GKeyFile     *key_file,
1262                        const gchar  *line,
1263                        gsize         length,
1264                        GError      **error)
1265 {
1266   GError *parse_error = NULL;
1267   const gchar *line_start;
1268
1269   g_return_if_fail (key_file != NULL);
1270   g_return_if_fail (line != NULL);
1271
1272   line_start = line;
1273   while (g_ascii_isspace (*line_start))
1274     line_start++;
1275
1276   if (g_key_file_line_is_comment (line_start))
1277     g_key_file_parse_comment (key_file, line, length, &parse_error);
1278   else if (g_key_file_line_is_group (line_start))
1279     g_key_file_parse_group (key_file, line_start,
1280                             length - (line_start - line),
1281                             &parse_error);
1282   else if (g_key_file_line_is_key_value_pair (line_start))
1283     g_key_file_parse_key_value_pair (key_file, line_start,
1284                                      length - (line_start - line),
1285                                      &parse_error);
1286   else
1287     {
1288       gchar *line_utf8 = g_utf8_make_valid (line, length);
1289       g_set_error (error, G_KEY_FILE_ERROR,
1290                    G_KEY_FILE_ERROR_PARSE,
1291                    _("Key file contains line “%s” which is not "
1292                      "a key-value pair, group, or comment"),
1293                    line_utf8);
1294       g_free (line_utf8);
1295
1296       return;
1297     }
1298
1299   if (parse_error)
1300     g_propagate_error (error, parse_error);
1301 }
1302
1303 static void
1304 g_key_file_parse_comment (GKeyFile     *key_file,
1305                           const gchar  *line,
1306                           gsize         length,
1307                           GError      **error)
1308 {
1309   GKeyFileKeyValuePair *pair;
1310   
1311   if (!(key_file->flags & G_KEY_FILE_KEEP_COMMENTS))
1312     return;
1313   
1314   g_warn_if_fail (key_file->current_group != NULL);
1315
1316   pair = g_slice_new (GKeyFileKeyValuePair);
1317   pair->key = NULL;
1318   pair->value = g_strndup (line, length);
1319   
1320   key_file->current_group->key_value_pairs =
1321     g_list_prepend (key_file->current_group->key_value_pairs, pair);
1322 }
1323
1324 static void
1325 g_key_file_parse_group (GKeyFile     *key_file,
1326                         const gchar  *line,
1327                         gsize         length,
1328                         GError      **error)
1329 {
1330   gchar *group_name;
1331   const gchar *group_name_start, *group_name_end;
1332   
1333   /* advance past opening '['
1334    */
1335   group_name_start = line + 1;
1336   group_name_end = line + length - 1;
1337   
1338   while (*group_name_end != ']')
1339     group_name_end--;
1340
1341   group_name = g_strndup (group_name_start, 
1342                           group_name_end - group_name_start);
1343   
1344   if (!g_key_file_is_group_name (group_name))
1345     {
1346       g_set_error (error, G_KEY_FILE_ERROR,
1347                    G_KEY_FILE_ERROR_PARSE,
1348                    _("Invalid group name: %s"), group_name);
1349       g_free (group_name);
1350       return;
1351     }
1352
1353   g_key_file_add_group (key_file, group_name);
1354   g_free (group_name);
1355 }
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 {
1363   gchar *key, *key_end, *value_start;
1364   const gchar *locale;
1365   gsize locale_len;
1366   gsize key_len, value_len;
1367
1368   if (key_file->current_group == NULL || key_file->current_group->name == NULL)
1369     {
1370       g_set_error_literal (error, G_KEY_FILE_ERROR,
1371                            G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
1372                            _("Key file does not start with a group"));
1373       return;
1374     }
1375
1376   key_end = value_start = strchr (line, '=');
1377
1378   g_warn_if_fail (key_end != NULL);
1379
1380   key_end--;
1381   value_start++;
1382
1383   /* Pull the key name from the line (chomping trailing whitespace)
1384    */
1385   while (g_ascii_isspace (*key_end))
1386     key_end--;
1387
1388   key_len = key_end - line + 2;
1389
1390   g_warn_if_fail (key_len <= length);
1391
1392   if (!g_key_file_is_key_name (line, key_len - 1))
1393     {
1394       g_set_error (error, G_KEY_FILE_ERROR,
1395                    G_KEY_FILE_ERROR_PARSE,
1396                    _("Invalid key name: %.*s"), (int) key_len - 1, line);
1397       return; 
1398     }
1399
1400   key = g_strndup (line, key_len - 1);
1401
1402   /* Pull the value from the line (chugging leading whitespace)
1403    */
1404   while (g_ascii_isspace (*value_start))
1405     value_start++;
1406
1407   value_len = line + length - value_start;
1408
1409   g_warn_if_fail (key_file->start_group != NULL);
1410
1411   /* Checked on entry to this function */
1412   g_assert (key_file->current_group != NULL);
1413   g_assert (key_file->current_group->name != NULL);
1414
1415   if (key_file->start_group == key_file->current_group
1416       && strcmp (key, "Encoding") == 0)
1417     {
1418       if (value_len != strlen ("UTF-8") ||
1419           g_ascii_strncasecmp (value_start, "UTF-8", value_len) != 0)
1420         {
1421           gchar *value_utf8 = g_utf8_make_valid (value_start, value_len);
1422           g_set_error (error, G_KEY_FILE_ERROR,
1423                        G_KEY_FILE_ERROR_UNKNOWN_ENCODING,
1424                        _("Key file contains unsupported "
1425                          "encoding “%s”"), value_utf8);
1426           g_free (value_utf8);
1427
1428           g_free (key);
1429           return;
1430         }
1431     }
1432
1433   /* Is this key a translation? If so, is it one that we care about?
1434    */
1435   locale = key_get_locale (key, &locale_len);
1436
1437   if (locale == NULL || g_key_file_locale_is_interesting (key_file, locale, locale_len))
1438     {
1439       GKeyFileKeyValuePair *pair;
1440
1441       pair = g_slice_new (GKeyFileKeyValuePair);
1442       pair->key = g_steal_pointer (&key);
1443       pair->value = g_strndup (value_start, value_len);
1444
1445       g_key_file_add_key_value_pair (key_file, key_file->current_group, pair);
1446     }
1447
1448   g_free (key);
1449 }
1450
1451 static const gchar *
1452 key_get_locale (const gchar *key,
1453                 gsize       *len_out)
1454 {
1455   const gchar *locale;
1456   gsize locale_len;
1457
1458   locale = g_strrstr (key, "[");
1459   if (locale != NULL)
1460     locale_len = strlen (locale);
1461   else
1462     locale_len = 0;
1463
1464   if (locale_len > 2)
1465     {
1466       locale++;  /* skip `[` */
1467       locale_len -= 2;  /* drop `[` and `]` */
1468     }
1469   else
1470     {
1471       locale = NULL;
1472       locale_len = 0;
1473     }
1474
1475   *len_out = locale_len;
1476   return locale;
1477 }
1478
1479 static void
1480 g_key_file_parse_data (GKeyFile     *key_file,
1481                        const gchar  *data,
1482                        gsize         length,
1483                        GError      **error)
1484 {
1485   GError *parse_error;
1486   gsize i;
1487
1488   g_return_if_fail (key_file != NULL);
1489   g_return_if_fail (data != NULL || length == 0);
1490
1491   parse_error = NULL;
1492
1493   if (!key_file->parse_buffer)
1494     key_file->parse_buffer = g_string_sized_new (128);
1495
1496   i = 0;
1497   while (i < length)
1498     {
1499       if (data[i] == '\n')
1500         {
1501           if (key_file->parse_buffer->len > 0
1502               && (key_file->parse_buffer->str[key_file->parse_buffer->len - 1]
1503                   == '\r'))
1504             g_string_erase (key_file->parse_buffer,
1505                             key_file->parse_buffer->len - 1,
1506                             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           if (key_file->parse_buffer->len > 0)
1513             g_key_file_flush_parse_buffer (key_file, &parse_error);
1514           else
1515             g_key_file_parse_comment (key_file, "", 1, &parse_error);
1516
1517           if (parse_error)
1518             {
1519               g_propagate_error (error, parse_error);
1520               return;
1521             }
1522           i++;
1523         }
1524       else
1525         {
1526           const gchar *start_of_line;
1527           const gchar *end_of_line;
1528           gsize line_length;
1529
1530           start_of_line = data + i;
1531           end_of_line = memchr (start_of_line, '\n', length - i);
1532
1533           if (end_of_line == NULL)
1534             end_of_line = data + length;
1535
1536           line_length = end_of_line - start_of_line;
1537
1538           g_string_append_len (key_file->parse_buffer, start_of_line, line_length);
1539           i += line_length;
1540         }
1541     }
1542 }
1543
1544 static void
1545 g_key_file_flush_parse_buffer (GKeyFile  *key_file,
1546                                GError   **error)
1547 {
1548   GError *file_error = NULL;
1549
1550   g_return_if_fail (key_file != NULL);
1551
1552   if (!key_file->parse_buffer)
1553     return;
1554
1555   file_error = NULL;
1556
1557   if (key_file->parse_buffer->len > 0)
1558     {
1559       g_key_file_parse_line (key_file, key_file->parse_buffer->str,
1560                              key_file->parse_buffer->len,
1561                              &file_error);
1562       g_string_erase (key_file->parse_buffer, 0, -1);
1563
1564       if (file_error)
1565         {
1566           g_propagate_error (error, file_error);
1567           return;
1568         }
1569     }
1570 }
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 {
1594   GString *data_string;
1595   GList *group_node, *key_file_node;
1596
1597   g_return_val_if_fail (key_file != NULL, NULL);
1598
1599   data_string = g_string_new (NULL);
1600
1601   for (group_node = g_list_last (key_file->groups);
1602        group_node != NULL;
1603        group_node = group_node->prev)
1604     {
1605       GKeyFileGroup *group;
1606
1607       group = (GKeyFileGroup *) group_node->data;
1608
1609       /* separate groups by at least an empty line */
1610       if (data_string->len >= 2 &&
1611           data_string->str[data_string->len - 2] != '\n')
1612         g_string_append_c (data_string, '\n');
1613
1614       if (group->comment != NULL)
1615         g_string_append_printf (data_string, "%s\n", group->comment->value);
1616
1617       if (group->name != NULL)
1618         g_string_append_printf (data_string, "[%s]\n", group->name);
1619
1620       for (key_file_node = g_list_last (group->key_value_pairs);
1621            key_file_node != NULL;
1622            key_file_node = key_file_node->prev)
1623         {
1624           GKeyFileKeyValuePair *pair;
1625
1626           pair = (GKeyFileKeyValuePair *) key_file_node->data;
1627
1628           if (pair->key != NULL)
1629             g_string_append_printf (data_string, "%s=%s\n", pair->key, pair->value);
1630           else
1631             g_string_append_printf (data_string, "%s\n", pair->value);
1632         }
1633     }
1634
1635   if (length)
1636     *length = data_string->len;
1637
1638   return g_string_free (data_string, FALSE);
1639 }
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 {
1665   GKeyFileGroup *group;
1666   GList *tmp;
1667   gchar **keys;
1668   gsize i, num_keys;
1669   
1670   g_return_val_if_fail (key_file != NULL, NULL);
1671   g_return_val_if_fail (group_name != NULL, NULL);
1672   
1673   group = g_key_file_lookup_group (key_file, group_name);
1674   
1675   if (!group)
1676     {
1677       g_set_error (error, G_KEY_FILE_ERROR,
1678                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
1679                    _("Key file does not have group “%s”"),
1680                    group_name);
1681       return NULL;
1682     }
1683
1684   num_keys = 0;
1685   for (tmp = group->key_value_pairs; tmp; tmp = tmp->next)
1686     {
1687       GKeyFileKeyValuePair *pair;
1688
1689       pair = (GKeyFileKeyValuePair *) tmp->data;
1690
1691       if (pair->key)
1692         num_keys++;
1693     }
1694   
1695   keys = g_new (gchar *, num_keys + 1);
1696
1697   i = num_keys - 1;
1698   for (tmp = group->key_value_pairs; tmp; tmp = tmp->next)
1699     {
1700       GKeyFileKeyValuePair *pair;
1701
1702       pair = (GKeyFileKeyValuePair *) tmp->data;
1703
1704       if (pair->key)
1705         {
1706           keys[i] = g_strdup (pair->key);
1707           i--;
1708         }
1709     }
1710
1711   keys[num_keys] = NULL;
1712
1713   if (length)
1714     *length = num_keys;
1715
1716   return keys;
1717 }
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 {
1732   g_return_val_if_fail (key_file != NULL, NULL);
1733
1734   if (key_file->start_group)
1735     return g_strdup (key_file->start_group->name);
1736
1737   return NULL;
1738 }
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 {
1757   GList *group_node;
1758   gchar **groups;
1759   gsize i, num_groups;
1760
1761   g_return_val_if_fail (key_file != NULL, NULL);
1762
1763   num_groups = g_list_length (key_file->groups);
1764
1765   g_return_val_if_fail (num_groups > 0, NULL);
1766
1767   group_node = g_list_last (key_file->groups);
1768   
1769   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   groups = g_new (gchar *, num_groups);
1777
1778
1779   i = 0;
1780   for (group_node = group_node->prev;
1781        group_node != NULL;
1782        group_node = group_node->prev)
1783     {
1784       GKeyFileGroup *group;
1785
1786       group = (GKeyFileGroup *) group_node->data;
1787
1788       g_warn_if_fail (group->name != NULL);
1789
1790       groups[i++] = g_strdup (group->name);
1791     }
1792   groups[i] = NULL;
1793
1794   if (length)
1795     *length = i;
1796
1797   return groups;
1798 }
1799
1800 static void
1801 set_not_found_key_error (const char *group_name,
1802                          const char *key,
1803                          GError    **error)
1804 {
1805   g_set_error (error, G_KEY_FILE_ERROR,
1806                G_KEY_FILE_ERROR_KEY_NOT_FOUND,
1807                _("Key file does not have key “%s” in group “%s”"),
1808                key, group_name);
1809 }
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 {
1838   GKeyFileGroup *group;
1839   GKeyFileKeyValuePair *pair;
1840   gchar *value = NULL;
1841
1842   g_return_val_if_fail (key_file != NULL, NULL);
1843   g_return_val_if_fail (group_name != NULL, NULL);
1844   g_return_val_if_fail (key != NULL, NULL);
1845   
1846   group = g_key_file_lookup_group (key_file, group_name);
1847
1848   if (!group)
1849     {
1850       g_set_error (error, G_KEY_FILE_ERROR,
1851                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
1852                    _("Key file does not have group “%s”"),
1853                    group_name);
1854       return NULL;
1855     }
1856
1857   pair = g_key_file_lookup_key_value_pair (key_file, group, key);
1858
1859   if (pair)
1860     value = g_strdup (pair->value);
1861   else
1862     set_not_found_key_error (group_name, key, error);
1863
1864   return value;
1865 }
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 {
1889   GKeyFileGroup *group;
1890   GKeyFileKeyValuePair *pair;
1891
1892   g_return_if_fail (key_file != NULL);
1893   g_return_if_fail (group_name != NULL && g_key_file_is_group_name (group_name));
1894   g_return_if_fail (key != NULL && g_key_file_is_key_name (key, strlen (key)));
1895   g_return_if_fail (value != NULL);
1896
1897   group = g_key_file_lookup_group (key_file, group_name);
1898
1899   if (!group)
1900     {
1901       g_key_file_add_group (key_file, group_name);
1902       group = (GKeyFileGroup *) key_file->groups->data;
1903
1904       g_key_file_add_key (key_file, group, key, value);
1905     }
1906   else
1907     {
1908       pair = g_key_file_lookup_key_value_pair (key_file, group, key);
1909
1910       if (!pair)
1911         g_key_file_add_key (key_file, group, key, value);
1912       else
1913         {
1914           g_free (pair->value);
1915           pair->value = g_strdup (value);
1916         }
1917     }
1918 }
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 {
1947   gchar *value, *string_value;
1948   GError *key_file_error;
1949
1950   g_return_val_if_fail (key_file != NULL, NULL);
1951   g_return_val_if_fail (group_name != NULL, NULL);
1952   g_return_val_if_fail (key != NULL, NULL);
1953
1954   key_file_error = NULL;
1955
1956   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
1957
1958   if (key_file_error)
1959     {
1960       g_propagate_error (error, key_file_error);
1961       return NULL;
1962     }
1963
1964   if (!g_utf8_validate (value, -1, NULL))
1965     {
1966       gchar *value_utf8 = g_utf8_make_valid (value, -1);
1967       g_set_error (error, G_KEY_FILE_ERROR,
1968                    G_KEY_FILE_ERROR_UNKNOWN_ENCODING,
1969                    _("Key file contains key “%s” with value “%s” "
1970                      "which is not UTF-8"), key, value_utf8);
1971       g_free (value_utf8);
1972       g_free (value);
1973
1974       return NULL;
1975     }
1976
1977   string_value = g_key_file_parse_value_as_string (key_file, value, NULL,
1978                                                    &key_file_error);
1979   g_free (value);
1980
1981   if (key_file_error)
1982     {
1983       if (g_error_matches (key_file_error,
1984                            G_KEY_FILE_ERROR,
1985                            G_KEY_FILE_ERROR_INVALID_VALUE))
1986         {
1987           g_set_error (error, G_KEY_FILE_ERROR,
1988                        G_KEY_FILE_ERROR_INVALID_VALUE,
1989                        _("Key file contains key “%s” "
1990                          "which has a value that cannot be interpreted."),
1991                        key);
1992           g_error_free (key_file_error);
1993         }
1994       else
1995         g_propagate_error (error, key_file_error);
1996     }
1997
1998   return string_value;
1999 }
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 {
2022   gchar *value;
2023
2024   g_return_if_fail (key_file != NULL);
2025   g_return_if_fail (string != NULL);
2026
2027   value = g_key_file_parse_string_as_value (key_file, string, FALSE);
2028   g_key_file_set_value (key_file, group_name, key, value);
2029   g_free (value);
2030 }
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 {
2060   GError *key_file_error = NULL;
2061   gchar *value, *string_value, **values;
2062   gint i, len;
2063   GSList *p, *pieces = NULL;
2064
2065   g_return_val_if_fail (key_file != NULL, NULL);
2066   g_return_val_if_fail (group_name != NULL, NULL);
2067   g_return_val_if_fail (key != NULL, NULL);
2068
2069   if (length)
2070     *length = 0;
2071
2072   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
2073
2074   if (key_file_error)
2075     {
2076       g_propagate_error (error, key_file_error);
2077       return NULL;
2078     }
2079
2080   if (!g_utf8_validate (value, -1, NULL))
2081     {
2082       gchar *value_utf8 = g_utf8_make_valid (value, -1);
2083       g_set_error (error, G_KEY_FILE_ERROR,
2084                    G_KEY_FILE_ERROR_UNKNOWN_ENCODING,
2085                    _("Key file contains key “%s” with value “%s” "
2086                      "which is not UTF-8"), key, value_utf8);
2087       g_free (value_utf8);
2088       g_free (value);
2089
2090       return NULL;
2091     }
2092
2093   string_value = g_key_file_parse_value_as_string (key_file, value, &pieces, &key_file_error);
2094   g_free (value);
2095   g_free (string_value);
2096
2097   if (key_file_error)
2098     {
2099       if (g_error_matches (key_file_error,
2100                            G_KEY_FILE_ERROR,
2101                            G_KEY_FILE_ERROR_INVALID_VALUE))
2102         {
2103           g_set_error (error, G_KEY_FILE_ERROR,
2104                        G_KEY_FILE_ERROR_INVALID_VALUE,
2105                        _("Key file contains key “%s” "
2106                          "which has a value that cannot be interpreted."),
2107                        key);
2108           g_error_free (key_file_error);
2109         }
2110       else
2111         g_propagate_error (error, key_file_error);
2112
2113       g_slist_free_full (pieces, g_free);
2114       return NULL;
2115     }
2116
2117   len = g_slist_length (pieces);
2118   values = g_new (gchar *, len + 1);
2119   for (p = pieces, i = 0; p; p = p->next)
2120     values[i++] = p->data;
2121   values[len] = NULL;
2122
2123   g_slist_free (pieces);
2124
2125   if (length)
2126     *length = len;
2127
2128   return values;
2129 }
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 {
2152   GString *value_list;
2153   gsize i;
2154
2155   g_return_if_fail (key_file != NULL);
2156   g_return_if_fail (list != NULL || length == 0);
2157
2158   value_list = g_string_sized_new (length * 128);
2159   for (i = 0; i < length && list[i] != NULL; i++)
2160     {
2161       gchar *value;
2162
2163       value = g_key_file_parse_string_as_value (key_file, list[i], TRUE);
2164       g_string_append (value_list, value);
2165       g_string_append_c (value_list, key_file->list_separator);
2166
2167       g_free (value);
2168     }
2169
2170   g_key_file_set_value (key_file, group_name, key, value_list->str);
2171   g_string_free (value_list, TRUE);
2172 }
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 {
2194   gchar *full_key, *value;
2195
2196   g_return_if_fail (key_file != NULL);
2197   g_return_if_fail (key != NULL);
2198   g_return_if_fail (locale != NULL);
2199   g_return_if_fail (string != NULL);
2200
2201   value = g_key_file_parse_string_as_value (key_file, string, FALSE);
2202   full_key = g_strdup_printf ("%s[%s]", key, locale);
2203   g_key_file_set_value (key_file, group_name, full_key, value);
2204   g_free (full_key);
2205   g_free (value);
2206 }
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 {
2241   gchar *candidate_key, *translated_value;
2242   GError *key_file_error;
2243   gchar **languages;
2244   gboolean free_languages = FALSE;
2245   gint i;
2246
2247   g_return_val_if_fail (key_file != NULL, NULL);
2248   g_return_val_if_fail (group_name != NULL, NULL);
2249   g_return_val_if_fail (key != NULL, NULL);
2250
2251   candidate_key = NULL;
2252   translated_value = NULL;
2253   key_file_error = NULL;
2254
2255   if (locale)
2256     {
2257       languages = g_get_locale_variants (locale);
2258       free_languages = TRUE;
2259     }
2260   else
2261     {
2262       languages = (gchar **) g_get_language_names ();
2263       free_languages = FALSE;
2264     }
2265   
2266   for (i = 0; languages[i]; i++)
2267     {
2268       candidate_key = g_strdup_printf ("%s[%s]", key, languages[i]);
2269       
2270       translated_value = g_key_file_get_string (key_file,
2271                                                 group_name,
2272                                                 candidate_key, NULL);
2273       g_free (candidate_key);
2274
2275       if (translated_value)
2276         break;
2277    }
2278
2279   /* Fallback to untranslated key
2280    */
2281   if (!translated_value)
2282     {
2283       translated_value = g_key_file_get_string (key_file, group_name, key,
2284                                                 &key_file_error);
2285       
2286       if (!translated_value)
2287         g_propagate_error (error, key_file_error);
2288     }
2289
2290   if (free_languages)
2291     g_strfreev (languages);
2292
2293   return translated_value;
2294 }
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 {
2324   gchar **languages_allocated = NULL;
2325   const gchar * const *languages;
2326   gchar *result = NULL;
2327   gsize i;
2328
2329   g_return_val_if_fail (key_file != NULL, NULL);
2330   g_return_val_if_fail (group_name != NULL, NULL);
2331   g_return_val_if_fail (key != NULL, NULL);
2332
2333   if (locale != NULL)
2334     {
2335       languages_allocated = g_get_locale_variants (locale);
2336       languages = (const gchar * const *) languages_allocated;
2337     }
2338   else
2339     languages = g_get_language_names ();
2340
2341   for (i = 0; languages[i] != NULL; i++)
2342     {
2343       gchar *candidate_key, *translated_value;
2344
2345       candidate_key = g_strdup_printf ("%s[%s]", key, languages[i]);
2346       translated_value = g_key_file_get_string (key_file, group_name, candidate_key, NULL);
2347       g_free (translated_value);
2348       g_free (candidate_key);
2349
2350       if (translated_value != NULL)
2351         break;
2352    }
2353
2354   result = g_strdup (languages[i]);
2355
2356   g_strfreev (languages_allocated);
2357
2358   return result;
2359 }
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 {
2399   GError *key_file_error;
2400   gchar **values, *value;
2401   char list_separator[2];
2402   gsize len;
2403
2404   g_return_val_if_fail (key_file != NULL, NULL);
2405   g_return_val_if_fail (group_name != NULL, NULL);
2406   g_return_val_if_fail (key != NULL, NULL);
2407
2408   key_file_error = NULL;
2409
2410   value = g_key_file_get_locale_string (key_file, group_name, 
2411                                         key, locale,
2412                                         &key_file_error);
2413   
2414   if (key_file_error)
2415     g_propagate_error (error, key_file_error);
2416   
2417   if (!value)
2418     {
2419       if (length)
2420         *length = 0;
2421       return NULL;
2422     }
2423
2424   len = strlen (value);
2425   if (value[len - 1] == key_file->list_separator)
2426     value[len - 1] = '\0';
2427
2428   list_separator[0] = key_file->list_separator;
2429   list_separator[1] = '\0';
2430   values = g_strsplit (value, list_separator, 0);
2431
2432   g_free (value);
2433
2434   if (length)
2435     *length = g_strv_length (values);
2436
2437   return values;
2438 }
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 {
2463   GString *value_list;
2464   gchar *full_key;
2465   gsize i;
2466
2467   g_return_if_fail (key_file != NULL);
2468   g_return_if_fail (key != NULL);
2469   g_return_if_fail (locale != NULL);
2470   g_return_if_fail (length != 0);
2471
2472   value_list = g_string_sized_new (length * 128);
2473   for (i = 0; i < length && list[i] != NULL; i++)
2474     {
2475       gchar *value;
2476       
2477       value = g_key_file_parse_string_as_value (key_file, list[i], TRUE);
2478       g_string_append (value_list, value);
2479       g_string_append_c (value_list, key_file->list_separator);
2480
2481       g_free (value);
2482     }
2483
2484   full_key = g_strdup_printf ("%s[%s]", key, locale);
2485   g_key_file_set_value (key_file, group_name, full_key, value_list->str);
2486   g_free (full_key);
2487   g_string_free (value_list, TRUE);
2488 }
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 {
2516   GError *key_file_error = NULL;
2517   gchar *value;
2518   gboolean bool_value;
2519
2520   g_return_val_if_fail (key_file != NULL, FALSE);
2521   g_return_val_if_fail (group_name != NULL, FALSE);
2522   g_return_val_if_fail (key != NULL, FALSE);
2523
2524   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
2525
2526   if (!value)
2527     {
2528       g_propagate_error (error, key_file_error);
2529       return FALSE;
2530     }
2531
2532   bool_value = g_key_file_parse_value_as_boolean (key_file, value,
2533                                                   &key_file_error);
2534   g_free (value);
2535
2536   if (key_file_error)
2537     {
2538       if (g_error_matches (key_file_error,
2539                            G_KEY_FILE_ERROR,
2540                            G_KEY_FILE_ERROR_INVALID_VALUE))
2541         {
2542           g_set_error (error, G_KEY_FILE_ERROR,
2543                        G_KEY_FILE_ERROR_INVALID_VALUE,
2544                        _("Key file contains key “%s” "
2545                          "which has a value that cannot be interpreted."),
2546                        key);
2547           g_error_free (key_file_error);
2548         }
2549       else
2550         g_propagate_error (error, key_file_error);
2551     }
2552
2553   return bool_value;
2554 }
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 {
2574   const gchar *result;
2575
2576   g_return_if_fail (key_file != NULL);
2577
2578   result = g_key_file_parse_boolean_as_value (key_file, value);
2579   g_key_file_set_value (key_file, group_name, key, result);
2580 }
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 {
2612   GError *key_file_error;
2613   gchar **values;
2614   gboolean *bool_values;
2615   gsize i, num_bools;
2616
2617   g_return_val_if_fail (key_file != NULL, NULL);
2618   g_return_val_if_fail (group_name != NULL, NULL);
2619   g_return_val_if_fail (key != NULL, NULL);
2620
2621   if (length)
2622     *length = 0;
2623
2624   key_file_error = NULL;
2625
2626   values = g_key_file_get_string_list (key_file, group_name, key,
2627                                        &num_bools, &key_file_error);
2628
2629   if (key_file_error)
2630     g_propagate_error (error, key_file_error);
2631
2632   if (!values)
2633     return NULL;
2634
2635   bool_values = g_new (gboolean, num_bools);
2636
2637   for (i = 0; i < num_bools; i++)
2638     {
2639       bool_values[i] = g_key_file_parse_value_as_boolean (key_file,
2640                                                           values[i],
2641                                                           &key_file_error);
2642
2643       if (key_file_error)
2644         {
2645           g_propagate_error (error, key_file_error);
2646           g_strfreev (values);
2647           g_free (bool_values);
2648
2649           return NULL;
2650         }
2651     }
2652   g_strfreev (values);
2653
2654   if (length)
2655     *length = num_bools;
2656
2657   return bool_values;
2658 }
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 {
2681   GString *value_list;
2682   gsize i;
2683
2684   g_return_if_fail (key_file != NULL);
2685   g_return_if_fail (list != NULL);
2686
2687   value_list = g_string_sized_new (length * 8);
2688   for (i = 0; i < length; i++)
2689     {
2690       const gchar *value;
2691
2692       value = g_key_file_parse_boolean_as_value (key_file, list[i]);
2693
2694       g_string_append (value_list, value);
2695       g_string_append_c (value_list, key_file->list_separator);
2696     }
2697
2698   g_key_file_set_value (key_file, group_name, key, value_list->str);
2699   g_string_free (value_list, TRUE);
2700 }
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 {
2729   GError *key_file_error;
2730   gchar *value;
2731   gint int_value;
2732
2733   g_return_val_if_fail (key_file != NULL, -1);
2734   g_return_val_if_fail (group_name != NULL, -1);
2735   g_return_val_if_fail (key != NULL, -1);
2736
2737   key_file_error = NULL;
2738
2739   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
2740
2741   if (key_file_error)
2742     {
2743       g_propagate_error (error, key_file_error);
2744       return 0;
2745     }
2746
2747   int_value = g_key_file_parse_value_as_integer (key_file, value,
2748                                                  &key_file_error);
2749   g_free (value);
2750
2751   if (key_file_error)
2752     {
2753       if (g_error_matches (key_file_error,
2754                            G_KEY_FILE_ERROR,
2755                            G_KEY_FILE_ERROR_INVALID_VALUE))
2756         {
2757           g_set_error (error, G_KEY_FILE_ERROR,
2758                        G_KEY_FILE_ERROR_INVALID_VALUE,
2759                        _("Key file contains key “%s” in group “%s” "
2760                          "which has a value that cannot be interpreted."),
2761                          key, group_name);
2762           g_error_free (key_file_error);
2763         }
2764       else
2765         g_propagate_error (error, key_file_error);
2766     }
2767
2768   return int_value;
2769 }
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 {
2789   gchar *result;
2790
2791   g_return_if_fail (key_file != NULL);
2792
2793   result = g_key_file_parse_integer_as_value (key_file, value);
2794   g_key_file_set_value (key_file, group_name, key, result);
2795   g_free (result);
2796 }
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 {
2820   gchar *s, *end;
2821   gint64 v;
2822
2823   g_return_val_if_fail (key_file != NULL, -1);
2824   g_return_val_if_fail (group_name != NULL, -1);
2825   g_return_val_if_fail (key != NULL, -1);
2826
2827   s = g_key_file_get_value (key_file, group_name, key, error);
2828
2829   if (s == NULL)
2830     return 0;
2831
2832   v = g_ascii_strtoll (s, &end, 10);
2833
2834   if (*s == '\0' || *end != '\0')
2835     {
2836       g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE,
2837                    _("Key “%s” in group “%s” has value “%s” "
2838                      "where %s was expected"),
2839                    key, group_name, s, "int64");
2840       g_free (s);
2841       return 0;
2842     }
2843
2844   g_free (s);
2845   return v;
2846 }
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 {
2866   gchar *result;
2867
2868   g_return_if_fail (key_file != NULL);
2869
2870   result = g_strdup_printf ("%" G_GINT64_FORMAT, value);
2871   g_key_file_set_value (key_file, group_name, key, result);
2872   g_free (result);
2873 }
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 {
2897   gchar *s, *end;
2898   guint64 v;
2899
2900   g_return_val_if_fail (key_file != NULL, -1);
2901   g_return_val_if_fail (group_name != NULL, -1);
2902   g_return_val_if_fail (key != NULL, -1);
2903
2904   s = g_key_file_get_value (key_file, group_name, key, error);
2905
2906   if (s == NULL)
2907     return 0;
2908
2909   v = g_ascii_strtoull (s, &end, 10);
2910
2911   if (*s == '\0' || *end != '\0')
2912     {
2913       g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE,
2914                    _("Key “%s” in group “%s” has value “%s” "
2915                      "where %s was expected"),
2916                    key, group_name, s, "uint64");
2917       g_free (s);
2918       return 0;
2919     }
2920
2921   g_free (s);
2922   return v;
2923 }
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 {
2943   gchar *result;
2944
2945   g_return_if_fail (key_file != NULL);
2946
2947   result = g_strdup_printf ("%" G_GUINT64_FORMAT, value);
2948   g_key_file_set_value (key_file, group_name, key, result);
2949   g_free (result);
2950 }
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 {
2983   GError *key_file_error = NULL;
2984   gchar **values;
2985   gint *int_values;
2986   gsize i, num_ints;
2987
2988   g_return_val_if_fail (key_file != NULL, NULL);
2989   g_return_val_if_fail (group_name != NULL, NULL);
2990   g_return_val_if_fail (key != NULL, NULL);
2991
2992   if (length)
2993     *length = 0;
2994
2995   values = g_key_file_get_string_list (key_file, group_name, key,
2996                                        &num_ints, &key_file_error);
2997
2998   if (key_file_error)
2999     g_propagate_error (error, key_file_error);
3000
3001   if (!values)
3002     return NULL;
3003
3004   int_values = g_new (gint, num_ints);
3005
3006   for (i = 0; i < num_ints; i++)
3007     {
3008       int_values[i] = g_key_file_parse_value_as_integer (key_file,
3009                                                          values[i],
3010                                                          &key_file_error);
3011
3012       if (key_file_error)
3013         {
3014           g_propagate_error (error, key_file_error);
3015           g_strfreev (values);
3016           g_free (int_values);
3017
3018           return NULL;
3019         }
3020     }
3021   g_strfreev (values);
3022
3023   if (length)
3024     *length = num_ints;
3025
3026   return int_values;
3027 }
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 {
3049   GString *values;
3050   gsize i;
3051
3052   g_return_if_fail (key_file != NULL);
3053   g_return_if_fail (list != NULL);
3054
3055   values = g_string_sized_new (length * 16);
3056   for (i = 0; i < length; i++)
3057     {
3058       gchar *value;
3059
3060       value = g_key_file_parse_integer_as_value (key_file, list[i]);
3061
3062       g_string_append (values, value);
3063       g_string_append_c (values, key_file->list_separator);
3064
3065       g_free (value);
3066     }
3067
3068   g_key_file_set_value (key_file, group_name, key, values->str);
3069   g_string_free (values, TRUE);
3070 }
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 {
3098   GError *key_file_error;
3099   gchar *value;
3100   gdouble double_value;
3101
3102   g_return_val_if_fail (key_file != NULL, -1);
3103   g_return_val_if_fail (group_name != NULL, -1);
3104   g_return_val_if_fail (key != NULL, -1);
3105
3106   key_file_error = NULL;
3107
3108   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
3109
3110   if (key_file_error)
3111     {
3112       g_propagate_error (error, key_file_error);
3113       return 0;
3114     }
3115
3116   double_value = g_key_file_parse_value_as_double (key_file, value,
3117                                                   &key_file_error);
3118   g_free (value);
3119
3120   if (key_file_error)
3121     {
3122       if (g_error_matches (key_file_error,
3123                            G_KEY_FILE_ERROR,
3124                            G_KEY_FILE_ERROR_INVALID_VALUE))
3125         {
3126           g_set_error (error, G_KEY_FILE_ERROR,
3127                        G_KEY_FILE_ERROR_INVALID_VALUE,
3128                        _("Key file contains key “%s” in group “%s” "
3129                          "which has a value that cannot be interpreted."),
3130                        key, group_name);
3131           g_error_free (key_file_error);
3132         }
3133       else
3134         g_propagate_error (error, key_file_error);
3135     }
3136
3137   return double_value;
3138 }
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 {
3158   gchar result[G_ASCII_DTOSTR_BUF_SIZE];
3159
3160   g_return_if_fail (key_file != NULL);
3161
3162   g_ascii_dtostr (result, sizeof (result), value);
3163   g_key_file_set_value (key_file, group_name, key, result);
3164 }
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 {
3196   GError *key_file_error = NULL;
3197   gchar **values;
3198   gdouble *double_values;
3199   gsize i, num_doubles;
3200
3201   g_return_val_if_fail (key_file != NULL, NULL);
3202   g_return_val_if_fail (group_name != NULL, NULL);
3203   g_return_val_if_fail (key != NULL, NULL);
3204
3205   if (length)
3206     *length = 0;
3207
3208   values = g_key_file_get_string_list (key_file, group_name, key,
3209                                        &num_doubles, &key_file_error);
3210
3211   if (key_file_error)
3212     g_propagate_error (error, key_file_error);
3213
3214   if (!values)
3215     return NULL;
3216
3217   double_values = g_new (gdouble, num_doubles);
3218
3219   for (i = 0; i < num_doubles; i++)
3220     {
3221       double_values[i] = g_key_file_parse_value_as_double (key_file,
3222                                                            values[i],
3223                                                            &key_file_error);
3224
3225       if (key_file_error)
3226         {
3227           g_propagate_error (error, key_file_error);
3228           g_strfreev (values);
3229           g_free (double_values);
3230
3231           return NULL;
3232         }
3233     }
3234   g_strfreev (values);
3235
3236   if (length)
3237     *length = num_doubles;
3238
3239   return double_values;
3240 }
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 {
3262   GString *values;
3263   gsize i;
3264
3265   g_return_if_fail (key_file != NULL);
3266   g_return_if_fail (list != NULL);
3267
3268   values = g_string_sized_new (length * 16);
3269   for (i = 0; i < length; i++)
3270     {
3271       gchar result[G_ASCII_DTOSTR_BUF_SIZE];
3272
3273       g_ascii_dtostr( result, sizeof (result), list[i] );
3274
3275       g_string_append (values, result);
3276       g_string_append_c (values, key_file->list_separator);
3277     }
3278
3279   g_key_file_set_value (key_file, group_name, key, values->str);
3280   g_string_free (values, TRUE);
3281 }
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 {
3290   GKeyFileGroup *group;
3291   GKeyFileKeyValuePair *pair;
3292   GList *key_node, *comment_node, *tmp;
3293   
3294   group = g_key_file_lookup_group (key_file, group_name);
3295   if (!group)
3296     {
3297       g_set_error (error, G_KEY_FILE_ERROR,
3298                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
3299                    _("Key file does not have group “%s”"),
3300                    group_name ? group_name : "(null)");
3301
3302       return FALSE;
3303     }
3304
3305   /* First find the key the comments are supposed to be
3306    * associated with
3307    */
3308   key_node = g_key_file_lookup_key_value_pair_node (key_file, group, key);
3309
3310   if (key_node == NULL)
3311     {
3312       set_not_found_key_error (group->name, key, error);
3313       return FALSE;
3314     }
3315
3316   /* Then find all the comments already associated with the
3317    * key and free them
3318    */
3319   tmp = key_node->next;
3320   while (tmp != NULL)
3321     {
3322       pair = (GKeyFileKeyValuePair *) tmp->data;
3323
3324       if (pair->key != NULL)
3325         break;
3326
3327       comment_node = tmp;
3328       tmp = tmp->next;
3329       g_key_file_remove_key_value_pair_node (key_file, group,
3330                                              comment_node); 
3331     }
3332
3333   if (comment == NULL)
3334     return TRUE;
3335
3336   /* Now we can add our new comment
3337    */
3338   pair = g_slice_new (GKeyFileKeyValuePair);
3339   pair->key = NULL;
3340   pair->value = g_key_file_parse_comment_as_value (key_file, comment);
3341   
3342   key_node = g_list_insert (key_node, pair, 1);
3343   (void) key_node;
3344
3345   return TRUE;
3346 }
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 {
3354   GKeyFileGroup *group;
3355   
3356   g_return_val_if_fail (group_name != NULL && g_key_file_is_group_name (group_name), FALSE);
3357
3358   group = g_key_file_lookup_group (key_file, group_name);
3359   if (!group)
3360     {
3361       g_set_error (error, G_KEY_FILE_ERROR,
3362                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
3363                    _("Key file does not have group “%s”"),
3364                    group_name);
3365
3366       return FALSE;
3367     }
3368
3369   /* First remove any existing comment
3370    */
3371   if (group->comment)
3372     {
3373       g_key_file_key_value_pair_free (group->comment);
3374       group->comment = NULL;
3375     }
3376
3377   if (comment == NULL)
3378     return TRUE;
3379
3380   /* Now we can add our new comment
3381    */
3382   group->comment = g_slice_new (GKeyFileKeyValuePair);
3383   group->comment->key = NULL;
3384   group->comment->value = g_key_file_parse_comment_as_value (key_file, comment);
3385
3386   return TRUE;
3387 }
3388
3389 static gboolean
3390 g_key_file_set_top_comment (GKeyFile     *key_file,
3391                             const gchar  *comment,
3392                             GError      **error)
3393 {
3394   GList *group_node;
3395   GKeyFileGroup *group;
3396   GKeyFileKeyValuePair *pair;
3397
3398   /* The last group in the list should be the top (comments only)
3399    * group in the file
3400    */
3401   g_warn_if_fail (key_file->groups != NULL);
3402   group_node = g_list_last (key_file->groups);
3403   group = (GKeyFileGroup *) group_node->data;
3404   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   g_list_free_full (group->key_value_pairs, (GDestroyNotify) g_key_file_key_value_pair_free);
3410   group->key_value_pairs = NULL;
3411
3412   if (comment == NULL)
3413      return TRUE;
3414
3415   pair = g_slice_new (GKeyFileKeyValuePair);
3416   pair->key = NULL;
3417   pair->value = g_key_file_parse_comment_as_value (key_file, comment);
3418   
3419   group->key_value_pairs =
3420     g_list_prepend (group->key_value_pairs, pair);
3421
3422   return TRUE;
3423 }
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 {
3453   g_return_val_if_fail (key_file != NULL, FALSE);
3454
3455   if (group_name != NULL && key != NULL) 
3456     {
3457       if (!g_key_file_set_key_comment (key_file, group_name, key, comment, error))
3458         return FALSE;
3459     } 
3460   else if (group_name != NULL) 
3461     {
3462       if (!g_key_file_set_group_comment (key_file, group_name, comment, error))
3463         return FALSE;
3464     } 
3465   else 
3466     {
3467       if (!g_key_file_set_top_comment (key_file, comment, error))
3468         return FALSE;
3469     }
3470
3471   return TRUE;
3472 }
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 {
3480   GKeyFileGroup *group;
3481   GKeyFileKeyValuePair *pair;
3482   GList *key_node, *tmp;
3483   GString *string;
3484   gchar *comment;
3485
3486   g_return_val_if_fail (group_name != NULL && g_key_file_is_group_name (group_name), NULL);
3487
3488   group = g_key_file_lookup_group (key_file, group_name);
3489   if (!group)
3490     {
3491       g_set_error (error, G_KEY_FILE_ERROR,
3492                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
3493                    _("Key file does not have group “%s”"),
3494                    group_name ? group_name : "(null)");
3495
3496       return NULL;
3497     }
3498
3499   /* First find the key the comments are supposed to be
3500    * associated with
3501    */
3502   key_node = g_key_file_lookup_key_value_pair_node (key_file, group, key);
3503
3504   if (key_node == NULL)
3505     {
3506       set_not_found_key_error (group->name, key, error);
3507       return NULL;
3508     }
3509
3510   string = NULL;
3511
3512   /* Then find all the comments already associated with the
3513    * key and concatenate them.
3514    */
3515   tmp = key_node->next;
3516   if (!key_node->next)
3517     return NULL;
3518
3519   pair = (GKeyFileKeyValuePair *) tmp->data;
3520   if (pair->key != NULL)
3521     return NULL;
3522
3523   while (tmp->next)
3524     {
3525       pair = (GKeyFileKeyValuePair *) tmp->next->data;
3526       
3527       if (pair->key != NULL)
3528         break;
3529
3530       tmp = tmp->next;
3531     }
3532
3533   while (tmp != key_node)
3534     {
3535       pair = (GKeyFileKeyValuePair *) tmp->data;
3536       
3537       if (string == NULL)
3538         string = g_string_sized_new (512);
3539
3540       comment = g_key_file_parse_value_as_comment (key_file, pair->value,
3541                                                    (tmp->prev == key_node));
3542       g_string_append (string, comment);
3543       g_free (comment);
3544       
3545       tmp = tmp->prev;
3546     }
3547
3548   if (string != NULL)
3549     {
3550       comment = string->str;
3551       g_string_free (string, FALSE);
3552     }
3553   else
3554     comment = NULL;
3555
3556   return comment;
3557 }
3558
3559 static gchar *
3560 get_group_comment (GKeyFile       *key_file,
3561                    GKeyFileGroup  *group,
3562                    GError        **error)
3563 {
3564   GString *string;
3565   GList *tmp;
3566   gchar *comment;
3567
3568   string = NULL;
3569
3570   tmp = group->key_value_pairs;
3571   while (tmp)
3572     {
3573       GKeyFileKeyValuePair *pair;
3574
3575       pair = (GKeyFileKeyValuePair *) tmp->data;
3576
3577       if (pair->key != NULL)
3578         {
3579           tmp = tmp->prev;
3580           break;
3581         }
3582
3583       if (tmp->next == NULL)
3584         break;
3585
3586       tmp = tmp->next;
3587     }
3588   
3589   while (tmp != NULL)
3590     {
3591       GKeyFileKeyValuePair *pair;
3592
3593       pair = (GKeyFileKeyValuePair *) tmp->data;
3594
3595       if (string == NULL)
3596         string = g_string_sized_new (512);
3597
3598       comment = g_key_file_parse_value_as_comment (key_file, pair->value,
3599                                                    (tmp->prev == NULL));
3600       g_string_append (string, comment);
3601       g_free (comment);
3602
3603       tmp = tmp->prev;
3604     }
3605
3606   if (string != NULL)
3607     return g_string_free (string, FALSE);
3608
3609   return NULL;
3610 }
3611
3612 static gchar *
3613 g_key_file_get_group_comment (GKeyFile     *key_file,
3614                               const gchar  *group_name,
3615                               GError      **error)
3616 {
3617   GList *group_node;
3618   GKeyFileGroup *group;
3619   
3620   group = g_key_file_lookup_group (key_file, group_name);
3621   if (!group)
3622     {
3623       g_set_error (error, G_KEY_FILE_ERROR,
3624                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
3625                    _("Key file does not have group “%s”"),
3626                    group_name ? group_name : "(null)");
3627
3628       return NULL;
3629     }
3630
3631   if (group->comment)
3632     return g_strdup (group->comment->value);
3633   
3634   group_node = g_key_file_lookup_group_node (key_file, group_name);
3635   group_node = group_node->next;
3636   group = (GKeyFileGroup *)group_node->data;  
3637   return get_group_comment (key_file, group, error);
3638 }
3639
3640 static gchar *
3641 g_key_file_get_top_comment (GKeyFile  *key_file,
3642                             GError   **error)
3643 {
3644   GList *group_node;
3645   GKeyFileGroup *group;
3646
3647   /* The last group in the list should be the top (comments only)
3648    * group in the file
3649    */
3650   g_warn_if_fail (key_file->groups != NULL);
3651   group_node = g_list_last (key_file->groups);
3652   group = (GKeyFileGroup *) group_node->data;
3653   g_warn_if_fail (group->name == NULL);
3654
3655   return get_group_comment (key_file, group, error);
3656 }
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 {
3684   g_return_val_if_fail (key_file != NULL, NULL);
3685
3686   if (group_name != NULL && key != NULL)
3687     return g_key_file_get_key_comment (key_file, group_name, key, error);
3688   else if (group_name != NULL)
3689     return g_key_file_get_group_comment (key_file, group_name, error);
3690   else
3691     return g_key_file_get_top_comment (key_file, error);
3692 }
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 {
3717   g_return_val_if_fail (key_file != NULL, FALSE);
3718
3719   if (group_name != NULL && key != NULL)
3720     return g_key_file_set_key_comment (key_file, group_name, key, NULL, error);
3721   else if (group_name != NULL)
3722     return g_key_file_set_group_comment (key_file, group_name, NULL, error);
3723   else
3724     return g_key_file_set_top_comment (key_file, NULL, error);
3725 }
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 {
3742   g_return_val_if_fail (key_file != NULL, FALSE);
3743   g_return_val_if_fail (group_name != NULL, FALSE);
3744
3745   return g_key_file_lookup_group (key_file, group_name) != NULL;
3746 }
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 {
3758   GKeyFileKeyValuePair *pair;
3759   GKeyFileGroup *group;
3760
3761   g_return_val_if_fail (key_file != NULL, FALSE);
3762   g_return_val_if_fail (group_name != NULL, FALSE);
3763   g_return_val_if_fail (key != NULL, FALSE);
3764
3765   group = g_key_file_lookup_group (key_file, group_name);
3766
3767   if (!group)
3768     {
3769       g_set_error (error, G_KEY_FILE_ERROR,
3770                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
3771                    _("Key file does not have group “%s”"),
3772                    group_name);
3773
3774       return FALSE;
3775     }
3776
3777   pair = g_key_file_lookup_key_value_pair (key_file, group, key);
3778
3779   if (has_key)
3780     *has_key = pair != NULL;
3781   return TRUE;
3782 }
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 {
3812   GError *temp_error = NULL;
3813   gboolean has_key;
3814
3815   if (g_key_file_has_key_full (key_file, group_name, key, &has_key, &temp_error))
3816     {
3817       return has_key;
3818     }
3819   else
3820     {
3821       g_propagate_error (error, temp_error);
3822       return FALSE;
3823     }
3824 }
3825
3826 static void
3827 g_key_file_add_group (GKeyFile    *key_file,
3828                       const gchar *group_name)
3829 {
3830   GKeyFileGroup *group;
3831
3832   g_return_if_fail (key_file != NULL);
3833   g_return_if_fail (group_name != NULL && g_key_file_is_group_name (group_name));
3834
3835   group = g_key_file_lookup_group (key_file, group_name);
3836   if (group != NULL)
3837     {
3838       key_file->current_group = group;
3839       return;
3840     }
3841
3842   group = g_slice_new0 (GKeyFileGroup);
3843   group->name = g_strdup (group_name);
3844   group->lookup_map = g_hash_table_new (g_str_hash, g_str_equal);
3845   key_file->groups = g_list_prepend (key_file->groups, group);
3846   key_file->current_group = group;
3847
3848   if (key_file->start_group == NULL)
3849     key_file->start_group = group;
3850
3851   if (!key_file->group_hash)
3852     key_file->group_hash = g_hash_table_new (g_str_hash, g_str_equal);
3853
3854   g_hash_table_insert (key_file->group_hash, (gpointer)group->name, group);
3855 }
3856
3857 static void
3858 g_key_file_key_value_pair_free (GKeyFileKeyValuePair *pair)
3859 {
3860   if (pair != NULL)
3861     {
3862       g_free (pair->key);
3863       g_free (pair->value);
3864       g_slice_free (GKeyFileKeyValuePair, pair);
3865     }
3866 }
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 {
3882
3883   GKeyFileKeyValuePair *pair;
3884
3885   pair = (GKeyFileKeyValuePair *) pair_node->data;
3886
3887   group->key_value_pairs = g_list_remove_link (group->key_value_pairs, pair_node);
3888
3889   g_warn_if_fail (pair->value != NULL);
3890
3891   g_key_file_key_value_pair_free (pair);
3892
3893   g_list_free_1 (pair_node);
3894 }
3895
3896 static void
3897 g_key_file_remove_group_node (GKeyFile *key_file,
3898                               GList    *group_node)
3899 {
3900   GKeyFileGroup *group;
3901   GList *tmp;
3902
3903   group = (GKeyFileGroup *) group_node->data;
3904
3905   if (group->name)
3906     {
3907       g_assert (key_file->group_hash);
3908       g_hash_table_remove (key_file->group_hash, group->name);
3909     }
3910
3911   /* If the current group gets deleted make the current group the last
3912    * added group.
3913    */
3914   if (key_file->current_group == group)
3915     {
3916       /* groups should always contain at least the top comment group,
3917        * unless g_key_file_clear has been called
3918        */
3919       if (key_file->groups)
3920         key_file->current_group = (GKeyFileGroup *) key_file->groups->data;
3921       else
3922         key_file->current_group = NULL;
3923     }
3924
3925   /* If the start group gets deleted make the start group the first
3926    * added group.
3927    */
3928   if (key_file->start_group == group)
3929     {
3930       tmp = g_list_last (key_file->groups);
3931       while (tmp != NULL)
3932         {
3933           if (tmp != group_node &&
3934               ((GKeyFileGroup *) tmp->data)->name != NULL)
3935             break;
3936
3937           tmp = tmp->prev;
3938         }
3939
3940       if (tmp)
3941         key_file->start_group = (GKeyFileGroup *) tmp->data;
3942       else
3943         key_file->start_group = NULL;
3944     }
3945
3946   key_file->groups = g_list_remove_link (key_file->groups, group_node);
3947
3948   tmp = group->key_value_pairs;
3949   while (tmp != NULL)
3950     {
3951       GList *pair_node;
3952
3953       pair_node = tmp;
3954       tmp = tmp->next;
3955       g_key_file_remove_key_value_pair_node (key_file, group, pair_node);
3956     }
3957
3958   g_warn_if_fail (group->key_value_pairs == NULL);
3959
3960   if (group->comment)
3961     {
3962       g_key_file_key_value_pair_free (group->comment);
3963       group->comment = NULL;
3964     }
3965
3966   if (group->lookup_map)
3967     {
3968       g_hash_table_destroy (group->lookup_map);
3969       group->lookup_map = NULL;
3970     }
3971
3972   g_free ((gchar *) group->name);
3973   g_slice_free (GKeyFileGroup, group);
3974   g_list_free_1 (group_node);
3975 }
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 {
3995   GList *group_node;
3996
3997   g_return_val_if_fail (key_file != NULL, FALSE);
3998   g_return_val_if_fail (group_name != NULL, FALSE);
3999
4000   group_node = g_key_file_lookup_group_node (key_file, group_name);
4001
4002   if (!group_node)
4003     {
4004       g_set_error (error, G_KEY_FILE_ERROR,
4005                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
4006                    _("Key file does not have group “%s”"),
4007                    group_name);
4008       return FALSE;
4009     }
4010
4011   g_key_file_remove_group_node (key_file, group_node);
4012
4013   return TRUE;  
4014 }
4015
4016 static void
4017 g_key_file_add_key_value_pair (GKeyFile             *key_file,
4018                                GKeyFileGroup        *group,
4019                                GKeyFileKeyValuePair *pair)
4020 {
4021   g_hash_table_replace (group->lookup_map, pair->key, pair);
4022   group->key_value_pairs = g_list_prepend (group->key_value_pairs, pair);
4023 }
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 {
4031   GKeyFileKeyValuePair *pair;
4032
4033   pair = g_slice_new (GKeyFileKeyValuePair);
4034   pair->key = g_strdup (key);
4035   pair->value = g_strdup (value);
4036
4037   g_key_file_add_key_value_pair (key_file, group, pair);
4038 }
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 {
4059   GKeyFileGroup *group;
4060   GKeyFileKeyValuePair *pair;
4061
4062   g_return_val_if_fail (key_file != NULL, FALSE);
4063   g_return_val_if_fail (group_name != NULL, FALSE);
4064   g_return_val_if_fail (key != NULL, FALSE);
4065
4066   pair = NULL;
4067
4068   group = g_key_file_lookup_group (key_file, group_name);
4069   if (!group)
4070     {
4071       g_set_error (error, G_KEY_FILE_ERROR,
4072                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
4073                    _("Key file does not have group “%s”"),
4074                    group_name);
4075       return FALSE;
4076     }
4077
4078   pair = g_key_file_lookup_key_value_pair (key_file, group, key);
4079
4080   if (!pair)
4081     {
4082       set_not_found_key_error (group->name, key, error);
4083       return FALSE;
4084     }
4085
4086   group->key_value_pairs = g_list_remove (group->key_value_pairs, pair);
4087   g_hash_table_remove (group->lookup_map, pair->key);
4088   g_key_file_key_value_pair_free (pair);
4089
4090   return TRUE;
4091 }
4092
4093 static GList *
4094 g_key_file_lookup_group_node (GKeyFile    *key_file,
4095                               const gchar *group_name)
4096 {
4097   GKeyFileGroup *group;
4098
4099   group = g_key_file_lookup_group (key_file, group_name);
4100   if (group == NULL)
4101     return NULL;
4102
4103   return g_list_find (key_file->groups, group);
4104 }
4105
4106 static GKeyFileGroup *
4107 g_key_file_lookup_group (GKeyFile    *key_file,
4108                          const gchar *group_name)
4109 {
4110   if (!key_file->group_hash)
4111     return NULL;
4112
4113   return (GKeyFileGroup *)g_hash_table_lookup (key_file->group_hash, group_name);
4114 }
4115
4116 static GList *
4117 g_key_file_lookup_key_value_pair_node (GKeyFile       *key_file,
4118                                        GKeyFileGroup  *group,
4119                                        const gchar    *key)
4120 {
4121   GList *key_node;
4122
4123   for (key_node = group->key_value_pairs;
4124        key_node != NULL;
4125        key_node = key_node->next)
4126     {
4127       GKeyFileKeyValuePair *pair;
4128
4129       pair = (GKeyFileKeyValuePair *) key_node->data; 
4130
4131       if (pair->key && strcmp (pair->key, key) == 0)
4132         break;
4133     }
4134
4135   return key_node;
4136 }
4137
4138 static GKeyFileKeyValuePair *
4139 g_key_file_lookup_key_value_pair (GKeyFile      *key_file,
4140                                   GKeyFileGroup *group,
4141                                   const gchar   *key)
4142 {
4143   return (GKeyFileKeyValuePair *) g_hash_table_lookup (group->lookup_map, key);
4144 }
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 {
4153   return (*line == '#' || *line == '\0' || *line == '\n');
4154 }
4155
4156 static gboolean 
4157 g_key_file_is_group_name (const gchar *name)
4158 {
4159   const gchar *p, *q;
4160
4161   g_assert (name != NULL);
4162
4163   p = q = name;
4164   while (*q && *q != ']' && *q != '[' && !g_ascii_iscntrl (*q))
4165     q = g_utf8_find_next_char (q, NULL);
4166   
4167   if (*q != '\0' || q == p)
4168     return FALSE;
4169
4170   return TRUE;
4171 }
4172
4173 static gboolean
4174 g_key_file_is_key_name (const gchar *name,
4175                         gsize        len)
4176 {
4177   const gchar *p, *q, *end;
4178
4179   g_assert (name != NULL);
4180
4181   p = q = name;
4182   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   while (q < end && *q && *q != '=' && *q != '[' && *q != ']')
4188     {
4189       q = g_utf8_find_next_char (q, end);
4190       if (q == NULL)
4191         q = end;
4192     }
4193   
4194   /* No empty keys, please */
4195   if (q == p)
4196     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   if (*p == ' ' || q[-1] == ' ')
4204     return FALSE;
4205
4206   if (*q == '[')
4207     {
4208       q++;
4209       while (q < end &&
4210              *q != '\0' &&
4211              (g_unichar_isalnum (g_utf8_get_char_validated (q, end - q)) || *q == '-' || *q == '_' || *q == '.' || *q == '@'))
4212         {
4213           q = g_utf8_find_next_char (q, end);
4214           if (q == NULL)
4215             {
4216               q = end;
4217               break;
4218             }
4219         }
4220
4221       if (*q != ']')
4222         return FALSE;     
4223
4224       q++;
4225     }
4226
4227   if (q < end)
4228     return FALSE;
4229
4230   return TRUE;
4231 }
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 {
4239   const gchar *p;
4240
4241   p = line;
4242   if (*p != '[')
4243     return FALSE;
4244
4245   p++;
4246
4247   while (*p && *p != ']')
4248     p = g_utf8_find_next_char (p, NULL);
4249
4250   if (*p != ']')
4251     return FALSE;
4252  
4253   /* silently accept whitespace after the ] */
4254   p = g_utf8_find_next_char (p, NULL);
4255   while (*p == ' ' || *p == '\t')
4256     p = g_utf8_find_next_char (p, NULL);
4257      
4258   if (*p)
4259     return FALSE;
4260
4261   return TRUE;
4262 }
4263
4264 static gboolean
4265 g_key_file_line_is_key_value_pair (const gchar *line)
4266 {
4267   const gchar *p;
4268
4269   p = g_utf8_strchr (line, -1, '=');
4270
4271   if (!p)
4272     return FALSE;
4273
4274   /* Key must be non-empty
4275    */
4276   if (*p == line[0])
4277     return FALSE;
4278
4279   return TRUE;
4280 }
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 {
4288   gchar *string_value, *q0, *q;
4289   const gchar *p;
4290
4291   string_value = g_new (gchar, strlen (value) + 1);
4292
4293   p = value;
4294   q0 = q = string_value;
4295   while (*p)
4296     {
4297       if (*p == '\\')
4298         {
4299           p++;
4300
4301           switch (*p)
4302             {
4303             case 's':
4304               *q = ' ';
4305               break;
4306
4307             case 'n':
4308               *q = '\n';
4309               break;
4310
4311             case 't':
4312               *q = '\t';
4313               break;
4314
4315             case 'r':
4316               *q = '\r';
4317               break;
4318
4319             case '\\':
4320               *q = '\\';
4321               break;
4322
4323             case '\0':
4324               g_set_error_literal (error, G_KEY_FILE_ERROR,
4325                                    G_KEY_FILE_ERROR_INVALID_VALUE,
4326                                    _("Key file contains escape character "
4327                                      "at end of line"));
4328               break;
4329
4330             default:
4331               if (pieces && *p == key_file->list_separator)
4332                 *q = key_file->list_separator;
4333               else
4334                 {
4335                   *q++ = '\\';
4336                   *q = *p;
4337                   
4338                   if (*error == NULL)
4339                     {
4340                       gchar sequence[3];
4341                       
4342                       sequence[0] = '\\';
4343                       sequence[1] = *p;
4344                       sequence[2] = '\0';
4345                       
4346                       g_set_error (error, G_KEY_FILE_ERROR,
4347                                    G_KEY_FILE_ERROR_INVALID_VALUE,
4348                                    _("Key file contains invalid escape "
4349                                      "sequence “%s”"), sequence);
4350                     }
4351                 }
4352               break;
4353             }
4354         }
4355       else
4356         {
4357           *q = *p;
4358           if (pieces && (*p == key_file->list_separator))
4359             {
4360               *pieces = g_slist_prepend (*pieces, g_strndup (q0, q - q0));
4361               q0 = q + 1; 
4362             }
4363         }
4364
4365       if (*p == '\0')
4366         break;
4367
4368       q++;
4369       p++;
4370     }
4371
4372   *q = '\0';
4373   if (pieces)
4374   {
4375     if (q0 < q)
4376       *pieces = g_slist_prepend (*pieces, g_strndup (q0, q - q0));
4377     *pieces = g_slist_reverse (*pieces);
4378   }
4379
4380   return string_value;
4381 }
4382
4383 static gchar *
4384 g_key_file_parse_string_as_value (GKeyFile    *key_file,
4385                                   const gchar *string,
4386                                   gboolean     escape_separator)
4387 {
4388   gchar *value, *q;
4389   const gchar *p;
4390   gsize length;
4391   gboolean parsing_leading_space;
4392
4393   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   value = g_new (gchar, 2 * length);
4399
4400   p = string;
4401   q = value;
4402   parsing_leading_space = TRUE;
4403   while (p < (string + length - 1))
4404     {
4405       gchar escaped_character[3] = { '\\', 0, 0 };
4406
4407       switch (*p)
4408         {
4409         case ' ':
4410           if (parsing_leading_space)
4411             {
4412               escaped_character[1] = 's';
4413               strcpy (q, escaped_character);
4414               q += 2;
4415             }
4416           else
4417             {
4418               *q = *p;
4419               q++;
4420             }
4421           break;
4422         case '\t':
4423           if (parsing_leading_space)
4424             {
4425               escaped_character[1] = 't';
4426               strcpy (q, escaped_character);
4427               q += 2;
4428             }
4429           else
4430             {
4431               *q = *p;
4432               q++;
4433             }
4434           break;
4435         case '\n':
4436           escaped_character[1] = 'n';
4437           strcpy (q, escaped_character);
4438           q += 2;
4439           break;
4440         case '\r':
4441           escaped_character[1] = 'r';
4442           strcpy (q, escaped_character);
4443           q += 2;
4444           break;
4445         case '\\':
4446           escaped_character[1] = '\\';
4447           strcpy (q, escaped_character);
4448           q += 2;
4449           parsing_leading_space = FALSE;
4450           break;
4451         default:
4452           if (escape_separator && *p == key_file->list_separator)
4453             {
4454               escaped_character[1] = key_file->list_separator;
4455               strcpy (q, escaped_character);
4456               q += 2;
4457               parsing_leading_space = TRUE;
4458             }
4459           else 
4460             {
4461               *q = *p;
4462               q++;
4463               parsing_leading_space = FALSE;
4464             }
4465           break;
4466         }
4467       p++;
4468     }
4469   *q = '\0';
4470
4471   return value;
4472 }
4473
4474 static gint
4475 g_key_file_parse_value_as_integer (GKeyFile     *key_file,
4476                                    const gchar  *value,
4477                                    GError      **error)
4478 {
4479   gchar *eof_int;
4480   glong long_value;
4481   gint int_value;
4482   int errsv;
4483
4484   errno = 0;
4485   long_value = strtol (value, &eof_int, 10);
4486   errsv = errno;
4487
4488   if (*value == '\0' || (*eof_int != '\0' && !g_ascii_isspace(*eof_int)))
4489     {
4490       gchar *value_utf8 = g_utf8_make_valid (value, -1);
4491       g_set_error (error, G_KEY_FILE_ERROR,
4492                    G_KEY_FILE_ERROR_INVALID_VALUE,
4493                    _("Value “%s” cannot be interpreted "
4494                      "as a number."), value_utf8);
4495       g_free (value_utf8);
4496
4497       return 0;
4498     }
4499
4500   int_value = long_value;
4501   if (int_value != long_value || errsv == ERANGE)
4502     {
4503       gchar *value_utf8 = g_utf8_make_valid (value, -1);
4504       g_set_error (error,
4505                    G_KEY_FILE_ERROR, 
4506                    G_KEY_FILE_ERROR_INVALID_VALUE,
4507                    _("Integer value “%s” out of range"), 
4508                    value_utf8);
4509       g_free (value_utf8);
4510
4511       return 0;
4512     }
4513   
4514   return int_value;
4515 }
4516
4517 static gchar *
4518 g_key_file_parse_integer_as_value (GKeyFile *key_file,
4519                                    gint      value)
4520
4521 {
4522   return g_strdup_printf ("%d", value);
4523 }
4524
4525 static gdouble
4526 g_key_file_parse_value_as_double  (GKeyFile     *key_file,
4527                                    const gchar  *value,
4528                                    GError      **error)
4529 {
4530   gchar *end_of_valid_d;
4531   gdouble double_value = 0;
4532
4533   double_value = g_ascii_strtod (value, &end_of_valid_d);
4534
4535   if (*end_of_valid_d != '\0' || end_of_valid_d == value)
4536     {
4537       gchar *value_utf8 = g_utf8_make_valid (value, -1);
4538       g_set_error (error, G_KEY_FILE_ERROR,
4539                    G_KEY_FILE_ERROR_INVALID_VALUE,
4540                    _("Value “%s” cannot be interpreted "
4541                      "as a float number."), 
4542                    value_utf8);
4543       g_free (value_utf8);
4544
4545       double_value = 0;
4546     }
4547
4548   return double_value;
4549 }
4550
4551 static gint
4552 strcmp_sized (const gchar *s1, size_t len1, const gchar *s2)
4553 {
4554   size_t len2 = strlen (s2);
4555   return strncmp (s1, s2, MAX (len1, len2));
4556 }
4557
4558 static gboolean
4559 g_key_file_parse_value_as_boolean (GKeyFile     *key_file,
4560                                    const gchar  *value,
4561                                    GError      **error)
4562 {
4563   gchar *value_utf8;
4564   gint i, length = 0;
4565
4566   /* Count the number of non-whitespace characters */
4567   for (i = 0; value[i]; i++)
4568     if (!g_ascii_isspace (value[i]))
4569       length = i + 1;
4570
4571   if (strcmp_sized (value, length, "true") == 0 || strcmp_sized (value, length, "1") == 0)
4572     return TRUE;
4573   else if (strcmp_sized (value, length, "false") == 0 || strcmp_sized (value, length, "0") == 0)
4574     return FALSE;
4575
4576   value_utf8 = g_utf8_make_valid (value, -1);
4577   g_set_error (error, G_KEY_FILE_ERROR,
4578                G_KEY_FILE_ERROR_INVALID_VALUE,
4579                _("Value “%s” cannot be interpreted "
4580                  "as a boolean."), value_utf8);
4581   g_free (value_utf8);
4582
4583   return FALSE;
4584 }
4585
4586 static const gchar *
4587 g_key_file_parse_boolean_as_value (GKeyFile *key_file,
4588                                    gboolean  value)
4589 {
4590   if (value)
4591     return "true";
4592   else
4593     return "false";
4594 }
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 {
4601   GString *string;
4602   gchar **lines;
4603   gsize i;
4604
4605   string = g_string_sized_new (512);
4606
4607   lines = g_strsplit (value, "\n", 0);
4608
4609   for (i = 0; lines[i] != NULL; i++)
4610     {
4611       const gchar *line = lines[i];
4612
4613       if (i != 0)
4614         g_string_append_c (string, '\n');
4615
4616       if (line[0] == '#')
4617         line++;
4618       g_string_append (string, line);
4619     }
4620   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   if (!is_final_line)
4625     g_string_append_c (string, '\n');
4626
4627   return g_string_free (string, FALSE);
4628 }
4629
4630 static gchar *
4631 g_key_file_parse_comment_as_value (GKeyFile      *key_file,
4632                                    const gchar   *comment)
4633 {
4634   GString *string;
4635   gchar **lines;
4636   gsize i;
4637
4638   string = g_string_sized_new (512);
4639
4640   lines = g_strsplit (comment, "\n", 0);
4641
4642   for (i = 0; lines[i] != NULL; i++)
4643     g_string_append_printf (string, "#%s%s", lines[i], 
4644                             lines[i + 1] == NULL? "" : "\n");
4645   g_strfreev (lines);
4646
4647   return g_string_free (string, FALSE);
4648 }
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 {
4673   gchar *contents;
4674   gboolean success;
4675   gsize length;
4676
4677   g_return_val_if_fail (key_file != NULL, FALSE);
4678   g_return_val_if_fail (filename != NULL, FALSE);
4679   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
4680
4681   contents = g_key_file_to_data (key_file, &length, NULL);
4682   g_assert (contents != NULL);
4683
4684   success = g_file_set_contents (filename, contents, length, error);
4685   g_free (contents);
4686
4687   return success;
4688 }