nexmon – Blame information for rev 1

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