[grilo] core: Add multi-valued API to GrlData
- From: Juan A. Suarez Romero <jasuarez src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [grilo] core: Add multi-valued API to GrlData
- Date: Fri, 4 Mar 2011 09:30:11 +0000 (UTC)
commit 58a09ac78883b05996ad547cedb6158d54d1d8c6
Author: Juan A. Suarez Romero <jasuarez igalia com>
Date: Thu Mar 3 11:27:49 2011 +0000
core: Add multi-valued API to GrlData
The old singled-valued API is still there, but will work with the first value
of each key.
Signed-off-by: Juan A. Suarez Romero <jasuarez igalia com>
src/data/grl-data.c | 662 +++++++++++++++++++++++++++++++++++++++++++--------
src/data/grl-data.h | 25 ++
2 files changed, 586 insertions(+), 101 deletions(-)
---
diff --git a/src/data/grl-data.c b/src/data/grl-data.c
index 116319c..e5ed4bf 100644
--- a/src/data/grl-data.c
+++ b/src/data/grl-data.c
@@ -25,7 +25,8 @@
/**
* SECTION:grl-data
* @short_description: Low-level class to store data
- * @see_also: #GrlMedia, #GrlMediaBox, #GrlMediaVideo, #GrlMediaAudio, #GrlMediaImage
+ * @see_also: #GrlMedia, #GrlMediaBox, #GrlMediaVideo, #GrlMediaAudio,
+ * #GrlMediaImage
*
* This class acts as dictionary where keys and their values can be stored. It
* is suggested to better high level classes, like #GrlMedia, which
@@ -34,6 +35,10 @@
#include "grl-data.h"
#include "grl-log.h"
+#include <grl-plugin-registry.h>
+
+#define GRL_LOG_DOMAIN_DEFAULT data_log_domain
+GRL_LOG_DOMAIN(data_log_domain);
enum {
PROP_0,
@@ -48,7 +53,7 @@ struct _GrlDataPrivate {
static void grl_data_set_property (GObject *object,
guint prop_id,
const GValue *value,
- GParamSpec *pspec);
+ GParamSpec *pspec);
static void grl_data_get_property (GObject *object,
guint prop_id,
@@ -56,20 +61,16 @@ static void grl_data_get_property (GObject *object,
GParamSpec *pspec);
static void grl_data_finalize (GObject *object);
+static void free_list_values (GrlKeyID key, GList *values, gpointer user_data);
#define GRL_DATA_GET_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE ((o), GRL_TYPE_DATA, GrlDataPrivate))
-G_DEFINE_TYPE (GrlData, grl_data, G_TYPE_OBJECT);
+static void free_list_values (GrlKeyID key, GList *values, gpointer user_data);
-static void
-free_val (GValue *val)
-{
- if (val) {
- g_value_unset (val);
- g_free (val);
- }
-}
+/* ================ GrlData GObject ================ */
+
+G_DEFINE_TYPE (GrlData, grl_data, G_TYPE_OBJECT);
static void
grl_data_class_init (GrlDataClass *klass)
@@ -98,13 +99,20 @@ grl_data_init (GrlData *self)
self->priv->data = g_hash_table_new_full (g_direct_hash,
g_direct_equal,
NULL,
- (GDestroyNotify) free_val);
+ NULL);
}
static void
grl_data_finalize (GObject *object)
{
+ GrlData *data = GRL_DATA (object);
+
g_signal_handlers_destroy (object);
+ g_hash_table_foreach (data->priv->data,
+ (GHFunc) free_list_values,
+ NULL);
+ g_hash_table_unref (data->priv->data);
+
G_OBJECT_CLASS (grl_data_parent_class)->finalize (object);
}
@@ -146,6 +154,38 @@ grl_data_get_property (GObject *object,
}
}
+/* ================ Utitilies ================ */
+
+/* Free the list of values, which are of type #GrlRelatedKeys */
+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);
+}
+
+/* Returns the sample key that represents the set of keys related with @key */
+static GrlKeyID
+get_sample_key (GrlKeyID key)
+{
+ GrlPluginRegistry *registry;
+ const GList *related_keys;
+
+ registry = grl_plugin_registry_get_default ();
+ related_keys =
+ grl_plugin_registry_lookup_metadata_key_relation (registry, key);
+
+ if (!related_keys) {
+ GRL_WARNING ("Related keys not found for key \"%s\"",
+ grl_metadata_key_get_name (related_keys->data));
+ return NULL;
+ } else {
+ return related_keys->data;
+ }
+}
+
+/* ================ API ================ */
+
/**
* grl_data_new:
*
@@ -165,78 +205,89 @@ grl_data_new (void)
/**
* grl_data_get:
* @data: data to retrieve value
- * @key: (type GObject.ParamSpec): key to look up.
+ * @key: (type Grl.KeyID): key to look up.
*
- * Get the value associated with the key. If it does not contain any value, NULL
- * will be returned.
+ * Get the first value from @data associated with @key.
*
- * Returns: (transfer none): a #GValue. This value should not be modified nor freed by user.
+ * Returns: (transfer none): a #GValue. This value should not be modified nor
+ * freed by user.
*
* Since: 0.1.4
**/
const GValue *
grl_data_get (GrlData *data, GrlKeyID key)
{
+ GrlRelatedKeys *relkeys = NULL;
+
g_return_val_if_fail (GRL_IS_DATA (data), NULL);
g_return_val_if_fail (key, NULL);
- return g_hash_table_lookup (data->priv->data, key);
+ if (grl_data_length (data, key) > 0) {
+ relkeys = grl_data_get_related_keys (data, key, 0);
+ }
+
+ if (!relkeys) {
+ return NULL;
+ }
+
+ return grl_related_keys_get (relkeys, key);
}
/**
* grl_data_set:
* @data: data to modify
- * @key: (type GObject.ParamSpec): key to change or add
+ * @key: (type Grl.KeyID): key to change or add
* @value: the new value
*
- * Sets the value associated with the key. If key already has a value and
- * #overwrite is TRUE, old value is freed and the new one is set.
+ * Sets the first value associated with @key in @data. If key already has a
+ * value and #overwrite is %TRUE, old value is freed and the new one is
+ * set. Else the new one is assigned.
*
- * Also, checks that value is compliant with the key specification, modifying it
- * accordingly. For instance, if the key requires a number between 0 and 10, but
- * value is outside this range, it will be adapted accordingly.
+ * Also, checks that @value is compliant with @key specification, modifying it
+ * accordingly. For instance, if @key requires a number between 0 and 10, but
+ * @value is outside this range, it will be adapted accordingly.
*
* Since: 0.1.4
**/
void
grl_data_set (GrlData *data, GrlKeyID key, const GValue *value)
{
- GValue *copy = NULL;
+ GrlRelatedKeys *relkeys = NULL;
g_return_if_fail (GRL_IS_DATA (data));
g_return_if_fail (key);
- if (data->priv->overwrite ||
- g_hash_table_lookup (data->priv->data, key) == NULL) {
- /* Dup value */
- if (value) {
- if (G_VALUE_TYPE (value) == GRL_METADATA_KEY_GET_TYPE (key)) {
- copy = g_new0 (GValue, 1);
- g_value_init (copy, G_VALUE_TYPE (value));
- g_value_copy (value, copy);
- } else {
- GRL_WARNING ("value has type %s, but expected %s",
- g_type_name (G_VALUE_TYPE (value)),
- g_type_name (GRL_METADATA_KEY_GET_TYPE (key)));
- }
- }
+ /* Get the right set of related keys */
+ if (grl_data_length (data, key) > 0) {
+ relkeys = grl_data_get_related_keys (data, key, 0);
+ }
- if (copy && g_param_value_validate (key, copy)) {
- GRL_WARNING ("'%s' value invalid, adjusting",
- GRL_METADATA_KEY_GET_NAME (key));
+ if (!relkeys) {
+ /* No related keys; add them */
+ relkeys = grl_related_keys_new ();
+ grl_related_keys_set (relkeys, key, value);
+ grl_data_add_related_keys (data, relkeys);
+ } else {
+ if (grl_related_keys_key_is_known (relkeys, key) &&
+ !data->priv->overwrite) {
+ /* relkeys already has a value, and we can not overwrite it */
+ return;
+ } else {
+ /* Set the new value */
+ grl_related_keys_set (relkeys, key, value);
}
- g_hash_table_insert (data->priv->data, key, copy);
}
}
/**
* grl_data_set_string:
* @data: data to modify
- * @key: (type GObject.ParamSpec): key to change or add
+ * @key: (type Grl.KeyID): key to change or add
* @strvalue: the new value
*
- * Sets the value associated with the key. If key already has a value and
- * #overwrite is TRUE, old value is freed and the new one is set.
+ * Sets the first string value associated with @key in @data. If @key already
+ * has a value and #overwrite is %TRUE, old value is freed and the new one is
+ * set.
*
* Since: 0.1.4
**/
@@ -259,12 +310,14 @@ grl_data_set_string (GrlData *data,
/**
* grl_data_get_string:
* @data: data to inspect
- * @key: (type GObject.ParamSpec): key to use
+ * @key: (type Grl.KeyID): key to use
*
- * Returns the value associated with the key. If key has no value, or value is
- * not string, or key is not in data, then NULL is returned.
+ * Returns the first string value associated with @key from @data. If @key has
+ * no first value, or value is not string, or @key is not in @data, then %NULL
+ * is returned.
*
- * Returns: string associated with key, or NULL in other case. Caller should not change nor free the value.
+ * Returns: string associated with @key, or %NULL in other case. Caller should
+ * not change nor free the value.
*
* Since: 0.1.4
**/
@@ -273,7 +326,7 @@ grl_data_get_string (GrlData *data, GrlKeyID key)
{
const GValue *value = grl_data_get (data, key);
- if (!value || !G_VALUE_HOLDS_STRING(value)) {
+ if (!value || !G_VALUE_HOLDS_STRING (value)) {
return NULL;
} else {
return g_value_get_string (value);
@@ -283,11 +336,11 @@ grl_data_get_string (GrlData *data, GrlKeyID key)
/**
* grl_data_set_int:
* @data: data to change
- * @key: (type GObject.ParamSpec): key to change or add
+ * @key: (type Grl.KeyID): key to change or add
* @intvalue: the new value
*
- * Sets the value associated with the key. If key already has a value and
- * #overwrite is TRUE, old value is replaced by the new one.
+ * Sets the first int value associated with @key in @data. If @key already has a
+ * first value and #overwrite is %TRUE, old value is replaced by the new one.
*
* Since: 0.1.4
**/
@@ -303,12 +356,13 @@ grl_data_set_int (GrlData *data, GrlKeyID key, gint intvalue)
/**
* grl_data_get_int:
* @data: data to inspect
- * @key: (type GObject.ParamSpec): key to use
+ * @key: (type Grl.KeyID): key to use
*
- * Returns the value associated with the key. If key has no value, or value is
- * not a gint, or key is not in data, then 0 is returned.
+ * Returns the first int value associated with @key from @data. If @key has no
+ * first value, or value is not a gint, or @key is not in data, then 0 is
+ * returned.
*
- * Returns: int value associated with key, or 0 in other case.
+ * Returns: int value associated with @key, or 0 in other case.
*
* Since: 0.1.4
**/
@@ -317,7 +371,7 @@ grl_data_get_int (GrlData *data, GrlKeyID key)
{
const GValue *value = grl_data_get (data, key);
- if (!value || !G_VALUE_HOLDS_INT(value)) {
+ if (!value || !G_VALUE_HOLDS_INT (value)) {
return 0;
} else {
return g_value_get_int (value);
@@ -327,11 +381,11 @@ grl_data_get_int (GrlData *data, GrlKeyID key)
/**
* grl_data_set_float:
* @data: data to change
- * @key: (type GObject.ParamSpec): key to change or add
+ * @key: (type Grl.KeyID): key to change or add
* @floatvalue: the new value
*
- * Sets the value associated with the key. If key already has a value and
- * #overwrite is TRUE, old value is replaced by the new one.
+ * Sets the first float value associated with @key in @data. If @key already has
+ * a first value and #overwrite is %TRUE, old value is replaced by the new one.
*
* Since: 0.1.5
**/
@@ -343,15 +397,17 @@ grl_data_set_float (GrlData *data, GrlKeyID key, float floatvalue)
g_value_set_float (&value, floatvalue);
grl_data_set (data, key, &value);
}
+
/**
* grl_data_get_float:
* @data: data to inspect
- * @key: (type GObject.ParamSpec): key to use
+ * @key: (type Grl.KeyID): key to use
*
- * Returns the value associated with the key. If key has no value, or value is
- * not a gfloat, or key is not in data, then 0 is returned.
+ * Returns the first float value associated with @key from @data. If @key has no
+ * first value, or value is not a gfloat, or @key is not in data, then 0 is
+ * returned.
*
- * Returns: float value associated with key, or 0 in other case.
+ * Returns: float value associated with @key, or 0 in other case.
*
* Since: 0.1.5
**/
@@ -360,7 +416,7 @@ grl_data_get_float (GrlData *data, GrlKeyID key)
{
const GValue *value = grl_data_get (data, key);
- if (!value || !G_VALUE_HOLDS_FLOAT(value)) {
+ if (!value || !G_VALUE_HOLDS_FLOAT (value)) {
return 0;
} else {
return g_value_get_float (value);
@@ -370,12 +426,13 @@ grl_data_get_float (GrlData *data, GrlKeyID key)
/**
* grl_data_set_binary:
* @data: data to change
- * @key: (type GObject.ParamSpec): key to change or add
+ * @key: (type Grl.KeyID): key to change or add
* @buf: buffer holding the data
* @size: size of the buffer
*
- * Sets the value associated with the key. If key already has a value and
- * #overwrite is TRUE, old value is replaced by the new one.
+ * Sets the first binary value associated with @key in @data. If @key already
+ * has a first value and #overwrite is %TRUE, old value is replaced by the new
+ * one.
**/
void
grl_data_set_binary (GrlData *data, GrlKeyID key, const guint8 *buf, gsize size)
@@ -396,14 +453,15 @@ grl_data_set_binary (GrlData *data, GrlKeyID key, const guint8 *buf, gsize size)
/**
* grl_data_get_binary:
* @data: data to inspect
- * @key: (type GObject.ParamSpec): key to use
- * @size: location to store the buffer size
+ * @key: (type Grl.KeyID): key to use
+ * @size: (out): location to store the buffer size
*
- * Returns the value associated with the key. If key has no value, or value is
- * not a gfloat, or key is not in data, then 0 is returned.
+ * Returns the first binary value associated with @key from @data. If @key has
+ * no first value, or value is not a gfloat, or @key is not in data, then %NULL
+ * is returned.
*
- * Returns: buffer location associated with the key, or NULL in other case. If
- * successful size will be set the to the buffer size.
+ * Returns: buffer location associated with the @key, or %NULL in other case. If
+ * successful @size will be set the to the buffer size.
**/
const guint8 *
grl_data_get_binary(GrlData *data, GrlKeyID key, gsize *size)
@@ -412,7 +470,7 @@ grl_data_get_binary(GrlData *data, GrlKeyID key, gsize *size)
const GValue *value = grl_data_get (data, key);
- if (!value || !G_VALUE_HOLDS_BOXED(value)) {
+ if (!value || !G_VALUE_HOLDS_BOXED (value)) {
return NULL;
} else {
GByteArray * array;
@@ -426,9 +484,9 @@ grl_data_get_binary(GrlData *data, GrlKeyID key, gsize *size)
/**
* grl_data_add:
* @data: data to change
- * @key: (type GObject.ParamSpec): key to add
+ * @key: (type Grl.KeyID): key to add
*
- * Adds a new key to data, with no value. If key already exists, it does
+ * Adds a new @key to @data, with no value. If key already exists, it does
* nothing.
*
* Since: 0.1.4
@@ -444,29 +502,29 @@ grl_data_add (GrlData *data, GrlKeyID key)
/**
* grl_data_remove:
* @data: data to change
- * @key: (type GObject.ParamSpec): key to remove
+ * @key: (type Grl.KeyID): key to remove
+ *
+ * Removes the first value for @key from @data. If there are other keys related
+ * to @key their values will also be removed from @data.
*
- * Removes key from data, freeing its value. If key is not in data, then
- * it does nothing.
+ * Notice this function ignores the value of #overwrite property.
*
* Since: 0.1.4
**/
void
grl_data_remove (GrlData *data, GrlKeyID key)
{
- g_return_if_fail (GRL_IS_DATA (data));
-
- g_hash_table_remove (data->priv->data, key);
+ grl_data_remove_nth (data, key, 0);
}
/**
* grl_data_has_key:
* @data: data to inspect
- * @key: (type GObject.ParamSpec): key to search
+ * @key: (type Grl.KeyID): key to search
*
- * Checks if key is in data.
+ * Checks if @key is in @data.
*
- * Returns: TRUE if key is in data, FALSE in other case.
+ * Returns: %TRUE if @key is in @data, %FALSE in other case.
*
* Since: 0.1.4
**/
@@ -482,11 +540,11 @@ grl_data_has_key (GrlData *data, GrlKeyID key)
* grl_data_get_keys:
* @data: data to inspect
*
- * Returns a list with keys contained in data.
+ * Returns a list with keys contained in @data.
*
- * Returns: (transfer container) (element-type GObject.ParamSpec): an array with
- * the keys. The content of the list should not be modified or freed. Use g_list_free()
- * when done using the list.
+ * Returns: (transfer container) (element-type Grl.KeyID): an array with the
+ * keys. The content of the list should not be modified or freed. Use
+ * g_list_free() when done using the list.
*
* Since: 0.1.4
**/
@@ -505,44 +563,446 @@ grl_data_get_keys (GrlData *data)
/**
* grl_data_key_is_known:
* @data: data to inspect
- * @key: (type GObject.ParamSpec): key to search
+ * @key: (type Grl.KeyID): key to search
*
- * Checks if the key has a value.
+ * Checks if the @key has a first value in @data.
*
- * Returns: TRUE if key has a value.
+ * Returns: %TRUE if key has a value.
*
* Since: 0.1.4
**/
gboolean
grl_data_key_is_known (GrlData *data, GrlKeyID key)
{
- GValue *v;
+ const GValue *v;
g_return_val_if_fail (GRL_IS_DATA (data), FALSE);
+ g_return_val_if_fail (key, FALSE);
- v = g_hash_table_lookup (data->priv->data, key);
+ v = grl_data_get (data, key);
if (!v) {
return FALSE;
}
if (G_VALUE_HOLDS_STRING (v)) {
- return g_value_get_string(v) != NULL;
+ return g_value_get_string (v) != NULL;
}
return TRUE;
}
/**
+ * grl_data_add_related_keys:
+ * @data: data to change
+ * @relkeys: a set of related properties with their values
+ *
+ * Adds a new set of values into @data.
+ *
+ * All keys in @prop must be related among them.
+ *
+ * @data will take the ownership of @relkeys, so do not modify it.
+ **/
+void
+grl_data_add_related_keys (GrlData *data,
+ GrlRelatedKeys *relkeys)
+{
+ GList *keys;
+ GList *list_relkeys;
+ GrlKeyID sample_key;
+
+ g_return_if_fail (GRL_IS_DATA (data));
+ g_return_if_fail (GRL_IS_RELATED_KEYS (relkeys));
+
+ keys = grl_related_keys_get_keys (relkeys, TRUE);
+ if (!keys) {
+ /* Ignore empty set of related keys */
+ GRL_WARNING ("Trying to add an empty GrlRelatedKeys to GrlData");
+ g_object_unref (relkeys);
+ return;
+ }
+
+ sample_key = get_sample_key (keys->data);
+ g_list_free (keys);
+
+ if (!sample_key) {
+ g_object_unref (relkeys);
+ return;
+ }
+
+ list_relkeys = g_hash_table_lookup (data->priv->data, sample_key);
+ list_relkeys = g_list_append (list_relkeys, relkeys);
+ g_hash_table_insert (data->priv->data, sample_key, list_relkeys);
+}
+
+/**
+ * grl_data_add_string:
+ * @data: data to append
+ * @key: (type Grl.KeyID): key to append
+ * @strvalue: the new value
+ *
+ * Appends a new string value for @key in @data.
+ *
+ * If there are other keys that are related to @key, %NULL values will be
+ * appended for each of them too.
+ **/
+void
+grl_data_add_string (GrlData *data,
+ GrlKeyID key,
+ const gchar *strvalue)
+{
+ GrlRelatedKeys *relkeys;
+
+ relkeys = grl_related_keys_new ();
+ grl_related_keys_set_string (relkeys, key, strvalue);
+ grl_data_add_related_keys (data, relkeys);
+}
+
+/**
+ * grl_data_add_int:
+ * @data: data to append
+ * @key: (type Grl.KeyID): key to append
+ * @intvalue: the new value
+ *
+ * Appends a new int value for @key in @data.
+ *
+ * If there are other keys that are related to @key, %NULL values will be
+ * appended for each of them too.
+ **/
+void
+grl_data_add_int (GrlData *data,
+ GrlKeyID key,
+ gint intvalue)
+{
+ GrlRelatedKeys *relkeys;
+
+ relkeys = grl_related_keys_new ();
+ grl_related_keys_set_int (relkeys, key, intvalue);
+ grl_data_add_related_keys (data, relkeys);
+}
+
+/**
+ * grl_data_add_float:
+ * @data: data to append
+ * @key: (type Grl.KeyID): key to append
+ * @floatvalue: the new value
+ *
+ * Appends a new float value for @key in @data.
+ *
+ * If there are other keys that are related to @key, %NULL values will be
+ * appended for each of them too.
+ **/
+void
+grl_data_add_float (GrlData *data,
+ GrlKeyID key,
+ gfloat floatvalue)
+{
+ GrlRelatedKeys *relkeys;
+
+ relkeys = grl_related_keys_new ();
+ grl_related_keys_set_float (relkeys, key, floatvalue);
+ grl_data_add_related_keys (data, relkeys);
+}
+
+/**
+ * grl_data_add_binary:
+ * @data: data to append
+ * @key: (type Grl.KeyID): key to append
+ * @buf: the buffer containing the new value
+ * @size: size of buffer
+ *
+ * Appends a new binary value for @key in @data.
+ *
+ * If there are other keys that are related to @key, %NULL values will be
+ * appended for each of them too.
+ **/
+void
+grl_data_add_binary (GrlData *data,
+ GrlKeyID key,
+ const guint8 *buf,
+ gsize size)
+{
+ GrlRelatedKeys *relkeys;
+
+ relkeys = grl_related_keys_new ();
+ grl_related_keys_set_binary (relkeys, key, buf, size);
+ grl_data_add_related_keys (data, relkeys);
+}
+
+/**
+ * grl_data_length:
+ * @data: a data
+ * @key: a metadata key
+ *
+ * Returns how many values @key has in @data.
+ *
+ * Returns: number of values
+ **/
+guint
+grl_data_length (GrlData *data,
+ GrlKeyID key)
+{
+ GrlKeyID sample_key;
+
+ g_return_val_if_fail (GRL_IS_DATA (data), 0);
+ g_return_val_if_fail (key, 0);
+
+ sample_key = get_sample_key (key);
+ if (!sample_key) {
+ return 0;
+ }
+
+ return g_list_length (g_hash_table_lookup (data->priv->data, sample_key));
+}
+
+/**
+ * grl_data_get_related_keys:
+ * @data: a data
+ * @key: a metadata key
+ * @index: element to retrieve, starting at 0
+ *
+ * Returns a set containing the values for @key and related keys at position
+ * @index from @data.
+ *
+ * If user changes any of the values in the related keys, the changes will
+ * become permanent.
+ *
+ * Returns: a #GrlRelatedKeys. Do not free it.
+ **/
+GrlRelatedKeys *
+grl_data_get_related_keys (GrlData *data,
+ GrlKeyID key,
+ guint index)
+{
+ GList *relkeys_list;
+ GrlKeyID sample_key;
+ GrlRelatedKeys *relkeys;
+
+ g_return_val_if_fail (GRL_IS_DATA (data), NULL);
+ g_return_val_if_fail (key, NULL);
+
+ sample_key = get_sample_key (key);
+ if (!sample_key) {
+ return NULL;
+ }
+
+ relkeys_list = g_hash_table_lookup (data->priv->data, sample_key);
+ relkeys = g_list_nth_data (relkeys_list, index);
+
+ if (!relkeys) {
+ GRL_WARNING ("%s: index %u out of range", __FUNCTION__, index);
+ return NULL;
+ }
+
+ return relkeys;
+}
+
+/**
+ * grl_data_get_all_single_related_keys:
+ * @data: a data
+ * @key: a metadata key
+ *
+ * Returns all non-%NULL values for @key from @data. This ignores related keys.
+ *
+ * Returns: (element-type GObject.Value) (transfer container): a #GList with
+ * values. Do not change or free the values. Free the list with #g_list_free.
+ **/
+GList *
+grl_data_get_all_single_related_keys (GrlData *data,
+ GrlKeyID key)
+{
+ GrlKeyID sample_key;
+
+ g_return_val_if_fail (GRL_IS_DATA (data), NULL);
+ g_return_val_if_fail (key, NULL);
+
+ sample_key = get_sample_key (key);
+ if (!sample_key) {
+ return NULL;
+ }
+
+ return g_list_copy (g_hash_table_lookup (data->priv->data, sample_key));
+}
+
+/**
+ * grl_data_get_all_single_related_keys_string:
+ * @data: a data
+ * @key: a metadata key
+ *
+ * Returns all non-%NULL values for @key from @data. @key must have been
+ * registered as a string-type key. This ignores related keys.
+ *
+ * Returns: (element-type utf8) (transfer container): a #GList with values. Do
+ * not change or free the strings. Free the list with #g_list_free.
+ **/
+GList *
+grl_data_get_all_single_related_keys_string (GrlData *data,
+ GrlKeyID key)
+{
+ GList *list_strings = NULL;
+ GList *list_values;
+ GList *value;
+ const gchar *string_value;
+
+ g_return_val_if_fail (GRL_IS_DATA (data), NULL);
+ g_return_val_if_fail (key, NULL);
+
+ /* Verify key is of type string */
+ if (GRL_METADATA_KEY_GET_TYPE (key) != G_TYPE_STRING) {
+ GRL_WARNING ("%s: requested key is not of type string", __FUNCTION__);
+ return NULL;
+ }
+
+ list_values = grl_data_get_all_single_related_keys (data, key);
+ for (value = list_values; value; value = g_list_next (value)) {
+ string_value = g_value_get_string (value->data);
+ if (string_value) {
+ list_strings = g_list_prepend (list_strings, (gpointer) string_value);
+ }
+ }
+
+ g_list_free (list_values);
+
+ return g_list_reverse (list_strings);
+}
+
+/**
+ * grl_data_remove_nth:
+ * @data: a data
+ * @key: a metadata key
+ * @index: index of key to be removed, starting at 0
+ *
+ * Removes the value at position @index for @key from @data. If there are other
+ * keys related to @key, their values at position @index will also be removed
+ * from @data.
+ **/
+void
+grl_data_remove_nth (GrlData *data,
+ GrlKeyID key,
+ guint index)
+{
+ GList *relkeys_element;
+ GList *relkeys_list;
+ GrlKeyID sample_key;
+
+ g_return_if_fail (GRL_IS_DATA (data));
+ g_return_if_fail (key);
+
+ sample_key = get_sample_key (key);
+ if (!sample_key) {
+ return;
+ }
+
+ relkeys_list = g_hash_table_lookup (data->priv->data, sample_key);
+ relkeys_element = g_list_nth (relkeys_list, index);
+ if (!relkeys_element) {
+ GRL_WARNING ("%s: index %u out of range", __FUNCTION__, index);
+ return;
+ }
+
+ g_object_unref (relkeys_element->data);
+ relkeys_list = g_list_delete_link (relkeys_list, relkeys_element);
+ g_hash_table_insert (data->priv->data, sample_key, relkeys_list);
+}
+
+/**
+ * grl_data_set_related_keys:
+ * @data: a data
+ * @relkeys: a set of related keys
+ * @index: position to be updated, starting at 0
+ *
+ * Updates the values at position @index in @data with values in @relkeys.
+ *
+ * @data will take ownership of @relkeys, so do not free it after invoking this
+ * function.
+ **/
+void
+grl_data_set_related_keys (GrlData *data,
+ GrlRelatedKeys *relkeys,
+ guint index)
+{
+ GList *keys;
+ GList *relkeys_element;
+ GList *relkeys_list;
+ GrlKeyID sample_key;
+
+ g_return_if_fail (GRL_IS_DATA (data));
+ g_return_if_fail (GRL_IS_RELATED_KEYS (relkeys));
+
+ keys = grl_related_keys_get_keys (relkeys, TRUE);
+ if (!keys) {
+ GRL_WARNING ("Trying to set an empty GrlRelatedKeys into GrlData");
+ g_object_unref (relkeys);
+ return;
+ }
+
+ sample_key = get_sample_key (keys->data);
+ g_list_free (keys);
+ if (!sample_key) {
+ return;
+ }
+
+ relkeys_list = g_hash_table_lookup (data->priv->data, sample_key);
+ relkeys_element = g_list_nth (relkeys_list, index);
+ if (!relkeys_element) {
+ GRL_WARNING ("%s: index %u out of range", __FUNCTION__, index);
+ return;
+ }
+
+ g_object_unref (relkeys_element->data);
+ relkeys_element->data = relkeys;
+}
+
+/**
+ * grl_data_dup:
+ * @data: data to duplicate
+ *
+ * Makes a deep copy of @data and all its contents.
+ *
+ * Returns: a new #GrlData. Free it with #g_object_unref.
+ **/
+GrlData *
+grl_data_dup (GrlData *data)
+{
+ GList *dup_relkeys_list;
+ GList *key;
+ GList *keys;
+ GList *relkeys_list;
+ GrlData *dup_data;
+
+ g_return_val_if_fail (GRL_IS_DATA (data), NULL);
+
+ dup_data = grl_data_new ();
+ keys = g_hash_table_get_keys (data->priv->data);
+ for (key = keys; key; key = g_list_next (key)) {
+ dup_relkeys_list = NULL;
+ relkeys_list = g_hash_table_lookup (data->priv->data, key->data);
+ while (relkeys_list) {
+ dup_relkeys_list =
+ g_list_prepend (dup_relkeys_list,
+ grl_related_keys_dup (relkeys_list->data));
+ relkeys_list = g_list_next (relkeys_list);
+ }
+ g_hash_table_insert (dup_data->priv->data,
+ key->data,
+ g_list_reverse (relkeys_list));
+ }
+
+ g_list_free (keys);
+
+ return dup_data;
+}
+
+/**
* grl_data_set_overwrite:
* @data: data to change
* @overwrite: if data can be overwritten
*
- * This controls if #grl_data_set will overwrite current value of a property
+ * This controls if #grl_data_set will overwrite the current value of a property
* with the new one.
*
- * Set it to TRUE so old values are overwritten, or FALSE in other case (default
- * is FALSE).
+ * Set it to %TRUE so old values are overwritten, or %FALSE in other case
+ * (default is %FALSE).
*
* Since: 0.1.4
**/
@@ -563,7 +1023,7 @@ grl_data_set_overwrite (GrlData *data, gboolean overwrite)
*
* Checks if old values are replaced when calling #grl_data_set.
*
- * Returns: TRUE if values will be overwritten.
+ * Returns: %TRUE if values will be overwritten.
*
* Since: 0.1.4
**/
diff --git a/src/data/grl-data.h b/src/data/grl-data.h
index 6af3ad4..2854162 100644
--- a/src/data/grl-data.h
+++ b/src/data/grl-data.h
@@ -32,6 +32,7 @@
#include <glib-object.h>
#include <grl-metadata-key.h>
#include <grl-definitions.h>
+#include <grl-related-keys.h>
G_BEGIN_DECLS
@@ -127,6 +128,30 @@ GList *grl_data_get_keys (GrlData *data);
gboolean grl_data_key_is_known (GrlData *data, GrlKeyID key);
+void grl_data_add_related_keys (GrlData *data, GrlRelatedKeys *relkeys);
+
+void grl_data_add_string (GrlData *data, GrlKeyID key, const gchar *strvalue);
+
+void grl_data_add_int (GrlData *data, GrlKeyID key, gint intvalue);
+
+void grl_data_add_float (GrlData *data, GrlKeyID key, gfloat floatvalue);
+
+void grl_data_add_binary (GrlData *data, GrlKeyID key, const guint8 *buf, gsize size);
+
+guint grl_data_length (GrlData *data, GrlKeyID key);
+
+GrlRelatedKeys *grl_data_get_related_keys (GrlData *data, GrlKeyID key, guint index);
+
+GList *grl_data_get_all_single_related_keys (GrlData *data, GrlKeyID key);
+
+GList *grl_data_get_all_single_related_keys_string (GrlData *data, GrlKeyID key);
+
+void grl_data_remove_nth (GrlData *data, GrlKeyID key, guint index);
+
+void grl_data_set_related_keys (GrlData *data, GrlRelatedKeys *relkeys, guint index);
+
+GrlData *grl_data_dup (GrlData *data);
+
void grl_data_set_overwrite (GrlData *data, gboolean overwrite);
gboolean grl_data_get_overwrite (GrlData *data);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]