*/
#include "config.h"
-#include "galias.h"
#include "gkeyfile.h"
#endif
#ifdef G_OS_WIN32
#include <io.h>
+
+#ifndef S_ISREG
+#define S_ISREG(mode) ((mode)&_S_IFREG)
#endif
+#endif /* G_OS_WIN23 */
+
#include "gconvert.h"
#include "gdataset.h"
#include "gerror.h"
#include "gstrfuncs.h"
#include "gutils.h"
+#include "galias.h"
+
typedef struct _GKeyFileGroup GKeyFileGroup;
struct _GKeyFile
{
GList *groups;
- gchar *start_group_name;
-
+ GKeyFileGroup *start_group;
GKeyFileGroup *current_group;
GString *parse_buffer; /* Holds up to one line of not-yet-parsed data */
gint fd,
GKeyFileFlags flags,
GError **error);
-static GList *g_key_file_lookup_group_node (GKeyFile *key_file,
- const gchar *group_name);
+static GList *g_key_file_lookup_group_node (GKeyFile *key_file,
+ const gchar *group_name);
static GKeyFileGroup *g_key_file_lookup_group (GKeyFile *key_file,
const gchar *group_name);
GKeyFileGroup *group,
const gchar *key);
-static void g_key_file_remove_group_node (GKeyFile *entry,
+static void g_key_file_remove_group_node (GKeyFile *key_file,
GList *group_node);
static void g_key_file_remove_key_value_pair_node (GKeyFile *key_file,
GKeyFileGroup *group,
GList *pair_node);
-static void g_key_file_add_key (GKeyFile *entry,
- const gchar *group_name,
+static void g_key_file_add_key (GKeyFile *key_file,
+ GKeyFileGroup *group,
const gchar *key,
const gchar *value);
-static void g_key_file_add_group (GKeyFile *entry,
+static void g_key_file_add_group (GKeyFile *key_file,
const gchar *group_name);
static void g_key_file_key_value_pair_free (GKeyFileKeyValuePair *pair);
static gboolean g_key_file_line_is_comment (const gchar *line);
static gboolean g_key_file_line_is_group (const gchar *line);
static gboolean g_key_file_line_is_key_value_pair (const gchar *line);
-static gchar *g_key_file_parse_value_as_string (GKeyFile *entry,
+static gchar *g_key_file_parse_value_as_string (GKeyFile *key_file,
const gchar *value,
GSList **separators,
GError **error);
-static gchar *g_key_file_parse_string_as_value (GKeyFile *entry,
+static gchar *g_key_file_parse_string_as_value (GKeyFile *key_file,
const gchar *string,
gboolean escape_separator);
-static gint g_key_file_parse_value_as_integer (GKeyFile *entry,
+static gint g_key_file_parse_value_as_integer (GKeyFile *key_file,
const gchar *value,
GError **error);
-static gchar *g_key_file_parse_integer_as_value (GKeyFile *entry,
+static gchar *g_key_file_parse_integer_as_value (GKeyFile *key_file,
gint value);
-static gboolean g_key_file_parse_value_as_boolean (GKeyFile *entry,
+static gboolean g_key_file_parse_value_as_boolean (GKeyFile *key_file,
const gchar *value,
GError **error);
-static gchar *g_key_file_parse_boolean_as_value (GKeyFile *entry,
+static gchar *g_key_file_parse_boolean_as_value (GKeyFile *key_file,
gboolean value);
-static gchar *g_key_file_parse_value_as_comment (GKeyFile *key_file,
- const gchar *value);
-static gchar *g_key_file_parse_comment_as_value (GKeyFile *key_file,
- const gchar *comment);
-static void g_key_file_parse_key_value_pair (GKeyFile *entry,
+static gchar *g_key_file_parse_value_as_comment (GKeyFile *key_file,
+ const gchar *value);
+static gchar *g_key_file_parse_comment_as_value (GKeyFile *key_file,
+ const gchar *comment);
+static void g_key_file_parse_key_value_pair (GKeyFile *key_file,
const gchar *line,
gsize length,
GError **error);
-static void g_key_file_parse_comment (GKeyFile *entry,
+static void g_key_file_parse_comment (GKeyFile *key_file,
const gchar *line,
gsize length,
GError **error);
-static void g_key_file_parse_group (GKeyFile *entry,
+static void g_key_file_parse_group (GKeyFile *key_file,
const gchar *line,
gsize length,
GError **error);
static gchar *key_get_locale (const gchar *key);
-static void g_key_file_parse_data (GKeyFile *entry,
+static void g_key_file_parse_data (GKeyFile *key_file,
const gchar *data,
gsize length,
GError **error);
-static void g_key_file_flush_parse_buffer (GKeyFile *entry,
+static void g_key_file_flush_parse_buffer (GKeyFile *key_file,
GError **error);
{
key_file->current_group = g_new0 (GKeyFileGroup, 1);
key_file->groups = g_list_prepend (NULL, key_file->current_group);
- key_file->start_group_name = NULL;
+ key_file->start_group = NULL;
key_file->parse_buffer = g_string_sized_new (128);
key_file->approximate_size = 0;
key_file->list_separator = ';';
if (key_file->parse_buffer)
g_string_free (key_file->parse_buffer, TRUE);
- g_free (key_file->start_group_name);
-
tmp = key_file->groups;
while (tmp != NULL)
{
{
gchar **data_dirs, *data_dir, *path;
gint fd;
- GError *file_error;
- file_error = NULL;
path = NULL;
fd = -1;
fd = g_open (path, O_RDONLY, 0);
- if (output_file != NULL)
- *output_file = g_strdup (path);
-
- g_free (path);
-
- if (fd < 0 && file_error == NULL)
- file_error = g_error_new (G_KEY_FILE_ERROR,
- G_KEY_FILE_ERROR_NOT_FOUND,
- _("Valid key file could not be "
- "found in data dirs"));
+ if (fd < 0)
+ {
+ g_free (path);
+ path = NULL;
+ }
candidate_file = strchr (candidate_file, '-');
*dirs = data_dirs;
- if (file_error)
+ if (fd < 0)
{
- if (fd >= 0)
- g_error_free (file_error);
- else
- g_propagate_error (error, file_error);
+ g_set_error (error, G_KEY_FILE_ERROR,
+ G_KEY_FILE_ERROR_NOT_FOUND,
+ _("Valid key file could not be "
+ "found in data dirs"));
}
- if (output_file && fd < 0)
- {
- g_free (*output_file);
- *output_file = NULL;
- }
+ if (output_file != NULL && fd > 0)
+ *output_file = g_strdup (path);
+
+ g_free (path);
return fd;
}
GError **error)
{
GError *key_file_error = NULL;
- gsize bytes_read;
+ gssize bytes_read;
struct stat stat_buf;
gchar read_buf[4096];
+
+ if (fstat (fd, &stat_buf) < 0)
+ {
+ g_set_error (error, G_FILE_ERROR,
+ g_file_error_from_errno (errno),
+ "%s", g_strerror (errno));
+ return FALSE;
+ }
- fstat (fd, &stat_buf);
- if ((stat_buf.st_mode & S_IFMT) == S_IFREG)
+ if (!S_ISREG (stat_buf.st_mode))
{
g_set_error (error, G_KEY_FILE_ERROR,
G_KEY_FILE_ERROR_PARSE,
if (bytes_read < 0)
{
- if (errno == EINTR)
+ if (errno == EINTR || errno == EAGAIN)
continue;
g_set_error (error, G_FILE_ERROR,
* @flags: flags from #GKeyFileFlags
* @error: return location for a #GError, or %NULL
*
- * Loads a key file from memory into an empty #GKeyFile structure.
- * If the object cannot be created then %error is set to a #GKeyFileError.
+ * Loads a key file from memory into an empty #GKeyFile structure. If
+ * the object cannot be created then %error is set to a
+ * #GKeyFileError.
*
* Return value: %TRUE if a key file could be loaded, %FALSE othewise
* Since: 2.6
g_return_val_if_fail (data != NULL, FALSE);
g_return_val_if_fail (length != 0, FALSE);
+ if (length == (gsize)-1)
+ length = strlen (data);
+
if (key_file->approximate_size > 0)
{
g_key_file_clear (key_file);
user_data_dir = g_get_user_data_dir ();
system_data_dirs = g_get_system_data_dirs ();
- all_data_dirs = g_new0 (gchar *, g_strv_length ((gchar **)system_data_dirs) + 1);
+ all_data_dirs = g_new0 (gchar *, g_strv_length ((gchar **)system_data_dirs) + 2);
i = 0;
all_data_dirs[i++] = g_strdup (user_data_dir);
found_file = FALSE;
data_dirs = all_data_dirs;
+ output_path = NULL;
while (*data_dirs != NULL && !found_file)
{
+ g_free (output_path);
+
fd = find_file_in_data_dirs (file, &output_path, &data_dirs,
&key_file_error);
{
if (key_file_error)
g_propagate_error (error, key_file_error);
- break;
+ break;
}
found_file = g_key_file_load_from_fd (key_file, fd, flags,
if (key_file_error)
{
g_propagate_error (error, key_file_error);
- g_free (output_path);
break;
}
-
- if (full_path)
- *full_path = output_path;
}
+ if (found_file && full_path)
+ *full_path = output_path;
+ else
+ g_free (output_path);
+
g_strfreev (all_data_dirs);
+
return found_file;
}
group_name = g_strndup (group_name_start,
group_name_end - group_name_start);
- if (key_file->start_group_name == NULL)
- key_file->start_group_name = g_strdup (group_name);
-
g_key_file_add_group (key_file, group_name);
g_free (group_name);
}
value = g_strndup (value_start, value_len);
- g_assert (key_file->start_group_name != NULL);
+ g_assert (key_file->start_group != NULL);
if (key_file->current_group
&& key_file->current_group->name
- && strcmp (key_file->start_group_name,
+ && strcmp (key_file->start_group->name,
key_file->current_group->name) == 0
&& strcmp (key, "Encoding") == 0)
{
locale = key_get_locale (key);
if (locale == NULL || g_key_file_locale_is_interesting (key_file, locale))
- g_key_file_add_key (key_file, key_file->current_group->name, key, value);
+ g_key_file_add_key (key_file, key_file->current_group, key, value);
g_free (locale);
g_free (key);
{
if (data[i] == '\n')
{
+ if (i > 0 && data[i - 1] == '\r')
+ g_string_erase (key_file->parse_buffer,
+ key_file->parse_buffer->len - 1,
+ 1);
+
/* When a newline is encountered flush the parse buffer so that the
* line can be parsed. Note that completely blank lines won't show
* up in the parse buffer, so they get parsed directly.
/**
* g_key_file_get_keys:
* @key_file: a #GKeyFile
- * @group_name: a group name, or %NULL
+ * @group_name: a group name
* @length: return location for the number of keys returned, or %NULL
* @error: return location for a #GError, or %NULL
*
- * Returns all keys for the group name @group_name. If @group_name is
- * %NULL, the start group is used. The array of returned keys will be
- * %NULL-terminated, so @length may optionally be %NULL.
+ * Returns all keys for the group name @group_name. The array of
+ * returned keys will be %NULL-terminated, so @length may
+ * optionally be %NULL. In the event that the @group_name cannot
+ * be found, %NULL is returned and @error is set to
+ * #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
*
* Return value: a newly-allocated %NULL-terminated array of
* strings. Use g_strfreev() to free it.
g_set_error (error, G_KEY_FILE_ERROR,
G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
_("Key file does not have group '%s'"),
- group_name);
+ group_name ? group_name : "(null)");
return NULL;
}
- num_keys = g_list_length (group->key_value_pairs);
+ num_keys = 0;
+ for (tmp = group->key_value_pairs; tmp; tmp = tmp->next)
+ {
+ GKeyFileKeyValuePair *pair;
+
+ pair = (GKeyFileKeyValuePair *) tmp->data;
+
+ if (pair->key)
+ num_keys++;
+ }
- keys = (gchar **) g_new0 (gchar **, num_keys + 1);
+ keys = g_new0 (gchar *, num_keys + 1);
- tmp = group->key_value_pairs;
- for (i = 0; i < num_keys; i++)
+ i = num_keys - 1;
+ for (tmp = group->key_value_pairs; tmp; tmp = tmp->next)
{
GKeyFileKeyValuePair *pair;
pair = (GKeyFileKeyValuePair *) tmp->data;
- keys[i] = g_strdup (pair->key);
- tmp = tmp->next;
+ if (pair->key)
+ {
+ keys[i] = g_strdup (pair->key);
+ i--;
+ }
}
- keys[i] = NULL;
+
+ keys[num_keys] = NULL;
if (length)
*length = num_keys;
{
g_return_val_if_fail (key_file != NULL, NULL);
- return g_strdup (key_file->start_group_name);
+ if (key_file->start_group)
+ return g_strdup (key_file->start_group->name);
+
+ return NULL;
}
/**
* list) is always the comment group at the top,
* which we skip
*/
- groups = (gchar **) g_new0 (gchar **, num_groups);
+ groups = g_new0 (gchar *, num_groups);
group_node = g_list_last (key_file->groups);
* @key_file: a #GKeyFile
* @group_name: a group name
* @key: a key
- * @error: return location for a #GError, or #NULL
+ * @error: return location for a #GError, or %NULL
*
* Returns the value associated with @key under @group_name.
+ *
* In the event the key cannot be found, %NULL is returned and
* @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND. In the
* event that the @group_name cannot be found, %NULL is returned
* and @error is set to #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
*
- * Return value: a string or %NULL if the specified key cannot be
- * found.
+ * Return value: a newly allocated string or %NULL if the specified
+ * key cannot be found.
*
* Since: 2.6
**/
g_set_error (error, G_KEY_FILE_ERROR,
G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
_("Key file does not have group '%s'"),
- group_name);
+ group_name ? group_name : "(null)");
return NULL;
}
* @key: a key
* @value: a string
*
- * Associates a new value with @key under @group_name.
- * If @key cannot be found then it is created. If @group_name
- * cannot be found then it is created as well.
+ * Associates a new value with @key under @group_name. If @key
+ * cannot be found then it is created. If @group_name cannot be
+ * found then it is created.
*
* Since: 2.6
**/
GKeyFileKeyValuePair *pair;
g_return_if_fail (key_file != NULL);
+ g_return_if_fail (group_name != NULL);
g_return_if_fail (key != NULL);
g_return_if_fail (value != NULL);
- if (!g_key_file_has_key (key_file, group_name, key, NULL))
- g_key_file_add_key (key_file, group_name, key, value);
+ group = g_key_file_lookup_group (key_file, group_name);
+
+ if (!group)
+ {
+ g_key_file_add_group (key_file, group_name);
+ group = (GKeyFileGroup *) key_file->groups->data;
+
+ g_key_file_add_key (key_file, group, key, value);
+ }
else
{
- group = g_key_file_lookup_group (key_file, group_name);
pair = g_key_file_lookup_key_value_pair (key_file, group, key);
- g_free (pair->value);
- pair->value = g_strdup (value);
+
+ if (!pair)
+ g_key_file_add_key (key_file, group, key, value);
+ else
+ {
+ g_free (pair->value);
+ pair->value = g_strdup (value);
+ }
}
}
* @key_file: a #GKeyFile
* @group_name: a group name
* @key: a key
- * @error: return location for a #GError, or #NULL
+ * @error: return location for a #GError, or %NULL
*
* Returns the value associated with @key under @group_name.
+ *
* In the event the key cannot be found, %NULL is returned and
* @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND. In the
* event that the @group_name cannot be found, %NULL is returned
* and @error is set to #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
*
- * Return value: a string or %NULL if the specified key cannot be
- * found.
+ * Return value: a newly allocated string or %NULL if the specified
+ * key cannot be found.
*
* Since: 2.6
**/
* @key: a key
* @string: a string
*
- * Associates a new string value with @key under @group_name.
- * If @key cannot be found then it is created. If @group_name
- * cannot be found then it is created as well.
+ * Associates a new string value with @key under @group_name. If
+ * @key cannot be found then it is created. If @group_name
+ * cannot be found then it is created.
*
* Since: 2.6
**/
* @error: return location for a #GError, or %NULL
*
* Returns the values associated with @key under @group_name.
+ *
* In the event the key cannot be found, %NULL is returned and
* @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND. In the
* event that the @group_name cannot be found, %NULL is returned
* @length: number of locale string values in @list
*
* Associates a list of string values for @key under @group_name.
- * If the @key cannot be found then it is created.
+ * If @key cannot be found then it is created. If @group_name
+ * cannot be found then it is created.
*
* Since: 2.6
**/
*
* Returns the value associated with @key under @group_name
* translated in the given @locale if available. If @locale is
- * %NULL then the current locale is assumed. If @key cannot be
- * found then %NULL is returned and @error is set to
+ * %NULL then the current locale is assumed.
+ *
+ * If @key cannot be found then %NULL is returned and @error is set to
* #G_KEY_FILE_ERROR_KEY_NOT_FOUND. If the value associated
* with @key cannot be interpreted or no suitable translation can
- * be found then the untranslated value is returned and @error is
- * set to #G_KEY_FILE_ERROR_INVALID_VALUE and
- * #G_KEY_FILE_ERROR_KEY_NOT_FOUND, respectively. In the
- * event that the @group_name cannot be found, %NULL is returned
- * and @error is set to #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
+ * be found then the untranslated value is returned.
+ *
+ * Return value: a newly allocated string or %NULL if the specified
+ * key cannot be found.
*
- * Return value: a string or %NULL if the specified key cannot be
- * found.
* Since: 2.6
**/
gchar *
translated_value = NULL;
key_file_error = NULL;
- if (!g_key_file_has_group (key_file, group_name))
- {
- g_set_error (error, G_KEY_FILE_ERROR,
- G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
- _("Key file does not have group '%s'"),
- group_name);
- return NULL;
- }
-
if (locale)
{
GSList *l, *list;
candidate_key, NULL);
g_free (candidate_key);
- if (translated_value)
+ if (translated_value && g_utf8_validate (translated_value, -1, NULL))
break;
- }
- if (translated_value && !g_utf8_validate (translated_value, -1, NULL))
- {
- g_set_error (error, G_KEY_FILE_ERROR,
- G_KEY_FILE_ERROR_INVALID_VALUE,
- _("Key file contains key '%s' "
- "which has value that cannot be interpreted."),
- candidate_key);
g_free (translated_value);
translated_value = NULL;
- }
+ }
/* Fallback to untranslated key
*/
if (!translated_value)
g_propagate_error (error, key_file_error);
- else
- g_set_error (error, G_KEY_FILE_ERROR,
- G_KEY_FILE_ERROR_KEY_NOT_FOUND,
- _("Key file contains no translated value "
- "for key '%s' with locale '%s'."),
- key, locale);
}
if (free_languages)
*
* Returns the values associated with @key under @group_name
* translated in the given @locale if available. If @locale is
- * %NULL then the current locale is assumed. If @key cannot be
- * found then %NULL is returned and @error is set to
+ * %NULL then the current locale is assumed.
+
+ * If @key cannot be found then %NULL is returned and @error is set to
* #G_KEY_FILE_ERROR_KEY_NOT_FOUND. If the values associated
* with @key cannot be interpreted or no suitable translations
- * can be found then the untranslated values are returned and
- * @error is set to #G_KEY_FILE_ERROR_INVALID_VALUE and
- * #G_KEY_FILE_ERROR_KEY_NOT_FOUND, respectively. In the
- * event that the @group_name cannot be found, %NULL is returned
- * and @error is set to #G_KEY_FILE_ERROR_GROUP_NOT_FOUND.
+ * can be found then the untranslated values are returned.
* The returned array is %NULL-terminated, so @length may optionally be %NULL.
*
* Return value: a newly allocated %NULL-terminated string array
*
* Associates a list of string values for @key and @locale under
* @group_name. If the translation for @key cannot be found then
- * it is created.
+ * it is created.
*
* Since: 2.6
**/
* @error: return location for a #GError
*
* Returns the value associated with @key under @group_name as a
- * boolean. If @key cannot be found then the return value is
- * undefined and @error is set to
- * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the value
- * associated with @key cannot be interpreted as a boolean then
- * the return value is also undefined and @error is set to
+ * boolean.
+ *
+ * If @key cannot be found then the return value is undefined and
+ * @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if
+ * the value associated with @key cannot be interpreted as a boolean
+ * then the return value is also undefined and @error is set to
* #G_KEY_FILE_ERROR_INVALID_VALUE.
*
* Return value: the value associated with the key as a boolean
* @value: %TRUE or %FALSE
*
* Associates a new boolean value with @key under @group_name.
- * If @key cannot be found then it is created.
+ * If @key cannot be found then it is created.
*
* Since: 2.6
**/
* @error: return location for a #GError
*
* Returns the values associated with @key under @group_name as
- * booleans. If @key cannot be found then the return value is
- * undefined and @error is set to
- * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the values
- * associated with @key cannot be interpreted as booleans then
- * the return value is also undefined and @error is set to
+ * booleans. If @group_name is %NULL, the start_group is used.
+ *
+ * If @key cannot be found then the return value is undefined and
+ * @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if
+ * the values associated with @key cannot be interpreted as booleans
+ * then the return value is also undefined and @error is set to
* #G_KEY_FILE_ERROR_INVALID_VALUE.
*
* Return value: the values associated with the key as a boolean
*
* Associates a list of boolean values with @key under
* @group_name. If @key cannot be found then it is created.
+ * If @group_name is %NULL, the start_group is used.
*
* Since: 2.6
**/
* @error: return location for a #GError
*
* Returns the value associated with @key under @group_name as an
- * integer. If @key cannot be found then the return value is
- * undefined and @error is set to
- * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the value
- * associated with @key cannot be interpreted as an integer then
- * the return value is also undefined and @error is set to
+ * integer. If @group_name is %NULL, the start_group is used.
+ *
+ * If @key cannot be found then the return value is undefined and
+ * @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if
+ * the value associated with @key cannot be interpreted as an integer
+ * then the return value is also undefined and @error is set to
* #G_KEY_FILE_ERROR_INVALID_VALUE.
*
* Return value: the value associated with the key as an integer.
* @error: return location for a #GError
*
* Returns the values associated with @key under @group_name as
- * integers. If @key cannot be found then the return value is
- * undefined and @error is set to
- * #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if the values
- * associated with @key cannot be interpreted as integers then
- * the return value is also undefined and @error is set to
+ * integers.
+ *
+ * If @key cannot be found then the return value is undefined and
+ * @error is set to #G_KEY_FILE_ERROR_KEY_NOT_FOUND. Likewise, if
+ * the values associated with @key cannot be interpreted as integers
+ * then the return value is also undefined and @error is set to
* #G_KEY_FILE_ERROR_INVALID_VALUE.
*
* Return value: the values associated with the key as a integer
g_set_error (error, G_KEY_FILE_ERROR,
G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
_("Key file does not have group '%s'"),
- group_name);
+ group_name ? group_name : "(null)");
return;
}
g_set_error (error, G_KEY_FILE_ERROR,
G_KEY_FILE_ERROR_KEY_NOT_FOUND,
_("Key file does not have key '%s' in group '%s'"),
- key, group_name);
+ key, group->name);
return;
}
g_set_error (error, G_KEY_FILE_ERROR,
G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
_("Key file does not have group '%s'"),
- group_name);
+ group_name ? group_name : "(null)");
return;
}
/**
* g_key_file_set_comment:
* @key_file: a #GKeyFile
- * @group_name: a group name
+ * @group_name: a group name, or %NULL
* @key: a key
* @comment: a comment
* @error: return location for a #GError
GError **error)
{
GKeyFileGroup *group;
+ GKeyFileKeyValuePair *pair;
GList *key_node, *tmp;
GString *string;
gchar *comment;
g_set_error (error, G_KEY_FILE_ERROR,
G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
_("Key file does not have group '%s'"),
- group_name);
+ group_name ? group_name : "(null)");
return NULL;
}
g_set_error (error, G_KEY_FILE_ERROR,
G_KEY_FILE_ERROR_KEY_NOT_FOUND,
_("Key file does not have key '%s' in group '%s'"),
- key, group_name);
+ key, group->name);
return NULL;
}
* key and concatentate them.
*/
tmp = key_node->next;
- while (tmp != NULL)
- {
- GKeyFileKeyValuePair *pair;
+ if (!key_node->next)
+ return NULL;
- pair = (GKeyFileKeyValuePair *) tmp->data;
+ pair = (GKeyFileKeyValuePair *) tmp->data;
+ if (pair->key != NULL)
+ return NULL;
+ while (tmp->next)
+ {
+ pair = (GKeyFileKeyValuePair *) tmp->next->data;
+
if (pair->key != NULL)
break;
+
+ tmp = tmp->next;
+ }
+
+ while (tmp != key_node)
+ {
+ GKeyFileKeyValuePair *pair;
+
+ pair = (GKeyFileKeyValuePair *) tmp->data;
if (string == NULL)
- string = g_string_sized_new (512);
-
+ string = g_string_sized_new (512);
+
comment = g_key_file_parse_value_as_comment (key_file, pair->value);
g_string_append (string, comment);
g_free (comment);
-
- tmp = tmp->next;
+
+ tmp = tmp->prev;
}
if (string != NULL)
}
static gchar *
+get_group_comment (GKeyFile *key_file,
+ GKeyFileGroup *group,
+ GError **error)
+{
+ GString *string;
+ GList *tmp;
+ gchar *comment;
+
+ string = NULL;
+
+ tmp = group->key_value_pairs;
+ while (tmp)
+ {
+ GKeyFileKeyValuePair *pair;
+
+ pair = (GKeyFileKeyValuePair *) tmp->data;
+
+ if (pair->key != NULL)
+ {
+ tmp = tmp->prev;
+ break;
+ }
+
+ if (tmp->next == NULL)
+ break;
+
+ tmp = tmp->next;
+ }
+
+ while (tmp != NULL)
+ {
+ GKeyFileKeyValuePair *pair;
+
+ pair = (GKeyFileKeyValuePair *) tmp->data;
+
+ if (string == NULL)
+ string = g_string_sized_new (512);
+
+ comment = g_key_file_parse_value_as_comment (key_file, pair->value);
+ g_string_append (string, comment);
+ g_free (comment);
+
+ tmp = tmp->prev;
+ }
+
+ if (string != NULL)
+ return g_string_free (string, FALSE);
+
+ return NULL;
+}
+
+static gchar *
g_key_file_get_group_comment (GKeyFile *key_file,
const gchar *group_name,
GError **error)
{
+ GList *group_node;
GKeyFileGroup *group;
- group = g_key_file_lookup_group (key_file, group_name);
+ group_node = g_key_file_lookup_group_node (key_file, group_name);
+ group = (GKeyFileGroup *)group_node->data;
if (!group)
{
g_set_error (error, G_KEY_FILE_ERROR,
G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
_("Key file does not have group '%s'"),
- group_name);
+ group_name ? group_name : "(null)");
return NULL;
}
if (group->comment)
return g_strdup (group->comment->value);
-
- return NULL;
+
+ group_node = group_node->next;
+ group = (GKeyFileGroup *)group_node->data;
+ return get_group_comment (key_file, group, error);
}
static gchar *
g_key_file_get_top_comment (GKeyFile *key_file,
GError **error)
{
- GList *group_node, *tmp;
+ GList *group_node;
GKeyFileGroup *group;
- GString *string;
- gchar *comment;
/* The last group in the list should be the top (comments only)
* group in the file
group = (GKeyFileGroup *) group_node->data;
g_assert (group->name == NULL);
- string = NULL;
-
- /* Then find all the comments already associated with the
- * key and concatentate them.
- */
- tmp = group->key_value_pairs;
- while (tmp != NULL)
- {
- GKeyFileKeyValuePair *pair;
-
- pair = (GKeyFileKeyValuePair *) tmp->data;
-
- if (pair->key != NULL)
- break;
-
- if (string == NULL)
- string = g_string_sized_new (512);
-
- comment = g_key_file_parse_value_as_comment (key_file, pair->value);
- g_string_append (string, comment);
- g_free (comment);
-
- tmp = tmp->next;
- }
-
- if (string != NULL)
- {
- comment = string->str;
- g_string_free (string, FALSE);
- }
- else
- comment = NULL;
-
- return comment;
+ return get_group_comment (key_file, group, error);
}
/**
* g_key_file_get_comment:
* @key_file: a #GKeyFile
- * @group_name: a group name
+ * @group_name: a group name, or %NULL
* @key: a key
* @error: return location for a #GError
*
- * Retreives a comment above @key from @group_name.
+ * Retrieves a comment above @key from @group_name.
* @group_name. If @key is %NULL then @comment will
* be read from above @group_name. If both @key
* and @group_name are NULL, then @comment will
* be read from above the first group in the file.
*
- * Since: 2.6
* Returns: a comment that should be freed with g_free()
+ *
+ * Since: 2.6
**/
gchar *
g_key_file_get_comment (GKeyFile *key_file,
/**
* g_key_file_remove_comment:
* @key_file: a #GKeyFile
- * @group_name: a group name
+ * @group_name: a group name, or %NULL
* @key: a key
* @error: return location for a #GError
*
g_key_file_has_group (GKeyFile *key_file,
const gchar *group_name)
{
- GList *tmp;
- GKeyFileGroup *group;
-
g_return_val_if_fail (key_file != NULL, FALSE);
g_return_val_if_fail (group_name != NULL, FALSE);
- for (tmp = key_file->groups; tmp != NULL; tmp = tmp->next)
- {
- group = (GKeyFileGroup *) tmp->data;
- if (group && group->name && (strcmp (group->name, group_name) == 0))
- return TRUE;
- }
-
- return FALSE;
+ return g_key_file_lookup_group_node (key_file, group_name) != NULL;
}
/**
* @error: return location for a #GError
*
* Looks whether the key file has the key @key in the group
- * @group_name.
+ * @group_name.
*
* Return value: %TRUE if @key is a part of @group_name, %FALSE
* otherwise.
GKeyFileGroup *group;
g_return_val_if_fail (key_file != NULL, FALSE);
- g_return_val_if_fail (key != NULL, FALSE);
g_return_val_if_fail (group_name != NULL, FALSE);
+ g_return_val_if_fail (key != NULL, FALSE);
group = g_key_file_lookup_group (key_file, group_name);
g_set_error (error, G_KEY_FILE_ERROR,
G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
_("Key file does not have group '%s'"),
- group_name);
+ group_name ? group_name : "(null)");
return FALSE;
}
g_return_if_fail (key_file != NULL);
g_return_if_fail (group_name != NULL);
- g_return_if_fail (g_key_file_lookup_group (key_file, group_name) == NULL);
+ g_return_if_fail (g_key_file_lookup_group_node (key_file, group_name) == NULL);
group = g_new0 (GKeyFileGroup, 1);
group->name = g_strdup (group_name);
key_file->approximate_size += strlen (group_name) + 3;
key_file->current_group = group;
- if (key_file->start_group_name == NULL)
- key_file->start_group_name = g_strdup (group_name);
+ if (key_file->start_group == NULL)
+ key_file->start_group = group;
}
static void
group = (GKeyFileGroup *) group_node->data;
- /* If the current group gets deleted make the current group the first
- * group.
+ /* If the current group gets deleted make the current group the last
+ * added group.
*/
if (key_file->current_group == group)
{
key_file->current_group = NULL;
}
+ /* If the start group gets deleted make the start group the first
+ * added group.
+ */
+ if (key_file->start_group == group)
+ {
+ tmp = g_list_last (key_file->groups);
+ while (tmp != NULL)
+ {
+ if (tmp != group_node &&
+ ((GKeyFileGroup *) tmp->data)->name != NULL)
+ break;
+
+ tmp = tmp->prev;
+ }
+
+ if (tmp)
+ key_file->start_group = (GKeyFileGroup *) tmp->data;
+ else
+ key_file->start_group = NULL;
+ }
+
key_file->groups = g_list_remove_link (key_file->groups, group_node);
if (group->name != NULL)
group_node = g_key_file_lookup_group_node (key_file, group_name);
if (!group_node)
- g_set_error (error, G_KEY_FILE_ERROR,
- G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
- _("Key file does not have group '%s'"),
- group_name);
+ {
+ g_set_error (error, G_KEY_FILE_ERROR,
+ G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
+ _("Key file does not have group '%s'"),
+ group_name);
+ return;
+ }
- g_key_file_remove_group_node (key_file, group_node);
+ g_key_file_remove_group_node (key_file, group_node);
}
static void
-g_key_file_add_key (GKeyFile *key_file,
- const gchar *group_name,
- const gchar *key,
- const gchar *value)
+g_key_file_add_key (GKeyFile *key_file,
+ GKeyFileGroup *group,
+ const gchar *key,
+ const gchar *value)
{
- GKeyFileGroup *group;
GKeyFileKeyValuePair *pair;
- group = g_key_file_lookup_group (key_file, group_name);
-
- if (!group)
- {
- g_key_file_add_group (key_file, group_name);
- group = (GKeyFileGroup *) key_file->groups->data;
- }
-
pair = g_new0 (GKeyFileKeyValuePair, 1);
pair->key = g_strdup (key);
pair = NULL;
- if (group_name == NULL)
- group = key_file->current_group;
- else
- group = g_key_file_lookup_group (key_file, group_name);
-
+ group = g_key_file_lookup_group (key_file, group_name);
if (!group)
{
g_set_error (error, G_KEY_FILE_ERROR,
G_KEY_FILE_ERROR_GROUP_NOT_FOUND,
_("Key file does not have group '%s'"),
- group_name);
+ group_name ? group_name : "(null)");
return;
}
- group->key_value_pairs = g_list_remove (group->key_value_pairs, key_file);
pair = g_key_file_lookup_key_value_pair (key_file, group, key);
if (!pair)
{
g_set_error (error, G_KEY_FILE_ERROR,
G_KEY_FILE_ERROR_KEY_NOT_FOUND,
- _("Key file does not have key '%s' in group '%s'"), key, group_name);
+ _("Key file does not have key '%s' in group '%s'"),
+ key, group->name);
return;
}
- g_hash_table_remove (group->lookup_map, pair->key);
-
key_file->approximate_size -= strlen (pair->key) + strlen (pair->value) + 2;
+
+ group->key_value_pairs = g_list_remove (group->key_value_pairs, pair);
+ g_hash_table_remove (group->lookup_map, pair->key);
g_key_file_key_value_pair_free (pair);
}
p = g_utf8_next_char (p);
- if (!*p)
- return FALSE;
-
- p = g_utf8_next_char (p);
-
/* Group name must be non-empty
*/
- if (*p == ']')
+ if (!*p || *p == ']')
return FALSE;
while (*p && *p != ']')
GSList **pieces,
GError **error)
{
- GError *parse_error = NULL;
gchar *string_value, *p, *q0, *q;
string_value = g_new0 (gchar, strlen (value) + 1);
*q = '\\';
break;
+ case '\0':
+ g_set_error (error, G_KEY_FILE_ERROR,
+ G_KEY_FILE_ERROR_INVALID_VALUE,
+ _("Key file contains escape character "
+ "at end of line"));
+ break;
+
default:
if (pieces && *p == key_file->list_separator)
*q = key_file->list_separator;
*q++ = '\\';
*q = *p;
- if (parse_error == NULL)
+ if (*error == NULL)
{
gchar sequence[3];
}
}
+ if (*p == '\0')
+ break;
+
q++;
p++;
}
- if (p[-1] == '\\' && error == NULL)
- g_set_error (error, G_KEY_FILE_ERROR,
- G_KEY_FILE_ERROR_INVALID_VALUE,
- _("Key file contains escape character at end of line"));
-
*q = '\0';
if (pieces)
{
{
gchar *value, *p, *q;
gsize length;
+ gboolean parsing_leading_space;
length = strlen (string) + 1;
p = (gchar *) string;
q = value;
+ parsing_leading_space = TRUE;
while (p < (string + length - 1))
{
gchar escaped_character[3] = { '\\', 0, 0 };
switch (*p)
{
case ' ':
- escaped_character[1] = 's';
- strcpy (q, escaped_character);
- q += 2;
+ if (parsing_leading_space)
+ {
+ escaped_character[1] = 's';
+ strcpy (q, escaped_character);
+ q += 2;
+ }
+ else
+ {
+ *q = *p;
+ q++;
+ }
+ break;
+ case '\t':
+ if (parsing_leading_space)
+ {
+ escaped_character[1] = 't';
+ strcpy (q, escaped_character);
+ q += 2;
+ }
+ else
+ {
+ *q = *p;
+ q++;
+ }
break;
case '\n':
escaped_character[1] = 'n';
strcpy (q, escaped_character);
q += 2;
break;
- case '\t':
- escaped_character[1] = 't';
- strcpy (q, escaped_character);
- q += 2;
- break;
case '\r':
escaped_character[1] = 'r';
strcpy (q, escaped_character);
escaped_character[1] = '\\';
strcpy (q, escaped_character);
q += 2;
+ parsing_leading_space = FALSE;
break;
default:
if (escape_separator && *p == key_file->list_separator)
escaped_character[1] = key_file->list_separator;
strcpy (q, escaped_character);
q += 2;
+ parsing_leading_space = TRUE;
}
else
{
*q = *p;
q++;
+ parsing_leading_space = FALSE;
}
break;
}
GError **error)
{
gchar *end_of_valid_int;
- gint int_value = 0;
+ glong long_value;
+ gint int_value;
- int_value = strtol (value, &end_of_valid_int, 0);
+ errno = 0;
+ long_value = strtol (value, &end_of_valid_int, 10);
- if (*end_of_valid_int != '\0')
- g_set_error (error, G_KEY_FILE_ERROR,
- G_KEY_FILE_ERROR_INVALID_VALUE,
- _("Value '%s' cannot be interpreted as a number."), value);
+ if (*value == '\0' || *end_of_valid_int != '\0')
+ {
+ g_set_error (error, G_KEY_FILE_ERROR,
+ G_KEY_FILE_ERROR_INVALID_VALUE,
+ _("Value '%s' cannot be interpreted as a number."), value);
+ return 0;
+ }
+ int_value = long_value;
+ if (int_value != long_value || errno == ERANGE)
+ {
+ g_set_error (error,
+ G_KEY_FILE_ERROR,
+ G_KEY_FILE_ERROR_INVALID_VALUE,
+ _("Integer value '%s' out of range"), value);
+ return 0;
+ }
+
return int_value;
}
return value;
}
-
+#define __G_KEY_FILE_C__
+#include "galiasdef.c"