Speed up group lookups
[platform/upstream/glib.git] / glib / gkeyfile.c
1 /* gkeyfile.c - key file parser
2  *
3  *  Copyright 2004  Red Hat, Inc.  
4  *
5  * Written by Ray Strode <rstrode@redhat.com>
6  *            Matthias Clasen <mclasen@redhat.com>
7  *
8  * GLib is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU Lesser General Public License as
10  * published by the Free Software Foundation; either version 2 of the
11  * License, or (at your option) any later version.
12  *
13  * GLib is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with GLib; see the file COPYING.LIB.  If not,
20  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  *   Boston, MA 02111-1307, USA.
22  */
23
24 #include "config.h"
25
26 #include "gkeyfile.h"
27
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <locale.h>
31 #include <string.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #ifdef HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39 #ifdef G_OS_WIN32
40 #include <io.h>
41
42 #ifndef S_ISREG
43 #define S_ISREG(mode) ((mode)&_S_IFREG)
44 #endif
45
46 #endif  /* G_OS_WIN23 */
47
48 #include "gconvert.h"
49 #include "gdataset.h"
50 #include "gerror.h"
51 #include "gfileutils.h"
52 #include "ghash.h"
53 #include "glibintl.h"
54 #include "glist.h"
55 #include "gslist.h"
56 #include "gmem.h"
57 #include "gmessages.h"
58 #include "gstdio.h"
59 #include "gstring.h"
60 #include "gstrfuncs.h"
61 #include "gutils.h"
62
63 #include "galias.h"
64
65 typedef struct _GKeyFileGroup GKeyFileGroup;
66
67 struct _GKeyFile
68 {
69   GList *groups;
70   GHashTable *group_hash;
71
72   GKeyFileGroup *start_group;
73   GKeyFileGroup *current_group;
74
75   GString *parse_buffer; /* Holds up to one line of not-yet-parsed data */
76
77   /* Used for sizing the output buffer during serialization
78    */
79   gsize approximate_size;
80
81   gchar list_separator;
82
83   GKeyFileFlags flags;
84 };
85
86 typedef struct _GKeyFileKeyValuePair GKeyFileKeyValuePair;
87
88 struct _GKeyFileGroup
89 {
90   const gchar *name;  /* NULL for above first group (which will be comments) */
91
92   GKeyFileKeyValuePair *comment; /* Special comment that is stuck to the top of a group */
93   gboolean has_trailing_blank_line;
94
95   GList *key_value_pairs; 
96
97   /* Used in parallel with key_value_pairs for
98    * increased lookup performance
99    */
100   GHashTable *lookup_map;
101 };
102
103 struct _GKeyFileKeyValuePair
104 {
105   gchar *key;  /* NULL for comments */
106   gchar *value;
107 };
108
109 static gint                  find_file_in_data_dirs            (const gchar            *file,
110                                                                 const gchar           **data_dirs,
111                                                                 gchar                 **output_file,
112                                                                 GError                **error);
113 static gboolean              g_key_file_load_from_fd           (GKeyFile               *key_file,
114                                                                 gint                    fd,
115                                                                 GKeyFileFlags           flags,
116                                                                 GError                **error);
117 static GList                *g_key_file_lookup_group_node      (GKeyFile               *key_file,
118                                                                 const gchar            *group_name);
119 static GKeyFileGroup        *g_key_file_lookup_group           (GKeyFile               *key_file,
120                                                                 const gchar            *group_name);
121
122 static GList                *g_key_file_lookup_key_value_pair_node  (GKeyFile       *key_file,
123                                                                      GKeyFileGroup  *group,
124                                                                      const gchar    *key);
125 static GKeyFileKeyValuePair *g_key_file_lookup_key_value_pair       (GKeyFile       *key_file,
126                                                                      GKeyFileGroup  *group,
127                                                                      const gchar    *key);
128
129 static void                  g_key_file_remove_group_node          (GKeyFile      *key_file,
130                                                                     GList         *group_node);
131 static void                  g_key_file_remove_key_value_pair_node (GKeyFile      *key_file,
132                                                                     GKeyFileGroup *group,
133                                                                     GList         *pair_node);
134
135 static void                  g_key_file_add_key                (GKeyFile               *key_file,
136                                                                 GKeyFileGroup          *group,
137                                                                 const gchar            *key,
138                                                                 const gchar            *value);
139 static void                  g_key_file_add_group              (GKeyFile               *key_file,
140                                                                 const gchar            *group_name);
141 static gboolean              g_key_file_is_group_name          (const gchar *name);
142 static gboolean              g_key_file_is_key_name            (const gchar *name);
143 static void                  g_key_file_key_value_pair_free    (GKeyFileKeyValuePair   *pair);
144 static gboolean              g_key_file_line_is_comment        (const gchar            *line);
145 static gboolean              g_key_file_line_is_group          (const gchar            *line);
146 static gboolean              g_key_file_line_is_key_value_pair (const gchar            *line);
147 static gchar                *g_key_file_parse_value_as_string  (GKeyFile               *key_file,
148                                                                 const gchar            *value,
149                                                                 GSList                **separators,
150                                                                 GError                **error);
151 static gchar                *g_key_file_parse_string_as_value  (GKeyFile               *key_file,
152                                                                 const gchar            *string,
153                                                                 gboolean                escape_separator);
154 static gint                  g_key_file_parse_value_as_integer (GKeyFile               *key_file,
155                                                                 const gchar            *value,
156                                                                 GError                **error);
157 static gchar                *g_key_file_parse_integer_as_value (GKeyFile               *key_file,
158                                                                 gint                    value);
159 static gdouble               g_key_file_parse_value_as_double  (GKeyFile               *key_file,
160                                                                 const gchar            *value,
161                                                                 GError                **error);
162 static gboolean              g_key_file_parse_value_as_boolean (GKeyFile               *key_file,
163                                                                 const gchar            *value,
164                                                                 GError                **error);
165 static gchar                *g_key_file_parse_boolean_as_value (GKeyFile               *key_file,
166                                                                 gboolean                value);
167 static gchar                *g_key_file_parse_value_as_comment (GKeyFile               *key_file,
168                                                                 const gchar            *value);
169 static gchar                *g_key_file_parse_comment_as_value (GKeyFile               *key_file,
170                                                                 const gchar            *comment);
171 static void                  g_key_file_parse_key_value_pair   (GKeyFile               *key_file,
172                                                                 const gchar            *line,
173                                                                 gsize                   length,
174                                                                 GError                **error);
175 static void                  g_key_file_parse_comment          (GKeyFile               *key_file,
176                                                                 const gchar            *line,
177                                                                 gsize                   length,
178                                                                 GError                **error);
179 static void                  g_key_file_parse_group            (GKeyFile               *key_file,
180                                                                 const gchar            *line,
181                                                                 gsize                   length,
182                                                                 GError                **error);
183 static gchar                *key_get_locale                    (const gchar            *key);
184 static void                  g_key_file_parse_data             (GKeyFile               *key_file,
185                                                                 const gchar            *data,
186                                                                 gsize                   length,
187                                                                 GError                **error);
188 static void                  g_key_file_flush_parse_buffer     (GKeyFile               *key_file,
189                                                                 GError                **error);
190
191
192 GQuark
193 g_key_file_error_quark (void)
194 {
195   return g_quark_from_static_string ("g-key-file-error-quark");
196 }
197
198 static void
199 g_key_file_init (GKeyFile *key_file)
200 {  
201   key_file->current_group = g_slice_new0 (GKeyFileGroup);
202   key_file->groups = g_list_prepend (NULL, key_file->current_group);
203   key_file->group_hash = g_hash_table_new (g_str_hash, g_str_equal);
204   key_file->start_group = NULL;
205   key_file->parse_buffer = g_string_sized_new (128);
206   key_file->approximate_size = 0;
207   key_file->list_separator = ';';
208   key_file->flags = 0;
209 }
210
211 static void
212 g_key_file_clear (GKeyFile *key_file)
213 {
214   GList *tmp, *group_node;
215
216   if (key_file->parse_buffer)
217     g_string_free (key_file->parse_buffer, TRUE);
218
219   tmp = key_file->groups;
220   while (tmp != NULL)
221     {
222       group_node = tmp;
223       tmp = tmp->next;
224       g_key_file_remove_group_node (key_file, group_node);
225     }
226
227   g_assert (key_file->groups == NULL);
228 }
229
230
231 /**
232  * g_key_file_new:
233  *
234  * Creates a new empty #GKeyFile object. Use
235  * g_key_file_load_from_file(), g_key_file_load_from_data(),
236  * g_key_file_load_from_dirs() or g_key_file_load_from_data_dirs() to
237  * read an existing key file.
238  *
239  * Return value: an empty #GKeyFile.
240  *
241  * Since: 2.6
242  **/
243 GKeyFile *
244 g_key_file_new (void)
245 {
246   GKeyFile *key_file;
247
248   key_file = g_slice_new0 (GKeyFile);
249   g_key_file_init (key_file);
250
251   return key_file;
252 }
253
254 /**
255  * g_key_file_set_list_separator:
256  * @key_file: a #GKeyFile 
257  * @separator: the separator
258  *
259  * Sets the character which is used to separate
260  * values in lists. Typically ';' or ',' are used
261  * as separators. The default list separator is ';'.
262  *
263  * Since: 2.6
264  */
265 void
266 g_key_file_set_list_separator (GKeyFile *key_file,
267                                gchar     separator)
268 {
269   g_return_if_fail (key_file != NULL);
270
271   key_file->list_separator = separator;
272 }
273
274
275 /* Iterates through all the directories in *dirs trying to
276  * open file.  When it successfully locates and opens a file it
277  * returns the file descriptor to the open file.  It also
278  * outputs the absolute path of the file in output_file.
279  */
280 static gint
281 find_file_in_data_dirs (const gchar   *file,
282                         const gchar  **dirs,
283                         gchar        **output_file,
284                         GError       **error)
285 {
286   const gchar **data_dirs, *data_dir;
287   gchar *path;
288   gint fd;
289
290   path = NULL;
291   fd = -1;
292
293   if (dirs == NULL)
294     return fd;
295
296   data_dirs = dirs;
297
298   while (data_dirs && (data_dir = *data_dirs) && fd < 0)
299     {
300       gchar *candidate_file, *sub_dir;
301
302       candidate_file = (gchar *) file;
303       sub_dir = g_strdup ("");
304       while (candidate_file != NULL && fd < 0)
305         {
306           gchar *p;
307
308           path = g_build_filename (data_dir, sub_dir,
309                                    candidate_file, NULL);
310
311           fd = g_open (path, O_RDONLY, 0);
312
313           if (fd < 0)
314             {
315               g_free (path);
316               path = NULL;
317             }
318
319           candidate_file = strchr (candidate_file, '-');
320
321           if (candidate_file == NULL)
322             break;
323
324           candidate_file++;
325
326           g_free (sub_dir);
327           sub_dir = g_strndup (file, candidate_file - file - 1);
328
329           for (p = sub_dir; *p != '\0'; p++)
330             {
331               if (*p == '-')
332                 *p = G_DIR_SEPARATOR;
333             }
334         }
335       g_free (sub_dir);
336       data_dirs++;
337     }
338
339   if (fd < 0)
340     {
341       g_set_error (error, G_KEY_FILE_ERROR,
342                    G_KEY_FILE_ERROR_NOT_FOUND,
343                    _("Valid key file could not be "
344                      "found in search dirs"));
345     }
346
347   if (output_file != NULL && fd > 0)
348     *output_file = g_strdup (path);
349
350   g_free (path);
351
352   return fd;
353 }
354
355 static gboolean
356 g_key_file_load_from_fd (GKeyFile       *key_file,
357                          gint            fd,
358                          GKeyFileFlags   flags,
359                          GError        **error)
360 {
361   GError *key_file_error = NULL;
362   gssize bytes_read;
363   struct stat stat_buf;
364   gchar read_buf[4096];
365   
366   if (fstat (fd, &stat_buf) < 0)
367     {
368       g_set_error (error, G_FILE_ERROR,
369                    g_file_error_from_errno (errno),
370                    "%s", g_strerror (errno));
371       return FALSE;
372     }
373
374   if (!S_ISREG (stat_buf.st_mode))
375     {
376       g_set_error (error, G_KEY_FILE_ERROR,
377                    G_KEY_FILE_ERROR_PARSE,
378                    _("Not a regular file"));
379       return FALSE;
380     }
381
382   if (stat_buf.st_size == 0)
383     {
384       g_set_error (error, G_KEY_FILE_ERROR,
385                    G_KEY_FILE_ERROR_PARSE,
386                    _("File is empty"));
387       return FALSE;
388     }
389
390   if (key_file->approximate_size > 0)
391     {
392       g_key_file_clear (key_file);
393       g_key_file_init (key_file);
394     }
395   key_file->flags = flags;
396
397   bytes_read = 0;
398   do
399     {
400       bytes_read = read (fd, read_buf, 4096);
401
402       if (bytes_read == 0)  /* End of File */
403         break;
404
405       if (bytes_read < 0)
406         {
407           if (errno == EINTR || errno == EAGAIN)
408             continue;
409
410           g_set_error (error, G_FILE_ERROR,
411                        g_file_error_from_errno (errno),
412                        "%s", g_strerror (errno));
413           return FALSE;
414         }
415
416       g_key_file_parse_data (key_file, 
417                              read_buf, bytes_read,
418                              &key_file_error);
419     }
420   while (!key_file_error);
421
422   if (key_file_error)
423     {
424       g_propagate_error (error, key_file_error);
425       return FALSE;
426     }
427
428   g_key_file_flush_parse_buffer (key_file, &key_file_error);
429
430   if (key_file_error)
431     {
432       g_propagate_error (error, key_file_error);
433       return FALSE;
434     }
435
436   return TRUE;
437 }
438
439 /**
440  * g_key_file_load_from_file:
441  * @key_file: an empty #GKeyFile struct
442  * @file: the path of a filename to load, in the GLib filename encoding
443  * @flags: flags from #GKeyFileFlags
444  * @error: return location for a #GError, or %NULL
445  *
446  * Loads a key file into an empty #GKeyFile structure.
447  * If the file could not be loaded then %error is set to 
448  * either a #GFileError or #GKeyFileError.
449  *
450  * Return value: %TRUE if a key file could be loaded, %FALSE otherwise
451  *
452  * Since: 2.6
453  **/
454 gboolean
455 g_key_file_load_from_file (GKeyFile       *key_file,
456                            const gchar    *file,
457                            GKeyFileFlags   flags,
458                            GError        **error)
459 {
460   GError *key_file_error = NULL;
461   gint fd;
462
463   g_return_val_if_fail (key_file != NULL, FALSE);
464   g_return_val_if_fail (file != NULL, FALSE);
465
466   fd = g_open (file, O_RDONLY, 0);
467
468   if (fd < 0)
469     {
470       g_set_error (error, G_FILE_ERROR,
471                    g_file_error_from_errno (errno),
472                    "%s", g_strerror (errno));
473       return FALSE;
474     }
475
476   g_key_file_load_from_fd (key_file, fd, flags, &key_file_error);
477   close (fd);
478
479   if (key_file_error)
480     {
481       g_propagate_error (error, key_file_error);
482       return FALSE;
483     }
484
485   return TRUE;
486 }
487
488 /**
489  * g_key_file_load_from_data:
490  * @key_file: an empty #GKeyFile struct
491  * @data: key file loaded in memory
492  * @length: the length of @data in bytes
493  * @flags: flags from #GKeyFileFlags
494  * @error: return location for a #GError, or %NULL
495  *
496  * Loads a key file from memory into an empty #GKeyFile structure.  
497  * If the object cannot be created then %error is set to a #GKeyFileError. 
498  *
499  * Return value: %TRUE if a key file could be loaded, %FALSE otherwise
500  *
501  * Since: 2.6
502  **/
503 gboolean
504 g_key_file_load_from_data (GKeyFile       *key_file,
505                            const gchar    *data,
506                            gsize           length,
507                            GKeyFileFlags   flags,
508                            GError        **error)
509 {
510   GError *key_file_error = NULL;
511
512   g_return_val_if_fail (key_file != NULL, FALSE);
513   g_return_val_if_fail (data != NULL, FALSE);
514   g_return_val_if_fail (length != 0, FALSE);
515
516   if (length == (gsize)-1)
517     length = strlen (data);
518
519   if (key_file->approximate_size > 0)
520     {
521       g_key_file_clear (key_file);
522       g_key_file_init (key_file);
523     }
524   key_file->flags = flags;
525
526   g_key_file_parse_data (key_file, data, length, &key_file_error);
527   
528   if (key_file_error)
529     {
530       g_propagate_error (error, key_file_error);
531       return FALSE;
532     }
533
534   g_key_file_flush_parse_buffer (key_file, &key_file_error);
535   
536   if (key_file_error)
537     {
538       g_propagate_error (error, key_file_error);
539       return FALSE;
540     }
541
542   return TRUE;
543 }
544
545 /**
546  * g_key_file_load_from_dirs:
547  * @key_file: an empty #GKeyFile struct
548  * @file: a relative path to a filename to open and parse
549  * @search_dirs: %NULL-terminated array of directories to search
550  * @full_path: return location for a string containing the full path
551  *   of the file, or %NULL
552  * @flags: flags from #GKeyFileFlags
553  * @error: return location for a #GError, or %NULL
554  *
555  * This function looks for a key file named @file in the paths
556  * specified in @search_dirs, loads the file into @key_file and
557  * returns the file's full path in @full_path.  If the file could not
558  * be loaded then an %error is set to either a #GFileError or
559  * #GKeyFileError.
560  *
561  * Return value: %TRUE if a key file could be loaded, %FALSE otherwise
562  *
563  * Since: 2.14
564  **/
565 gboolean
566 g_key_file_load_from_dirs (GKeyFile       *key_file,
567                            const gchar    *file,
568                            const gchar   **search_dirs,
569                            gchar         **full_path,
570                            GKeyFileFlags   flags,
571                            GError        **error)
572 {
573   GError *key_file_error = NULL;
574   const gchar **data_dirs;
575   gchar *output_path;
576   gint fd;
577   gboolean found_file;
578
579   g_return_val_if_fail (key_file != NULL, FALSE);
580   g_return_val_if_fail (!g_path_is_absolute (file), FALSE);
581   g_return_val_if_fail (search_dirs != NULL, FALSE);
582
583   found_file = FALSE;
584   data_dirs = search_dirs;
585   output_path = NULL;
586   while (*data_dirs != NULL && !found_file)
587     {
588       g_free (output_path);
589
590       fd = find_file_in_data_dirs (file, data_dirs, &output_path,
591                                    &key_file_error);
592
593       if (fd < 0)
594         {
595           if (key_file_error)
596             g_propagate_error (error, key_file_error);
597           break;
598         }
599
600       found_file = g_key_file_load_from_fd (key_file, fd, flags,
601                                             &key_file_error);
602       close (fd);
603
604       if (key_file_error)
605         {
606           g_propagate_error (error, key_file_error);
607           break;
608         }
609     }
610
611   if (found_file && full_path)
612     *full_path = output_path;
613   else
614     g_free (output_path);
615
616   return found_file;
617 }
618
619 /**
620  * g_key_file_load_from_data_dirs:
621  * @key_file: an empty #GKeyFile struct
622  * @file: a relative path to a filename to open and parse
623  * @full_path: return location for a string containing the full path
624  *   of the file, or %NULL
625  * @flags: flags from #GKeyFileFlags 
626  * @error: return location for a #GError, or %NULL
627  *
628  * This function looks for a key file named @file in the paths 
629  * returned from g_get_user_data_dir() and g_get_system_data_dirs(), 
630  * loads the file into @key_file and returns the file's full path in 
631  * @full_path.  If the file could not be loaded then an %error is
632  * set to either a #GFileError or #GKeyFileError.
633  *
634  * Return value: %TRUE if a key file could be loaded, %FALSE othewise
635  * Since: 2.6
636  **/
637 gboolean
638 g_key_file_load_from_data_dirs (GKeyFile       *key_file,
639                                 const gchar    *file,
640                                 gchar         **full_path,
641                                 GKeyFileFlags   flags,
642                                 GError        **error)
643 {
644   gchar **all_data_dirs;
645   const gchar * user_data_dir;
646   const gchar * const * system_data_dirs;
647   gsize i, j;
648   gboolean found_file;
649
650   g_return_val_if_fail (key_file != NULL, FALSE);
651   g_return_val_if_fail (!g_path_is_absolute (file), FALSE);
652
653   user_data_dir = g_get_user_data_dir ();
654   system_data_dirs = g_get_system_data_dirs ();
655   all_data_dirs = g_new (gchar *, g_strv_length ((gchar **)system_data_dirs) + 2);
656
657   i = 0;
658   all_data_dirs[i++] = g_strdup (user_data_dir);
659
660   j = 0;
661   while (system_data_dirs[j] != NULL)
662     all_data_dirs[i++] = g_strdup (system_data_dirs[j++]);
663   all_data_dirs[i] = NULL;
664
665   found_file = g_key_file_load_from_dirs (key_file,
666                                           file,
667                                           (const gchar **)all_data_dirs,
668                                           full_path,
669                                           flags,
670                                           error);
671
672   g_strfreev (all_data_dirs);
673
674   return found_file;
675 }
676
677 /**
678  * g_key_file_free:
679  * @key_file: a #GKeyFile
680  *
681  * Frees a #GKeyFile.
682  *
683  * Since: 2.6
684  **/
685 void
686 g_key_file_free (GKeyFile *key_file)
687 {
688   g_return_if_fail (key_file != NULL);
689   
690   g_key_file_clear (key_file);
691   g_slice_free (GKeyFile, key_file);
692 }
693
694 /* If G_KEY_FILE_KEEP_TRANSLATIONS is not set, only returns
695  * true for locales that match those in g_get_language_names().
696  */
697 static gboolean
698 g_key_file_locale_is_interesting (GKeyFile    *key_file,
699                                   const gchar *locale)
700 {
701   const gchar * const * current_locales;
702   gsize i;
703
704   if (key_file->flags & G_KEY_FILE_KEEP_TRANSLATIONS)
705     return TRUE;
706
707   current_locales = g_get_language_names ();
708
709   for (i = 0; current_locales[i] != NULL; i++)
710     {
711       if (g_ascii_strcasecmp (current_locales[i], locale) == 0)
712         return TRUE;
713     }
714
715   return FALSE;
716 }
717
718 static void
719 g_key_file_parse_line (GKeyFile     *key_file,
720                        const gchar  *line,
721                        gsize         length,
722                        GError      **error)
723 {
724   GError *parse_error = NULL;
725   gchar *line_start;
726
727   g_return_if_fail (key_file != NULL);
728   g_return_if_fail (line != NULL);
729
730   line_start = (gchar *) line;
731   while (g_ascii_isspace (*line_start))
732     line_start++;
733
734   if (g_key_file_line_is_comment (line_start))
735     g_key_file_parse_comment (key_file, line, length, &parse_error);
736   else if (g_key_file_line_is_group (line_start))
737     g_key_file_parse_group (key_file, line_start,
738                             length - (line_start - line),
739                             &parse_error);
740   else if (g_key_file_line_is_key_value_pair (line_start))
741     g_key_file_parse_key_value_pair (key_file, line_start,
742                                      length - (line_start - line),
743                                      &parse_error);
744   else
745     {
746       gchar *line_utf8 = _g_utf8_make_valid (line);
747       g_set_error (error, G_KEY_FILE_ERROR,
748                    G_KEY_FILE_ERROR_PARSE,
749                    _("Key file contains line '%s' which is not "
750                      "a key-value pair, group, or comment"), 
751                    line_utf8);
752       g_free (line_utf8);
753
754       return;
755     }
756
757   if (parse_error)
758     g_propagate_error (error, parse_error);
759 }
760
761 static void
762 g_key_file_parse_comment (GKeyFile     *key_file,
763                           const gchar  *line,
764                           gsize         length,
765                           GError      **error)
766 {
767   GKeyFileKeyValuePair *pair;
768   
769   if (!(key_file->flags & G_KEY_FILE_KEEP_COMMENTS))
770     return;
771   
772   g_assert (key_file->current_group != NULL);
773
774   pair = g_slice_new (GKeyFileKeyValuePair);
775   pair->key = NULL;
776   pair->value = g_strndup (line, length);
777   
778   key_file->current_group->key_value_pairs =
779     g_list_prepend (key_file->current_group->key_value_pairs, pair);
780
781   if (length == 0 || line[0] != '#')
782     key_file->current_group->has_trailing_blank_line = TRUE;
783 }
784
785 static void
786 g_key_file_parse_group (GKeyFile     *key_file,
787                         const gchar  *line,
788                         gsize         length,
789                         GError      **error)
790 {
791   gchar *group_name;
792   const gchar *group_name_start, *group_name_end;
793   
794   /* advance past opening '['
795    */
796   group_name_start = line + 1;
797   group_name_end = line + length - 1;
798   
799   while (*group_name_end != ']')
800     group_name_end--;
801
802   group_name = g_strndup (group_name_start, 
803                           group_name_end - group_name_start);
804   
805   if (!g_key_file_is_group_name (group_name))
806     {
807       g_set_error (error, G_KEY_FILE_ERROR,
808                    G_KEY_FILE_ERROR_PARSE,
809                    _("Invalid group name: %s"), group_name);
810       g_free (group_name);
811       return;
812     }
813
814   g_key_file_add_group (key_file, group_name);
815   g_free (group_name);
816 }
817
818 static void
819 g_key_file_parse_key_value_pair (GKeyFile     *key_file,
820                                  const gchar  *line,
821                                  gsize         length,
822                                  GError      **error)
823 {
824   gchar *key, *value, *key_end, *value_start, *locale;
825   gsize key_len, value_len;
826
827   if (key_file->current_group == NULL || key_file->current_group->name == NULL)
828     {
829       g_set_error (error, G_KEY_FILE_ERROR,
830                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
831                    _("Key file does not start with a group"));
832       return;
833     }
834
835   key_end = value_start = strchr (line, '=');
836
837   g_assert (key_end != NULL);
838
839   key_end--;
840   value_start++;
841
842   /* Pull the key name from the line (chomping trailing whitespace)
843    */
844   while (g_ascii_isspace (*key_end))
845     key_end--;
846
847   key_len = key_end - line + 2;
848
849   g_assert (key_len <= length);
850
851   key = g_strndup (line, key_len - 1);
852
853   if (!g_key_file_is_key_name (key))
854     {
855       g_set_error (error, G_KEY_FILE_ERROR,
856                    G_KEY_FILE_ERROR_PARSE,
857                    _("Invalid key name: %s"), key);
858       g_free (key);
859       return; 
860     }
861
862   /* Pull the value from the line (chugging leading whitespace)
863    */
864   while (g_ascii_isspace (*value_start))
865     value_start++;
866
867   value_len = line + length - value_start + 1;
868
869   value = g_strndup (value_start, value_len);
870
871   g_assert (key_file->start_group != NULL);
872
873   if (key_file->current_group
874       && key_file->current_group->name
875       && strcmp (key_file->start_group->name,
876                  key_file->current_group->name) == 0
877       && strcmp (key, "Encoding") == 0)
878     {
879       if (g_ascii_strcasecmp (value, "UTF-8") != 0)
880         {
881           gchar *value_utf8 = _g_utf8_make_valid (value);
882           g_set_error (error, G_KEY_FILE_ERROR,
883                        G_KEY_FILE_ERROR_UNKNOWN_ENCODING,
884                        _("Key file contains unsupported "
885                          "encoding '%s'"), value_utf8);
886           g_free (value_utf8);
887
888           g_free (key);
889           g_free (value);
890           return;
891         }
892     }
893
894   /* Is this key a translation? If so, is it one that we care about?
895    */
896   locale = key_get_locale (key);
897
898   if (locale == NULL || g_key_file_locale_is_interesting (key_file, locale))
899     g_key_file_add_key (key_file, key_file->current_group, key, value);
900
901   g_free (locale);
902   g_free (key);
903   g_free (value);
904 }
905
906 static gchar *
907 key_get_locale (const gchar *key)
908 {
909   gchar *locale;
910
911   locale = g_strrstr (key, "[");
912
913   if (locale && strlen (locale) <= 2)
914     locale = NULL;
915
916   if (locale)
917     locale = g_strndup (locale + 1, strlen (locale) - 2);
918
919   return locale;
920 }
921
922 static void
923 g_key_file_parse_data (GKeyFile     *key_file,
924                        const gchar  *data,
925                        gsize         length,
926                        GError      **error)
927 {
928   GError *parse_error;
929   gsize i;
930
931   g_return_if_fail (key_file != NULL);
932   g_return_if_fail (data != NULL);
933
934   parse_error = NULL;
935
936   for (i = 0; i < length; i++)
937     {
938       if (data[i] == '\n')
939         {
940           if (i > 0 && data[i - 1] == '\r')
941             g_string_erase (key_file->parse_buffer,
942                             key_file->parse_buffer->len - 1,
943                             1);
944             
945           /* When a newline is encountered flush the parse buffer so that the
946            * line can be parsed.  Note that completely blank lines won't show
947            * up in the parse buffer, so they get parsed directly.
948            */
949           if (key_file->parse_buffer->len > 0)
950             g_key_file_flush_parse_buffer (key_file, &parse_error);
951           else
952             g_key_file_parse_comment (key_file, "", 1, &parse_error);
953
954           if (parse_error)
955             {
956               g_propagate_error (error, parse_error);
957               return;
958             }
959         }
960       else
961         g_string_append_c (key_file->parse_buffer, data[i]);
962     }
963
964   key_file->approximate_size += length;
965 }
966
967 static void
968 g_key_file_flush_parse_buffer (GKeyFile  *key_file,
969                                GError   **error)
970 {
971   GError *file_error = NULL;
972
973   g_return_if_fail (key_file != NULL);
974
975   file_error = NULL;
976
977   if (key_file->parse_buffer->len > 0)
978     {
979       g_key_file_parse_line (key_file, key_file->parse_buffer->str,
980                              key_file->parse_buffer->len,
981                              &file_error);
982       g_string_erase (key_file->parse_buffer, 0, -1);
983
984       if (file_error)
985         {
986           g_propagate_error (error, file_error);
987           return;
988         }
989     }
990 }
991
992 /**
993  * g_key_file_to_data:
994  * @key_file: a #GKeyFile
995  * @length: return location for the length of the 
996  *   returned string, or %NULL
997  * @error: return location for a #GError, or %NULL
998  *
999  * This function outputs @key_file as a string.  
1000  *
1001  * Return value: a newly allocated string holding
1002  *   the contents of the #GKeyFile 
1003  *
1004  * Since: 2.6
1005  **/
1006 gchar *
1007 g_key_file_to_data (GKeyFile  *key_file,
1008                     gsize     *length,
1009                     GError   **error)
1010 {
1011   GString *data_string;
1012   GList *group_node, *key_file_node;
1013   gboolean has_blank_line = TRUE;
1014
1015   g_return_val_if_fail (key_file != NULL, NULL);
1016
1017   data_string = g_string_sized_new (2 * key_file->approximate_size);
1018   
1019   for (group_node = g_list_last (key_file->groups);
1020        group_node != NULL;
1021        group_node = group_node->prev)
1022     {
1023       GKeyFileGroup *group;
1024
1025       group = (GKeyFileGroup *) group_node->data;
1026
1027       /* separate groups by at least an empty line */
1028       if (!has_blank_line)
1029         g_string_append_c (data_string, '\n');
1030       has_blank_line = group->has_trailing_blank_line;
1031
1032       if (group->comment != NULL)
1033         g_string_append_printf (data_string, "%s\n", group->comment->value);
1034
1035       if (group->name != NULL)
1036         g_string_append_printf (data_string, "[%s]\n", group->name);
1037
1038       for (key_file_node = g_list_last (group->key_value_pairs);
1039            key_file_node != NULL;
1040            key_file_node = key_file_node->prev)
1041         {
1042           GKeyFileKeyValuePair *pair;
1043
1044           pair = (GKeyFileKeyValuePair *) key_file_node->data;
1045
1046           if (pair->key != NULL)
1047             g_string_append_printf (data_string, "%s=%s\n", pair->key, pair->value);
1048           else
1049             g_string_append_printf (data_string, "%s\n", pair->value);
1050         }
1051     }
1052
1053   if (length)
1054     *length = data_string->len;
1055
1056   return g_string_free (data_string, FALSE);
1057 }
1058
1059 /**
1060  * g_key_file_get_keys:
1061  * @key_file: a #GKeyFile
1062  * @group_name: a group name
1063  * @length: return location for the number of keys returned, or %NULL
1064  * @error: return location for a #GError, or %NULL
1065  *
1066  * Returns all keys for the group name @group_name.  The array of
1067  * returned keys will be %NULL-terminated, so @length may
1068  * optionally be %NULL. In the event that the @group_name cannot
1069  * be found, %NULL is returned and @error is set to
1070  * #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
1071  *
1072  * Return value: a newly-allocated %NULL-terminated array of strings. 
1073  *     Use g_strfreev() to free it.
1074  *
1075  * Since: 2.6
1076  **/
1077 gchar **
1078 g_key_file_get_keys (GKeyFile     *key_file,
1079                      const gchar  *group_name,
1080                      gsize        *length,
1081                      GError      **error)
1082 {
1083   GKeyFileGroup *group;
1084   GList *tmp;
1085   gchar **keys;
1086   gsize i, num_keys;
1087   
1088   g_return_val_if_fail (key_file != NULL, NULL);
1089   g_return_val_if_fail (group_name != NULL, NULL);
1090   
1091   group = g_key_file_lookup_group (key_file, group_name);
1092   
1093   if (!group)
1094     {
1095       g_set_error (error, G_KEY_FILE_ERROR,
1096                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
1097                    _("Key file does not have group '%s'"),
1098                    group_name ? group_name : "(null)");
1099       return NULL;
1100     }
1101
1102   num_keys = 0;
1103   for (tmp = group->key_value_pairs; tmp; tmp = tmp->next)
1104     {
1105       GKeyFileKeyValuePair *pair;
1106
1107       pair = (GKeyFileKeyValuePair *) tmp->data;
1108
1109       if (pair->key)
1110         num_keys++;
1111     }
1112   
1113   keys = g_new (gchar *, num_keys + 1);
1114
1115   i = num_keys - 1;
1116   for (tmp = group->key_value_pairs; tmp; tmp = tmp->next)
1117     {
1118       GKeyFileKeyValuePair *pair;
1119
1120       pair = (GKeyFileKeyValuePair *) tmp->data;
1121
1122       if (pair->key)
1123         {
1124           keys[i] = g_strdup (pair->key);
1125           i--;
1126         }
1127     }
1128
1129   keys[num_keys] = NULL;
1130
1131   if (length)
1132     *length = num_keys;
1133
1134   return keys;
1135 }
1136
1137 /**
1138  * g_key_file_get_start_group:
1139  * @key_file: a #GKeyFile
1140  *
1141  * Returns the name of the start group of the file. 
1142  *
1143  * Return value: The start group of the key file.
1144  *
1145  * Since: 2.6
1146  **/
1147 gchar *
1148 g_key_file_get_start_group (GKeyFile *key_file)
1149 {
1150   g_return_val_if_fail (key_file != NULL, NULL);
1151
1152   if (key_file->start_group)
1153     return g_strdup (key_file->start_group->name);
1154
1155   return NULL;
1156 }
1157
1158 /**
1159  * g_key_file_get_groups:
1160  * @key_file: a #GKeyFile
1161  * @length: return location for the number of returned groups, or %NULL
1162  *
1163  * Returns all groups in the key file loaded with @key_file.  
1164  * The array of returned groups will be %NULL-terminated, so 
1165  * @length may optionally be %NULL.
1166  *
1167  * Return value: a newly-allocated %NULL-terminated array of strings. 
1168  *   Use g_strfreev() to free it.
1169  * Since: 2.6
1170  **/
1171 gchar **
1172 g_key_file_get_groups (GKeyFile *key_file,
1173                        gsize    *length)
1174 {
1175   GList *group_node;
1176   gchar **groups;
1177   gsize i, num_groups;
1178
1179   g_return_val_if_fail (key_file != NULL, NULL);
1180
1181   num_groups = g_list_length (key_file->groups);
1182
1183   g_assert (num_groups > 0);
1184
1185   /* Only need num_groups instead of num_groups + 1
1186    * because the first group of the file (last in the
1187    * list) is always the comment group at the top,
1188    * which we skip
1189    */
1190   groups = g_new (gchar *, num_groups);
1191
1192   group_node = g_list_last (key_file->groups);
1193   
1194   g_assert (((GKeyFileGroup *) group_node->data)->name == NULL);
1195
1196   i = 0;
1197   for (group_node = group_node->prev;
1198        group_node != NULL;
1199        group_node = group_node->prev)
1200     {
1201       GKeyFileGroup *group;
1202
1203       group = (GKeyFileGroup *) group_node->data;
1204
1205       g_assert (group->name != NULL);
1206
1207       groups[i++] = g_strdup (group->name);
1208     }
1209   groups[i] = NULL;
1210
1211   if (length)
1212     *length = i;
1213
1214   return groups;
1215 }
1216
1217 /**
1218  * g_key_file_get_value:
1219  * @key_file: a #GKeyFile
1220  * @group_name: a group name
1221  * @key: a key
1222  * @error: return location for a #GError, or %NULL
1223  *
1224  * Returns the value associated with @key under @group_name.  
1225  *
1226  * In the event the key cannot be found, %NULL is returned and 
1227  * @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND.  In the 
1228  * event that the @group_name cannot be found, %NULL is returned 
1229  * and @error is set to #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
1230  *
1231  * Return value: a newly allocated string or %NULL if the specified 
1232  *  key cannot be found.
1233  *
1234  * Since: 2.6
1235  **/
1236 gchar *
1237 g_key_file_get_value (GKeyFile     *key_file,
1238                       const gchar  *group_name,
1239                       const gchar  *key,
1240                       GError      **error)
1241 {
1242   GKeyFileGroup *group;
1243   GKeyFileKeyValuePair *pair;
1244   gchar *value = NULL;
1245
1246   g_return_val_if_fail (key_file != NULL, NULL);
1247   g_return_val_if_fail (group_name != NULL, NULL);
1248   g_return_val_if_fail (key != NULL, NULL);
1249   
1250   group = g_key_file_lookup_group (key_file, group_name);
1251
1252   if (!group)
1253     {
1254       g_set_error (error, G_KEY_FILE_ERROR,
1255                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
1256                    _("Key file does not have group '%s'"),
1257                    group_name ? group_name : "(null)");
1258       return NULL;
1259     }
1260
1261   pair = g_key_file_lookup_key_value_pair (key_file, group, key);
1262
1263   if (pair)
1264     value = g_strdup (pair->value);
1265   else
1266     g_set_error (error, G_KEY_FILE_ERROR,
1267                  G_KEY_FILE_ERROR_KEY_NOT_FOUND,
1268                  _("Key file does not have key '%s'"), key);
1269
1270   return value;
1271 }
1272
1273 /**
1274  * g_key_file_set_value:
1275  * @key_file: a #GKeyFile
1276  * @group_name: a group name
1277  * @key: a key
1278  * @value: a string
1279  *
1280  * Associates a new value with @key under @group_name.  
1281  * If @key cannot be found then it is created. 
1282  * If @group_name cannot be found then it is created.
1283  *
1284  * Since: 2.6
1285  **/
1286 void
1287 g_key_file_set_value (GKeyFile    *key_file,
1288                       const gchar *group_name,
1289                       const gchar *key,
1290                       const gchar *value)
1291 {
1292   GKeyFileGroup *group;
1293   GKeyFileKeyValuePair *pair;
1294
1295   g_return_if_fail (key_file != NULL);
1296   g_return_if_fail (g_key_file_is_group_name (group_name));
1297   g_return_if_fail (g_key_file_is_key_name (key));
1298   g_return_if_fail (value != NULL);
1299
1300   group = g_key_file_lookup_group (key_file, group_name);
1301
1302   if (!group)
1303     {
1304       g_key_file_add_group (key_file, group_name);
1305       group = (GKeyFileGroup *) key_file->groups->data;
1306
1307       g_key_file_add_key (key_file, group, key, value);
1308     }
1309   else
1310     {
1311       pair = g_key_file_lookup_key_value_pair (key_file, group, key);
1312
1313       if (!pair)
1314         g_key_file_add_key (key_file, group, key, value);
1315       else
1316         {
1317           g_free (pair->value);
1318           pair->value = g_strdup (value);
1319         }
1320     }
1321 }
1322
1323 /**
1324  * g_key_file_get_string:
1325  * @key_file: a #GKeyFile
1326  * @group_name: a group name
1327  * @key: a key
1328  * @error: return location for a #GError, or %NULL
1329  *
1330  * Returns the value associated with @key under @group_name.  
1331  *
1332  * In the event the key cannot be found, %NULL is returned and 
1333  * @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND.  In the 
1334  * event that the @group_name cannot be found, %NULL is returned 
1335  * and @error is set to #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
1336  *
1337  * Return value: a newly allocated string or %NULL if the specified 
1338  *   key cannot be found.
1339  *
1340  * Since: 2.6
1341  **/
1342 gchar *
1343 g_key_file_get_string (GKeyFile     *key_file,
1344                        const gchar  *group_name,
1345                        const gchar  *key,
1346                        GError      **error)
1347 {
1348   gchar *value, *string_value;
1349   GError *key_file_error;
1350
1351   g_return_val_if_fail (key_file != NULL, NULL);
1352   g_return_val_if_fail (group_name != NULL, NULL);
1353   g_return_val_if_fail (key != NULL, NULL);
1354
1355   key_file_error = NULL;
1356
1357   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
1358
1359   if (key_file_error)
1360     {
1361       g_propagate_error (error, key_file_error);
1362       return NULL;
1363     }
1364
1365   if (!g_utf8_validate (value, -1, NULL))
1366     {
1367       gchar *value_utf8 = _g_utf8_make_valid (value);
1368       g_set_error (error, G_KEY_FILE_ERROR,
1369                    G_KEY_FILE_ERROR_UNKNOWN_ENCODING,
1370                    _("Key file contains key '%s' with value '%s' "
1371                      "which is not UTF-8"), key, value_utf8);
1372       g_free (value_utf8);
1373       g_free (value);
1374
1375       return NULL;
1376     }
1377
1378   string_value = g_key_file_parse_value_as_string (key_file, value, NULL,
1379                                                    &key_file_error);
1380   g_free (value);
1381
1382   if (key_file_error)
1383     {
1384       if (g_error_matches (key_file_error,
1385                            G_KEY_FILE_ERROR,
1386                            G_KEY_FILE_ERROR_INVALID_VALUE))
1387         {
1388           g_set_error (error, G_KEY_FILE_ERROR,
1389                        G_KEY_FILE_ERROR_INVALID_VALUE,
1390                        _("Key file contains key '%s' "
1391                          "which has value that cannot be interpreted."),
1392                        key);
1393           g_error_free (key_file_error);
1394         }
1395       else
1396         g_propagate_error (error, key_file_error);
1397     }
1398
1399   return string_value;
1400 }
1401
1402 /**
1403  * g_key_file_set_string:
1404  * @key_file: a #GKeyFile
1405  * @group_name: a group name
1406  * @key: a key
1407  * @string: a string
1408  *
1409  * Associates a new string value with @key under @group_name.  
1410  * If @key cannot be found then it is created.  
1411  * If @group_name cannot be found then it is created.
1412  *
1413  * Since: 2.6
1414  **/
1415 void
1416 g_key_file_set_string (GKeyFile    *key_file,
1417                        const gchar *group_name,
1418                        const gchar *key,
1419                        const gchar *string)
1420 {
1421   gchar *value;
1422
1423   g_return_if_fail (key_file != NULL);
1424   g_return_if_fail (string != NULL);
1425
1426   value = g_key_file_parse_string_as_value (key_file, string, FALSE);
1427   g_key_file_set_value (key_file, group_name, key, value);
1428   g_free (value);
1429 }
1430
1431 /**
1432  * g_key_file_get_string_list:
1433  * @key_file: a #GKeyFile
1434  * @group_name: a group name
1435  * @key: a key
1436  * @length: return location for the number of returned strings, or %NULL
1437  * @error: return location for a #GError, or %NULL
1438  *
1439  * Returns the values associated with @key under @group_name.
1440  *
1441  * In the event the key cannot be found, %NULL is returned and
1442  * @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND.  In the
1443  * event that the @group_name cannot be found, %NULL is returned
1444  * and @error is set to #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
1445  *
1446  * Return value: a %NULL-terminated string array or %NULL if the specified 
1447  *   key cannot be found. The array should be freed with g_strfreev().
1448  *
1449  * Since: 2.6
1450  **/
1451 gchar **
1452 g_key_file_get_string_list (GKeyFile     *key_file,
1453                             const gchar  *group_name,
1454                             const gchar  *key,
1455                             gsize        *length,
1456                             GError      **error)
1457 {
1458   GError *key_file_error = NULL;
1459   gchar *value, *string_value, **values;
1460   gint i, len;
1461   GSList *p, *pieces = NULL;
1462
1463   g_return_val_if_fail (key_file != NULL, NULL);
1464   g_return_val_if_fail (group_name != NULL, NULL);
1465   g_return_val_if_fail (key != NULL, NULL);
1466
1467   if (length)
1468     *length = 0;
1469
1470   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
1471
1472   if (key_file_error)
1473     {
1474       g_propagate_error (error, key_file_error);
1475       return NULL;
1476     }
1477
1478   if (!g_utf8_validate (value, -1, NULL))
1479     {
1480       gchar *value_utf8 = _g_utf8_make_valid (value);
1481       g_set_error (error, G_KEY_FILE_ERROR,
1482                    G_KEY_FILE_ERROR_UNKNOWN_ENCODING,
1483                    _("Key file contains key '%s' with value '%s' "
1484                      "which is not UTF-8"), key, value_utf8);
1485       g_free (value_utf8);
1486       g_free (value);
1487
1488       return NULL;
1489     }
1490
1491   string_value = g_key_file_parse_value_as_string (key_file, value, &pieces, &key_file_error);
1492   g_free (value);
1493   g_free (string_value);
1494
1495   if (key_file_error)
1496     {
1497       if (g_error_matches (key_file_error,
1498                            G_KEY_FILE_ERROR,
1499                            G_KEY_FILE_ERROR_INVALID_VALUE))
1500         {
1501           g_set_error (error, G_KEY_FILE_ERROR,
1502                        G_KEY_FILE_ERROR_INVALID_VALUE,
1503                        _("Key file contains key '%s' "
1504                          "which has value that cannot be interpreted."),
1505                        key);
1506           g_error_free (key_file_error);
1507         }
1508       else
1509         g_propagate_error (error, key_file_error);
1510     }
1511
1512   len = g_slist_length (pieces);
1513   values = g_new (gchar *, len + 1);
1514   for (p = pieces, i = 0; p; p = p->next)
1515     values[i++] = p->data;
1516   values[len] = NULL;
1517
1518   g_slist_free (pieces);
1519
1520   if (length)
1521     *length = len;
1522
1523   return values;
1524 }
1525
1526 /**
1527  * g_key_file_set_string_list:
1528  * @key_file: a #GKeyFile
1529  * @group_name: a group name
1530  * @key: a key
1531  * @list: an array of locale string values
1532  * @length: number of locale string values in @list
1533  *
1534  * Associates a list of string values for @key under @group_name.
1535  * If @key cannot be found then it is created.  
1536  * If @group_name cannot be found then it is created.
1537  *
1538  * Since: 2.6
1539  **/
1540 void
1541 g_key_file_set_string_list (GKeyFile            *key_file,
1542                             const gchar         *group_name,
1543                             const gchar         *key,
1544                             const gchar * const  list[],
1545                             gsize                length)
1546 {
1547   GString *value_list;
1548   gsize i;
1549
1550   g_return_if_fail (key_file != NULL);
1551   g_return_if_fail (list != NULL);
1552
1553   value_list = g_string_sized_new (length * 128);
1554   for (i = 0; i < length && list[i] != NULL; i++)
1555     {
1556       gchar *value;
1557
1558       value = g_key_file_parse_string_as_value (key_file, list[i], TRUE);
1559       g_string_append (value_list, value);
1560       g_string_append_c (value_list, key_file->list_separator);
1561
1562       g_free (value);
1563     }
1564
1565   g_key_file_set_value (key_file, group_name, key, value_list->str);
1566   g_string_free (value_list, TRUE);
1567 }
1568
1569 /**
1570  * g_key_file_set_locale_string:
1571  * @key_file: a #GKeyFile
1572  * @group_name: a group name
1573  * @key: a key
1574  * @locale: a locale
1575  * @string: a string
1576  *
1577  * Associates a string value for @key and @locale under @group_name.  
1578  * If the translation for @key cannot be found then it is created.
1579  *
1580  * Since: 2.6
1581  **/
1582 void
1583 g_key_file_set_locale_string (GKeyFile     *key_file,
1584                               const gchar  *group_name,
1585                               const gchar  *key,
1586                               const gchar  *locale,
1587                               const gchar  *string)
1588 {
1589   gchar *full_key, *value;
1590
1591   g_return_if_fail (key_file != NULL);
1592   g_return_if_fail (key != NULL);
1593   g_return_if_fail (locale != NULL);
1594   g_return_if_fail (string != NULL);
1595
1596   value = g_key_file_parse_string_as_value (key_file, string, FALSE);
1597   full_key = g_strdup_printf ("%s[%s]", key, locale);
1598   g_key_file_set_value (key_file, group_name, full_key, value);
1599   g_free (full_key);
1600   g_free (value);
1601 }
1602
1603 extern GSList *_g_compute_locale_variants (const gchar *locale);
1604
1605 /**
1606  * g_key_file_get_locale_string:
1607  * @key_file: a #GKeyFile
1608  * @group_name: a group name
1609  * @key: a key
1610  * @locale: a locale or %NULL
1611  * @error: return location for a #GError, or %NULL
1612  *
1613  * Returns the value associated with @key under @group_name
1614  * translated in the given @locale if available.  If @locale is
1615  * %NULL then the current locale is assumed. 
1616  *
1617  * If @key cannot be found then %NULL is returned and @error is set 
1618  * to #G_KEY_FILE_ERROR_KEY_NOT_FOUND. If the value associated
1619  * with @key cannot be interpreted or no suitable translation can
1620  * be found then the untranslated value is returned.
1621  *
1622  * Return value: a newly allocated string or %NULL if the specified 
1623  *   key cannot be found.
1624  *
1625  * Since: 2.6
1626  **/
1627 gchar *
1628 g_key_file_get_locale_string (GKeyFile     *key_file,
1629                               const gchar  *group_name,
1630                               const gchar  *key,
1631                               const gchar  *locale,
1632                               GError      **error)
1633 {
1634   gchar *candidate_key, *translated_value;
1635   GError *key_file_error;
1636   gchar **languages;
1637   gboolean free_languages = FALSE;
1638   gint i;
1639
1640   g_return_val_if_fail (key_file != NULL, NULL);
1641   g_return_val_if_fail (group_name != NULL, NULL);
1642   g_return_val_if_fail (key != NULL, NULL);
1643
1644   candidate_key = NULL;
1645   translated_value = NULL;
1646   key_file_error = NULL;
1647
1648   if (locale)
1649     {
1650       GSList *l, *list;
1651
1652       list = _g_compute_locale_variants (locale);
1653
1654       languages = g_new (gchar *, g_slist_length (list) + 1);
1655       for (l = list, i = 0; l; l = l->next, i++)
1656         languages[i] = l->data;
1657       languages[i] = NULL;
1658
1659       g_slist_free (list);
1660       free_languages = TRUE;
1661     }
1662   else
1663     {
1664       languages = (gchar **) g_get_language_names ();
1665       free_languages = FALSE;
1666     }
1667   
1668   for (i = 0; languages[i]; i++)
1669     {
1670       candidate_key = g_strdup_printf ("%s[%s]", key, languages[i]);
1671       
1672       translated_value = g_key_file_get_string (key_file,
1673                                                 group_name,
1674                                                 candidate_key, NULL);
1675       g_free (candidate_key);
1676
1677       if (translated_value)
1678         break;
1679
1680       g_free (translated_value);
1681       translated_value = NULL;
1682    }
1683
1684   /* Fallback to untranslated key
1685    */
1686   if (!translated_value)
1687     {
1688       translated_value = g_key_file_get_string (key_file, group_name, key,
1689                                                 &key_file_error);
1690       
1691       if (!translated_value)
1692         g_propagate_error (error, key_file_error);
1693     }
1694
1695   if (free_languages)
1696     g_strfreev (languages);
1697
1698   return translated_value;
1699 }
1700
1701 /** 
1702  * g_key_file_get_locale_string_list: 
1703  * @key_file: a #GKeyFile
1704  * @group_name: a group name
1705  * @key: a key
1706  * @locale: a locale
1707  * @length: return location for the number of returned strings or %NULL
1708  * @error: return location for a #GError or %NULL
1709  *
1710  * Returns the values associated with @key under @group_name
1711  * translated in the given @locale if available.  If @locale is
1712  * %NULL then the current locale is assumed.
1713
1714  * If @key cannot be found then %NULL is returned and @error is set 
1715  * to #G_KEY_FILE_ERROR_KEY_NOT_FOUND. If the values associated
1716  * with @key cannot be interpreted or no suitable translations
1717  * can be found then the untranslated values are returned. The 
1718  * returned array is %NULL-terminated, so @length may optionally 
1719  * be %NULL.
1720  *
1721  * Return value: a newly allocated %NULL-terminated string array
1722  *   or %NULL if the key isn't found. The string array should be freed
1723  *   with g_strfreev().
1724  *
1725  * Since: 2.6
1726  **/
1727 gchar **
1728 g_key_file_get_locale_string_list (GKeyFile     *key_file,
1729                                    const gchar  *group_name,
1730                                    const gchar  *key,
1731                                    const gchar  *locale,
1732                                    gsize        *length,
1733                                    GError      **error)
1734 {
1735   GError *key_file_error;
1736   gchar **values, *value;
1737
1738   g_return_val_if_fail (key_file != NULL, NULL);
1739   g_return_val_if_fail (group_name != NULL, NULL);
1740   g_return_val_if_fail (key != NULL, NULL);
1741
1742   key_file_error = NULL;
1743
1744   value = g_key_file_get_locale_string (key_file, group_name, 
1745                                         key, locale,
1746                                         &key_file_error);
1747   
1748   if (key_file_error)
1749     g_propagate_error (error, key_file_error);
1750   
1751   if (!value)
1752     {
1753       if (length)
1754         *length = 0;
1755       return NULL;
1756     }
1757
1758   if (value[strlen (value) - 1] == ';')
1759     value[strlen (value) - 1] = '\0';
1760
1761   values = g_strsplit (value, ";", 0);
1762
1763   g_free (value);
1764
1765   if (length)
1766     *length = g_strv_length (values);
1767
1768   return values;
1769 }
1770
1771 /**
1772  * g_key_file_set_locale_string_list:
1773  * @key_file: a #GKeyFile
1774  * @group_name: a group name
1775  * @key: a key
1776  * @locale: a locale
1777  * @list: a %NULL-terminated array of locale string values
1778  * @length: the length of @list
1779  *
1780  * Associates a list of string values for @key and @locale under
1781  * @group_name.  If the translation for @key cannot be found then
1782  * it is created. 
1783  *
1784  * Since: 2.6
1785  **/
1786 void
1787 g_key_file_set_locale_string_list (GKeyFile            *key_file,
1788                                    const gchar         *group_name,
1789                                    const gchar         *key,
1790                                    const gchar         *locale,
1791                                    const gchar * const  list[],
1792                                    gsize                length)
1793 {
1794   GString *value_list;
1795   gchar *full_key;
1796   gsize i;
1797
1798   g_return_if_fail (key_file != NULL);
1799   g_return_if_fail (key != NULL);
1800   g_return_if_fail (locale != NULL);
1801   g_return_if_fail (length != 0);
1802
1803   value_list = g_string_sized_new (length * 128);
1804   for (i = 0; i < length && list[i] != NULL; i++)
1805     {
1806       gchar *value;
1807       
1808       value = g_key_file_parse_string_as_value (key_file, list[i], TRUE);
1809       
1810       g_string_append (value_list, value);
1811       g_string_append_c (value_list, ';');
1812
1813       g_free (value);
1814     }
1815
1816   full_key = g_strdup_printf ("%s[%s]", key, locale);
1817   g_key_file_set_value (key_file, group_name, full_key, value_list->str);
1818   g_free (full_key);
1819   g_string_free (value_list, TRUE);
1820 }
1821
1822 /**
1823  * g_key_file_get_boolean:
1824  * @key_file: a #GKeyFile
1825  * @group_name: a group name
1826  * @key: a key
1827  * @error: return location for a #GError
1828  *
1829  * Returns the value associated with @key under @group_name as a
1830  * boolean. 
1831  *
1832  * If @key cannot be found then %FALSE is returned and @error is set
1833  * to #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the value
1834  * associated with @key cannot be interpreted as a boolean then %FALSE
1835  * is returned and @error is set to #G_KEY_FILE_ERROR_INVALID_VALUE.
1836  *
1837  * Return value: the value associated with the key as a boolean, 
1838  *    or %FALSE if the key was not found or could not be parsed.
1839  *
1840  * Since: 2.6
1841  **/
1842 gboolean
1843 g_key_file_get_boolean (GKeyFile     *key_file,
1844                         const gchar  *group_name,
1845                         const gchar  *key,
1846                         GError      **error)
1847 {
1848   GError *key_file_error = NULL;
1849   gchar *value;
1850   gboolean bool_value;
1851
1852   g_return_val_if_fail (key_file != NULL, FALSE);
1853   g_return_val_if_fail (group_name != NULL, FALSE);
1854   g_return_val_if_fail (key != NULL, FALSE);
1855
1856   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
1857
1858   if (!value)
1859     {
1860       g_propagate_error (error, key_file_error);
1861       return FALSE;
1862     }
1863
1864   bool_value = g_key_file_parse_value_as_boolean (key_file, value,
1865                                                   &key_file_error);
1866   g_free (value);
1867
1868   if (key_file_error)
1869     {
1870       if (g_error_matches (key_file_error,
1871                            G_KEY_FILE_ERROR,
1872                            G_KEY_FILE_ERROR_INVALID_VALUE))
1873         {
1874           g_set_error (error, G_KEY_FILE_ERROR,
1875                        G_KEY_FILE_ERROR_INVALID_VALUE,
1876                        _("Key file contains key '%s' "
1877                          "which has value that cannot be interpreted."),
1878                        key);
1879           g_error_free (key_file_error);
1880         }
1881       else
1882         g_propagate_error (error, key_file_error);
1883     }
1884
1885   return bool_value;
1886 }
1887
1888 /**
1889  * g_key_file_set_boolean:
1890  * @key_file: a #GKeyFile
1891  * @group_name: a group name
1892  * @key: a key
1893  * @value: %TRUE or %FALSE
1894  *
1895  * Associates a new boolean value with @key under @group_name.
1896  * If @key cannot be found then it is created. 
1897  *
1898  * Since: 2.6
1899  **/
1900 void
1901 g_key_file_set_boolean (GKeyFile    *key_file,
1902                         const gchar *group_name,
1903                         const gchar *key,
1904                         gboolean     value)
1905 {
1906   gchar *result;
1907
1908   g_return_if_fail (key_file != NULL);
1909
1910   result = g_key_file_parse_boolean_as_value (key_file, value);
1911   g_key_file_set_value (key_file, group_name, key, result);
1912   g_free (result);
1913 }
1914
1915 /**
1916  * g_key_file_get_boolean_list:
1917  * @key_file: a #GKeyFile
1918  * @group_name: a group name
1919  * @key: a key
1920  * @length: the number of booleans returned
1921  * @error: return location for a #GError
1922  *
1923  * Returns the values associated with @key under @group_name as
1924  * booleans. If @group_name is %NULL, the start_group is used.
1925  *
1926  * If @key cannot be found then %NULL is returned and @error is set to
1927  * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the values associated
1928  * with @key cannot be interpreted as booleans then %NULL is returned
1929  * and @error is set to #G_KEY_FILE_ERROR_INVALID_VALUE.
1930  *
1931  * Return value: the values associated with the key as a list of
1932  *    booleans, or %NULL if the key was not found or could not be parsed.
1933  * 
1934  * Since: 2.6
1935  **/
1936 gboolean *
1937 g_key_file_get_boolean_list (GKeyFile     *key_file,
1938                              const gchar  *group_name,
1939                              const gchar  *key,
1940                              gsize        *length,
1941                              GError      **error)
1942 {
1943   GError *key_file_error;
1944   gchar **values;
1945   gboolean *bool_values;
1946   gsize i, num_bools;
1947
1948   g_return_val_if_fail (key_file != NULL, NULL);
1949   g_return_val_if_fail (group_name != NULL, NULL);
1950   g_return_val_if_fail (key != NULL, NULL);
1951
1952   if (length)
1953     *length = 0;
1954
1955   key_file_error = NULL;
1956
1957   values = g_key_file_get_string_list (key_file, group_name, key,
1958                                        &num_bools, &key_file_error);
1959
1960   if (key_file_error)
1961     g_propagate_error (error, key_file_error);
1962
1963   if (!values)
1964     return NULL;
1965
1966   bool_values = g_new (gboolean, num_bools);
1967
1968   for (i = 0; i < num_bools; i++)
1969     {
1970       bool_values[i] = g_key_file_parse_value_as_boolean (key_file,
1971                                                           values[i],
1972                                                           &key_file_error);
1973
1974       if (key_file_error)
1975         {
1976           g_propagate_error (error, key_file_error);
1977           g_strfreev (values);
1978           g_free (bool_values);
1979
1980           return NULL;
1981         }
1982     }
1983   g_strfreev (values);
1984
1985   if (length)
1986     *length = num_bools;
1987
1988   return bool_values;
1989 }
1990
1991 /**
1992  * g_key_file_set_boolean_list:
1993  * @key_file: a #GKeyFile
1994  * @group_name: a group name
1995  * @key: a key
1996  * @list: an array of boolean values
1997  * @length: length of @list
1998  *
1999  * Associates a list of boolean values with @key under @group_name.  
2000  * If @key cannot be found then it is created.
2001  * If @group_name is %NULL, the start_group is used.
2002  *
2003  * Since: 2.6
2004  **/
2005 void
2006 g_key_file_set_boolean_list (GKeyFile    *key_file,
2007                              const gchar *group_name,
2008                              const gchar *key,
2009                              gboolean     list[],
2010                              gsize        length)
2011 {
2012   GString *value_list;
2013   gsize i;
2014
2015   g_return_if_fail (key_file != NULL);
2016   g_return_if_fail (list != NULL);
2017
2018   value_list = g_string_sized_new (length * 8);
2019   for (i = 0; i < length; i++)
2020     {
2021       gchar *value;
2022
2023       value = g_key_file_parse_boolean_as_value (key_file, list[i]);
2024
2025       g_string_append (value_list, value);
2026       g_string_append_c (value_list, key_file->list_separator);
2027
2028       g_free (value);
2029     }
2030
2031   g_key_file_set_value (key_file, group_name, key, value_list->str);
2032   g_string_free (value_list, TRUE);
2033 }
2034
2035 /**
2036  * g_key_file_get_integer:
2037  * @key_file: a #GKeyFile
2038  * @group_name: a group name
2039  * @key: a key
2040  * @error: return location for a #GError
2041  *
2042  * Returns the value associated with @key under @group_name as an
2043  * integer. If @group_name is %NULL, the start group is used.
2044  *
2045  * If @key cannot be found then 0 is returned and @error is set to
2046  * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the value associated
2047  * with @key cannot be interpreted as an integer then 0 is returned
2048  * and @error is set to #G_KEY_FILE_ERROR_INVALID_VALUE.
2049  *
2050  * Return value: the value associated with the key as an integer, or
2051  *     0 if the key was not found or could not be parsed.
2052  *
2053  * Since: 2.6
2054  **/
2055 gint
2056 g_key_file_get_integer (GKeyFile     *key_file,
2057                         const gchar  *group_name,
2058                         const gchar  *key,
2059                         GError      **error)
2060 {
2061   GError *key_file_error;
2062   gchar *value;
2063   gint int_value;
2064
2065   g_return_val_if_fail (key_file != NULL, -1);
2066   g_return_val_if_fail (group_name != NULL, -1);
2067   g_return_val_if_fail (key != NULL, -1);
2068
2069   key_file_error = NULL;
2070
2071   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
2072
2073   if (key_file_error)
2074     {
2075       g_propagate_error (error, key_file_error);
2076       return 0;
2077     }
2078
2079   int_value = g_key_file_parse_value_as_integer (key_file, value,
2080                                                  &key_file_error);
2081   g_free (value);
2082
2083   if (key_file_error)
2084     {
2085       if (g_error_matches (key_file_error,
2086                            G_KEY_FILE_ERROR,
2087                            G_KEY_FILE_ERROR_INVALID_VALUE))
2088         {
2089           g_set_error (error, G_KEY_FILE_ERROR,
2090                        G_KEY_FILE_ERROR_INVALID_VALUE,
2091                        _("Key file contains key '%s' in group '%s' "
2092                          "which has value that cannot be interpreted."), key, 
2093                        group_name);
2094           g_error_free (key_file_error);
2095         }
2096       else
2097         g_propagate_error (error, key_file_error);
2098     }
2099
2100   return int_value;
2101 }
2102
2103 /**
2104  * g_key_file_set_integer:
2105  * @key_file: a #GKeyFile
2106  * @group_name: a group name
2107  * @key: a key
2108  * @value: an integer value
2109  *
2110  * Associates a new integer value with @key under @group_name.
2111  * If @key cannot be found then it is created.
2112  *
2113  * Since: 2.6
2114  **/
2115 void
2116 g_key_file_set_integer (GKeyFile    *key_file,
2117                         const gchar *group_name,
2118                         const gchar *key,
2119                         gint         value)
2120 {
2121   gchar *result;
2122
2123   g_return_if_fail (key_file != NULL);
2124
2125   result = g_key_file_parse_integer_as_value (key_file, value);
2126   g_key_file_set_value (key_file, group_name, key, result);
2127   g_free (result);
2128 }
2129
2130 /**
2131  * g_key_file_get_integer_list:
2132  * @key_file: a #GKeyFile
2133  * @group_name: a group name
2134  * @key: a key
2135  * @length: the number of integers returned
2136  * @error: return location for a #GError
2137  *
2138  * Returns the values associated with @key under @group_name as
2139  * integers. 
2140  *
2141  * If @key cannot be found then %NULL is returned and @error is set to
2142  * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the values associated
2143  * with @key cannot be interpreted as integers then %NULL is returned
2144  * and @error is set to #G_KEY_FILE_ERROR_INVALID_VALUE.
2145  *
2146  * Return value: the values associated with the key as a list of
2147  *     integers, or %NULL if the key was not found or could not be parsed.
2148  *
2149  * Since: 2.6
2150  **/
2151 gint *
2152 g_key_file_get_integer_list (GKeyFile     *key_file,
2153                              const gchar  *group_name,
2154                              const gchar  *key,
2155                              gsize        *length,
2156                              GError      **error)
2157 {
2158   GError *key_file_error = NULL;
2159   gchar **values;
2160   gint *int_values;
2161   gsize i, num_ints;
2162
2163   g_return_val_if_fail (key_file != NULL, NULL);
2164   g_return_val_if_fail (group_name != NULL, NULL);
2165   g_return_val_if_fail (key != NULL, NULL);
2166
2167   if (length)
2168     *length = 0;
2169
2170   values = g_key_file_get_string_list (key_file, group_name, key,
2171                                        &num_ints, &key_file_error);
2172
2173   if (key_file_error)
2174     g_propagate_error (error, key_file_error);
2175
2176   if (!values)
2177     return NULL;
2178
2179   int_values = g_new (gint, num_ints);
2180
2181   for (i = 0; i < num_ints; i++)
2182     {
2183       int_values[i] = g_key_file_parse_value_as_integer (key_file,
2184                                                          values[i],
2185                                                          &key_file_error);
2186
2187       if (key_file_error)
2188         {
2189           g_propagate_error (error, key_file_error);
2190           g_strfreev (values);
2191           g_free (int_values);
2192
2193           return NULL;
2194         }
2195     }
2196   g_strfreev (values);
2197
2198   if (length)
2199     *length = num_ints;
2200
2201   return int_values;
2202 }
2203
2204 /**
2205  * g_key_file_set_integer_list:
2206  * @key_file: a #GKeyFile
2207  * @group_name: a group name
2208  * @key: a key
2209  * @list: an array of integer values
2210  * @length: number of integer values in @list
2211  *
2212  * Associates a list of integer values with @key under @group_name.  
2213  * If @key cannot be found then it is created.
2214  *
2215  * Since: 2.6
2216  **/
2217 void
2218 g_key_file_set_integer_list (GKeyFile    *key_file,
2219                              const gchar *group_name,
2220                              const gchar *key,
2221                              gint         list[],
2222                              gsize        length)
2223 {
2224   GString *values;
2225   gsize i;
2226
2227   g_return_if_fail (key_file != NULL);
2228   g_return_if_fail (list != NULL);
2229
2230   values = g_string_sized_new (length * 16);
2231   for (i = 0; i < length; i++)
2232     {
2233       gchar *value;
2234
2235       value = g_key_file_parse_integer_as_value (key_file, list[i]);
2236
2237       g_string_append (values, value);
2238       g_string_append_c (values, ';');
2239
2240       g_free (value);
2241     }
2242
2243   g_key_file_set_value (key_file, group_name, key, values->str);
2244   g_string_free (values, TRUE);
2245 }
2246
2247 /**
2248  * g_key_file_get_double:
2249  * @key_file: a #GKeyFile
2250  * @group_name: a group name
2251  * @key: a key
2252  * @error: return location for a #GError
2253  *
2254  * Returns the value associated with @key under @group_name as a
2255  * double. If @group_name is %NULL, the start_group is used.
2256  *
2257  * If @key cannot be found then 0.0 is returned and @error is set to
2258  * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the value associated
2259  * with @key cannot be interpreted as a double then 0.0 is returned
2260  * and @error is set to #G_KEY_FILE_ERROR_INVALID_VALUE.
2261  *
2262  * Return value: the value associated with the key as a double, or
2263  *     0.0 if the key was not found or could not be parsed.
2264  *
2265  * Since: 2.12
2266  **/
2267 gdouble
2268 g_key_file_get_double  (GKeyFile     *key_file,
2269                         const gchar  *group_name,
2270                         const gchar  *key,
2271                         GError      **error)
2272 {
2273   GError *key_file_error;
2274   gchar *value;
2275   gdouble double_value;
2276
2277   g_return_val_if_fail (key_file != NULL, -1);
2278   g_return_val_if_fail (group_name != NULL, -1);
2279   g_return_val_if_fail (key != NULL, -1);
2280
2281   key_file_error = NULL;
2282
2283   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
2284
2285   if (key_file_error)
2286     {
2287       g_propagate_error (error, key_file_error);
2288       return 0;
2289     }
2290
2291   double_value = g_key_file_parse_value_as_double (key_file, value,
2292                                                   &key_file_error);
2293   g_free (value);
2294
2295   if (key_file_error)
2296     {
2297       if (g_error_matches (key_file_error,
2298                            G_KEY_FILE_ERROR,
2299                            G_KEY_FILE_ERROR_INVALID_VALUE))
2300         {
2301           g_set_error (error, G_KEY_FILE_ERROR,
2302                        G_KEY_FILE_ERROR_INVALID_VALUE,
2303                        _("Key file contains key '%s' in group '%s' "
2304                          "which has value that cannot be interpreted."), key,
2305                        group_name);
2306           g_error_free (key_file_error);
2307         }
2308       else
2309         g_propagate_error (error, key_file_error);
2310     }
2311
2312   return double_value;
2313 }
2314
2315 /**
2316  * g_key_file_set_double:
2317  * @key_file: a #GKeyFile
2318  * @group_name: a group name
2319  * @key: a key
2320  * @value: an double value
2321  *
2322  * Associates a new double value with @key under @group_name.
2323  * If @key cannot be found then it is created. 
2324  * If @group_name is %NULL, the start group is used.
2325  *
2326  * Since: 2.12
2327  **/
2328 void
2329 g_key_file_set_double  (GKeyFile    *key_file,
2330                         const gchar *group_name,
2331                         const gchar *key,
2332                         gdouble      value)
2333 {
2334   gchar result[G_ASCII_DTOSTR_BUF_SIZE];
2335
2336   g_return_if_fail (key_file != NULL);
2337
2338   g_ascii_dtostr (result, sizeof (result), value);
2339   g_key_file_set_value (key_file, group_name, key, result);
2340 }
2341
2342 /**
2343  * g_key_file_get_double_list:
2344  * @key_file: a #GKeyFile
2345  * @group_name: a group name
2346  * @key: a key
2347  * @length: the number of doubles returned
2348  * @error: return location for a #GError
2349  *
2350  * Returns the values associated with @key under @group_name as
2351  * doubles. If @group_name is %NULL, the start group is used.
2352  *
2353  * If @key cannot be found then %NULL is returned and @error is set to
2354  * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the values associated
2355  * with @key cannot be interpreted as doubles then %NULL is returned
2356  * and @error is set to #G_KEY_FILE_ERROR_INVALID_VALUE.
2357  *
2358  * Return value: the values associated with the key as a list of
2359  *     doubles, or %NULL if the key was not found or could not be parsed.
2360  *
2361  * Since: 2.12
2362  **/
2363 gdouble *
2364 g_key_file_get_double_list  (GKeyFile     *key_file,
2365                              const gchar  *group_name,
2366                              const gchar  *key,
2367                              gsize        *length,
2368                              GError      **error)
2369 {
2370   GError *key_file_error = NULL;
2371   gchar **values;
2372   gdouble *double_values;
2373   gsize i, num_doubles;
2374
2375   g_return_val_if_fail (key_file != NULL, NULL);
2376   g_return_val_if_fail (group_name != NULL, NULL);
2377   g_return_val_if_fail (key != NULL, NULL);
2378
2379   if (length)
2380     *length = 0;
2381
2382   values = g_key_file_get_string_list (key_file, group_name, key,
2383                                        &num_doubles, &key_file_error);
2384
2385   if (key_file_error)
2386     g_propagate_error (error, key_file_error);
2387
2388   if (!values)
2389     return NULL;
2390
2391   double_values = g_new (gdouble, num_doubles);
2392
2393   for (i = 0; i < num_doubles; i++)
2394     {
2395       double_values[i] = g_key_file_parse_value_as_double (key_file,
2396                                                            values[i],
2397                                                            &key_file_error);
2398
2399       if (key_file_error)
2400         {
2401           g_propagate_error (error, key_file_error);
2402           g_strfreev (values);
2403           g_free (double_values);
2404
2405           return NULL;
2406         }
2407     }
2408   g_strfreev (values);
2409
2410   if (length)
2411     *length = num_doubles;
2412
2413   return double_values;
2414 }
2415
2416 /**
2417  * g_key_file_set_double_list:
2418  * @key_file: a #GKeyFile
2419  * @group_name: a group name
2420  * @key: a key
2421  * @list: an array of double values
2422  * @length: number of double values in @list
2423  *
2424  * Associates a list of double values with @key under
2425  * @group_name.  If @key cannot be found then it is created.
2426  * If @group_name is %NULL the start group is used.
2427  *
2428  * Since: 2.12
2429  **/
2430 void
2431 g_key_file_set_double_list (GKeyFile    *key_file,
2432                             const gchar *group_name,
2433                             const gchar *key,
2434                             gdouble      list[],
2435                             gsize        length)
2436 {
2437   GString *values;
2438   gsize i;
2439
2440   g_return_if_fail (key_file != NULL);
2441   g_return_if_fail (list != NULL);
2442
2443   values = g_string_sized_new (length * 16);
2444   for (i = 0; i < length; i++)
2445     {
2446       gchar result[G_ASCII_DTOSTR_BUF_SIZE];
2447
2448       g_ascii_dtostr( result, sizeof (result), list[i] );
2449
2450       g_string_append (values, result);
2451       g_string_append_c (values, ';');
2452     }
2453
2454   g_key_file_set_value (key_file, group_name, key, values->str);
2455   g_string_free (values, TRUE);
2456 }
2457
2458 static gboolean
2459 g_key_file_set_key_comment (GKeyFile     *key_file,
2460                             const gchar  *group_name,
2461                             const gchar  *key,
2462                             const gchar  *comment,
2463                             GError      **error)
2464 {
2465   GKeyFileGroup *group;
2466   GKeyFileKeyValuePair *pair;
2467   GList *key_node, *comment_node, *tmp;
2468   
2469   group = g_key_file_lookup_group (key_file, group_name);
2470   if (!group)
2471     {
2472       g_set_error (error, G_KEY_FILE_ERROR,
2473                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
2474                    _("Key file does not have group '%s'"),
2475                    group_name ? group_name : "(null)");
2476
2477       return FALSE;
2478     }
2479
2480   /* First find the key the comments are supposed to be
2481    * associated with
2482    */
2483   key_node = g_key_file_lookup_key_value_pair_node (key_file, group, key);
2484
2485   if (key_node == NULL)
2486     {
2487       g_set_error (error, G_KEY_FILE_ERROR,
2488                    G_KEY_FILE_ERROR_KEY_NOT_FOUND,
2489                    _("Key file does not have key '%s' in group '%s'"),
2490                    key, group->name);
2491       return FALSE;
2492     }
2493
2494   /* Then find all the comments already associated with the
2495    * key and free them
2496    */
2497   tmp = key_node->next;
2498   while (tmp != NULL)
2499     {
2500       GKeyFileKeyValuePair *pair;
2501
2502       pair = (GKeyFileKeyValuePair *) tmp->data;
2503
2504       if (pair->key != NULL)
2505         break;
2506
2507       comment_node = tmp;
2508       tmp = tmp->next;
2509       g_key_file_remove_key_value_pair_node (key_file, group,
2510                                              comment_node); 
2511     }
2512
2513   if (comment == NULL)
2514     return TRUE;
2515
2516   /* Now we can add our new comment
2517    */
2518   pair = g_slice_new (GKeyFileKeyValuePair);
2519   pair->key = NULL;
2520   pair->value = g_key_file_parse_comment_as_value (key_file, comment);
2521   
2522   key_node = g_list_insert (key_node, pair, 1);
2523
2524   return TRUE;
2525 }
2526
2527 static gboolean
2528 g_key_file_set_group_comment (GKeyFile     *key_file,
2529                               const gchar  *group_name,
2530                               const gchar  *comment,
2531                               GError      **error)
2532 {
2533   GKeyFileGroup *group;
2534   
2535   g_return_val_if_fail (g_key_file_is_group_name (group_name), FALSE);
2536
2537   group = g_key_file_lookup_group (key_file, group_name);
2538   if (!group)
2539     {
2540       g_set_error (error, G_KEY_FILE_ERROR,
2541                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
2542                    _("Key file does not have group '%s'"),
2543                    group_name ? group_name : "(null)");
2544
2545       return FALSE;
2546     }
2547
2548   /* First remove any existing comment
2549    */
2550   if (group->comment)
2551     {
2552       g_key_file_key_value_pair_free (group->comment);
2553       group->comment = NULL;
2554     }
2555
2556   if (comment == NULL)
2557     return TRUE;
2558
2559   /* Now we can add our new comment
2560    */
2561   group->comment = g_slice_new (GKeyFileKeyValuePair);
2562   group->comment->key = NULL;
2563   group->comment->value = g_key_file_parse_comment_as_value (key_file, comment);
2564
2565   return TRUE;
2566 }
2567
2568 static gboolean
2569 g_key_file_set_top_comment (GKeyFile     *key_file,
2570                             const gchar  *comment,
2571                             GError      **error)
2572 {
2573   GList *group_node;
2574   GKeyFileGroup *group;
2575   GKeyFileKeyValuePair *pair;
2576
2577   /* The last group in the list should be the top (comments only)
2578    * group in the file
2579    */
2580   g_assert (key_file->groups != NULL);
2581   group_node = g_list_last (key_file->groups);
2582   group = (GKeyFileGroup *) group_node->data;
2583   g_assert (group->name == NULL);
2584
2585   /* Note all keys must be comments at the top of
2586    * the file, so we can just free it all.
2587    */
2588   if (group->key_value_pairs != NULL)
2589     {
2590       g_list_foreach (group->key_value_pairs, 
2591                       (GFunc) g_key_file_key_value_pair_free, 
2592                       NULL);
2593       g_list_free (group->key_value_pairs);
2594       group->key_value_pairs = NULL;
2595     }
2596
2597   if (comment == NULL)
2598      return TRUE;
2599
2600   pair = g_slice_new (GKeyFileKeyValuePair);
2601   pair->key = NULL;
2602   pair->value = g_key_file_parse_comment_as_value (key_file, comment);
2603   
2604   group->key_value_pairs =
2605     g_list_prepend (group->key_value_pairs, pair);
2606
2607   return TRUE;
2608 }
2609
2610 /**
2611  * g_key_file_set_comment:
2612  * @key_file: a #GKeyFile
2613  * @group_name: a group name, or %NULL
2614  * @key: a key
2615  * @comment: a comment
2616  * @error: return location for a #GError
2617  *
2618  * Places a comment above @key from @group_name.
2619  * If @key is %NULL then @comment will be written above @group_name.  
2620  * If both @key and @group_name  are %NULL, then @comment will be 
2621  * written above the first group in the file.
2622  *
2623  * Returns: %TRUE if the comment was written, %FALSE otherwise
2624  *
2625  * Since: 2.6
2626  **/
2627 gboolean
2628 g_key_file_set_comment (GKeyFile     *key_file,
2629                         const gchar  *group_name,
2630                         const gchar  *key,
2631                         const gchar  *comment,
2632                         GError      **error)
2633 {
2634   g_return_val_if_fail (key_file != NULL, FALSE);
2635
2636   if (group_name != NULL && key != NULL) 
2637     {
2638       if (!g_key_file_set_key_comment (key_file, group_name, key, comment, error))
2639         return FALSE;
2640     } 
2641   else if (group_name != NULL) 
2642     {
2643       if (!g_key_file_set_group_comment (key_file, group_name, comment, error))
2644         return FALSE;
2645     } 
2646   else 
2647     {
2648       if (!g_key_file_set_top_comment (key_file, comment, error))
2649         return FALSE;
2650     }
2651
2652   if (comment != NULL)
2653     key_file->approximate_size += strlen (comment);
2654
2655   return TRUE;
2656 }
2657
2658 static gchar *
2659 g_key_file_get_key_comment (GKeyFile     *key_file,
2660                             const gchar  *group_name,
2661                             const gchar  *key,
2662                             GError      **error)
2663 {
2664   GKeyFileGroup *group;
2665   GKeyFileKeyValuePair *pair;
2666   GList *key_node, *tmp;
2667   GString *string;
2668   gchar *comment;
2669
2670   g_return_val_if_fail (g_key_file_is_group_name (group_name), NULL);
2671
2672   group = g_key_file_lookup_group (key_file, group_name);
2673   if (!group)
2674     {
2675       g_set_error (error, G_KEY_FILE_ERROR,
2676                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
2677                    _("Key file does not have group '%s'"),
2678                    group_name ? group_name : "(null)");
2679
2680       return NULL;
2681     }
2682
2683   /* First find the key the comments are supposed to be
2684    * associated with
2685    */
2686   key_node = g_key_file_lookup_key_value_pair_node (key_file, group, key);
2687
2688   if (key_node == NULL)
2689     {
2690       g_set_error (error, G_KEY_FILE_ERROR,
2691                    G_KEY_FILE_ERROR_KEY_NOT_FOUND,
2692                    _("Key file does not have key '%s' in group '%s'"),
2693                    key, group->name);
2694       return NULL;
2695     }
2696
2697   string = NULL;
2698
2699   /* Then find all the comments already associated with the
2700    * key and concatentate them.
2701    */
2702   tmp = key_node->next;
2703   if (!key_node->next)
2704     return NULL;
2705
2706   pair = (GKeyFileKeyValuePair *) tmp->data;
2707   if (pair->key != NULL)
2708     return NULL;
2709
2710   while (tmp->next)
2711     {
2712       pair = (GKeyFileKeyValuePair *) tmp->next->data;
2713       
2714       if (pair->key != NULL)
2715         break;
2716
2717       tmp = tmp->next;
2718     }
2719
2720   while (tmp != key_node)
2721     {
2722       GKeyFileKeyValuePair *pair;
2723       
2724       pair = (GKeyFileKeyValuePair *) tmp->data;
2725       
2726       if (string == NULL)
2727         string = g_string_sized_new (512);
2728       
2729       comment = g_key_file_parse_value_as_comment (key_file, pair->value);
2730       g_string_append (string, comment);
2731       g_free (comment);
2732       
2733       tmp = tmp->prev;
2734     }
2735
2736   if (string != NULL)
2737     {
2738       comment = string->str;
2739       g_string_free (string, FALSE);
2740     }
2741   else
2742     comment = NULL;
2743
2744   return comment;
2745 }
2746
2747 static gchar *
2748 get_group_comment (GKeyFile       *key_file,
2749                    GKeyFileGroup  *group,
2750                    GError        **error)
2751 {
2752   GString *string;
2753   GList *tmp;
2754   gchar *comment;
2755
2756   string = NULL;
2757
2758   tmp = group->key_value_pairs;
2759   while (tmp)
2760     {
2761       GKeyFileKeyValuePair *pair;
2762
2763       pair = (GKeyFileKeyValuePair *) tmp->data;
2764
2765       if (pair->key != NULL)
2766         {
2767           tmp = tmp->prev;
2768           break;
2769         }
2770
2771       if (tmp->next == NULL)
2772         break;
2773
2774       tmp = tmp->next;
2775     }
2776   
2777   while (tmp != NULL)
2778     {
2779       GKeyFileKeyValuePair *pair;
2780
2781       pair = (GKeyFileKeyValuePair *) tmp->data;
2782
2783       if (string == NULL)
2784         string = g_string_sized_new (512);
2785
2786       comment = g_key_file_parse_value_as_comment (key_file, pair->value);
2787       g_string_append (string, comment);
2788       g_free (comment);
2789
2790       tmp = tmp->prev;
2791     }
2792
2793   if (string != NULL)
2794     return g_string_free (string, FALSE);
2795
2796   return NULL;
2797 }
2798
2799 static gchar *
2800 g_key_file_get_group_comment (GKeyFile     *key_file,
2801                               const gchar  *group_name,
2802                               GError      **error)
2803 {
2804   GList *group_node;
2805   GKeyFileGroup *group;
2806   
2807   group = g_key_file_lookup_group (key_file, group_name);
2808   if (!group)
2809     {
2810       g_set_error (error, G_KEY_FILE_ERROR,
2811                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
2812                    _("Key file does not have group '%s'"),
2813                    group_name ? group_name : "(null)");
2814
2815       return NULL;
2816     }
2817
2818   if (group->comment)
2819     return g_strdup (group->comment->value);
2820   
2821   group_node = g_key_file_lookup_group_node (key_file, group_name);
2822   group_node = group_node->next;
2823   group = (GKeyFileGroup *)group_node->data;  
2824   return get_group_comment (key_file, group, error);
2825 }
2826
2827 static gchar *
2828 g_key_file_get_top_comment (GKeyFile  *key_file,
2829                             GError   **error)
2830 {
2831   GList *group_node;
2832   GKeyFileGroup *group;
2833
2834   /* The last group in the list should be the top (comments only)
2835    * group in the file
2836    */
2837   g_assert (key_file->groups != NULL);
2838   group_node = g_list_last (key_file->groups);
2839   group = (GKeyFileGroup *) group_node->data;
2840   g_assert (group->name == NULL);
2841
2842   return get_group_comment (key_file, group, error);
2843 }
2844
2845 /**
2846  * g_key_file_get_comment:
2847  * @key_file: a #GKeyFile
2848  * @group_name: a group name, or %NULL
2849  * @key: a key
2850  * @error: return location for a #GError
2851  *
2852  * Retrieves a comment above @key from @group_name.
2853  * If @key is %NULL then @comment will be read from above 
2854  * @group_name. If both @key and @group_name are %NULL, then 
2855  * @comment will be read from above the first group in the file.
2856  *
2857  * Returns: a comment that should be freed with g_free()
2858  *
2859  * Since: 2.6
2860  **/
2861 gchar * 
2862 g_key_file_get_comment (GKeyFile     *key_file,
2863                         const gchar  *group_name,
2864                         const gchar  *key,
2865                         GError      **error)
2866 {
2867   g_return_val_if_fail (key_file != NULL, NULL);
2868
2869   if (group_name != NULL && key != NULL)
2870     return g_key_file_get_key_comment (key_file, group_name, key, error);
2871   else if (group_name != NULL)
2872     return g_key_file_get_group_comment (key_file, group_name, error);
2873   else
2874     return g_key_file_get_top_comment (key_file, error);
2875 }
2876
2877 /**
2878  * g_key_file_remove_comment:
2879  * @key_file: a #GKeyFile
2880  * @group_name: a group name, or %NULL
2881  * @key: a key
2882  * @error: return location for a #GError
2883  *
2884  * Removes a comment above @key from @group_name.
2885  * If @key is %NULL then @comment will be removed above @group_name. 
2886  * If both @key and @group_name are %NULL, then @comment will
2887  * be removed above the first group in the file.
2888  *
2889  * Returns: %TRUE if the comment was removed, %FALSE otherwise
2890  *
2891  * Since: 2.6
2892  **/
2893
2894 gboolean
2895 g_key_file_remove_comment (GKeyFile     *key_file,
2896                            const gchar  *group_name,
2897                            const gchar  *key,
2898                            GError      **error)
2899 {
2900   g_return_val_if_fail (key_file != NULL, FALSE);
2901
2902   if (group_name != NULL && key != NULL)
2903     return g_key_file_set_key_comment (key_file, group_name, key, NULL, error);
2904   else if (group_name != NULL)
2905     return g_key_file_set_group_comment (key_file, group_name, NULL, error);
2906   else
2907     return g_key_file_set_top_comment (key_file, NULL, error);
2908 }
2909
2910 /**
2911  * g_key_file_has_group:
2912  * @key_file: a #GKeyFile
2913  * @group_name: a group name
2914  *
2915  * Looks whether the key file has the group @group_name.
2916  *
2917  * Return value: %TRUE if @group_name is a part of @key_file, %FALSE
2918  * otherwise.
2919  * Since: 2.6
2920  **/
2921 gboolean
2922 g_key_file_has_group (GKeyFile    *key_file,
2923                       const gchar *group_name)
2924 {
2925   g_return_val_if_fail (key_file != NULL, FALSE);
2926   g_return_val_if_fail (group_name != NULL, FALSE);
2927
2928   return g_key_file_lookup_group (key_file, group_name) != NULL;
2929 }
2930
2931 /**
2932  * g_key_file_has_key:
2933  * @key_file: a #GKeyFile
2934  * @group_name: a group name
2935  * @key: a key name
2936  * @error: return location for a #GError
2937  *
2938  * Looks whether the key file has the key @key in the group
2939  * @group_name. 
2940  *
2941  * Return value: %TRUE if @key is a part of @group_name, %FALSE
2942  * otherwise.
2943  *
2944  * Since: 2.6
2945  **/
2946 gboolean
2947 g_key_file_has_key (GKeyFile     *key_file,
2948                     const gchar  *group_name,
2949                     const gchar  *key,
2950                     GError      **error)
2951 {
2952   GKeyFileKeyValuePair *pair;
2953   GKeyFileGroup *group;
2954
2955   g_return_val_if_fail (key_file != NULL, FALSE);
2956   g_return_val_if_fail (group_name != NULL, FALSE);
2957   g_return_val_if_fail (key != NULL, FALSE);
2958
2959   group = g_key_file_lookup_group (key_file, group_name);
2960
2961   if (!group)
2962     {
2963       g_set_error (error, G_KEY_FILE_ERROR,
2964                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
2965                    _("Key file does not have group '%s'"),
2966                    group_name ? group_name : "(null)");
2967
2968       return FALSE;
2969     }
2970
2971   pair = g_key_file_lookup_key_value_pair (key_file, group, key);
2972
2973   return pair != NULL;
2974 }
2975
2976 static void
2977 g_key_file_add_group (GKeyFile    *key_file,
2978                       const gchar *group_name)
2979 {
2980   GKeyFileGroup *group;
2981
2982   g_return_if_fail (key_file != NULL);
2983   g_return_if_fail (g_key_file_is_group_name (group_name));
2984
2985   group = g_key_file_lookup_group (key_file, group_name);
2986   if (group != NULL)
2987     {
2988       key_file->current_group = group;
2989       return;
2990     }
2991
2992   group = g_slice_new0 (GKeyFileGroup);
2993   group->name = g_strdup (group_name);
2994   group->lookup_map = g_hash_table_new (g_str_hash, g_str_equal);
2995   key_file->groups = g_list_prepend (key_file->groups, group);
2996   key_file->approximate_size += strlen (group_name) + 3;
2997   key_file->current_group = group;
2998
2999   if (key_file->start_group == NULL)
3000     key_file->start_group = group;
3001
3002   g_hash_table_insert (key_file->group_hash, group->name, group);
3003 }
3004
3005 static void
3006 g_key_file_key_value_pair_free (GKeyFileKeyValuePair *pair)
3007 {
3008   if (pair != NULL)
3009     {
3010       g_free (pair->key);
3011       g_free (pair->value);
3012       g_slice_free (GKeyFileKeyValuePair, pair);
3013     }
3014 }
3015
3016 /* Be careful not to call this function on a node with data in the
3017  * lookup map without removing it from the lookup map, first.
3018  *
3019  * Some current cases where this warning is not a concern are
3020  * when:
3021  *   - the node being removed is a comment node
3022  *   - the entire lookup map is getting destroyed soon after
3023  *     anyway.
3024  */ 
3025 static void
3026 g_key_file_remove_key_value_pair_node (GKeyFile      *key_file,
3027                                        GKeyFileGroup *group,
3028                                        GList         *pair_node)
3029 {
3030
3031   GKeyFileKeyValuePair *pair;
3032
3033   pair = (GKeyFileKeyValuePair *) pair_node->data;
3034
3035   group->key_value_pairs = g_list_remove_link (group->key_value_pairs, pair_node);
3036
3037   if (pair->key != NULL)
3038     key_file->approximate_size -= strlen (pair->key) + 1;
3039
3040   g_assert (pair->value != NULL);
3041   key_file->approximate_size -= strlen (pair->value);
3042
3043   g_key_file_key_value_pair_free (pair);
3044
3045   g_list_free_1 (pair_node);
3046 }
3047
3048 static void
3049 g_key_file_remove_group_node (GKeyFile *key_file,
3050                               GList    *group_node)
3051 {
3052   GKeyFileGroup *group;
3053   GList *tmp;
3054
3055   group = (GKeyFileGroup *) group_node->data;
3056
3057   if (group->name)
3058     g_hash_table_remove (key_file->group_hash, group->name);
3059
3060   /* If the current group gets deleted make the current group the last
3061    * added group.
3062    */
3063   if (key_file->current_group == group)
3064     {
3065       /* groups should always contain at least the top comment group,
3066        * unless g_key_file_clear has been called
3067        */
3068       if (key_file->groups)
3069         key_file->current_group = (GKeyFileGroup *) key_file->groups->data;
3070       else
3071         key_file->current_group = NULL;
3072     }
3073
3074   /* If the start group gets deleted make the start group the first
3075    * added group.
3076    */
3077   if (key_file->start_group == group)
3078     {
3079       tmp = g_list_last (key_file->groups);
3080       while (tmp != NULL)
3081         {
3082           if (tmp != group_node &&
3083               ((GKeyFileGroup *) tmp->data)->name != NULL)
3084             break;
3085
3086           tmp = tmp->prev;
3087         }
3088
3089       if (tmp)
3090         key_file->start_group = (GKeyFileGroup *) tmp->data;
3091       else
3092         key_file->start_group = NULL;
3093     }
3094
3095   key_file->groups = g_list_remove_link (key_file->groups, group_node);
3096
3097   if (group->name != NULL)
3098     key_file->approximate_size -= strlen (group->name) + 3;
3099
3100   tmp = group->key_value_pairs;
3101   while (tmp != NULL)
3102     {
3103       GList *pair_node;
3104
3105       pair_node = tmp;
3106       tmp = tmp->next;
3107       g_key_file_remove_key_value_pair_node (key_file, group, pair_node);
3108     }
3109
3110   g_assert (group->key_value_pairs == NULL);
3111
3112   if (group->lookup_map)
3113     {
3114       g_hash_table_destroy (group->lookup_map);
3115       group->lookup_map = NULL;
3116     }
3117
3118   g_free ((gchar *) group->name);
3119   g_slice_free (GKeyFileGroup, group);
3120   g_list_free_1 (group_node);
3121 }
3122
3123 /**
3124  * g_key_file_remove_group:
3125  * @key_file: a #GKeyFile
3126  * @group_name: a group name
3127  * @error: return location for a #GError or %NULL
3128  *
3129  * Removes the specified group, @group_name, 
3130  * from the key file. 
3131  *
3132  * Returns: %TRUE if the group was removed, %FALSE otherwise
3133  *
3134  * Since: 2.6
3135  **/
3136 gboolean
3137 g_key_file_remove_group (GKeyFile     *key_file,
3138                          const gchar  *group_name,
3139                          GError      **error)
3140 {
3141   GList *group_node;
3142
3143   g_return_val_if_fail (key_file != NULL, FALSE);
3144   g_return_val_if_fail (group_name != NULL, FALSE);
3145
3146   group_node = g_key_file_lookup_group_node (key_file, group_name);
3147
3148   if (!group_node)
3149     {
3150       g_set_error (error, G_KEY_FILE_ERROR,
3151                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
3152                    _("Key file does not have group '%s'"),
3153                    group_name);
3154       return FALSE;
3155     }
3156
3157   g_key_file_remove_group_node (key_file, group_node);
3158
3159   return TRUE;  
3160 }
3161
3162 static void
3163 g_key_file_add_key (GKeyFile      *key_file,
3164                     GKeyFileGroup *group,
3165                     const gchar   *key,
3166                     const gchar   *value)
3167 {
3168   GKeyFileKeyValuePair *pair;
3169
3170   pair = g_slice_new (GKeyFileKeyValuePair);
3171   pair->key = g_strdup (key);
3172   pair->value = g_strdup (value);
3173
3174   g_hash_table_replace (group->lookup_map, pair->key, pair);
3175   group->key_value_pairs = g_list_prepend (group->key_value_pairs, pair);
3176   group->has_trailing_blank_line = FALSE;
3177   key_file->approximate_size += strlen (key) + strlen (value) + 2;
3178 }
3179
3180 /**
3181  * g_key_file_remove_key:
3182  * @key_file: a #GKeyFile
3183  * @group_name: a group name
3184  * @key: a key name to remove
3185  * @error: return location for a #GError or %NULL
3186  *
3187  * Removes @key in @group_name from the key file. 
3188  *
3189  * Returns: %TRUE if the key was removed, %FALSE otherwise
3190  *
3191  * Since: 2.6
3192  **/
3193 gboolean
3194 g_key_file_remove_key (GKeyFile     *key_file,
3195                        const gchar  *group_name,
3196                        const gchar  *key,
3197                        GError      **error)
3198 {
3199   GKeyFileGroup *group;
3200   GKeyFileKeyValuePair *pair;
3201
3202   g_return_val_if_fail (key_file != NULL, FALSE);
3203   g_return_val_if_fail (group_name != NULL, FALSE);
3204   g_return_val_if_fail (key != NULL, FALSE);
3205
3206   pair = NULL;
3207
3208   group = g_key_file_lookup_group (key_file, group_name);
3209   if (!group)
3210     {
3211       g_set_error (error, G_KEY_FILE_ERROR,
3212                    G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
3213                    _("Key file does not have group '%s'"),
3214                    group_name ? group_name : "(null)");
3215       return FALSE;
3216     }
3217
3218   pair = g_key_file_lookup_key_value_pair (key_file, group, key);
3219
3220   if (!pair)
3221     {
3222       g_set_error (error, G_KEY_FILE_ERROR,
3223                    G_KEY_FILE_ERROR_KEY_NOT_FOUND,
3224                    _("Key file does not have key '%s' in group '%s'"),
3225                    key, group->name);
3226       return FALSE;
3227     }
3228
3229   key_file->approximate_size -= strlen (pair->key) + strlen (pair->value) + 2;
3230
3231   group->key_value_pairs = g_list_remove (group->key_value_pairs, pair);
3232   g_hash_table_remove (group->lookup_map, pair->key);  
3233   g_key_file_key_value_pair_free (pair);
3234
3235   return TRUE;
3236 }
3237
3238 static GList *
3239 g_key_file_lookup_group_node (GKeyFile    *key_file,
3240                               const gchar *group_name)
3241 {
3242   GKeyFileGroup *group;
3243   GList *tmp;
3244
3245   for (tmp = key_file->groups; tmp != NULL; tmp = tmp->next)
3246     {
3247       group = (GKeyFileGroup *) tmp->data;
3248
3249       if (group && group->name && strcmp (group->name, group_name) == 0)
3250         break;
3251     }
3252
3253   return tmp;
3254 }
3255
3256 static GKeyFileGroup *
3257 g_key_file_lookup_group (GKeyFile    *key_file,
3258                          const gchar *group_name)
3259 {
3260   return (GKeyFileGroup *)g_hash_table_lookup (key_file->group_hash, group_name);
3261 }
3262
3263 static GList *
3264 g_key_file_lookup_key_value_pair_node (GKeyFile       *key_file,
3265                                        GKeyFileGroup  *group,
3266                                        const gchar    *key)
3267 {
3268   GList *key_node;
3269
3270   for (key_node = group->key_value_pairs;
3271        key_node != NULL;
3272        key_node = key_node->next)
3273     {
3274       GKeyFileKeyValuePair *pair;
3275
3276       pair = (GKeyFileKeyValuePair *) key_node->data; 
3277
3278       if (pair->key && strcmp (pair->key, key) == 0)
3279         break;
3280     }
3281
3282   return key_node;
3283 }
3284
3285 static GKeyFileKeyValuePair *
3286 g_key_file_lookup_key_value_pair (GKeyFile      *key_file,
3287                                   GKeyFileGroup *group,
3288                                   const gchar   *key)
3289 {
3290   return (GKeyFileKeyValuePair *) g_hash_table_lookup (group->lookup_map, key);
3291 }
3292
3293 /* Lines starting with # or consisting entirely of whitespace are merely
3294  * recorded, not parsed. This function assumes all leading whitespace
3295  * has been stripped.
3296  */
3297 static gboolean
3298 g_key_file_line_is_comment (const gchar *line)
3299 {
3300   return (*line == '#' || *line == '\0' || *line == '\n');
3301 }
3302
3303 static gboolean 
3304 g_key_file_is_group_name (const gchar *name)
3305 {
3306   gchar *p, *q;
3307
3308   if (name == NULL)
3309     return FALSE;
3310
3311   p = q = (gchar *) name;
3312   while (*q && *q != ']' && *q != '[' && !g_ascii_iscntrl (*q))
3313     q = g_utf8_find_next_char (q, NULL);
3314   
3315   if (*q != '\0' || q == p)
3316     return FALSE;
3317
3318   return TRUE;
3319 }
3320
3321 static gboolean
3322 g_key_file_is_key_name (const gchar *name)
3323 {
3324   gchar *p, *q;
3325
3326   if (name == NULL)
3327     return FALSE;
3328
3329   p = q = (gchar *) name;
3330   /* We accept a little more than the desktop entry spec says,
3331    * since gnome-vfs uses mime-types as keys in its cache.
3332    */
3333   while (*q && *q != '=' && *q != '[' && *q != ']')
3334     q = g_utf8_find_next_char (q, NULL);
3335   
3336   /* No empty keys, please */
3337   if (q == p)
3338     return FALSE;
3339
3340   /* We accept spaces in the middle of keys to not break
3341    * existing apps, but we don't tolerate initial or final
3342    * spaces, which would lead to silent corruption when
3343    * rereading the file.
3344    */
3345   if (*p == ' ' || q[-1] == ' ')
3346     return FALSE;
3347
3348   if (*q == '[')
3349     {
3350       q++;
3351       while (*q && (g_unichar_isalnum (g_utf8_get_char_validated (q, -1)) || *q == '-' || *q == '_' || *q == '.' || *q == '@'))
3352         q = g_utf8_find_next_char (q, NULL);
3353
3354       if (*q != ']')
3355         return FALSE;     
3356
3357       q++;
3358     }
3359
3360   if (*q != '\0')
3361     return FALSE;
3362
3363   return TRUE;
3364 }
3365
3366 /* A group in a key file is made up of a starting '[' followed by one
3367  * or more letters making up the group name followed by ']'.
3368  */
3369 static gboolean
3370 g_key_file_line_is_group (const gchar *line)
3371 {
3372   gchar *p;
3373
3374   p = (gchar *) line;
3375   if (*p != '[')
3376     return FALSE;
3377
3378   p++;
3379
3380   while (*p && *p != ']')
3381     p = g_utf8_find_next_char (p, NULL);
3382
3383   if (*p != ']')
3384     return FALSE;
3385  
3386   /* silently accept whitespace after the ] */
3387   p = g_utf8_find_next_char (p, NULL);
3388   while (*p == ' ' || *p == '\t')
3389     p = g_utf8_find_next_char (p, NULL);
3390      
3391   if (*p)
3392     return FALSE;
3393
3394   return TRUE;
3395 }
3396
3397 static gboolean
3398 g_key_file_line_is_key_value_pair (const gchar *line)
3399 {
3400   gchar *p;
3401
3402   p = (gchar *) g_utf8_strchr (line, -1, '=');
3403
3404   if (!p)
3405     return FALSE;
3406
3407   /* Key must be non-empty
3408    */
3409   if (*p == line[0])
3410     return FALSE;
3411
3412   return TRUE;
3413 }
3414
3415 static gchar *
3416 g_key_file_parse_value_as_string (GKeyFile     *key_file,
3417                                   const gchar  *value,
3418                                   GSList      **pieces,
3419                                   GError      **error)
3420 {
3421   gchar *string_value, *p, *q0, *q;
3422
3423   string_value = g_new (gchar, strlen (value) + 1);
3424
3425   p = (gchar *) value;
3426   q0 = q = string_value;
3427   while (*p)
3428     {
3429       if (*p == '\\')
3430         {
3431           p++;
3432
3433           switch (*p)
3434             {
3435             case 's':
3436               *q = ' ';
3437               break;
3438
3439             case 'n':
3440               *q = '\n';
3441               break;
3442
3443             case 't':
3444               *q = '\t';
3445               break;
3446
3447             case 'r':
3448               *q = '\r';
3449               break;
3450
3451             case '\\':
3452               *q = '\\';
3453               break;
3454
3455             case '\0':
3456               g_set_error (error, G_KEY_FILE_ERROR,
3457                            G_KEY_FILE_ERROR_INVALID_VALUE,
3458                            _("Key file contains escape character "
3459                              "at end of line"));
3460               break;
3461
3462             default:
3463               if (pieces && *p == key_file->list_separator)
3464                 *q = key_file->list_separator;
3465               else
3466                 {
3467                   *q++ = '\\';
3468                   *q = *p;
3469                   
3470                   if (*error == NULL)
3471                     {
3472                       gchar sequence[3];
3473                       
3474                       sequence[0] = '\\';
3475                       sequence[1] = *p;
3476                       sequence[2] = '\0';
3477                       
3478                       g_set_error (error, G_KEY_FILE_ERROR,
3479                                    G_KEY_FILE_ERROR_INVALID_VALUE,
3480                                    _("Key file contains invalid escape "
3481                                      "sequence '%s'"), sequence);
3482                     }
3483                 }
3484               break;
3485             }
3486         }
3487       else
3488         {
3489           *q = *p;
3490           if (pieces && (*p == key_file->list_separator))
3491             {
3492               *pieces = g_slist_prepend (*pieces, g_strndup (q0, q - q0));
3493               q0 = q + 1; 
3494             }
3495         }
3496
3497       if (*p == '\0')
3498         break;
3499
3500       q++;
3501       p++;
3502     }
3503
3504   *q = '\0';
3505   if (pieces)
3506   {
3507     if (q0 < q)
3508       *pieces = g_slist_prepend (*pieces, g_strndup (q0, q - q0));
3509     *pieces = g_slist_reverse (*pieces);
3510   }
3511
3512   return string_value;
3513 }
3514
3515 static gchar *
3516 g_key_file_parse_string_as_value (GKeyFile    *key_file,
3517                                   const gchar *string,
3518                                   gboolean     escape_separator)
3519 {
3520   gchar *value, *p, *q;
3521   gsize length;
3522   gboolean parsing_leading_space;
3523
3524   length = strlen (string) + 1;
3525
3526   /* Worst case would be that every character needs to be escaped.
3527    * In other words every character turns to two characters
3528    */
3529   value = g_new (gchar, 2 * length);
3530
3531   p = (gchar *) string;
3532   q = value;
3533   parsing_leading_space = TRUE;
3534   while (p < (string + length - 1))
3535     {
3536       gchar escaped_character[3] = { '\\', 0, 0 };
3537
3538       switch (*p)
3539         {
3540         case ' ':
3541           if (parsing_leading_space)
3542             {
3543               escaped_character[1] = 's';
3544               strcpy (q, escaped_character);
3545               q += 2;
3546             }
3547           else
3548             {
3549               *q = *p;
3550               q++;
3551             }
3552           break;
3553         case '\t':
3554           if (parsing_leading_space)
3555             {
3556               escaped_character[1] = 't';
3557               strcpy (q, escaped_character);
3558               q += 2;
3559             }
3560           else
3561             {
3562               *q = *p;
3563               q++;
3564             }
3565           break;
3566         case '\n':
3567           escaped_character[1] = 'n';
3568           strcpy (q, escaped_character);
3569           q += 2;
3570           break;
3571         case '\r':
3572           escaped_character[1] = 'r';
3573           strcpy (q, escaped_character);
3574           q += 2;
3575           break;
3576         case '\\':
3577           escaped_character[1] = '\\';
3578           strcpy (q, escaped_character);
3579           q += 2;
3580           parsing_leading_space = FALSE;
3581           break;
3582         default:
3583           if (escape_separator && *p == key_file->list_separator)
3584             {
3585               escaped_character[1] = key_file->list_separator;
3586               strcpy (q, escaped_character);
3587               q += 2;
3588               parsing_leading_space = TRUE;
3589             }
3590           else 
3591             {
3592               *q = *p;
3593               q++;
3594               parsing_leading_space = FALSE;
3595             }
3596           break;
3597         }
3598       p++;
3599     }
3600   *q = '\0';
3601
3602   return value;
3603 }
3604
3605 static gint
3606 g_key_file_parse_value_as_integer (GKeyFile     *key_file,
3607                                    const gchar  *value,
3608                                    GError      **error)
3609 {
3610   gchar *end_of_valid_int;
3611  glong long_value;
3612   gint int_value;
3613
3614   errno = 0;
3615   long_value = strtol (value, &end_of_valid_int, 10);
3616
3617   if (*value == '\0' || *end_of_valid_int != '\0')
3618     {
3619       gchar *value_utf8 = _g_utf8_make_valid (value);
3620       g_set_error (error, G_KEY_FILE_ERROR,
3621                    G_KEY_FILE_ERROR_INVALID_VALUE,
3622                    _("Value '%s' cannot be interpreted "
3623                      "as a number."), value_utf8);
3624       g_free (value_utf8);
3625
3626       return 0;
3627     }
3628
3629   int_value = long_value;
3630   if (int_value != long_value || errno == ERANGE)
3631     {
3632       gchar *value_utf8 = _g_utf8_make_valid (value);
3633       g_set_error (error,
3634                    G_KEY_FILE_ERROR, 
3635                    G_KEY_FILE_ERROR_INVALID_VALUE,
3636                    _("Integer value '%s' out of range"), 
3637                    value_utf8);
3638       g_free (value_utf8);
3639
3640       return 0;
3641     }
3642   
3643   return int_value;
3644 }
3645
3646 static gchar *
3647 g_key_file_parse_integer_as_value (GKeyFile *key_file,
3648                                    gint      value)
3649
3650 {
3651   return g_strdup_printf ("%d", value);
3652 }
3653
3654 static gdouble
3655 g_key_file_parse_value_as_double  (GKeyFile     *key_file,
3656                                    const gchar  *value,
3657                                    GError      **error)
3658 {
3659   gchar *end_of_valid_d;
3660   gdouble double_value = 0;
3661
3662   double_value = g_ascii_strtod (value, &end_of_valid_d);
3663
3664   if (*end_of_valid_d != '\0' || end_of_valid_d == value)
3665     {
3666       gchar *value_utf8 = _g_utf8_make_valid (value);
3667       g_set_error (error, G_KEY_FILE_ERROR,
3668                    G_KEY_FILE_ERROR_INVALID_VALUE,
3669                    _("Value '%s' cannot be interpreted "
3670                      "as a float number."), 
3671                    value_utf8);
3672       g_free (value_utf8);
3673     }
3674
3675   return double_value;
3676 }
3677
3678 static gboolean
3679 g_key_file_parse_value_as_boolean (GKeyFile     *key_file,
3680                                    const gchar  *value,
3681                                    GError      **error)
3682 {
3683   gchar *value_utf8;
3684
3685   if (strcmp (value, "true") == 0 || strcmp (value, "1") == 0)
3686     return TRUE;
3687   else if (strcmp (value, "false") == 0 || strcmp (value, "0") == 0)
3688     return FALSE;
3689
3690   value_utf8 = _g_utf8_make_valid (value);
3691   g_set_error (error, G_KEY_FILE_ERROR,
3692                G_KEY_FILE_ERROR_INVALID_VALUE,
3693                _("Value '%s' cannot be interpreted "
3694                  "as a boolean."), value_utf8);
3695   g_free (value_utf8);
3696
3697   return FALSE;
3698 }
3699
3700 static gchar *
3701 g_key_file_parse_boolean_as_value (GKeyFile *key_file,
3702                                    gboolean  value)
3703 {
3704   if (value)
3705     return g_strdup ("true");
3706   else
3707     return g_strdup ("false");
3708 }
3709
3710 static gchar *
3711 g_key_file_parse_value_as_comment (GKeyFile    *key_file,
3712                                    const gchar *value)
3713 {
3714   GString *string;
3715   gchar **lines;
3716   gsize i;
3717
3718   string = g_string_sized_new (512);
3719
3720   lines = g_strsplit (value, "\n", 0);
3721
3722   for (i = 0; lines[i] != NULL; i++)
3723     {
3724         if (lines[i][0] != '#')
3725            g_string_append_printf (string, "%s\n", lines[i]);
3726         else 
3727            g_string_append_printf (string, "%s\n", lines[i] + 1);
3728     }
3729   g_strfreev (lines);
3730
3731   return g_string_free (string, FALSE);
3732 }
3733
3734 static gchar *
3735 g_key_file_parse_comment_as_value (GKeyFile      *key_file,
3736                                    const gchar   *comment)
3737 {
3738   GString *string;
3739   gchar **lines;
3740   gsize i;
3741
3742   string = g_string_sized_new (512);
3743
3744   lines = g_strsplit (comment, "\n", 0);
3745
3746   for (i = 0; lines[i] != NULL; i++)
3747     g_string_append_printf (string, "#%s%s", lines[i], 
3748                             lines[i + 1] == NULL? "" : "\n");
3749   g_strfreev (lines);
3750
3751   return g_string_free (string, FALSE);
3752 }
3753
3754 #define __G_KEY_FILE_C__
3755 #include "galiasdef.c"