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