[gspell/wip/icu: 2/5] language: remove iso-codes dependency and XML parsing code




commit d5a8b72e194a6542ac4f7c850fe126c3c80d3a05
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Mon Oct 5 17:46:38 2020 +0200

    language: remove iso-codes dependency and XML parsing code
    
    The ICU library will be used instead of the iso-codes package to get the
    display names from the language codes
    (e.g. "fr_BE" -> "French (Belgium)").
    
    To avoid duplicates g_tree_replace() was used before this commit. It's
    now replaced by simple list traversals. The list is small anyway,
    performances should really not matter, so simple code is preferable.
    
    https://gitlab.gnome.org/GNOME/gspell/-/issues/14

 README                   |   1 -
 configure.ac             |  26 ----
 gspell/gspell-language.c | 321 ++++-------------------------------------------
 3 files changed, 21 insertions(+), 327 deletions(-)
---
diff --git a/README b/README
index 1d98258..9277db9 100644
--- a/README
+++ b/README
@@ -27,7 +27,6 @@ Dependencies
 * GLib >= 2.44
 * GTK >= 3.20
 * Enchant >= 2.1.3
-* iso-codes
 * ICU - http://site.icu-project.org/
 
 Notes for packagers
diff --git a/configure.ac b/configure.ac
index 5d87a1f..2b6be74 100644
--- a/configure.ac
+++ b/configure.ac
@@ -93,32 +93,6 @@ AX_PKG_CHECK_MODULES([DEP],
                     [glib-2.0 >= $glib_req  gtk+-3.0 >= $gtk_req  enchant-2 >= $enchant_req],
                     [icu-uc])
 
-# iso-codes
-AX_REQUIRE_DEFINED([PKG_CHECK_EXISTS])
-PKG_CHECK_EXISTS([iso-codes],
-                [have_iso_codes=yes],
-                [have_iso_codes=no])
-
-if test "x$have_iso_codes" = "xyes"; then
-       AC_MSG_CHECKING([whether iso-codes has iso-639 and iso-3166 domains])
-       if $PKG_CONFIG --variable=domains iso-codes | grep 639 > /dev/null && \
-          $PKG_CONFIG --variable=domains iso-codes | grep 3166 > /dev/null ; then
-               result=yes
-       else
-               result=no
-               have_iso_codes=no
-       fi
-       AC_MSG_RESULT([$result])
-fi
-
-if test "x$have_iso_codes" = "xyes"; then
-       AC_DEFINE_UNQUOTED([ISO_CODES_PREFIX],
-                          ["`$PKG_CONFIG --variable=prefix iso-codes`"],
-                          [ISO codes prefix])
-else
-       AC_MSG_ERROR([iso-codes is required.])
-fi
-
 # i18n
 AM_GNU_GETTEXT([external])
 # FIXME: Remove AM_GNU_GETTEXT_VERSION once autoreconf supports AM_GNU_GETTEXT_REQUIRE_VERSION.
diff --git a/gspell/gspell-language.c b/gspell/gspell-language.c
index 4df9224..f11485e 100644
--- a/gspell/gspell-language.c
+++ b/gspell/gspell-language.c
@@ -3,7 +3,7 @@
  *
  * Copyright 2006 - Paolo Maggi
  * Copyright 2008 - Novell, Inc.
- * Copyright 2015, 2016 - Sébastien Wilmet
+ * Copyright 2015, 2016, 2020 - Sébastien Wilmet
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -27,7 +27,6 @@
 #include <string.h>
 #include <glib/gi18n-lib.h>
 #include <enchant.h>
-#include "gspell-init.h"
 
 #ifdef OS_OSX
 #include "gspell-osx.h"
@@ -43,9 +42,6 @@
  * checking, i.e. a language for which a dictionary is installed.
  */
 
-#define ISO_639_DOMAIN "iso_639"
-#define ISO_3166_DOMAIN        "iso_3166"
-
 struct _GspellLanguage
 {
        gchar *code;
@@ -53,268 +49,40 @@ struct _GspellLanguage
        gchar *collate_key;
 };
 
-typedef struct _DictsData DictsData;
-struct _DictsData
-{
-       GHashTable *iso_639_table;
-       GHashTable *iso_3166_table;
-       GTree *tree;
-};
-
 G_DEFINE_BOXED_TYPE (GspellLanguage,
                     gspell_language,
                     gspell_language_copy,
                     gspell_language_free)
 
-static gchar *
-get_iso_codes_prefix (void)
-{
-       gchar *prefix = NULL;
-
-#ifdef G_OS_WIN32
-       HMODULE gspell_dll;
-
-       gspell_dll = _gspell_init_get_dll ();
-       prefix = g_win32_get_package_installation_directory_of_module ((gpointer) gspell_dll);
-#endif
-
-       if (prefix == NULL)
-       {
-               prefix = g_strdup (ISO_CODES_PREFIX);
-       }
-
-       return prefix;
-}
-
-static gchar *
-get_iso_codes_localedir (void)
-{
-       gchar *prefix;
-       gchar *localedir;
-
-       prefix = get_iso_codes_prefix ();
-       localedir = g_build_filename (prefix, "share", "locale", NULL);
-       g_free (prefix);
-
-       return localedir;
-}
-
-static void
-iso_639_start_element (GMarkupParseContext  *context,
-                      const gchar          *element_name,
-                      const gchar         **attribute_names,
-                      const gchar         **attribute_values,
-                      gpointer              data,
-                      GError              **error)
-{
-       GHashTable *hash_table = data;
-       const gchar *iso_639_1_code = NULL;
-       const gchar *iso_639_2_code = NULL;
-       const gchar *name = NULL;
-       const gchar *code = NULL;
-       gint i;
-
-       if (g_strcmp0 (element_name, "iso_639_entry") != 0)
-       {
-               return;
-       }
-
-       for (i = 0; attribute_names[i] != NULL; i++)
-       {
-               if (g_str_equal (attribute_names[i], "name"))
-               {
-                       name = attribute_values[i];
-               }
-               else if (g_str_equal (attribute_names[i], "iso_639_1_code"))
-               {
-                       iso_639_1_code = attribute_values[i];
-               }
-               else if (g_str_equal (attribute_names[i], "iso_639_2T_code"))
-               {
-                       iso_639_2_code = attribute_values[i];
-               }
-       }
-
-       code = (iso_639_1_code != NULL) ? iso_639_1_code : iso_639_2_code;
-
-       if (code != NULL && code[0] != '\0' &&
-           name != NULL && name[0] != '\0')
-       {
-               g_hash_table_insert (hash_table,
-                                    g_strdup (code),
-                                    g_strdup (dgettext (ISO_639_DOMAIN, name)));
-       }
-}
-
-static void
-iso_3166_start_element (GMarkupParseContext  *context,
-                       const gchar          *element_name,
-                       const gchar         **attribute_names,
-                       const gchar         **attribute_values,
-                       gpointer              data,
-                       GError              **error)
-{
-       GHashTable *hash_table = data;
-       const gchar *name = NULL;
-       const gchar *code = NULL;
-       gint i;
-
-       if (g_strcmp0 (element_name, "iso_3166_entry") != 0)
-       {
-               return;
-       }
-
-       for (i = 0; attribute_names[i] != NULL; i++)
-       {
-               if (g_str_equal (attribute_names[i], "name"))
-               {
-                       name = attribute_values[i];
-               }
-               else if (g_str_equal (attribute_names[i], "alpha_2_code"))
-               {
-                       code = attribute_values[i];
-               }
-       }
-
-       if (code != NULL && code[0] != '\0' &&
-           name != NULL && name[0] != '\0')
-       {
-               g_hash_table_insert (hash_table,
-                                    g_ascii_strdown (code, -1),
-                                    g_strdup (dgettext (ISO_3166_DOMAIN, name)));
-       }
-}
-
-static void
-iso_codes_parse (const GMarkupParser *parser,
-                const gchar         *basename,
-                GHashTable          *hash_table)
-{
-       GMappedFile *mapped_file;
-       gchar *prefix;
-       gchar *filename;
-       GError *error = NULL;
-
-       prefix = get_iso_codes_prefix ();
-       filename = g_build_filename (prefix,
-                                    "share",
-                                    "xml",
-                                    "iso-codes",
-                                    basename,
-                                    NULL);
-       g_free (prefix);
-
-       mapped_file = g_mapped_file_new (filename, FALSE, &error);
-       g_free (filename);
-
-       if (mapped_file != NULL)
-       {
-               GMarkupParseContext *context;
-               const gchar *contents;
-               gsize length;
-
-               context = g_markup_parse_context_new (parser, 0, hash_table, NULL);
-               contents = g_mapped_file_get_contents (mapped_file);
-               length = g_mapped_file_get_length (mapped_file);
-               g_markup_parse_context_parse (context, contents, length, &error);
-               g_markup_parse_context_free (context);
-               g_mapped_file_unref (mapped_file);
-       }
-
-       if (error != NULL)
-       {
-               g_warning ("%s: %s", basename, error->message);
-               g_clear_error (&error);
-       }
-}
-
 static void
 spell_language_dict_describe_cb (const gchar * const language_code,
                                  const gchar * const provider_name,
                                  const gchar * const provider_desc,
                                  const gchar * const provider_file,
-                                DictsData *data)
+                                gpointer            user_data)
 {
-       const gchar *iso_639_name;
-       const gchar *iso_3166_name;
-       gchar *language_name;
-       gchar *lowercase;
-       gchar **tokens;
-
-       /* Split language code into lowercase tokens. */
-       lowercase = g_ascii_strdown (language_code, -1);
-       tokens = g_strsplit (lowercase, "_", -1);
-       g_free (lowercase);
-
-       g_return_if_fail (tokens != NULL);
-
-       iso_639_name = g_hash_table_lookup (data->iso_639_table, tokens[0]);
-
-       if (iso_639_name == NULL)
-       {
-               /* Translators: %s is the language ISO code. */
-               language_name = g_strdup_printf (C_("language", "Unknown (%s)"), language_code);
-               goto exit;
-       }
+       GList **available_languages = user_data;
+       GList *l;
+       GspellLanguage *language;
 
-       if (g_strv_length (tokens) < 2)
+       for (l = *available_languages; l != NULL; l = l->next)
        {
-               language_name = g_strdup (iso_639_name);
-               goto exit;
-       }
+               GspellLanguage *cur_language = l->data;
 
-       iso_3166_name = g_hash_table_lookup (data->iso_3166_table, tokens[1]);
-
-       if (iso_3166_name != NULL)
-       {
-               /* Translators: The first %s is the language name, and the
-                * second is the country name. Example: "French (France)".
-                */
-               language_name = g_strdup_printf (C_("language", "%s (%s)"),
-                                                iso_639_name,
-                                                iso_3166_name);
-       }
-       else
-       {
-               /* Translators: The first %s is the language name, and the
-                * second is the country name. Example: "French (France)".
-                */
-               language_name = g_strdup_printf (C_("language", "%s (%s)"),
-                                                iso_639_name,
-                                                tokens[1]);
+               if (g_strcmp0 (cur_language->code, language_code) == 0)
+               {
+                       /* Avoid duplicates. */
+                       return;
+               }
        }
 
-exit:
-       g_strfreev (tokens);
-
-       g_tree_replace (data->tree, g_strdup (language_code), language_name);
-}
-
-static gboolean
-spell_language_traverse_cb (const gchar  *code,
-                           const gchar  *name,
-                           GList       **available_languages)
-{
-       GspellLanguage *language;
-
        language = g_slice_new (GspellLanguage);
-       language->code = g_strdup (code);
-       language->name = g_strdup (name);
-       language->collate_key = g_utf8_collate_key (name, -1);
-
-       *available_languages = g_list_insert_sorted (*available_languages,
-                                                    language,
-                                                    (GCompareFunc) gspell_language_compare);
+       language->code = g_strdup (language_code);
+       /* Translators: %s is the language ISO code. */
+       language->name = g_strdup_printf (C_("language", "Unknown (%s)"), language_code);
+       language->collate_key = g_utf8_collate_key (language->name, -1);
 
-       return FALSE;
-}
-
-static gint
-tree_compare_func (gconstpointer a,
-                  gconstpointer b,
-                  gpointer      user_data)
-{
-       return g_strcmp0 (a, b);
+       *available_languages = g_list_prepend (*available_languages, language);
 }
 
 /**
@@ -328,21 +96,7 @@ gspell_language_get_available (void)
 {
        static gboolean initialized = FALSE;
        static GList *available_languages = NULL;
-       gchar *localedir;
        EnchantBroker *broker;
-       DictsData data;
-
-       GMarkupParser iso_639_parser =
-       {
-               iso_639_start_element,
-               NULL, NULL, NULL, NULL
-       };
-
-       GMarkupParser iso_3166_parser =
-       {
-               iso_3166_start_element,
-               NULL, NULL, NULL, NULL
-       };
 
        if (initialized)
        {
@@ -351,47 +105,14 @@ gspell_language_get_available (void)
 
        initialized = TRUE;
 
-       localedir = get_iso_codes_localedir ();
-
-       bindtextdomain (ISO_639_DOMAIN, localedir);
-       bind_textdomain_codeset (ISO_639_DOMAIN, "UTF-8");
-
-       bindtextdomain (ISO_3166_DOMAIN, localedir);
-       bind_textdomain_codeset (ISO_3166_DOMAIN, "UTF-8");
-
-       g_free (localedir);
-
-       data.iso_639_table = g_hash_table_new_full (g_str_hash,
-                                                   g_str_equal,
-                                                   (GDestroyNotify) g_free,
-                                                   (GDestroyNotify) g_free);
-
-       data.iso_3166_table = g_hash_table_new_full (g_str_hash,
-                                                    g_str_equal,
-                                                    (GDestroyNotify) g_free,
-                                                    (GDestroyNotify) g_free);
-
-       iso_codes_parse (&iso_639_parser, "iso_639.xml", data.iso_639_table);
-       iso_codes_parse (&iso_3166_parser, "iso_3166.xml", data.iso_3166_table);
-
-       data.tree = g_tree_new_full (tree_compare_func,
-                                    NULL,
-                                    (GDestroyNotify) g_free,
-                                    (GDestroyNotify) g_free);
-
        broker = enchant_broker_init ();
        enchant_broker_list_dicts (broker,
-                                  (EnchantDictDescribeFn) spell_language_dict_describe_cb,
-                                  &data);
+                                  spell_language_dict_describe_cb,
+                                  &available_languages);
        enchant_broker_free (broker);
 
-       g_tree_foreach (data.tree,
-                       (GTraverseFunc) spell_language_traverse_cb,
-                       &available_languages);
-
-       g_hash_table_unref (data.iso_639_table);
-       g_hash_table_unref (data.iso_3166_table);
-       g_tree_unref (data.tree);
+       available_languages = g_list_sort (available_languages,
+                                          (GCompareFunc) gspell_language_compare);
 
        return available_languages;
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]