summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Hughes <richard@hughsie.com>2016-08-25 11:27:57 +0100
committerRichard Hughes <richard@hughsie.com>2016-08-25 14:32:49 +0100
commit21a4c541aedccf2e8da173a31036af4e914ba9a1 (patch)
treea27ba5d893e9902ac5855317ac34a347693d4843
parented45f5888642fe2d3ce29daa3ca5cc8d85f9bb89 (diff)
downloadappstream-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.c69
-rw-r--r--libappstream-glib/as-utils.c68
-rw-r--r--libappstream-glib/as-utils.h3
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