X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=glib%2Fgkeyfile.c;h=7a8a7832b814eff073c2da4b7994b3a9a3356e0a;hb=402a1081aef6cd276c0636557413ed5942a771ef;hp=5f9115b6fae9a7e4f9e7a90b64e29e9b2f0181cc;hpb=7e52a0584f2ec6f355f696d84d24e1dae4079280;p=platform%2Fupstream%2Fglib.git diff --git a/glib/gkeyfile.c b/glib/gkeyfile.c index 5f9115b..7a8a783 100644 --- a/glib/gkeyfile.c +++ b/glib/gkeyfile.c @@ -22,7 +22,6 @@ */ #include "config.h" -#include "galias.h" #include "gkeyfile.h" @@ -39,8 +38,13 @@ #endif #ifdef G_OS_WIN32 #include + +#ifndef S_ISREG +#define S_ISREG(mode) ((mode)&_S_IFREG) #endif +#endif /* G_OS_WIN23 */ + #include "gconvert.h" #include "gdataset.h" #include "gerror.h" @@ -56,14 +60,15 @@ #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 */ @@ -107,8 +112,8 @@ static gboolean g_key_file_load_from_fd (GKeyFile 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); @@ -119,61 +124,61 @@ static GKeyFileKeyValuePair *g_key_file_lookup_key_value_pair (GKeyFile 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); @@ -193,7 +198,7 @@ g_key_file_init (GKeyFile *key_file) { 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 = ';'; @@ -208,8 +213,6 @@ g_key_file_clear (GKeyFile *key_file) 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) { @@ -277,9 +280,7 @@ find_file_in_data_dirs (const gchar *file, { gchar **data_dirs, *data_dir, *path; gint fd; - GError *file_error; - file_error = NULL; path = NULL; fd = -1; @@ -303,16 +304,11 @@ find_file_in_data_dirs (const gchar *file, 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, '-'); @@ -336,19 +332,18 @@ find_file_in_data_dirs (const gchar *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; } @@ -360,11 +355,18 @@ g_key_file_load_from_fd (GKeyFile *key_file, 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 (!S_ISREG (stat_buf.st_mode)) { g_set_error (error, G_KEY_FILE_ERROR, @@ -398,7 +400,7 @@ g_key_file_load_from_fd (GKeyFile *key_file, if (bytes_read < 0) { - if (errno == EINTR) + if (errno == EINTR || errno == EAGAIN) continue; g_set_error (error, G_FILE_ERROR, @@ -486,8 +488,9 @@ g_key_file_load_from_file (GKeyFile *key_file, * @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 @@ -505,6 +508,9 @@ g_key_file_load_from_data (GKeyFile *key_file, 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); @@ -570,7 +576,7 @@ g_key_file_load_from_data_dirs (GKeyFile *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); @@ -581,8 +587,11 @@ g_key_file_load_from_data_dirs (GKeyFile *key_file, 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); @@ -590,7 +599,7 @@ g_key_file_load_from_data_dirs (GKeyFile *key_file, { 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, @@ -600,15 +609,17 @@ g_key_file_load_from_data_dirs (GKeyFile *key_file, 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; } @@ -734,9 +745,6 @@ g_key_file_parse_group (GKeyFile *key_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); } @@ -785,11 +793,11 @@ g_key_file_parse_key_value_pair (GKeyFile *key_file, 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) { @@ -810,7 +818,7 @@ g_key_file_parse_key_value_pair (GKeyFile *key_file, 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); @@ -851,6 +859,11 @@ g_key_file_parse_data (GKeyFile *key_file, { 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. @@ -966,13 +979,15 @@ g_key_file_to_data (GKeyFile *key_file, /** * 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. @@ -1000,25 +1015,38 @@ g_key_file_get_keys (GKeyFile *key_file, 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; @@ -1041,7 +1069,10 @@ g_key_file_get_start_group (GKeyFile *key_file) { 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; } /** @@ -1076,7 +1107,7 @@ g_key_file_get_groups (GKeyFile *key_file, * 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); @@ -1108,16 +1139,17 @@ g_key_file_get_groups (GKeyFile *key_file, * @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 **/ @@ -1142,7 +1174,7 @@ g_key_file_get_value (GKeyFile *key_file, 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; } @@ -1165,9 +1197,9 @@ g_key_file_get_value (GKeyFile *key_file, * @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 **/ @@ -1181,17 +1213,30 @@ g_key_file_set_value (GKeyFile *key_file, 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); + } } } @@ -1200,16 +1245,17 @@ g_key_file_set_value (GKeyFile *key_file, * @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 **/ @@ -1277,9 +1323,9 @@ g_key_file_get_string (GKeyFile *key_file, * @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 **/ @@ -1310,6 +1356,7 @@ g_key_file_set_string (GKeyFile *key_file, * @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 @@ -1398,7 +1445,8 @@ g_key_file_get_string_list (GKeyFile *key_file, * @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 **/ @@ -1481,18 +1529,16 @@ extern GSList *_g_compute_locale_variants (const gchar *locale); * * 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 * @@ -1516,15 +1562,6 @@ g_key_file_get_locale_string (GKeyFile *key_file, 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; @@ -1554,20 +1591,12 @@ g_key_file_get_locale_string (GKeyFile *key_file, 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 */ @@ -1578,12 +1607,6 @@ g_key_file_get_locale_string (GKeyFile *key_file, 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) @@ -1603,15 +1626,12 @@ g_key_file_get_locale_string (GKeyFile *key_file, * * 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 @@ -1671,7 +1691,7 @@ g_key_file_get_locale_string_list (GKeyFile *key_file, * * 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 **/ @@ -1720,11 +1740,12 @@ g_key_file_set_locale_string_list (GKeyFile *key_file, * @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 @@ -1784,7 +1805,7 @@ g_key_file_get_boolean (GKeyFile *key_file, * @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 **/ @@ -1814,14 +1835,17 @@ g_key_file_set_boolean (GKeyFile *key_file, * @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 + * + * Since: 2.6 **/ gboolean * g_key_file_get_boolean_list (GKeyFile *key_file, @@ -1885,6 +1909,7 @@ g_key_file_get_boolean_list (GKeyFile *key_file, * * 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 **/ @@ -1928,14 +1953,16 @@ g_key_file_set_boolean_list (GKeyFile *key_file, * @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. + * * Since: 2.6 **/ gint @@ -2024,14 +2051,16 @@ g_key_file_set_integer (GKeyFile *key_file, * @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 + * * Since: 2.6 **/ gint * @@ -2146,7 +2175,7 @@ g_key_file_set_key_comment (GKeyFile *key_file, 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; } @@ -2161,7 +2190,7 @@ g_key_file_set_key_comment (GKeyFile *key_file, 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; } @@ -2211,7 +2240,7 @@ g_key_file_set_group_comment (GKeyFile *key_file, 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; } @@ -2279,7 +2308,7 @@ g_key_file_set_top_comment (GKeyFile *key_file, /** * 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 @@ -2319,6 +2348,7 @@ g_key_file_get_key_comment (GKeyFile *key_file, GError **error) { GKeyFileGroup *group; + GKeyFileKeyValuePair *pair; GList *key_node, *tmp; GString *string; gchar *comment; @@ -2329,7 +2359,7 @@ g_key_file_get_key_comment (GKeyFile *key_file, 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; } @@ -2344,7 +2374,7 @@ g_key_file_get_key_comment (GKeyFile *key_file, 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; } @@ -2354,23 +2384,37 @@ g_key_file_get_key_comment (GKeyFile *key_file, * 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) @@ -2385,37 +2429,91 @@ g_key_file_get_key_comment (GKeyFile *key_file, } 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 @@ -2425,57 +2523,25 @@ g_key_file_get_top_comment (GKeyFile *key_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, @@ -2496,7 +2562,7 @@ 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 * @@ -2540,20 +2606,10 @@ gboolean 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; } /** @@ -2564,10 +2620,11 @@ g_key_file_has_group (GKeyFile *key_file, * @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. + * * Since: 2.6 **/ gboolean @@ -2580,8 +2637,8 @@ g_key_file_has_key (GKeyFile *key_file, 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); @@ -2590,7 +2647,7 @@ g_key_file_has_key (GKeyFile *key_file, 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; } @@ -2608,7 +2665,7 @@ g_key_file_add_group (GKeyFile *key_file, 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); @@ -2617,8 +2674,8 @@ g_key_file_add_group (GKeyFile *key_file, 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 @@ -2673,8 +2730,8 @@ g_key_file_remove_group_node (GKeyFile *key_file, 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) { @@ -2687,6 +2744,27 @@ g_key_file_remove_group_node (GKeyFile *key_file, 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) @@ -2739,31 +2817,25 @@ g_key_file_remove_group (GKeyFile *key_file, 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); @@ -2800,34 +2872,31 @@ g_key_file_remove_key (GKeyFile *key_file, 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); } @@ -2920,14 +2989,9 @@ g_key_file_line_is_group (const gchar *line) 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 != ']') @@ -2963,7 +3027,6 @@ g_key_file_parse_value_as_string (GKeyFile *key_file, GSList **pieces, GError **error) { - GError *parse_error = NULL; gchar *string_value, *p, *q0, *q; string_value = g_new0 (gchar, strlen (value) + 1); @@ -2998,6 +3061,13 @@ g_key_file_parse_value_as_string (GKeyFile *key_file, *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; @@ -3006,7 +3076,7 @@ g_key_file_parse_value_as_string (GKeyFile *key_file, *q++ = '\\'; *q = *p; - if (parse_error == NULL) + if (*error == NULL) { gchar sequence[3]; @@ -3033,15 +3103,13 @@ g_key_file_parse_value_as_string (GKeyFile *key_file, } } + 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) { @@ -3060,6 +3128,7 @@ g_key_file_parse_string_as_value (GKeyFile *key_file, { gchar *value, *p, *q; gsize length; + gboolean parsing_leading_space; length = strlen (string) + 1; @@ -3070,6 +3139,7 @@ g_key_file_parse_string_as_value (GKeyFile *key_file, p = (gchar *) string; q = value; + parsing_leading_space = TRUE; while (p < (string + length - 1)) { gchar escaped_character[3] = { '\\', 0, 0 }; @@ -3077,20 +3147,36 @@ g_key_file_parse_string_as_value (GKeyFile *key_file, 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); @@ -3100,6 +3186,7 @@ g_key_file_parse_string_as_value (GKeyFile *key_file, escaped_character[1] = '\\'; strcpy (q, escaped_character); q += 2; + parsing_leading_space = FALSE; break; default: if (escape_separator && *p == key_file->list_separator) @@ -3107,11 +3194,13 @@ g_key_file_parse_string_as_value (GKeyFile *key_file, 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; } @@ -3128,15 +3217,30 @@ g_key_file_parse_value_as_integer (GKeyFile *key_file, 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; } @@ -3230,4 +3334,5 @@ g_key_file_parse_comment_as_value (GKeyFile *key_file, return value; } - +#define __G_KEY_FILE_C__ +#include "galiasdef.c"