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