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