[PATCH 4/9] core: Add API to handle multivalued data
- From: "Juan A. Suarez Romero" <jasuarez igalia com>
- To: grilo-list gnome org
- Subject: [PATCH 4/9] core: Add API to handle multivalued data
- Date: Mon, 21 Feb 2011 10:36:30 +0100
Signed-off-by: Juan A. Suarez Romero <jasuarez igalia com>
---
src/data/grl-data-multi.c | 307 +++++++++++++++++++++++++++++++++++++++++++--
src/data/grl-data-multi.h | 12 ++-
2 files changed, 308 insertions(+), 11 deletions(-)
diff --git a/src/data/grl-data-multi.c b/src/data/grl-data-multi.c
index 2047bc7..819e5e7 100644
--- a/src/data/grl-data-multi.c
+++ b/src/data/grl-data-multi.c
@@ -34,6 +34,7 @@
#include "grl-data-multi.h"
#include "grl-log.h"
+#include "grl-plugin-registry.h"
struct _GrlDataMultiPrivate {
GHashTable *extended_data;
@@ -44,17 +45,11 @@ static void grl_data_multi_finalize (GObject *object);
#define GRL_DATA_MULTI_GET_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE ((o), GRL_TYPE_DATA_MULTI, GrlDataMultiPrivate))
-G_DEFINE_TYPE (GrlDataMulti, grl_data_multi, GRL_TYPE_DATA);
+static void free_list_values (GrlKeyID key, GList *values, gpointer user_data);
-static void
-free_list_values (GrlKeyID key,
- GList *values,
- gpointer user_data)
-{
- g_list_foreach (values, (GFunc) g_object_unref, NULL);
- g_list_free (values);
-}
+/* ================ GrlDataMulti GObject ================ */
+G_DEFINE_TYPE (GrlDataMulti, grl_data_multi, GRL_TYPE_DATA);
static void
grl_data_multi_class_init (GrlDataMultiClass *klass)
@@ -89,6 +84,17 @@ grl_data_multi_finalize (GObject *object)
G_OBJECT_CLASS (grl_data_multi_parent_class)->finalize (object);
}
+/* ================ Utitilies ================ */
+
+static void
+free_list_values (GrlKeyID key, GList *values, gpointer user_data)
+{
+ g_list_foreach (values, (GFunc) g_object_unref, NULL);
+ g_list_free (values);
+}
+
+/* ================ API ================ */
+
/**
* grl_data_multi_new:
*
@@ -102,3 +108,286 @@ grl_data_multi_new (void)
return g_object_new (GRL_TYPE_DATA_MULTI,
NULL);
}
+
+/**
+ * grl_data_multi_add:
+ * @mdata: a multivalued data
+ * @prop: a set of related properties with their values
+ *
+ * Adds a new set of values.
+ *
+ * All keys in prop must be related among them.
+ *
+ * mdata will take the ownership of prop, so do not modify it.
+ **/
+void
+grl_data_multi_add (GrlDataMulti *mdata,
+ GrlProperty *prop)
+{
+ GList *key;
+ GList *keys;
+ GList *values;
+ GrlPluginRegistry *registry;
+ const GList *related_keys;
+ guint l;
+
+ g_return_if_fail (GRL_IS_DATA_MULTI (mdata));
+ g_return_if_fail (GRL_IS_PROPERTY (prop));
+
+ keys = grl_data_get_keys (GRL_DATA (prop));
+ if (!keys) {
+ /* Ignore empty properties */
+ GRL_WARNING ("Empty set of values");
+ g_object_unref (prop);
+ return;
+ }
+
+ /* It is assumed that this property only contains values for related properties.
+ Check if it must be inserted in data or in extended_data */
+
+ l = grl_data_multi_length (mdata, keys->data);
+
+ if (l > 0) {
+ /* Add it in extended data */
+ registry = grl_plugin_registry_get_default ();
+ related_keys = grl_plugin_registry_lookup_metadata_relation (registry,
+ keys->data);
+ while (related_keys) {
+ values = g_hash_table_lookup (mdata->priv->extended_data,
+ related_keys->data);
+ values = g_list_append (values, g_object_ref (prop));
+ g_hash_table_insert (mdata->priv->extended_data,
+ related_keys->data,
+ values);
+ related_keys = g_list_next (related_keys);
+ }
+ g_list_free (keys);
+ } else {
+ /* Insert it as single valued data */
+ for (key = keys; key; key = g_list_next (key)) {
+ grl_data_set (GRL_DATA (mdata),
+ key->data,
+ grl_data_get (GRL_DATA (prop), key->data));
+ }
+ g_list_free (keys);
+ }
+ g_object_unref (prop);
+}
+
+/**
+ * grl_data_multi_length:
+ * @mdata: a multivalued data
+ * @key: a metadata key
+ *
+ * Returns how many values key has in mdata.
+ *
+ * Returns: number of values
+ **/
+guint
+grl_data_multi_length (GrlDataMulti *mdata,
+ GrlKeyID key)
+{
+ GrlPluginRegistry *registry;
+ const GList *related_keys;
+ gboolean found = FALSE;
+ guint length;
+
+ g_return_val_if_fail (GRL_IS_DATA_MULTI (mdata), 0);
+
+ /* Check first extended data */
+ length = g_list_length (g_hash_table_lookup (mdata->priv->extended_data,
+ key));
+ if (length == 0) {
+ /* Check if we can find the information in data */
+ registry = grl_plugin_registry_get_default ();
+ related_keys = grl_plugin_registry_lookup_metadata_relation (registry, key);
+ while (related_keys && !found) {
+ found = grl_data_key_is_known (GRL_DATA (mdata), related_keys->data);
+ related_keys = g_list_next (related_keys);
+ }
+
+ if (found) {
+ return 1;
+ } else {
+ return 0;
+ }
+ } else {
+ return length + 1;
+ }
+}
+
+/**
+ * grl_data_multi_get:
+ * @mdata: a multivalued data
+ * @key: a metadata key
+ * @pos: element to retrieve, starting at 0
+ *
+ * Returns a set containing the values for key and related keys at position specified.
+ *
+ * Returns: a new #GrlProperty. It must be freed with #g_object_unref()
+ **/
+GrlProperty *
+grl_data_multi_get (GrlDataMulti *mdata,
+ GrlKeyID key,
+ guint pos)
+{
+ GrlData *collect_from = NULL;
+ GrlPluginRegistry *registry;
+ GrlProperty *prop = NULL;
+ const GList *related_keys;
+ GList *list_el;
+
+ g_return_val_if_fail (GRL_IS_DATA_MULTI (mdata), NULL);
+
+ if (pos == 0) {
+ collect_from = GRL_DATA (mdata);
+ } else {
+ list_el = g_list_nth (g_hash_table_lookup (mdata->priv->extended_data, key), pos - 1);
+ if (list_el) {
+ collect_from = GRL_DATA (list_el->data);
+ } else {
+ GRL_WARNING ("Wrong position %u to get data", pos);
+ }
+ }
+
+ if (collect_from) {
+ registry = grl_plugin_registry_get_default ();
+ related_keys = grl_plugin_registry_lookup_metadata_relation (registry, key);
+ prop = grl_property_new ();
+ while (related_keys) {
+ grl_data_set (GRL_DATA (prop), key, grl_data_get (collect_from, key));
+ related_keys = g_list_next (related_keys);
+ }
+ }
+
+ return prop;
+}
+
+/**
+ * grl_data_multi_remove:
+ * @mdata: a multivalued data
+ * @key: a metadata key
+ * @pos: position of key to be removed, starting at 0
+ *
+ * Removes key and related keys from position in mdata.
+ **/
+void
+grl_data_multi_remove (GrlDataMulti *mdata,
+ GrlKeyID key,
+ guint pos)
+{
+ GList *list_values;
+ GList *to_remove;
+ GrlPluginRegistry *registry;
+ GrlProperty *prop_at_1;
+ const GList *rel_key;
+ const GList *related_keys;
+
+ g_return_if_fail (GRL_IS_DATA_MULTI (mdata));
+
+ /* If element to remove is in position 0 (single-data), then we can replace it
+ by value in pos 1 (extended-data) and then remove 1. If element to remove
+ is >0 then we must remove it and shift values the empty position */
+
+ if (pos < 2) {
+ /* For sure related keys will be needed */
+ registry = grl_plugin_registry_get_default ();
+ related_keys = grl_plugin_registry_lookup_metadata_relation (registry, key);
+ }
+
+ if (pos == 0) {
+ prop_at_1 = grl_data_multi_get (mdata, key, 1);
+ if (prop_at_1) {
+ for (rel_key = related_keys; rel_key; rel_key = g_list_next (rel_key)) {
+ grl_data_set (GRL_DATA (mdata),
+ rel_key->data,
+ grl_data_get (GRL_DATA (prop_at_1), rel_key->data));
+ }
+ pos = 1;
+ } else {
+ /* There is no multivalues; remove data */
+ for (rel_key = related_keys; rel_key; rel_key = g_list_next (rel_key)) {
+ grl_data_remove (GRL_DATA (mdata), rel_key->data);
+ }
+ }
+ }
+
+ if (pos > 0) {
+ list_values = g_hash_table_lookup (mdata->priv->extended_data, key);
+ to_remove = g_list_nth (list_values, pos - 1);
+ if (!to_remove) {
+ /* Wrong index; ignore */
+ return;
+ }
+
+ g_object_unref (to_remove->data);
+ list_values = g_list_delete_link (list_values, to_remove);
+ if (pos == 1) {
+ /* Removed the head of extended-data; we need to update all related keys
+ to point to the new header */
+ for (rel_key = related_keys; rel_key; rel_key = g_list_next (rel_key)) {
+ g_hash_table_insert (mdata->priv->extended_data,
+ rel_key->data,
+ list_values);
+ }
+ }
+ }
+}
+
+/**
+ * grl_data_multi_update:
+ * @mdata: a multivalued data
+ * @prop: a set of related keys
+ * @pos: position to be updated
+ *
+ * Updates the values at position in mdata with values in prop.
+ *
+ * GrlDataMulti will take ownership of prop, so do not free it after invoking
+ * this function.
+ **/
+void
+grl_data_multi_update (GrlDataMulti *mdata,
+ GrlProperty *prop,
+ guint pos)
+{
+ GList *keys;
+ GList *list_val;
+ GrlPluginRegistry *registry;
+ const GList *related_keys;
+
+ g_return_if_fail (GRL_IS_DATA_MULTI (mdata));
+ g_return_if_fail (GRL_IS_PROPERTY (prop));
+
+ keys = grl_data_get_keys (GRL_DATA (prop));
+ if (!keys) {
+ GRL_WARNING ("Empty properties");
+ g_object_unref (prop);
+ return;
+ }
+
+ if (pos == 0) {
+ registry = grl_plugin_registry_get_default ();
+ related_keys = grl_plugin_registry_lookup_metadata_relation (registry,
+ keys->data);
+ while (related_keys) {
+ grl_data_set (GRL_DATA (mdata),
+ related_keys->data,
+ grl_data_get (GRL_DATA (prop), related_keys->data));
+ related_keys = g_list_next (related_keys);
+ }
+ g_object_unref (prop);
+ } else {
+ /* Replace the entire element */
+ list_val = g_list_nth (g_hash_table_lookup (mdata->priv->extended_data,
+ keys->data),
+ pos - 1);
+ if (!list_val) {
+ GRL_WARNING ("Wrong position %u when updating", pos);
+ g_object_unref (prop);
+ return;
+ }
+
+ g_object_unref (list_val->data);
+ list_val->data = prop;
+ }
+}
diff --git a/src/data/grl-data-multi.h b/src/data/grl-data-multi.h
index 3e25973..590197e 100644
--- a/src/data/grl-data-multi.h
+++ b/src/data/grl-data-multi.h
@@ -30,9 +30,8 @@
#define _GRL_DATA_MULTI_H_
#include <grl-data.h>
+#include <grl-property.h>
#include <glib-object.h>
-/* #include <grl-metadata-key.h> */
-/* #include <grl-definitions.h> */
G_BEGIN_DECLS
@@ -94,6 +93,15 @@ GType grl_data_multi_get_type (void) G_GNUC_CONST;
GrlDataMulti *grl_data_multi_new (void);
+void grl_data_multi_add (GrlDataMulti *mdata, GrlProperty *prop);
+
+guint grl_data_multi_length (GrlDataMulti *mdata, GrlKeyID key);
+
+GrlProperty *grl_data_multi_get (GrlDataMulti *mdata, GrlKeyID key, guint pos);
+
+void grl_data_multi_remove (GrlDataMulti *mdata, GrlKeyID key, guint pos);
+
+void grl_data_multi_update (GrlDataMulti *mdata, GrlProperty *prop, guint pos);
G_END_DECLS
#endif /* _GRL_DATA_MULTI_H_ */
--
1.7.1
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]