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