Merge branch 'keyfile-parsing-performance' into 'main'

Keyfile parsing performance improvements

See merge request GNOME/glib!1991
This commit is contained in:
Sebastian Dröge 2021-11-02 11:08:15 +00:00
commit 82be9c4f11
3 changed files with 184 additions and 150 deletions

View File

@ -511,8 +511,8 @@ struct _GKeyFile
GKeyFileFlags flags; GKeyFileFlags flags;
gboolean checked_locales; gboolean checked_locales; /* TRUE if @locales has been initialised */
gchar **locales; gchar **locales; /* (nullable) */
gint ref_count; /* (atomic) */ gint ref_count; /* (atomic) */
}; };
@ -575,7 +575,8 @@ static void g_key_file_add_key (GKeyFile
static void g_key_file_add_group (GKeyFile *key_file, static void g_key_file_add_group (GKeyFile *key_file,
const gchar *group_name); const gchar *group_name);
static gboolean g_key_file_is_group_name (const gchar *name); static gboolean g_key_file_is_group_name (const gchar *name);
static gboolean g_key_file_is_key_name (const gchar *name); static gboolean g_key_file_is_key_name (const gchar *name,
gsize len);
static void g_key_file_key_value_pair_free (GKeyFileKeyValuePair *pair); 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_comment (const gchar *line);
static gboolean g_key_file_line_is_group (const gchar *line); static gboolean g_key_file_line_is_group (const gchar *line);
@ -598,7 +599,7 @@ static gdouble g_key_file_parse_value_as_double (GKeyFile
static gboolean g_key_file_parse_value_as_boolean (GKeyFile *key_file, static gboolean g_key_file_parse_value_as_boolean (GKeyFile *key_file,
const gchar *value, const gchar *value,
GError **error); GError **error);
static gchar *g_key_file_parse_boolean_as_value (GKeyFile *key_file, static const gchar *g_key_file_parse_boolean_as_value (GKeyFile *key_file,
gboolean value); gboolean value);
static gchar *g_key_file_parse_value_as_comment (GKeyFile *key_file, static gchar *g_key_file_parse_value_as_comment (GKeyFile *key_file,
const gchar *value, const gchar *value,
@ -617,7 +618,8 @@ static void g_key_file_parse_group (GKeyFile
const gchar *line, const gchar *line,
gsize length, gsize length,
GError **error); GError **error);
static gchar *key_get_locale (const gchar *key); static const gchar *key_get_locale (const gchar *key,
gsize *len_out);
static void g_key_file_parse_data (GKeyFile *key_file, static void g_key_file_parse_data (GKeyFile *key_file,
const gchar *data, const gchar *data,
gsize length, gsize length,
@ -745,9 +747,10 @@ find_file_in_data_dirs (const gchar *file,
while (data_dirs && (data_dir = *data_dirs) && fd == -1) while (data_dirs && (data_dir = *data_dirs) && fd == -1)
{ {
gchar *candidate_file, *sub_dir; const gchar *candidate_file;
gchar *sub_dir;
candidate_file = (gchar *) file; candidate_file = file;
sub_dir = g_strdup (""); sub_dir = g_strdup ("");
while (candidate_file != NULL && fd == -1) while (candidate_file != NULL && fd == -1)
{ {
@ -1227,7 +1230,8 @@ g_key_file_unref (GKeyFile *key_file)
*/ */
static gboolean static gboolean
g_key_file_locale_is_interesting (GKeyFile *key_file, g_key_file_locale_is_interesting (GKeyFile *key_file,
const gchar *locale) const gchar *locale,
gsize locale_len)
{ {
gsize i; gsize i;
@ -1236,13 +1240,15 @@ g_key_file_locale_is_interesting (GKeyFile *key_file,
if (!key_file->checked_locales) if (!key_file->checked_locales)
{ {
g_assert (key_file->locales == NULL);
key_file->locales = g_strdupv ((gchar **)g_get_language_names ()); key_file->locales = g_strdupv ((gchar **)g_get_language_names ());
key_file->checked_locales = TRUE; key_file->checked_locales = TRUE;
} }
for (i = 0; key_file->locales[i] != NULL; i++) for (i = 0; key_file->locales[i] != NULL; i++)
{ {
if (g_ascii_strcasecmp (key_file->locales[i], locale) == 0) if (g_ascii_strncasecmp (key_file->locales[i], locale, locale_len) == 0 &&
key_file->locales[i][locale_len] == '\0')
return TRUE; return TRUE;
} }
@ -1256,12 +1262,12 @@ g_key_file_parse_line (GKeyFile *key_file,
GError **error) GError **error)
{ {
GError *parse_error = NULL; GError *parse_error = NULL;
gchar *line_start; const gchar *line_start;
g_return_if_fail (key_file != NULL); g_return_if_fail (key_file != NULL);
g_return_if_fail (line != NULL); g_return_if_fail (line != NULL);
line_start = (gchar *) line; line_start = line;
while (g_ascii_isspace (*line_start)) while (g_ascii_isspace (*line_start))
line_start++; line_start++;
@ -1352,7 +1358,9 @@ g_key_file_parse_key_value_pair (GKeyFile *key_file,
gsize length, gsize length,
GError **error) GError **error)
{ {
gchar *key, *value, *key_end, *value_start, *locale; gchar *key, *key_end, *value_start;
const gchar *locale;
gsize locale_len;
gsize key_len, value_len; gsize key_len, value_len;
if (key_file->current_group == NULL || key_file->current_group->name == NULL) if (key_file->current_group == NULL || key_file->current_group->name == NULL)
@ -1379,37 +1387,36 @@ g_key_file_parse_key_value_pair (GKeyFile *key_file,
g_warn_if_fail (key_len <= length); g_warn_if_fail (key_len <= length);
key = g_strndup (line, key_len - 1); if (!g_key_file_is_key_name (line, key_len - 1))
if (!g_key_file_is_key_name (key))
{ {
g_set_error (error, G_KEY_FILE_ERROR, g_set_error (error, G_KEY_FILE_ERROR,
G_KEY_FILE_ERROR_PARSE, G_KEY_FILE_ERROR_PARSE,
_("Invalid key name: %s"), key); _("Invalid key name: %.*s"), (int) key_len - 1, line);
g_free (key);
return; return;
} }
key = g_strndup (line, key_len - 1);
/* Pull the value from the line (chugging leading whitespace) /* Pull the value from the line (chugging leading whitespace)
*/ */
while (g_ascii_isspace (*value_start)) while (g_ascii_isspace (*value_start))
value_start++; value_start++;
value_len = line + length - value_start + 1; value_len = line + length - value_start;
value = g_strndup (value_start, value_len);
g_warn_if_fail (key_file->start_group != NULL); g_warn_if_fail (key_file->start_group != NULL);
if (key_file->current_group /* Checked on entry to this function */
&& key_file->current_group->name g_assert (key_file->current_group != NULL);
&& strcmp (key_file->start_group->name, g_assert (key_file->current_group->name != NULL);
key_file->current_group->name) == 0
if (key_file->start_group == key_file->current_group
&& strcmp (key, "Encoding") == 0) && strcmp (key, "Encoding") == 0)
{ {
if (g_ascii_strcasecmp (value, "UTF-8") != 0) if (value_len != strlen ("UTF-8") ||
g_ascii_strncasecmp (value_start, "UTF-8", value_len) != 0)
{ {
gchar *value_utf8 = g_utf8_make_valid (value, value_len); gchar *value_utf8 = g_utf8_make_valid (value_start, value_len);
g_set_error (error, G_KEY_FILE_ERROR, g_set_error (error, G_KEY_FILE_ERROR,
G_KEY_FILE_ERROR_UNKNOWN_ENCODING, G_KEY_FILE_ERROR_UNKNOWN_ENCODING,
_("Key file contains unsupported " _("Key file contains unsupported "
@ -1417,47 +1424,53 @@ g_key_file_parse_key_value_pair (GKeyFile *key_file,
g_free (value_utf8); g_free (value_utf8);
g_free (key); g_free (key);
g_free (value);
return; return;
} }
} }
/* Is this key a translation? If so, is it one that we care about? /* Is this key a translation? If so, is it one that we care about?
*/ */
locale = key_get_locale (key); locale = key_get_locale (key, &locale_len);
if (locale == NULL || g_key_file_locale_is_interesting (key_file, locale)) if (locale == NULL || g_key_file_locale_is_interesting (key_file, locale, locale_len))
{ {
GKeyFileKeyValuePair *pair; GKeyFileKeyValuePair *pair;
pair = g_slice_new (GKeyFileKeyValuePair); pair = g_slice_new (GKeyFileKeyValuePair);
pair->key = key; pair->key = g_steal_pointer (&key);
pair->value = value; pair->value = g_strndup (value_start, value_len);
g_key_file_add_key_value_pair (key_file, key_file->current_group, pair); g_key_file_add_key_value_pair (key_file, key_file->current_group, pair);
} }
else
{
g_free (key);
g_free (value);
}
g_free (locale); g_free (key);
} }
static gchar * static const gchar *
key_get_locale (const gchar *key) key_get_locale (const gchar *key,
gsize *len_out)
{ {
gchar *locale; const gchar *locale;
gsize locale_len;
locale = g_strrstr (key, "["); locale = g_strrstr (key, "[");
if (locale != NULL)
locale_len = strlen (locale);
else
locale_len = 0;
if (locale && strlen (locale) <= 2) if (locale_len > 2)
locale = NULL; {
locale++; /* skip `[` */
if (locale) locale_len -= 2; /* drop `[` and `]` */
locale = g_strndup (locale + 1, strlen (locale) - 2); }
else
{
locale = NULL;
locale_len = 0;
}
*len_out = locale_len;
return locale; return locale;
} }
@ -1875,8 +1888,8 @@ g_key_file_set_value (GKeyFile *key_file,
GKeyFileKeyValuePair *pair; GKeyFileKeyValuePair *pair;
g_return_if_fail (key_file != NULL); g_return_if_fail (key_file != NULL);
g_return_if_fail (g_key_file_is_group_name (group_name)); g_return_if_fail (group_name != NULL && g_key_file_is_group_name (group_name));
g_return_if_fail (g_key_file_is_key_name (key)); g_return_if_fail (key != NULL && g_key_file_is_key_name (key, strlen (key)));
g_return_if_fail (value != NULL); g_return_if_fail (value != NULL);
group = g_key_file_lookup_group (key_file, group_name); group = g_key_file_lookup_group (key_file, group_name);
@ -2556,13 +2569,12 @@ g_key_file_set_boolean (GKeyFile *key_file,
const gchar *key, const gchar *key,
gboolean value) gboolean value)
{ {
gchar *result; const gchar *result;
g_return_if_fail (key_file != NULL); g_return_if_fail (key_file != NULL);
result = g_key_file_parse_boolean_as_value (key_file, value); result = g_key_file_parse_boolean_as_value (key_file, value);
g_key_file_set_value (key_file, group_name, key, result); g_key_file_set_value (key_file, group_name, key, result);
g_free (result);
} }
/** /**
@ -2673,14 +2685,12 @@ g_key_file_set_boolean_list (GKeyFile *key_file,
value_list = g_string_sized_new (length * 8); value_list = g_string_sized_new (length * 8);
for (i = 0; i < length; i++) for (i = 0; i < length; i++)
{ {
gchar *value; const gchar *value;
value = g_key_file_parse_boolean_as_value (key_file, list[i]); value = g_key_file_parse_boolean_as_value (key_file, list[i]);
g_string_append (value_list, value); g_string_append (value_list, value);
g_string_append_c (value_list, key_file->list_separator); g_string_append_c (value_list, key_file->list_separator);
g_free (value);
} }
g_key_file_set_value (key_file, group_name, key, value_list->str); g_key_file_set_value (key_file, group_name, key, value_list->str);
@ -3341,7 +3351,7 @@ g_key_file_set_group_comment (GKeyFile *key_file,
{ {
GKeyFileGroup *group; GKeyFileGroup *group;
g_return_val_if_fail (g_key_file_is_group_name (group_name), FALSE); g_return_val_if_fail (group_name != NULL && g_key_file_is_group_name (group_name), FALSE);
group = g_key_file_lookup_group (key_file, group_name); group = g_key_file_lookup_group (key_file, group_name);
if (!group) if (!group)
@ -3471,7 +3481,7 @@ g_key_file_get_key_comment (GKeyFile *key_file,
GString *string; GString *string;
gchar *comment; gchar *comment;
g_return_val_if_fail (g_key_file_is_group_name (group_name), NULL); g_return_val_if_fail (group_name != NULL && g_key_file_is_group_name (group_name), NULL);
group = g_key_file_lookup_group (key_file, group_name); group = g_key_file_lookup_group (key_file, group_name);
if (!group) if (!group)
@ -3818,7 +3828,7 @@ g_key_file_add_group (GKeyFile *key_file,
GKeyFileGroup *group; GKeyFileGroup *group;
g_return_if_fail (key_file != NULL); g_return_if_fail (key_file != NULL);
g_return_if_fail (g_key_file_is_group_name (group_name)); g_return_if_fail (group_name != NULL && g_key_file_is_group_name (group_name));
group = g_key_file_lookup_group (key_file, group_name); group = g_key_file_lookup_group (key_file, group_name);
if (group != NULL) if (group != NULL)
@ -4083,17 +4093,12 @@ g_key_file_lookup_group_node (GKeyFile *key_file,
const gchar *group_name) const gchar *group_name)
{ {
GKeyFileGroup *group; GKeyFileGroup *group;
GList *tmp;
for (tmp = key_file->groups; tmp != NULL; tmp = tmp->next) group = g_key_file_lookup_group (key_file, group_name);
{ if (group == NULL)
group = (GKeyFileGroup *) tmp->data; return NULL;
if (group && group->name && strcmp (group->name, group_name) == 0) return g_list_find (key_file->groups, group);
break;
}
return tmp;
} }
static GKeyFileGroup * static GKeyFileGroup *
@ -4149,12 +4154,11 @@ g_key_file_line_is_comment (const gchar *line)
static gboolean static gboolean
g_key_file_is_group_name (const gchar *name) g_key_file_is_group_name (const gchar *name)
{ {
gchar *p, *q; const gchar *p, *q;
if (name == NULL) g_assert (name != NULL);
return FALSE;
p = q = (gchar *) name; p = q = name;
while (*q && *q != ']' && *q != '[' && !g_ascii_iscntrl (*q)) while (*q && *q != ']' && *q != '[' && !g_ascii_iscntrl (*q))
q = g_utf8_find_next_char (q, NULL); q = g_utf8_find_next_char (q, NULL);
@ -4165,19 +4169,25 @@ g_key_file_is_group_name (const gchar *name)
} }
static gboolean static gboolean
g_key_file_is_key_name (const gchar *name) g_key_file_is_key_name (const gchar *name,
gsize len)
{ {
gchar *p, *q; const gchar *p, *q, *end;
if (name == NULL) g_assert (name != NULL);
return FALSE;
p = q = name;
end = name + len;
p = q = (gchar *) name;
/* We accept a little more than the desktop entry spec says, /* We accept a little more than the desktop entry spec says,
* since gnome-vfs uses mime-types as keys in its cache. * since gnome-vfs uses mime-types as keys in its cache.
*/ */
while (*q && *q != '=' && *q != '[' && *q != ']') while (q < end && *q && *q != '=' && *q != '[' && *q != ']')
q = g_utf8_find_next_char (q, NULL); {
q = g_utf8_find_next_char (q, end);
if (q == NULL)
q = end;
}
/* No empty keys, please */ /* No empty keys, please */
if (q == p) if (q == p)
@ -4194,8 +4204,17 @@ g_key_file_is_key_name (const gchar *name)
if (*q == '[') if (*q == '[')
{ {
q++; q++;
while (*q && (g_unichar_isalnum (g_utf8_get_char_validated (q, -1)) || *q == '-' || *q == '_' || *q == '.' || *q == '@')) while (q < end &&
q = g_utf8_find_next_char (q, NULL); *q != '\0' &&
(g_unichar_isalnum (g_utf8_get_char_validated (q, end - q)) || *q == '-' || *q == '_' || *q == '.' || *q == '@'))
{
q = g_utf8_find_next_char (q, end);
if (q == NULL)
{
q = end;
break;
}
}
if (*q != ']') if (*q != ']')
return FALSE; return FALSE;
@ -4203,7 +4222,7 @@ g_key_file_is_key_name (const gchar *name)
q++; q++;
} }
if (*q != '\0') if (q < end)
return FALSE; return FALSE;
return TRUE; return TRUE;
@ -4215,9 +4234,9 @@ g_key_file_is_key_name (const gchar *name)
static gboolean static gboolean
g_key_file_line_is_group (const gchar *line) g_key_file_line_is_group (const gchar *line)
{ {
gchar *p; const gchar *p;
p = (gchar *) line; p = line;
if (*p != '[') if (*p != '[')
return FALSE; return FALSE;
@ -4243,9 +4262,9 @@ g_key_file_line_is_group (const gchar *line)
static gboolean static gboolean
g_key_file_line_is_key_value_pair (const gchar *line) g_key_file_line_is_key_value_pair (const gchar *line)
{ {
gchar *p; const gchar *p;
p = (gchar *) g_utf8_strchr (line, -1, '='); p = g_utf8_strchr (line, -1, '=');
if (!p) if (!p)
return FALSE; return FALSE;
@ -4264,11 +4283,12 @@ g_key_file_parse_value_as_string (GKeyFile *key_file,
GSList **pieces, GSList **pieces,
GError **error) GError **error)
{ {
gchar *string_value, *p, *q0, *q; gchar *string_value, *q0, *q;
const gchar *p;
string_value = g_new (gchar, strlen (value) + 1); string_value = g_new (gchar, strlen (value) + 1);
p = (gchar *) value; p = value;
q0 = q = string_value; q0 = q = string_value;
while (*p) while (*p)
{ {
@ -4363,7 +4383,8 @@ g_key_file_parse_string_as_value (GKeyFile *key_file,
const gchar *string, const gchar *string,
gboolean escape_separator) gboolean escape_separator)
{ {
gchar *value, *p, *q; gchar *value, *q;
const gchar *p;
gsize length; gsize length;
gboolean parsing_leading_space; gboolean parsing_leading_space;
@ -4374,7 +4395,7 @@ g_key_file_parse_string_as_value (GKeyFile *key_file,
*/ */
value = g_new (gchar, 2 * length); value = g_new (gchar, 2 * length);
p = (gchar *) string; p = string;
q = value; q = value;
parsing_leading_space = TRUE; parsing_leading_space = TRUE;
while (p < (string + length - 1)) while (p < (string + length - 1))
@ -4560,14 +4581,14 @@ g_key_file_parse_value_as_boolean (GKeyFile *key_file,
return FALSE; return FALSE;
} }
static gchar * static const gchar *
g_key_file_parse_boolean_as_value (GKeyFile *key_file, g_key_file_parse_boolean_as_value (GKeyFile *key_file,
gboolean value) gboolean value)
{ {
if (value) if (value)
return g_strdup ("true"); return "true";
else else
return g_strdup ("false"); return "false";
} }
static gchar * static gchar *

View File

@ -1874,7 +1874,9 @@ g_ascii_strcasecmp (const gchar *s1,
* @n: number of characters to compare * @n: number of characters to compare
* *
* Compare @s1 and @s2, ignoring the case of ASCII characters and any * Compare @s1 and @s2, ignoring the case of ASCII characters and any
* characters after the first @n in each string. * characters after the first @n in each string. If either string is
* less than @n bytes long, comparison will stop at the first nul byte
* encountered.
* *
* Unlike the BSD strcasecmp() function, this only recognizes standard * Unlike the BSD strcasecmp() function, this only recognizes standard
* ASCII letters and ignores the locale, treating all non-ASCII * ASCII letters and ignores the locale, treating all non-ASCII

View File

@ -45,7 +45,7 @@ check_string_value (GKeyFile *keyfile,
value = g_key_file_get_string (keyfile, group, key, &error); value = g_key_file_get_string (keyfile, group, key, &error);
check_no_error (&error); check_no_error (&error);
g_assert (value != NULL); g_assert_nonnull (value);
g_assert_cmpstr (value, ==, expected); g_assert_cmpstr (value, ==, expected);
g_free (value); g_free (value);
} }
@ -62,7 +62,7 @@ check_locale_string_value (GKeyFile *keyfile,
value = g_key_file_get_locale_string (keyfile, group, key, locale, &error); value = g_key_file_get_locale_string (keyfile, group, key, locale, &error);
check_no_error (&error); check_no_error (&error);
g_assert (value != NULL); g_assert_nonnull (value);
g_assert_cmpstr (value, ==, expected); g_assert_cmpstr (value, ==, expected);
g_free (value); g_free (value);
} }
@ -95,14 +95,14 @@ check_string_list_value (GKeyFile *keyfile,
value = g_key_file_get_string_list (keyfile, group, key, &len, &error); value = g_key_file_get_string_list (keyfile, group, key, &len, &error);
check_no_error (&error); check_no_error (&error);
g_assert (value != NULL); g_assert_nonnull (value);
va_start (args, key); va_start (args, key);
i = 0; i = 0;
v = va_arg (args, gchar*); v = va_arg (args, gchar*);
while (v) while (v)
{ {
g_assert (value[i] != NULL); g_assert_nonnull (value[i]);
g_assert_cmpstr (v, ==, value[i]); g_assert_cmpstr (v, ==, value[i]);
i++; i++;
v = va_arg (args, gchar*); v = va_arg (args, gchar*);
@ -128,14 +128,14 @@ check_locale_string_list_value (GKeyFile *keyfile,
value = g_key_file_get_locale_string_list (keyfile, group, key, locale, &len, &error); value = g_key_file_get_locale_string_list (keyfile, group, key, locale, &len, &error);
check_no_error (&error); check_no_error (&error);
g_assert (value != NULL); g_assert_nonnull (value);
va_start (args, locale); va_start (args, locale);
i = 0; i = 0;
v = va_arg (args, gchar*); v = va_arg (args, gchar*);
while (v) while (v)
{ {
g_assert (value[i] != NULL); g_assert_nonnull (value[i]);
g_assert_cmpstr (v, ==, value[i]); g_assert_cmpstr (v, ==, value[i]);
i++; i++;
v = va_arg (args, gchar*); v = va_arg (args, gchar*);
@ -160,7 +160,7 @@ check_integer_list_value (GKeyFile *keyfile,
value = g_key_file_get_integer_list (keyfile, group, key, &len, &error); value = g_key_file_get_integer_list (keyfile, group, key, &len, &error);
check_no_error (&error); check_no_error (&error);
g_assert (value != NULL); g_assert_nonnull (value);
va_start (args, key); va_start (args, key);
i = 0; i = 0;
@ -192,7 +192,7 @@ check_double_list_value (GKeyFile *keyfile,
value = g_key_file_get_double_list (keyfile, group, key, &len, &error); value = g_key_file_get_double_list (keyfile, group, key, &len, &error);
check_no_error (&error); check_no_error (&error);
g_assert (value != NULL); g_assert_nonnull (value);
va_start (args, key); va_start (args, key);
i = 0; i = 0;
@ -224,7 +224,7 @@ check_boolean_list_value (GKeyFile *keyfile,
value = g_key_file_get_boolean_list (keyfile, group, key, &len, &error); value = g_key_file_get_boolean_list (keyfile, group, key, &len, &error);
check_no_error (&error); check_no_error (&error);
g_assert (value != NULL); g_assert_nonnull (value);
va_start (args, key); va_start (args, key);
i = 0; i = 0;
@ -436,7 +436,7 @@ test_comments (void)
check_no_error (&error); check_no_error (&error);
comment = g_key_file_get_comment (keyfile, "group1", "key2", &error); comment = g_key_file_get_comment (keyfile, "group1", "key2", &error);
check_no_error (&error); check_no_error (&error);
g_assert (comment == NULL); g_assert_null (comment);
comment = g_key_file_get_comment (keyfile, "group1", "key4", &error); comment = g_key_file_get_comment (keyfile, "group1", "key4", &error);
check_no_error (&error); check_no_error (&error);
@ -452,7 +452,7 @@ test_comments (void)
check_error (&error, check_error (&error,
G_KEY_FILE_ERROR, G_KEY_FILE_ERROR,
G_KEY_FILE_ERROR_GROUP_NOT_FOUND); G_KEY_FILE_ERROR_GROUP_NOT_FOUND);
g_assert (comment == NULL); g_assert_null (comment);
g_key_file_free (keyfile); g_key_file_free (keyfile);
} }
@ -479,7 +479,7 @@ test_listing (void)
keyfile = load_data (data, 0); keyfile = load_data (data, 0);
names = g_key_file_get_groups (keyfile, &len); names = g_key_file_get_groups (keyfile, &len);
g_assert (names != NULL); g_assert_nonnull (names);
check_length ("groups", g_strv_length (names), len, 2); check_length ("groups", g_strv_length (names), len, 2);
check_name ("group name", names[0], "group1", 0); check_name ("group name", names[0], "group1", 0);
@ -501,20 +501,20 @@ test_listing (void)
g_strfreev (names); g_strfreev (names);
g_assert (g_key_file_has_group (keyfile, "group1")); g_assert_true (g_key_file_has_group (keyfile, "group1"));
g_assert (g_key_file_has_group (keyfile, "group2")); g_assert_true (g_key_file_has_group (keyfile, "group2"));
g_assert (!g_key_file_has_group (keyfile, "group10")); g_assert_false (g_key_file_has_group (keyfile, "group10"));
g_assert (!g_key_file_has_group (keyfile, "group20")); g_assert_false (g_key_file_has_group (keyfile, "group20"));
start = g_key_file_get_start_group (keyfile); start = g_key_file_get_start_group (keyfile);
g_assert_cmpstr (start, ==, "group1"); g_assert_cmpstr (start, ==, "group1");
g_free (start); g_free (start);
g_assert (g_key_file_has_key (keyfile, "group1", "key1", &error)); g_assert_true (g_key_file_has_key (keyfile, "group1", "key1", &error));
check_no_error (&error); check_no_error (&error);
g_assert (g_key_file_has_key (keyfile, "group2", "key3", &error)); g_assert_true (g_key_file_has_key (keyfile, "group2", "key3", &error));
check_no_error (&error); check_no_error (&error);
g_assert (!g_key_file_has_key (keyfile, "group2", "no-such-key", NULL)); g_assert_false (g_key_file_has_key (keyfile, "group2", "no-such-key", NULL));
g_key_file_has_key (keyfile, "no-such-group", "key", &error); g_key_file_has_key (keyfile, "no-such-group", "key", &error);
check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND); check_error (&error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND);
@ -902,7 +902,7 @@ test_group_remove (void)
keyfile = load_data (data, 0); keyfile = load_data (data, 0);
names = g_key_file_get_groups (keyfile, &len); names = g_key_file_get_groups (keyfile, &len);
g_assert (names != NULL); g_assert_nonnull (names);
check_length ("groups", g_strv_length (names), len, 3); check_length ("groups", g_strv_length (names), len, 3);
check_name ("group name", names[0], "group1", 0); check_name ("group name", names[0], "group1", 0);
@ -915,7 +915,7 @@ test_group_remove (void)
g_strfreev (names); g_strfreev (names);
names = g_key_file_get_groups (keyfile, &len); names = g_key_file_get_groups (keyfile, &len);
g_assert (names != NULL); g_assert_nonnull (names);
check_length ("groups", g_strv_length (names), len, 2); check_length ("groups", g_strv_length (names), len, 2);
check_name ("group name", names[0], "group2", 0); check_name ("group name", names[0], "group2", 0);
@ -927,7 +927,7 @@ test_group_remove (void)
g_strfreev (names); g_strfreev (names);
names = g_key_file_get_groups (keyfile, &len); names = g_key_file_get_groups (keyfile, &len);
g_assert (names != NULL); g_assert_nonnull (names);
check_length ("groups", g_strv_length (names), len, 1); check_length ("groups", g_strv_length (names), len, 1);
check_name ("group name", names[0], "group3", 0); check_name ("group name", names[0], "group3", 0);
@ -1058,7 +1058,7 @@ test_group_names (void)
check_error (&error, check_error (&error,
G_KEY_FILE_ERROR, G_KEY_FILE_ERROR,
G_KEY_FILE_ERROR_GROUP_NOT_FOUND); G_KEY_FILE_ERROR_GROUP_NOT_FOUND);
g_assert (value == NULL); g_assert_null (value);
g_key_file_free (keyfile); g_key_file_free (keyfile);
keyfile = g_key_file_new (); keyfile = g_key_file_new ();
@ -1067,7 +1067,7 @@ test_group_names (void)
check_error (&error, check_error (&error,
G_KEY_FILE_ERROR, G_KEY_FILE_ERROR,
G_KEY_FILE_ERROR_GROUP_NOT_FOUND); G_KEY_FILE_ERROR_GROUP_NOT_FOUND);
g_assert (value == NULL); g_assert_null (value);
g_key_file_free (keyfile); g_key_file_free (keyfile);
keyfile = g_key_file_new (); keyfile = g_key_file_new ();
@ -1076,7 +1076,7 @@ test_group_names (void)
check_error (&error, check_error (&error,
G_KEY_FILE_ERROR, G_KEY_FILE_ERROR,
G_KEY_FILE_ERROR_GROUP_NOT_FOUND); G_KEY_FILE_ERROR_GROUP_NOT_FOUND);
g_assert (value == NULL); g_assert_null (value);
g_key_file_free (keyfile); g_key_file_free (keyfile);
keyfile = g_key_file_new (); keyfile = g_key_file_new ();
@ -1335,7 +1335,7 @@ test_reload_idempotency (void)
check_no_error (&error); check_no_error (&error);
data1 = g_key_file_to_data (keyfile, &len1, &error); data1 = g_key_file_to_data (keyfile, &len1, &error);
g_assert (data1 != NULL); g_assert_nonnull (data1);
g_key_file_free (keyfile); g_key_file_free (keyfile);
keyfile = g_key_file_new (); keyfile = g_key_file_new ();
@ -1346,7 +1346,7 @@ test_reload_idempotency (void)
check_no_error (&error); check_no_error (&error);
data2 = g_key_file_to_data (keyfile, &len2, &error); data2 = g_key_file_to_data (keyfile, &len2, &error);
g_assert (data2 != NULL); g_assert_nonnull (data2);
g_key_file_free (keyfile); g_key_file_free (keyfile);
g_assert_cmpstr (data1, ==, data2); g_assert_cmpstr (data1, ==, data2);
@ -1377,13 +1377,13 @@ test_int64 (void)
ok = g_key_file_load_from_data (file, int64_data, strlen (int64_data), ok = g_key_file_load_from_data (file, int64_data, strlen (int64_data),
0, NULL); 0, NULL);
g_assert (ok); g_assert_true (ok);
c = g_key_file_get_uint64 (file, "bees", "c", NULL); c = g_key_file_get_uint64 (file, "bees", "c", NULL);
g_assert (c == G_GUINT64_CONSTANT (123456789123456789)); g_assert_cmpuint (c, ==, G_GUINT64_CONSTANT (123456789123456789));
d = g_key_file_get_int64 (file, "bees", "d", NULL); d = g_key_file_get_int64 (file, "bees", "d", NULL);
g_assert (d == G_GINT64_CONSTANT (-123456789123456789)); g_assert_cmpint (d, ==, G_GINT64_CONSTANT (-123456789123456789));
g_key_file_set_uint64 (file, "bees", "c", g_key_file_set_uint64 (file, "bees", "c",
G_GUINT64_CONSTANT (987654321987654321)); G_GUINT64_CONSTANT (987654321987654321));
@ -1417,7 +1417,7 @@ test_load (void)
loaded = g_key_file_load_from_file (file, g_test_get_filename (G_TEST_DIST, "keyfiletest.ini", NULL), 0, &error); loaded = g_key_file_load_from_file (file, g_test_get_filename (G_TEST_DIST, "keyfiletest.ini", NULL), 0, &error);
#endif #endif
g_assert_no_error (error); g_assert_no_error (error);
g_assert (loaded); g_assert_true (loaded);
g_key_file_set_locale_string (file, "test", "key4", "de", "Vierter Schlüssel"); g_key_file_set_locale_string (file, "test", "key4", "de", "Vierter Schlüssel");
g_key_file_set_boolean_list (file, "test", "key5", bools, 2); g_key_file_set_boolean_list (file, "test", "key5", bools, 2);
@ -1431,7 +1431,7 @@ test_load (void)
file = g_key_file_new (); file = g_key_file_new ();
error = NULL; error = NULL;
g_assert (!g_key_file_load_from_data_dirs (file, "keyfile-test.ini", NULL, 0, &error)); g_assert_false (g_key_file_load_from_data_dirs (file, "keyfile-test.ini", NULL, 0, &error));
g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND); g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND);
g_error_free (error); g_error_free (error);
g_key_file_free (file); g_key_file_free (file);
@ -1456,25 +1456,25 @@ test_save (void)
kf = g_key_file_new (); kf = g_key_file_new ();
ok = g_key_file_load_from_data (kf, data, strlen (data), 0, NULL); ok = g_key_file_load_from_data (kf, data, strlen (data), 0, NULL);
g_assert (ok); g_assert_true (ok);
file = g_strdup ("key_file_XXXXXX"); file = g_strdup ("key_file_XXXXXX");
fd = g_mkstemp (file); fd = g_mkstemp (file);
g_assert (fd != -1); g_assert_cmpint (fd, !=, -1);
ok = g_close (fd, &error); ok = g_close (fd, &error);
g_assert (ok); g_assert_true (ok);
g_assert_no_error (error); g_assert_no_error (error);
ok = g_key_file_save_to_file (kf, file, &error); ok = g_key_file_save_to_file (kf, file, &error);
g_assert (ok); g_assert_true (ok);
g_assert_no_error (error); g_assert_no_error (error);
kf2 = g_key_file_new (); kf2 = g_key_file_new ();
ok = g_key_file_load_from_file (kf2, file, 0, &error); ok = g_key_file_load_from_file (kf2, file, 0, &error);
g_assert (ok); g_assert_true (ok);
g_assert_no_error (error); g_assert_no_error (error);
c = g_key_file_get_uint64 (kf2, "bees", "c", NULL); c = g_key_file_get_uint64 (kf2, "bees", "c", NULL);
g_assert (c == G_GUINT64_CONSTANT (123456789123456789)); g_assert_cmpuint (c, ==, G_GUINT64_CONSTANT (123456789123456789));
remove (file); remove (file);
g_free (file); g_free (file);
@ -1490,10 +1490,10 @@ test_load_fail (void)
file = g_key_file_new (); file = g_key_file_new ();
error = NULL; error = NULL;
g_assert (!g_key_file_load_from_file (file, g_test_get_filename (G_TEST_DIST, "keyfile.c", NULL), 0, &error)); g_assert_false (g_key_file_load_from_file (file, g_test_get_filename (G_TEST_DIST, "keyfile.c", NULL), 0, &error));
g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_PARSE); g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_PARSE);
g_clear_error (&error); g_clear_error (&error);
g_assert (!g_key_file_load_from_file (file, "/nosuchfile", 0, &error)); g_assert_false (g_key_file_load_from_file (file, "/nosuchfile", 0, &error));
g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT); g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT);
g_clear_error (&error); g_clear_error (&error);
@ -1517,22 +1517,22 @@ test_non_utf8 (void)
file = g_key_file_new (); file = g_key_file_new ();
ok = g_key_file_load_from_data (file, data, strlen (data), 0, NULL); ok = g_key_file_load_from_data (file, data, strlen (data), 0, NULL);
g_assert (ok); g_assert_true (ok);
error = NULL; error = NULL;
s = g_key_file_get_string (file, "group", "a", &error); s = g_key_file_get_string (file, "group", "a", &error);
g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_UNKNOWN_ENCODING); g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_UNKNOWN_ENCODING);
g_assert (s == NULL); g_assert_null (s);
g_clear_error (&error); g_clear_error (&error);
l = g_key_file_get_string_list (file, "group", "b", NULL, &error); l = g_key_file_get_string_list (file, "group", "b", NULL, &error);
g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_UNKNOWN_ENCODING); g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_UNKNOWN_ENCODING);
g_assert (l == NULL); g_assert_null (l);
g_clear_error (&error); g_clear_error (&error);
l = g_key_file_get_string_list (file, "group", "c", NULL, &error); l = g_key_file_get_string_list (file, "group", "c", NULL, &error);
g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE); g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE);
g_assert (l == NULL); g_assert_null (l);
g_clear_error (&error); g_clear_error (&error);
@ -1587,8 +1587,8 @@ test_ref (void)
file = g_key_file_new (); file = g_key_file_new ();
ok = g_key_file_load_from_data (file, data, strlen (data), 0, NULL); ok = g_key_file_load_from_data (file, data, strlen (data), 0, NULL);
g_assert (ok); g_assert_true (ok);
g_assert (g_key_file_has_key (file, "group", "a", NULL)); g_assert_true (g_key_file_has_key (file, "group", "a", NULL));
g_key_file_ref (file); g_key_file_ref (file);
g_key_file_free (file); g_key_file_free (file);
g_key_file_unref (file); g_key_file_unref (file);
@ -1666,7 +1666,7 @@ test_limbo (void)
error = NULL; error = NULL;
ok = g_key_file_load_from_data (file, data, strlen (data), 0, &error); ok = g_key_file_load_from_data (file, data, strlen (data), 0, &error);
g_assert (!ok); g_assert_false (ok);
g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND); g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND);
g_clear_error (&error); g_clear_error (&error);
g_key_file_free (file); g_key_file_free (file);
@ -1675,21 +1675,32 @@ test_limbo (void)
static void static void
test_utf8 (void) test_utf8 (void)
{ {
GKeyFile *file; const gchar *invalid_encoding_names[] =
static const char data[] = {
"[group]\n" "non-UTF-8",
"Encoding=non-UTF-8\n"; "UTF",
gboolean ok; "UTF-9",
GError *error; };
gsize i;
file = g_key_file_new (); for (i = 0; i < G_N_ELEMENTS (invalid_encoding_names); i++)
{
GKeyFile *file = NULL;
gchar *data = NULL;
gboolean ok;
GError *error = NULL;
error = NULL; g_test_message ("Testing invalid encoding %s", invalid_encoding_names[i]);
ok = g_key_file_load_from_data (file, data, strlen (data), 0, &error);
g_assert (!ok); file = g_key_file_new ();
g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_UNKNOWN_ENCODING); data = g_strdup_printf ("[group]\n"
g_clear_error (&error); "Encoding=%s\n", invalid_encoding_names[i]);
g_key_file_free (file); ok = g_key_file_load_from_data (file, data, strlen (data), 0, &error);
g_assert_false (ok);
g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_UNKNOWN_ENCODING);
g_clear_error (&error);
g_key_file_free (file);
}
} }
static void static void