From f93f24e41c21bdf937b08f301a435de4e5710c21 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Sun, 14 Mar 2021 14:24:27 +0000 Subject: [PATCH] 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 --- glib/gkeyfile.c | 46 +++++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/glib/gkeyfile.c b/glib/gkeyfile.c index 9fd9c6eed..fa99da8d9 100644 --- a/glib/gkeyfile.c +++ b/glib/gkeyfile.c @@ -618,7 +618,8 @@ static void g_key_file_parse_group (GKeyFile const gchar *line, gsize length, 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, const gchar *data, gsize length, @@ -1229,7 +1230,8 @@ g_key_file_unref (GKeyFile *key_file) */ static gboolean g_key_file_locale_is_interesting (GKeyFile *key_file, - const gchar *locale) + const gchar *locale, + gsize locale_len) { gsize i; @@ -1244,7 +1246,8 @@ g_key_file_locale_is_interesting (GKeyFile *key_file, 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; } @@ -1354,7 +1357,9 @@ g_key_file_parse_key_value_pair (GKeyFile *key_file, gsize length, 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; 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? */ - 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; @@ -1436,22 +1441,33 @@ g_key_file_parse_key_value_pair (GKeyFile *key_file, } g_free (key); - g_free (locale); } -static gchar * -key_get_locale (const gchar *key) +static const gchar * +key_get_locale (const gchar *key, + gsize *len_out) { - gchar *locale; + const gchar *locale; + gsize locale_len; locale = g_strrstr (key, "["); + if (locale != NULL) + locale_len = strlen (locale); + else + locale_len = 0; - if (locale && strlen (locale) <= 2) - locale = NULL; - - if (locale) - locale = g_strndup (locale + 1, strlen (locale) - 2); + if (locale_len > 2) + { + locale++; /* skip `[` */ + locale_len -= 2; /* drop `[` and `]` */ + } + else + { + locale = NULL; + locale_len = 0; + } + *len_out = locale_len; return locale; }