diff options
author | Richard Hughes <richard@hughsie.com> | 2016-08-25 11:27:57 +0100 |
---|---|---|
committer | Richard Hughes <richard@hughsie.com> | 2016-08-25 14:32:49 +0100 |
commit | 21a4c541aedccf2e8da173a31036af4e914ba9a1 (patch) | |
tree | a27ba5d893e9902ac5855317ac34a347693d4843 | |
parent | ed45f5888642fe2d3ce29daa3ca5cc8d85f9bb89 (diff) | |
download | appstream-glib-wip/hughsie/unique-id-hash.tar.gz |
Add two hash functions specifically for unique-idswip/hughsie/unique-id-hash
-rw-r--r-- | libappstream-glib/as-self-test.c | 69 | ||||
-rw-r--r-- | libappstream-glib/as-utils.c | 68 | ||||
-rw-r--r-- | libappstream-glib/as-utils.h | 3 |
3 files changed, 140 insertions, 0 deletions
diff --git a/libappstream-glib/as-self-test.c b/libappstream-glib/as-self-test.c index bb6b0dc..71b57d7 100644 --- a/libappstream-glib/as-self-test.c +++ b/libappstream-glib/as-self-test.c @@ -4864,6 +4864,73 @@ as_test_store_merge_func (void) g_assert_cmpstr (as_app_get_source_file (app2), ==, NULL); } +/* shows the unique-id globbing functions at work */ +static void +as_test_utils_unique_id_hash_func (void) +{ + AsApp *found; + g_autoptr(AsApp) app = NULL; + g_autoptr(GHashTable) hash = NULL; + + /* create new app */ + app = as_app_new (); + as_app_set_id (app, "org.gnome.Software.desktop"); + as_app_set_branch (app, "master"); + g_assert_cmpstr (as_app_get_unique_id (app), ==, + "*/*/*/*/org.gnome.Software.desktop/master"); + + /* add to hash table using the unique ID as a key */ + hash = g_hash_table_new (as_utils_unique_id_hash_safe, + as_utils_unique_id_equal_safe); + g_hash_table_insert (hash, as_app_get_unique_id (app), app); + + /* get with exact key */ + found = g_hash_table_lookup (hash, "*/*/*/*/org.gnome.Software.desktop/master"); + g_assert (found != NULL); + + /* get with more details specified */ + found = g_hash_table_lookup (hash, "system/*/*/*/org.gnome.Software.desktop/master"); + g_assert (found != NULL); + + /* get with less details specified */ + found = g_hash_table_lookup (hash, "*/*/*/*/org.gnome.Software.desktop/*"); + g_assert (found != NULL); + + /* different key */ + found = g_hash_table_lookup (hash, "*/*/*/*/gimp.desktop/*"); + g_assert (found == NULL); + + /* different branch */ + found = g_hash_table_lookup (hash, "*/*/*/*/org.gnome.Software.desktop/stable"); + g_assert (found == NULL); +} + +/* shows the as_utils_unique_id_*_safe functions are safe with bare text */ +static void +as_test_utils_unique_id_hash_safe_func (void) +{ + AsApp *found; + g_autoptr(AsApp) app = NULL; + g_autoptr(GHashTable) hash = NULL; + + /* create new app */ + app = as_app_new (); + as_app_set_id (app, "org.gnome.Software.desktop"); + + /* add to hash table using the unique ID as a key */ + hash = g_hash_table_new (as_utils_unique_id_hash_safe, + as_utils_unique_id_equal_safe); + g_hash_table_insert (hash, "dave", app); + + /* get with exact key */ + found = g_hash_table_lookup (hash, "dave"); + g_assert (found != NULL); + + /* different key */ + found = g_hash_table_lookup (hash, "frank"); + g_assert (found == NULL); +} + int main (int argc, char **argv) { @@ -4873,6 +4940,8 @@ main (int argc, char **argv) g_log_set_fatal_mask (NULL, G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL); /* tests go here */ + g_test_add_func ("/AppStream/utils{unique_id-hash}", as_test_utils_unique_id_hash_func); + g_test_add_func ("/AppStream/utils{unique_id-hash2}", as_test_utils_unique_id_hash_safe_func); g_test_add_func ("/AppStream/utils{unique_id}", as_test_utils_unique_id_func); g_test_add_func ("/AppStream/utils{locale-compat}", as_test_utils_locale_compat_func); g_test_add_func ("/AppStream/utils{string-replace}", as_test_utils_string_replace_func); diff --git a/libappstream-glib/as-utils.c b/libappstream-glib/as-utils.c index c959677..fbd64ed 100644 --- a/libappstream-glib/as-utils.c +++ b/libappstream-glib/as-utils.c @@ -1855,3 +1855,71 @@ as_utils_unique_id_equal (const gchar *unique_id1, const gchar *unique_id2) } return TRUE; } + +/** + * as_utils_unique_id_hash_safe: + * @v: a unique ID + * + * Converts a unique-id to a hash value. + * + * This function implements the widely used DJB hash on the ID subset of the + * unique-id string. + * + * It can be passed to g_hash_table_new() as the hash_func parameter, + * when using non-NULL strings or unique_ids as keys in a GHashTable. + * + * Returns: a hash value corresponding to the key + * + * Since: 0.6.2 + */ +guint +as_utils_unique_id_hash_safe (gconstpointer v) +{ + const gchar *str = v; + gsize i; + guint hash = 5381; + guint section_cnt = 0; + + /* not a unique ID */ + if (!as_utils_unique_id_valid (v)) + return g_str_hash (v); + + /* only include the app-id */ + for (i = 0; str[i] != '\0'; i++) { + if (str[i] == '/') { + if (++section_cnt > 4) + break; + continue; + } + if (section_cnt < 4) + continue; + hash = (guint) ((hash << 5) + hash) + (guint) (str[i]); + } + return hash; +} + +/** + * as_utils_unique_id_equal_safe: + * @v1: a unique ID + * @v2: another unique ID + * + * Compares two unique_id's for equality and returns TRUE if they are equal. + * It can be passed to g_hash_table_new() as the key_equal_func parameter, + * when using non-NULL strings or unique-id's as keys in a GHashTable. + * + * Note that this function is primarily meant as a hash table comparison + * function. For a general-purpose, unique-id specific comparison function, + * see g_strcmp0(). + * + * Returns: %TRUE if the two keys are equal + * + * Since: 0.6.2 + */ +gboolean +as_utils_unique_id_equal_safe (gconstpointer v1, gconstpointer v2) +{ + if (as_utils_unique_id_valid (v1) && + as_utils_unique_id_valid (v2)) + return as_utils_unique_id_equal (v1, v2); + return g_str_equal (v1, v2); +} diff --git a/libappstream-glib/as-utils.h b/libappstream-glib/as-utils.h index e38c412..35c2708 100644 --- a/libappstream-glib/as-utils.h +++ b/libappstream-glib/as-utils.h @@ -141,6 +141,9 @@ gchar *as_utils_unique_id_build (AsAppScope scope, gboolean as_utils_unique_id_equal (const gchar *unique_id1, const gchar *unique_id2); gboolean as_utils_unique_id_valid (const gchar *unique_id); +guint as_utils_unique_id_hash_safe (gconstpointer v); +gboolean as_utils_unique_id_equal_safe (gconstpointer v1, + gconstpointer v2); G_END_DECLS |