summaryrefslogtreecommitdiff
path: root/libappstream-glib
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 19:21:54 +0100
commit67f486be685533602eba085fc4accdabda6be4bf (patch)
tree34a8e697f5ecf036b27b56c2b73e45f6712cf4e5 /libappstream-glib
parente552f4245472e484dc8cb9e8930826e436d3225f (diff)
downloadappstream-glib-67f486be685533602eba085fc4accdabda6be4bf.tar.gz
Add a hash function specifically designed for unique-ids
Diffstat (limited to 'libappstream-glib')
-rw-r--r--libappstream-glib/as-self-test.c69
-rw-r--r--libappstream-glib/as-utils.c43
-rw-r--r--libappstream-glib/as-utils.h1
3 files changed, 112 insertions, 1 deletions
diff --git a/libappstream-glib/as-self-test.c b/libappstream-glib/as-self-test.c
index ea5b2af..c80ed1d 100644
--- a/libappstream-glib/as-self-test.c
+++ b/libappstream-glib/as-self-test.c
@@ -4866,6 +4866,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 ((GHashFunc) as_utils_unique_id_hash,
+ (GEqualFunc) as_utils_unique_id_equal);
+ g_hash_table_insert (hash, (gpointer) 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 ((GHashFunc) as_utils_unique_id_hash,
+ (GEqualFunc) as_utils_unique_id_equal);
+ 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)
{
@@ -4875,6 +4942,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..6ec25cf 100644
--- a/libappstream-glib/as-utils.c
+++ b/libappstream-glib/as-utils.c
@@ -1828,7 +1828,7 @@ as_utils_unique_id_equal (const gchar *unique_id1, const gchar *unique_id2)
/* invalid */
if (!as_utils_unique_id_valid (unique_id1) ||
!as_utils_unique_id_valid (unique_id2))
- return FALSE;
+ return g_strcmp0 (unique_id1, unique_id2) == 0;
/* look at each part */
for (i = 0; i < AS_UTILS_UNIQUE_ID_PARTS; i++) {
@@ -1855,3 +1855,44 @@ as_utils_unique_id_equal (const gchar *unique_id1, const gchar *unique_id2)
}
return TRUE;
}
+
+/**
+ * as_utils_unique_id_hash:
+ * @unique_id: 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 (const gchar *unique_id)
+{
+ gsize i;
+ guint hash = 5381;
+ guint section_cnt = 0;
+
+ /* not a unique ID */
+ if (!as_utils_unique_id_valid (unique_id))
+ return g_str_hash (unique_id);
+
+ /* only include the app-id */
+ for (i = 0; unique_id[i] != '\0'; i++) {
+ if (unique_id[i] == '/') {
+ if (++section_cnt > 4)
+ break;
+ continue;
+ }
+ if (section_cnt < 4)
+ continue;
+ hash = (guint) ((hash << 5) + hash) + (guint) (unique_id[i]);
+ }
+ return hash;
+}
diff --git a/libappstream-glib/as-utils.h b/libappstream-glib/as-utils.h
index e38c412..7f7cde1 100644
--- a/libappstream-glib/as-utils.h
+++ b/libappstream-glib/as-utils.h
@@ -141,6 +141,7 @@ 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 (const gchar *unique_id);
G_END_DECLS