gkeyfile: Avoid allocating a copy of the locale for a key

Instead compare it inline. This should avoid a lot of allocations in key
files with lots of translations (such as desktop files).

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
This commit is contained in:
Philip Withnall 2021-03-14 14:24:27 +00:00
parent 5a38dc79f0
commit f93f24e41c

View File

@ -618,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,
@ -1229,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;
@ -1244,7 +1246,8 @@ g_key_file_locale_is_interesting (GKeyFile *key_file,
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;
} }
@ -1354,7 +1357,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)
@ -1422,9 +1427,9 @@ g_key_file_parse_key_value_pair (GKeyFile *key_file,
/* 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;
@ -1436,22 +1441,33 @@ g_key_file_parse_key_value_pair (GKeyFile *key_file,
} }
g_free (key); g_free (key);
g_free (locale);
} }
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;
} }