LCOV - code coverage report
Current view: top level - glib/glib - gkeyfile.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 1285 1375 93.5 %
Date: 2024-04-16 05:15:53 Functions: 96 96 100.0 %
Branches: 550 671 82.0 %

           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         [ +  + ]:      16321 : G_DEFINE_QUARK (g-key-file-error-quark, g_key_file_error)
     628                 :            : 
     629                 :            : static void
     630                 :       3500 : g_key_file_init (GKeyFile *key_file)
     631                 :            : {  
     632                 :       3500 :   key_file->current_group = g_new0 (GKeyFileGroup, 1);
     633                 :       3500 :   key_file->groups = g_list_prepend (NULL, key_file->current_group);
     634                 :       3500 :   key_file->group_hash = NULL;
     635                 :       3500 :   key_file->start_group = NULL;
     636                 :       3500 :   key_file->parse_buffer = NULL;
     637                 :       3500 :   key_file->list_separator = ';';
     638                 :       3500 :   key_file->flags = 0;
     639                 :       3500 : }
     640                 :            : 
     641                 :            : static void
     642                 :       3500 : g_key_file_clear (GKeyFile *key_file)
     643                 :            : {
     644                 :            :   GList *tmp, *group_node;
     645                 :            : 
     646         [ +  + ]:       3500 :   if (key_file->locales) 
     647                 :            :     {
     648                 :        649 :       g_strfreev (key_file->locales);
     649                 :        649 :       key_file->locales = NULL;
     650                 :            :     }
     651                 :       3500 :   key_file->checked_locales = FALSE;
     652                 :            : 
     653         [ +  + ]:       3500 :   if (key_file->parse_buffer)
     654                 :            :     {
     655                 :       1197 :       g_string_free (key_file->parse_buffer, TRUE);
     656                 :       1197 :       key_file->parse_buffer = NULL;
     657                 :            :     }
     658                 :            : 
     659                 :       3500 :   tmp = key_file->groups;
     660         [ +  + ]:       8549 :   while (tmp != NULL)
     661                 :            :     {
     662                 :       5049 :       group_node = tmp;
     663                 :       5049 :       tmp = tmp->next;
     664                 :       5049 :       g_key_file_remove_group_node (key_file, group_node);
     665                 :            :     }
     666                 :            : 
     667         [ +  + ]:       3500 :   if (key_file->group_hash != NULL)
     668                 :            :     {
     669                 :       1236 :       g_hash_table_destroy (key_file->group_hash);
     670                 :       1236 :       key_file->group_hash = NULL;
     671                 :            :     }
     672                 :            : 
     673         [ -  + ]:       3500 :   g_warn_if_fail (key_file->groups == NULL);
     674                 :       3500 : }
     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                 :       2293 : g_key_file_new (void)
     691                 :            : {
     692                 :            :   GKeyFile *key_file;
     693                 :            : 
     694                 :       2293 :   key_file = g_new0 (GKeyFile, 1);
     695                 :       2293 :   key_file->ref_count = 1;
     696                 :       2293 :   g_key_file_init (key_file);
     697                 :            : 
     698                 :       2293 :   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                 :       1128 : g_key_file_load_from_fd (GKeyFile       *key_file,
     805                 :            :                          gint            fd,
     806                 :            :                          GKeyFileFlags   flags,
     807                 :            :                          GError        **error)
     808                 :            : {
     809                 :       1128 :   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         [ -  + ]:       1128 :   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         [ -  + ]:       1128 :   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                 :       1128 :   list_separator = key_file->list_separator;
     833                 :       1128 :   g_key_file_clear (key_file);
     834                 :       1128 :   g_key_file_init (key_file);
     835                 :       1128 :   key_file->list_separator = list_separator;
     836                 :       1128 :   key_file->flags = flags;
     837                 :            : 
     838                 :            :   do
     839                 :            :     {
     840                 :            :       int errsv;
     841                 :            : 
     842                 :       2480 :       bytes_read = read (fd, read_buf, 4096);
     843                 :       2480 :       errsv = errno;
     844                 :            : 
     845         [ +  + ]:       2480 :       if (bytes_read == 0)  /* End of File */
     846                 :       1127 :         break;
     847                 :            : 
     848         [ -  + ]:       1353 :       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                 :       1353 :       g_key_file_parse_data (key_file,
     860                 :            :                              read_buf, bytes_read,
     861                 :            :                              &key_file_error);
     862                 :            :     }
     863         [ +  + ]:       1353 :   while (!key_file_error);
     864                 :            : 
     865         [ +  + ]:       1128 :   if (key_file_error)
     866                 :            :     {
     867                 :          1 :       g_propagate_error (error, key_file_error);
     868                 :          1 :       return FALSE;
     869                 :            :     }
     870                 :            : 
     871                 :       1127 :   g_key_file_flush_parse_buffer (key_file, &key_file_error);
     872                 :            : 
     873         [ -  + ]:       1127 :   if (key_file_error)
     874                 :            :     {
     875                 :          0 :       g_propagate_error (error, key_file_error);
     876                 :          0 :       return FALSE;
     877                 :            :     }
     878                 :            : 
     879                 :       1127 :   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                 :       2159 : g_key_file_load_from_file (GKeyFile       *key_file,
     904                 :            :                            const gchar    *file,
     905                 :            :                            GKeyFileFlags   flags,
     906                 :            :                            GError        **error)
     907                 :            : {
     908                 :       2159 :   GError *key_file_error = NULL;
     909                 :            :   gint fd;
     910                 :            :   int errsv;
     911                 :            : 
     912                 :       2159 :   g_return_val_if_fail (key_file != NULL, FALSE);
     913                 :       2159 :   g_return_val_if_fail (file != NULL, FALSE);
     914                 :            : 
     915                 :       2159 :   fd = g_open (file, O_RDONLY | O_CLOEXEC, 0);
     916                 :       2159 :   errsv = errno;
     917                 :            : 
     918         [ +  + ]:       2159 :   if (fd == -1)
     919                 :            :     {
     920                 :       1032 :       g_set_error_literal (error, G_FILE_ERROR,
     921                 :       1032 :                            g_file_error_from_errno (errsv),
     922                 :            :                            g_strerror (errsv));
     923                 :       1032 :       return FALSE;
     924                 :            :     }
     925                 :            : 
     926                 :       1127 :   g_key_file_load_from_fd (key_file, fd, flags, &key_file_error);
     927                 :       1127 :   close (fd);
     928                 :            : 
     929         [ +  + ]:       1127 :   if (key_file_error)
     930                 :            :     {
     931                 :          1 :       g_propagate_error (error, key_file_error);
     932                 :          1 :       return FALSE;
     933                 :            :     }
     934                 :            : 
     935                 :       1126 :   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                 :       2070 : g_key_file_free (GKeyFile *key_file)
    1193                 :            : {
    1194                 :       2070 :   g_return_if_fail (key_file != NULL);
    1195                 :            : 
    1196                 :       2070 :   g_key_file_clear (key_file);
    1197                 :            : 
    1198         [ +  + ]:       2070 :   if (g_atomic_int_dec_and_test (&key_file->ref_count))
    1199                 :       2068 :     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                 :      44699 : g_key_file_parse_line (GKeyFile     *key_file,
    1257                 :            :                        const gchar  *line,
    1258                 :            :                        gsize         length,
    1259                 :            :                        GError      **error)
    1260                 :            : {
    1261                 :      44699 :   GError *parse_error = NULL;
    1262                 :            :   const gchar *line_start;
    1263                 :            : 
    1264                 :      44705 :   g_return_if_fail (key_file != NULL);
    1265                 :      44699 :   g_return_if_fail (line != NULL);
    1266                 :            : 
    1267                 :      44699 :   line_start = line;
    1268         [ +  + ]:      44705 :   while (g_ascii_isspace (*line_start))
    1269                 :          6 :     line_start++;
    1270                 :            : 
    1271         [ +  + ]:      44699 :   if (g_key_file_line_is_comment (line_start))
    1272                 :        140 :     g_key_file_parse_comment (key_file, line, length, &parse_error);
    1273         [ +  + ]:      44559 :   else if (g_key_file_line_is_group (line_start))
    1274                 :       1471 :     g_key_file_parse_group (key_file, line_start,
    1275                 :       1471 :                             length - (line_start - line),
    1276                 :            :                             &parse_error);
    1277         [ +  + ]:      43088 :   else if (g_key_file_line_is_key_value_pair (line_start))
    1278                 :      43082 :     g_key_file_parse_key_value_pair (key_file, line_start,
    1279                 :      43082 :                                      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         [ +  + ]:      44693 :   if (parse_error)
    1295                 :         11 :     g_propagate_error (error, parse_error);
    1296                 :            : }
    1297                 :            : 
    1298                 :            : static void
    1299                 :        437 : g_key_file_parse_comment (GKeyFile     *key_file,
    1300                 :            :                           const gchar  *line,
    1301                 :            :                           gsize         length,
    1302                 :            :                           GError      **error)
    1303                 :            : {
    1304                 :            :   GKeyFileKeyValuePair *pair;
    1305                 :            :   
    1306         [ +  + ]:        437 :   if (!(key_file->flags & G_KEY_FILE_KEEP_COMMENTS))
    1307                 :        407 :     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                 :       1471 : 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                 :       1471 :   group_name_start = line + 1;
    1331                 :       1471 :   group_name_end = line + length - 1;
    1332                 :            :   
    1333         [ +  + ]:       1472 :   while (*group_name_end != ']')
    1334                 :          1 :     group_name_end--;
    1335                 :            : 
    1336                 :       1471 :   group_name = g_strndup (group_name_start, 
    1337                 :       1471 :                           group_name_end - group_name_start);
    1338                 :            :   
    1339         [ +  + ]:       1471 :   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                 :       1468 :   g_key_file_add_group (key_file, group_name, FALSE);
    1349                 :       1468 :   g_free (group_name);
    1350                 :            : }
    1351                 :            : 
    1352                 :            : static void
    1353                 :      43082 : 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   [ +  -  +  + ]:      43082 :   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                 :      43081 :   key_end = value_start = strchr (line, '=');
    1372                 :            : 
    1373         [ -  + ]:      43081 :   g_warn_if_fail (key_end != NULL);
    1374                 :            : 
    1375                 :      43081 :   key_end--;
    1376                 :      43081 :   value_start++;
    1377                 :            : 
    1378                 :            :   /* Pull the key name from the line (chomping trailing whitespace)
    1379                 :            :    */
    1380         [ +  + ]:      43197 :   while (g_ascii_isspace (*key_end))
    1381                 :        116 :     key_end--;
    1382                 :            : 
    1383                 :      43081 :   key_len = key_end - line + 2;
    1384                 :            : 
    1385         [ -  + ]:      43081 :   g_warn_if_fail (key_len <= length);
    1386                 :            : 
    1387         [ +  + ]:      43081 :   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                 :      43077 :   key = g_strndup (line, key_len - 1);
    1396                 :            : 
    1397                 :            :   /* Pull the value from the line (chugging leading whitespace)
    1398                 :            :    */
    1399         [ +  + ]:      43191 :   while (g_ascii_isspace (*value_start))
    1400                 :        114 :     value_start++;
    1401                 :            : 
    1402                 :      43077 :   value_len = line + length - value_start;
    1403                 :            : 
    1404         [ -  + ]:      43077 :   g_warn_if_fail (key_file->start_group != NULL);
    1405                 :            : 
    1406                 :            :   /* Checked on entry to this function */
    1407                 :      43077 :   g_assert (key_file->current_group != NULL);
    1408                 :      43077 :   g_assert (key_file->current_group->name != NULL);
    1409                 :            : 
    1410         [ +  + ]:      43077 :   if (key_file->start_group == key_file->current_group
    1411         [ +  + ]:      42511 :       && 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                 :      43074 :   locale = key_get_locale (key, &locale_len);
    1431                 :            : 
    1432   [ +  +  +  + ]:      43074 :   if (locale == NULL || g_key_file_locale_is_interesting (key_file, locale, locale_len))
    1433                 :            :     {
    1434                 :            :       GKeyFileKeyValuePair *pair;
    1435                 :            : 
    1436                 :      21337 :       pair = g_new (GKeyFileKeyValuePair, 1);
    1437                 :      21337 :       pair->key = g_steal_pointer (&key);
    1438                 :      21337 :       pair->value = g_strndup (value_start, value_len);
    1439                 :            : 
    1440                 :      21337 :       g_key_file_add_key_value_pair (key_file, key_file->current_group, pair,
    1441                 :      21337 :                                      key_file->current_group->key_value_pairs);
    1442                 :            :     }
    1443                 :            : 
    1444                 :      43074 :   g_free (key);
    1445                 :            : }
    1446                 :            : 
    1447                 :            : static const gchar *
    1448                 :      43074 : key_get_locale (const gchar *key,
    1449                 :            :                 gsize       *len_out)
    1450                 :            : {
    1451                 :            :   const gchar *locale;
    1452                 :            :   gsize locale_len;
    1453                 :            : 
    1454                 :      43074 :   locale = g_strrstr (key, "[");
    1455         [ +  + ]:      43074 :   if (locale != NULL)
    1456                 :      21868 :     locale_len = strlen (locale);
    1457                 :            :   else
    1458                 :      21206 :     locale_len = 0;
    1459                 :            : 
    1460         [ +  + ]:      43074 :   if (locale_len > 2)
    1461                 :            :     {
    1462                 :      21868 :       locale++;  /* skip `[` */
    1463                 :      21868 :       locale_len -= 2;  /* drop `[` and `]` */
    1464                 :            :     }
    1465                 :            :   else
    1466                 :            :     {
    1467                 :      21206 :       locale = NULL;
    1468                 :      21206 :       locale_len = 0;
    1469                 :            :     }
    1470                 :            : 
    1471                 :      43074 :   *len_out = locale_len;
    1472                 :      43074 :   return locale;
    1473                 :            : }
    1474                 :            : 
    1475                 :            : static void
    1476                 :       1430 : 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                 :       1447 :   g_return_if_fail (key_file != NULL);
    1485                 :       1430 :   g_return_if_fail (data != NULL || length == 0);
    1486                 :            : 
    1487                 :       1430 :   parse_error = NULL;
    1488                 :            : 
    1489         [ +  + ]:       1430 :   if (!key_file->parse_buffer)
    1490                 :       1197 :     key_file->parse_buffer = g_string_sized_new (128);
    1491                 :            : 
    1492                 :       1430 :   i = 0;
    1493         [ +  + ]:      91271 :   while (i < length)
    1494                 :            :     {
    1495         [ +  + ]:      89858 :       if (data[i] == '\n')
    1496                 :            :         {
    1497         [ +  + ]:      44952 :           if (key_file->parse_buffer->len > 0
    1498         [ +  + ]:      44655 :               && (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         [ +  + ]:      44952 :           if (key_file->parse_buffer->len > 0)
    1509                 :      44655 :             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         [ +  + ]:      44952 :           if (parse_error)
    1514                 :            :             {
    1515                 :         17 :               g_propagate_error (error, parse_error);
    1516                 :         17 :               return;
    1517                 :            :             }
    1518                 :      44935 :           i++;
    1519                 :            :         }
    1520                 :            :       else
    1521                 :            :         {
    1522                 :            :           const gchar *start_of_line;
    1523                 :            :           const gchar *end_of_line;
    1524                 :            :           gsize line_length;
    1525                 :            : 
    1526                 :      44906 :           start_of_line = data + i;
    1527                 :      44906 :           end_of_line = memchr (start_of_line, '\n', length - i);
    1528                 :            : 
    1529         [ +  + ]:      44906 :           if (end_of_line == NULL)
    1530                 :        277 :             end_of_line = data + length;
    1531                 :            : 
    1532                 :      44906 :           line_length = end_of_line - start_of_line;
    1533                 :            : 
    1534         [ -  + ]:      44906 :           g_string_append_len (key_file->parse_buffer, start_of_line, line_length);
    1535                 :      44906 :           i += line_length;
    1536                 :            :         }
    1537                 :            :     }
    1538                 :            : }
    1539                 :            : 
    1540                 :            : static void
    1541                 :      45843 : g_key_file_flush_parse_buffer (GKeyFile  *key_file,
    1542                 :            :                                GError   **error)
    1543                 :            : {
    1544                 :      45843 :   GError *file_error = NULL;
    1545                 :            : 
    1546                 :      45868 :   g_return_if_fail (key_file != NULL);
    1547                 :            : 
    1548         [ +  + ]:      45843 :   if (!key_file->parse_buffer)
    1549                 :          8 :     return;
    1550                 :            : 
    1551                 :      45835 :   file_error = NULL;
    1552                 :            : 
    1553         [ +  + ]:      45835 :   if (key_file->parse_buffer->len > 0)
    1554                 :            :     {
    1555                 :      44699 :       g_key_file_parse_line (key_file, key_file->parse_buffer->str,
    1556                 :      44699 :                              key_file->parse_buffer->len,
    1557                 :            :                              &file_error);
    1558                 :      44699 :       g_string_erase (key_file->parse_buffer, 0, -1);
    1559                 :            : 
    1560         [ +  + ]:      44699 :       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                 :        369 : 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                 :        369 :   g_return_val_if_fail (key_file != NULL, NULL);
    1659                 :        369 :   g_return_val_if_fail (group_name != NULL, NULL);
    1660                 :            :   
    1661                 :        369 :   group = g_key_file_lookup_group (key_file, group_name);
    1662                 :            :   
    1663         [ +  + ]:        369 :   if (!group)
    1664                 :            :     {
    1665                 :        175 :       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                 :        175 :       return NULL;
    1670                 :            :     }
    1671                 :            : 
    1672                 :        194 :   num_keys = 0;
    1673         [ +  + ]:      10302 :   for (tmp = group->key_value_pairs; tmp; tmp = tmp->next)
    1674                 :            :     {
    1675                 :            :       GKeyFileKeyValuePair *pair;
    1676                 :            : 
    1677                 :      10108 :       pair = (GKeyFileKeyValuePair *) tmp->data;
    1678                 :            : 
    1679         [ +  + ]:      10108 :       if (pair->key)
    1680                 :      10030 :         num_keys++;
    1681                 :            :     }
    1682                 :            :   
    1683                 :        194 :   keys = g_new (gchar *, num_keys + 1);
    1684                 :            : 
    1685                 :        194 :   i = num_keys - 1;
    1686         [ +  + ]:      10302 :   for (tmp = group->key_value_pairs; tmp; tmp = tmp->next)
    1687                 :            :     {
    1688                 :            :       GKeyFileKeyValuePair *pair;
    1689                 :            : 
    1690                 :      10108 :       pair = (GKeyFileKeyValuePair *) tmp->data;
    1691                 :            : 
    1692         [ +  + ]:      10108 :       if (pair->key)
    1693                 :            :         {
    1694                 :      10030 :           keys[i] = g_strdup (pair->key);
    1695                 :      10030 :           i--;
    1696                 :            :         }
    1697                 :            :     }
    1698                 :            : 
    1699                 :        194 :   keys[num_keys] = NULL;
    1700                 :            : 
    1701         [ +  + ]:        194 :   if (length)
    1702                 :          3 :     *length = num_keys;
    1703                 :            : 
    1704                 :        194 :   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                 :      15817 : set_not_found_key_error (const char *group_name,
    1790                 :            :                          const char *key,
    1791                 :            :                          GError    **error)
    1792                 :            : {
    1793                 :      15817 :   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                 :      15817 : }
    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                 :      29736 : 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                 :      29736 :   gchar *value = NULL;
    1829                 :            : 
    1830                 :      29736 :   g_return_val_if_fail (key_file != NULL, NULL);
    1831                 :      29736 :   g_return_val_if_fail (group_name != NULL, NULL);
    1832                 :      29736 :   g_return_val_if_fail (key != NULL, NULL);
    1833                 :            :   
    1834                 :      29736 :   group = g_key_file_lookup_group (key_file, group_name);
    1835                 :            : 
    1836         [ +  + ]:      29736 :   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                 :      29618 :   pair = g_key_file_lookup_key_value_pair (key_file, group, key);
    1846                 :            : 
    1847         [ +  + ]:      29618 :   if (pair)
    1848                 :      27694 :     value = g_strdup (pair->value);
    1849                 :            :   else
    1850                 :      15771 :     set_not_found_key_error (group_name, key, error);
    1851                 :            : 
    1852                 :      29618 :   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                 :      11753 : 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                 :      11753 :   GError *key_file_error = NULL;
    2049                 :            :   gchar *value, *string_value, **values;
    2050                 :            :   gint i, len;
    2051                 :      11753 :   GSList *p, *pieces = NULL;
    2052                 :            : 
    2053                 :      11753 :   g_return_val_if_fail (key_file != NULL, NULL);
    2054                 :      11753 :   g_return_val_if_fail (group_name != NULL, NULL);
    2055                 :      11753 :   g_return_val_if_fail (key != NULL, NULL);
    2056                 :            : 
    2057         [ +  + ]:      11753 :   if (length)
    2058                 :        212 :     *length = 0;
    2059                 :            : 
    2060                 :      11753 :   value = g_key_file_get_value (key_file, group_name, key, &key_file_error);
    2061                 :            : 
    2062         [ +  + ]:      11753 :   if (key_file_error)
    2063                 :            :     {
    2064                 :       1432 :       g_propagate_error (error, key_file_error);
    2065                 :       1432 :       return NULL;
    2066                 :            :     }
    2067                 :            : 
    2068         [ +  + ]:      10321 :   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                 :      10320 :   string_value = g_key_file_parse_value_as_string (key_file, value, &pieces, &key_file_error);
    2082                 :      10320 :   g_free (value);
    2083                 :      10320 :   g_free (string_value);
    2084                 :            : 
    2085         [ +  + ]:      10320 :   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                 :      10319 :   len = g_slist_length (pieces);
    2106                 :      10319 :   values = g_new (gchar *, len + 1);
    2107         [ +  + ]:      22019 :   for (p = pieces, i = 0; p; p = p->next)
    2108                 :      11700 :     values[i++] = p->data;
    2109                 :      10319 :   values[len] = NULL;
    2110                 :            : 
    2111                 :      10319 :   g_slist_free (pieces);
    2112                 :            : 
    2113         [ +  + ]:      10319 :   if (length)
    2114                 :         84 :     *length = len;
    2115                 :            : 
    2116                 :      10319 :   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                 :       1717 :       g_propagate_error (error, key_file_error);
    2517                 :       1717 :       return FALSE;
    2518                 :            :     }
    2519                 :            : 
    2520                 :        236 :   bool_value = g_key_file_parse_value_as_boolean (key_file, value,
    2521                 :            :                                                   &key_file_error);
    2522                 :        236 :   g_free (value);
    2523                 :            : 
    2524         [ +  + ]:        236 :   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                 :        236 :   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                 :       1554 : g_key_file_add_group (GKeyFile    *key_file,
    3823                 :            :                       const gchar *group_name,
    3824                 :            :                       gboolean created)
    3825                 :            : {
    3826                 :            :   GKeyFileGroup *group;
    3827                 :            : 
    3828                 :       1554 :   g_return_if_fail (key_file != NULL);
    3829                 :       1554 :   g_return_if_fail (group_name != NULL && g_key_file_is_group_name (group_name));
    3830                 :            : 
    3831                 :       1554 :   group = g_key_file_lookup_group (key_file, group_name);
    3832         [ +  + ]:       1554 :   if (group != NULL)
    3833                 :            :     {
    3834                 :          2 :       key_file->current_group = group;
    3835                 :          2 :       return;
    3836                 :            :     }
    3837                 :            : 
    3838                 :       1552 :   group = g_new0 (GKeyFileGroup, 1);
    3839                 :       1552 :   group->name = g_strdup (group_name);
    3840                 :       1552 :   group->lookup_map = g_hash_table_new (g_str_hash, g_str_equal);
    3841                 :       1552 :   key_file->groups = g_list_prepend (key_file->groups, group);
    3842                 :       1552 :   key_file->current_group = group;
    3843                 :            : 
    3844         [ +  + ]:       1552 :   if (key_file->start_group == NULL)
    3845                 :            :     {
    3846                 :       1236 :       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         [ +  + ]:       1552 :   if (!key_file->group_hash)
    3867                 :       1236 :     key_file->group_hash = g_hash_table_new (g_str_hash, g_str_equal);
    3868                 :            : 
    3869                 :       1552 :   g_hash_table_insert (key_file->group_hash, (gpointer)group->name, group);
    3870                 :            : }
    3871                 :            : 
    3872                 :            : static void
    3873                 :      21938 : g_key_file_key_value_pair_free (GKeyFileKeyValuePair *pair)
    3874                 :            : {
    3875         [ +  - ]:      21938 :   if (pair != NULL)
    3876                 :            :     {
    3877                 :      21938 :       g_free (pair->key);
    3878                 :      21938 :       g_free (pair->value);
    3879                 :      21938 :       g_free_sized (pair, sizeof (GKeyFileKeyValuePair));
    3880                 :            :     }
    3881                 :      21938 : }
    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                 :      21862 : 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                 :      21862 :   pair = (GKeyFileKeyValuePair *) pair_node->data;
    3901                 :            : 
    3902                 :      21862 :   group->key_value_pairs = g_list_remove_link (group->key_value_pairs, pair_node);
    3903                 :            : 
    3904         [ -  + ]:      21862 :   g_warn_if_fail (pair->value != NULL);
    3905                 :            : 
    3906                 :      21862 :   g_key_file_key_value_pair_free (pair);
    3907                 :            : 
    3908                 :      21862 :   g_list_free_1 (pair_node);
    3909                 :      21862 : }
    3910                 :            : 
    3911                 :            : static void
    3912                 :       5052 : g_key_file_remove_group_node (GKeyFile *key_file,
    3913                 :            :                               GList    *group_node)
    3914                 :            : {
    3915                 :            :   GKeyFileGroup *group;
    3916                 :            :   GList *tmp;
    3917                 :            : 
    3918                 :       5052 :   group = (GKeyFileGroup *) group_node->data;
    3919                 :            : 
    3920         [ +  + ]:       5052 :   if (group->name)
    3921                 :            :     {
    3922                 :       1552 :       g_assert (key_file->group_hash);
    3923                 :       1552 :       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         [ +  + ]:       5052 :   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         [ +  - ]:       3500 :       if (key_file->groups)
    3935                 :       3500 :         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         [ +  + ]:       5052 :   if (key_file->start_group == group)
    3944                 :            :     {
    3945                 :       1238 :       tmp = g_list_last (key_file->groups);
    3946         [ +  + ]:       3714 :       while (tmp != NULL)
    3947                 :            :         {
    3948         [ +  + ]:       2478 :           if (tmp != group_node &&
    3949         [ +  + ]:       1240 :               ((GKeyFileGroup *) tmp->data)->name != NULL)
    3950                 :          2 :             break;
    3951                 :            : 
    3952                 :       2476 :           tmp = tmp->prev;
    3953                 :            :         }
    3954                 :            : 
    3955         [ +  + ]:       1238 :       if (tmp)
    3956                 :          2 :         key_file->start_group = (GKeyFileGroup *) tmp->data;
    3957                 :            :       else
    3958                 :       1236 :         key_file->start_group = NULL;
    3959                 :            :     }
    3960                 :            : 
    3961                 :       5052 :   key_file->groups = g_list_remove_link (key_file->groups, group_node);
    3962                 :            : 
    3963                 :       5052 :   tmp = group->key_value_pairs;
    3964         [ +  + ]:      26910 :   while (tmp != NULL)
    3965                 :            :     {
    3966                 :            :       GList *pair_node;
    3967                 :            : 
    3968                 :      21858 :       pair_node = tmp;
    3969                 :      21858 :       tmp = tmp->next;
    3970                 :      21858 :       g_key_file_remove_key_value_pair_node (key_file, group, pair_node);
    3971                 :            :     }
    3972                 :            : 
    3973         [ -  + ]:       5052 :   g_warn_if_fail (group->key_value_pairs == NULL);
    3974                 :            : 
    3975         [ +  + ]:       5052 :   if (group->lookup_map)
    3976                 :            :     {
    3977                 :       1552 :       g_hash_table_destroy (group->lookup_map);
    3978                 :       1552 :       group->lookup_map = NULL;
    3979                 :            :     }
    3980                 :            : 
    3981                 :       5052 :   g_free ((gchar *) group->name);
    3982                 :       5052 :   g_free_sized (group, sizeof (GKeyFileGroup));
    3983                 :       5052 :   g_list_free_1 (group_node);
    3984                 :       5052 : }
    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                 :      21602 : g_key_file_add_key_value_pair (GKeyFile             *key_file,
    4027                 :            :                                GKeyFileGroup        *group,
    4028                 :            :                                GKeyFileKeyValuePair *pair,
    4029                 :            :                                GList                *sibling)
    4030                 :            : {
    4031                 :      21602 :   g_hash_table_replace (group->lookup_map, pair->key, pair);
    4032                 :      21602 :   group->key_value_pairs = g_list_insert_before (group->key_value_pairs, sibling, pair);
    4033                 :      21602 : }
    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                 :      32330 : g_key_file_lookup_group (GKeyFile    *key_file,
    4124                 :            :                          const gchar *group_name)
    4125                 :            : {
    4126         [ +  + ]:      32330 :   if (!key_file->group_hash)
    4127                 :       1383 :     return NULL;
    4128                 :            : 
    4129                 :      30947 :   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                 :      30002 : g_key_file_lookup_key_value_pair (GKeyFile      *key_file,
    4156                 :            :                                   GKeyFileGroup *group,
    4157                 :            :                                   const gchar   *key)
    4158                 :            : {
    4159                 :      30002 :   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                 :      44699 : g_key_file_line_is_comment (const gchar *line)
    4168                 :            : {
    4169   [ +  +  +  -  :      44699 :   return (*line == '#' || *line == '\0' || *line == '\n');
                   -  + ]
    4170                 :            : }
    4171                 :            : 
    4172                 :            : static gboolean 
    4173                 :       3371 : g_key_file_is_group_name (const gchar *name)
    4174                 :            : {
    4175                 :            :   const gchar *p, *q;
    4176                 :            : 
    4177                 :       3371 :   g_assert (name != NULL);
    4178                 :            : 
    4179                 :       3371 :   p = q = name;
    4180   [ +  +  +  -  :      51413 :   while (*q && *q != ']' && *q != '[' && !g_ascii_iscntrl (*q))
             +  +  +  + ]
    4181                 :      48042 :     q = g_utf8_find_next_char (q, NULL);
    4182                 :            :   
    4183   [ +  +  +  + ]:       3371 :   if (*q != '\0' || q == p)
    4184                 :          3 :     return FALSE;
    4185                 :            : 
    4186                 :       3368 :   return TRUE;
    4187                 :            : }
    4188                 :            : 
    4189                 :            : static gboolean
    4190                 :      43421 : g_key_file_is_key_name (const gchar *name,
    4191                 :            :                         gsize        len)
    4192                 :            : {
    4193                 :            :   const gchar *p, *q, *end;
    4194                 :            : 
    4195                 :      43421 :   g_assert (name != NULL);
    4196                 :            : 
    4197                 :      43421 :   p = q = name;
    4198                 :      43421 :   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   [ +  +  +  -  :     574909 :   while (q < end && *q && *q != '=' && *q != '[' && *q != ']')
          +  -  +  +  +  
                      - ]
    4204                 :            :     {
    4205                 :     488067 :       q = g_utf8_find_next_char (q, end);
    4206         [ +  + ]:     488067 :       if (q == NULL)
    4207                 :      21546 :         q = end;
    4208                 :            :     }
    4209                 :            :   
    4210                 :            :   /* No empty keys, please */
    4211         [ +  + ]:      43421 :   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   [ +  -  +  + ]:      43420 :   if (*p == ' ' || q[-1] == ' ')
    4220                 :          1 :     return FALSE;
    4221                 :            : 
    4222         [ +  + ]:      43419 :   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         [ -  + ]:      43417 :   if (q < end)
    4244                 :          0 :     return FALSE;
    4245                 :            : 
    4246                 :      43417 :   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                 :      44559 : g_key_file_line_is_group (const gchar *line)
    4254                 :            : {
    4255                 :            :   const gchar *p;
    4256                 :            : 
    4257                 :      44559 :   p = line;
    4258         [ +  + ]:      44559 :   if (*p != '[')
    4259                 :      43086 :     return FALSE;
    4260                 :            : 
    4261                 :       1473 :   p++;
    4262                 :            : 
    4263   [ +  -  +  + ]:      22381 :   while (*p && *p != ']')
    4264                 :      20908 :     p = g_utf8_find_next_char (p, NULL);
    4265                 :            : 
    4266         [ -  + ]:       1473 :   if (*p != ']')
    4267                 :          0 :     return FALSE;
    4268                 :            :  
    4269                 :            :   /* silently accept whitespace after the ] */
    4270                 :       1473 :   p = g_utf8_find_next_char (p, NULL);
    4271   [ +  +  -  + ]:       1475 :   while (*p == ' ' || *p == '\t')
    4272                 :          2 :     p = g_utf8_find_next_char (p, NULL);
    4273                 :            :      
    4274         [ +  + ]:       1473 :   if (*p)
    4275                 :          2 :     return FALSE;
    4276                 :            : 
    4277                 :       1471 :   return TRUE;
    4278                 :            : }
    4279                 :            : 
    4280                 :            : static gboolean
    4281                 :      43088 : g_key_file_line_is_key_value_pair (const gchar *line)
    4282                 :            : {
    4283                 :            :   const gchar *p;
    4284                 :            : 
    4285                 :      43088 :   p = g_utf8_strchr (line, -1, '=');
    4286                 :            : 
    4287         [ +  + ]:      43088 :   if (!p)
    4288                 :          5 :     return FALSE;
    4289                 :            : 
    4290                 :            :   /* Key must be non-empty
    4291                 :            :    */
    4292         [ +  + ]:      43083 :   if (*p == line[0])
    4293                 :          1 :     return FALSE;
    4294                 :            : 
    4295                 :      43082 :   return TRUE;
    4296                 :            : }
    4297                 :            : 
    4298                 :            : static gchar *
    4299                 :      13481 : 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                 :      13481 :   GSList *tmp_pieces = NULL;
    4306                 :            :   const gchar *p;
    4307                 :            : 
    4308                 :      13481 :   g_assert (pieces == NULL || *pieces == NULL);
    4309                 :            : 
    4310                 :      13481 :   string_value = g_new (gchar, strlen (value) + 1);
    4311                 :            : 
    4312                 :      13481 :   p = value;
    4313                 :      13481 :   q0 = q = string_value;
    4314         [ +  + ]:     259862 :   while (*p)
    4315                 :            :     {
    4316         [ +  + ]:     246386 :       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                 :     246369 :           *q = *p;
    4378   [ +  +  +  + ]:     246369 :           if (pieces && (*p == key_file->list_separator))
    4379                 :            :             {
    4380                 :      11479 :               tmp_pieces = g_slist_prepend (tmp_pieces, g_strndup (q0, q - q0));
    4381                 :      11479 :               q0 = q + 1;
    4382                 :            :             }
    4383                 :            :         }
    4384                 :            : 
    4385         [ -  + ]:     246381 :       if (*p == '\0')
    4386                 :          0 :         break;
    4387                 :            : 
    4388                 :     246381 :       q++;
    4389                 :     246381 :       p++;
    4390                 :            :     }
    4391                 :            : 
    4392                 :      13476 :   *q = '\0';
    4393         [ +  + ]:      13476 :   if (pieces)
    4394                 :            :     {
    4395         [ +  + ]:      10319 :       if (q0 < q)
    4396                 :        221 :         tmp_pieces = g_slist_prepend (tmp_pieces, g_strndup (q0, q - q0));
    4397                 :      10319 :       *pieces = g_slist_reverse (tmp_pieces);
    4398                 :            :     }
    4399                 :            : 
    4400                 :      13476 :   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                 :        410 : strcmp_sized (const gchar *s1, size_t len1, const gchar *s2)
    4579                 :            : {
    4580                 :        410 :   size_t len2 = strlen (s2);
    4581                 :        410 :   return strncmp (s1, s2, MAX (len1, len2));
    4582                 :            : }
    4583                 :            : 
    4584                 :            : static gboolean
    4585                 :        238 : g_key_file_parse_value_as_boolean (GKeyFile     *key_file,
    4586                 :            :                                    const gchar  *value,
    4587                 :            :                                    GError      **error)
    4588                 :            : {
    4589                 :            :   gchar *value_utf8;
    4590                 :        238 :   gint i, length = 0;
    4591                 :            : 
    4592                 :            :   /* Count the number of non-whitespace characters */
    4593         [ +  + ]:       1254 :   for (i = 0; value[i]; i++)
    4594         [ +  + ]:       1016 :     if (!g_ascii_isspace (value[i]))
    4595                 :       1015 :       length = i + 1;
    4596                 :            : 
    4597   [ +  +  +  + ]:        238 :   if (strcmp_sized (value, length, "true") == 0 || strcmp_sized (value, length, "1") == 0)
    4598                 :        155 :     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                 :            : }

Generated by: LCOV version 1.14