[PATCH 7/8] core: Add range-filtering



From: "Juan A. Suarez Romero" <jasuarez igalia com>

Contains modifications by Guillaume Emont <guijemont igalia com>
---
 src/Makefile.am                  |    4 +-
 src/grl-caps.c                   |   52 ++++++++++++
 src/grl-caps.h                   |    6 ++
 src/grl-operation-options-priv.h |    1 +
 src/grl-operation-options.c      |  171 ++++++++++++++++++++++++++++++++++++++
 src/grl-operation-options.h      |   16 ++++
 src/grl-range-value.c            |   92 ++++++++++++++++++++
 src/grl-range-value.h            |   57 +++++++++++++
 8 files changed, 398 insertions(+), 1 deletions(-)
 create mode 100644 src/grl-range-value.c
 create mode 100644 src/grl-range-value.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 085fc32..b1d64eb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -55,6 +55,7 @@ lib@GRL_NAME@_la_SOURCES =					\
 	grl-value-helper.c					\
 	grl-caps.c 						\
 	grl-operation-options.c grl-operation-options-priv.h	\
+	grl-range-value.c					\
 	grilo.c
 
 data_c_sources =		\
@@ -87,7 +88,8 @@ lib@GRL_NAME@inc_HEADERS =	\
 	grl-operation.h		\
 	grl-value-helper.h	\
 	grl-caps.h		\
-	grl-operation-options.h
+	grl-operation-options.h \
+	grl-range-value.h
 
 data_h_headers =		\
 	data/grl-data.h		\
diff --git a/src/grl-caps.c b/src/grl-caps.c
index 4669499..0654240 100644
--- a/src/grl-caps.c
+++ b/src/grl-caps.c
@@ -62,6 +62,7 @@ struct _GrlCapsPrivate {
   GHashTable *data;
   GrlTypeFilter type_filter;
   GList *key_filter;
+  GList *key_range_filter;
 };
 
 
@@ -77,6 +78,8 @@ grl_caps_finalize (GrlCaps *self)
 {
   g_hash_table_unref (self->priv->data);
   g_list_free (self->priv->key_filter);
+  g_list_free (self->priv->key_range_filter);
+
   G_OBJECT_CLASS (grl_caps_parent_class)->finalize ((GObject *) self);
 }
 
@@ -91,6 +94,7 @@ grl_caps_init (GrlCaps *self)
    * has to explicitly modify its caps. */
   self->priv->type_filter = GRL_TYPE_FILTER_NONE;
   self->priv->key_filter = NULL;
+  self->priv->key_range_filter = NULL;
 }
 
 static void
@@ -152,6 +156,11 @@ grl_caps_test_option (GrlCaps *caps, const gchar *key, const GValue *value)
     return grl_caps_is_key_filter (caps, metadata_key);
   }
 
+  if (0 == g_strcmp0 (key, GRL_OPERATION_OPTION_KEY_RANGE_FILTER)) {
+    GrlKeyID grl_key = g_value_get_grl_key_id (value);
+    return grl_caps_is_key_range_filter (caps, grl_key);
+  }
+
   return FALSE;
 }
 
@@ -213,3 +222,46 @@ grl_caps_is_key_filter (GrlCaps *caps, GrlKeyID key)
 
   return FALSE;
 }
+
+/**
+ * grl_caps_get_key_range_filter:
+ * @caps:
+ *
+ * Returns: (transfer none) (element-type GrlKeyID):
+ */
+GList *
+grl_caps_get_key_range_filter (GrlCaps *caps)
+{
+  g_return_val_if_fail (caps, NULL);
+
+  return caps->priv->key_range_filter;
+}
+
+/**
+ * grl_caps_set_key_range_filter:
+ * @caps:
+ * @keys: (transfer none) (element-type GrlKeyID):
+ */
+void
+grl_caps_set_key_range_filter (GrlCaps *caps, GList *keys)
+{
+  g_return_if_fail (caps);
+
+  if (caps->priv->key_range_filter) {
+    g_list_free (caps->priv->key_range_filter);
+  }
+
+  caps->priv->key_range_filter = g_list_copy (keys);
+}
+
+gboolean
+grl_caps_is_key_range_filter (GrlCaps *caps, GrlKeyID key)
+{
+  g_return_val_if_fail (caps, FALSE);
+
+  if(caps->priv->key_range_filter) {
+    return g_list_find (caps->priv->key_range_filter, GRLKEYID_TO_POINTER (key)) != NULL;
+  }
+
+  return FALSE;
+}
diff --git a/src/grl-caps.h b/src/grl-caps.h
index e3abdfa..b53de9f 100644
--- a/src/grl-caps.h
+++ b/src/grl-caps.h
@@ -94,6 +94,12 @@ void grl_caps_set_key_filter (GrlCaps *caps, GList *keys);
 
 gboolean grl_caps_is_key_filter (GrlCaps *caps, GrlKeyID key);
 
+GList *grl_caps_get_key_range_filter (GrlCaps *caps);
+
+void grl_caps_set_key_range_filter (GrlCaps *caps, GList *keys);
+
+gboolean grl_caps_is_key_range_filter (GrlCaps *caps, GrlKeyID key);
+
 G_END_DECLS
 
 #endif /* _GRL_CAPS_H_ */
diff --git a/src/grl-operation-options-priv.h b/src/grl-operation-options-priv.h
index 2f5d9c3..172edb2 100644
--- a/src/grl-operation-options-priv.h
+++ b/src/grl-operation-options-priv.h
@@ -36,6 +36,7 @@
 #define GRL_OPERATION_OPTION_FLAGS "flags"
 #define GRL_OPERATION_OPTION_TYPE_FILTER "type-filter"
 #define GRL_OPERATION_OPTION_KEY_EQUAL_FILTER "key-equal-filter"
+#define GRL_OPERATION_OPTION_KEY_RANGE_FILTER "key-range-filter"
 
 gboolean grl_operation_options_key_is_set (GrlOperationOptions *options,
                                            const gchar *key);
diff --git a/src/grl-operation-options.c b/src/grl-operation-options.c
index 265f20f..9f681d8 100644
--- a/src/grl-operation-options.c
+++ b/src/grl-operation-options.c
@@ -30,6 +30,7 @@
  */
 #include <grl-operation-options.h>
 #include <grl-value-helper.h>
+#include <grl-range-value.h>
 #include <grl-log.h>
 #include <grl-plugin-registry.h>
 
@@ -44,6 +45,7 @@ G_DEFINE_TYPE (GrlOperationOptions, grl_operation_options, G_TYPE_OBJECT);
 struct _GrlOperationOptionsPrivate {
   GHashTable *data;
   GHashTable *key_filter;
+  GHashTable *key_range_filter;
   GrlCaps *caps;
 };
 
@@ -63,6 +65,7 @@ grl_operation_options_finalize (GrlOperationOptions *self)
 {
   g_hash_table_unref (self->priv->data);
   g_hash_table_unref (self->priv->key_filter);
+  g_hash_table_unref (self->priv->key_range_filter);
   if (self->priv->caps)
     g_object_unref (self->priv->caps);
   G_OBJECT_CLASS (grl_operation_options_parent_class)->finalize ((GObject *) self);
@@ -75,6 +78,7 @@ grl_operation_options_init (GrlOperationOptions *self)
 
   self->priv->data = grl_g_value_hashtable_new ();
   self->priv->key_filter = grl_g_value_hashtable_new_direct ();
+  self->priv->key_range_filter = grl_range_value_hashtable_new ();
   self->priv->caps = NULL;
 }
 
@@ -141,6 +145,12 @@ key_filter_dup (gpointer key_p, GValue *value, GHashTable *destination)
   g_hash_table_insert (destination, key_p, grl_g_value_dup (value));
 }
 
+static void
+key_range_filter_dup (GrlKeyID key, GrlRangeValue *value, GHashTable *destination)
+{
+  grl_range_value_hashtable_insert (destination, GRLKEYID_TO_POINTER (key), value->min, value->max);
+}
+
 /* ========== API ========== */
 
 /**
@@ -191,6 +201,7 @@ grl_operation_options_obey_caps (GrlOperationOptions *options,
   GHashTableIter table_iter;
   gpointer key_ptr;
   GValue *value;
+  GrlRangeValue *range_value;
 
   if (supported_options) {
     *supported_options = grl_operation_options_new (caps);
@@ -230,6 +241,26 @@ grl_operation_options_obey_caps (GrlOperationOptions *options,
     }
   }
 
+  /* Check filter-by-range-key */
+  g_hash_table_iter_init (&table_iter, options->priv->key_range_filter);
+  while (g_hash_table_iter_next (&table_iter, &key_ptr, (gpointer *)&range_value)) {
+    GrlKeyID key_id = GRLPOINTER_TO_KEYID (key_ptr);
+    if (grl_caps_is_key_range_filter (caps, key_id)) {
+      if (supported_options) {
+        g_hash_table_insert ((*supported_options)->priv->key_range_filter,
+                             key_ptr,
+                             grl_range_value_dup (range_value));
+      }
+    } else {
+      ret = FALSE;
+      if (unsupported_options) {
+        g_hash_table_insert ((*unsupported_options)->priv->key_range_filter,
+                             key_ptr,
+                             grl_range_value_dup (range_value));
+      }
+    }
+  }
+
   return ret;
 }
 
@@ -254,6 +285,10 @@ grl_operation_options_copy (GrlOperationOptions *options)
                         (GHFunc) key_filter_dup,
                         copy->priv->key_filter);
 
+  g_hash_table_foreach (options->priv->key_range_filter,
+                        (GHFunc) key_range_filter_dup,
+                        copy->priv->key_range_filter);
+
   return copy;
 }
 
@@ -595,3 +630,139 @@ grl_operation_options_get_key_filter_list (GrlOperationOptions *options)
 {
   return g_hash_table_get_keys (options->priv->key_filter);
 }
+
+gboolean
+grl_operation_options_set_key_range_filter_value (GrlOperationOptions *options,
+                                                  GrlKeyID key,
+                                                  GValue *min_value,
+                                                  GValue *max_value)
+{
+  gboolean ret;
+
+  ret = (options->priv->caps == NULL) ||
+    grl_caps_is_key_range_filter (options->priv->caps, key);
+
+  if (ret) {
+    if (min_value || max_value) {
+      grl_range_value_hashtable_insert (options->priv->key_range_filter,
+                                        GRLKEYID_TO_POINTER (key),
+                                        min_value, max_value);
+    } else {
+      g_hash_table_remove (options->priv->key_range_filter,
+                           GRLKEYID_TO_POINTER (key));
+    }
+  }
+
+  return ret;
+}
+
+gboolean
+grl_operation_options_set_key_range_filter (GrlOperationOptions *options,
+                                            ...)
+{
+  GType key_type;
+  GValue min_value = { 0 };
+  GValue *min_p_value;
+  gint min_int_value;
+  gchar *min_str_value;
+  GValue max_value = { 0 };
+  GValue *max_p_value;
+  gint max_int_value;
+  gchar *max_str_value;
+  GrlKeyID next_key;
+  gboolean skip;
+  gboolean success = TRUE;
+  va_list args;
+
+  va_start (args, options);
+  next_key = va_arg (args, GrlKeyID);
+  while (next_key) {
+    key_type = GRL_METADATA_KEY_GET_TYPE (next_key);
+    g_value_init (&min_value, key_type);
+    g_value_init (&max_value, key_type);
+    min_p_value = NULL;
+    max_p_value = NULL;
+    skip = FALSE;
+    if (key_type == G_TYPE_STRING) {
+      min_str_value = va_arg (args, gchar *);
+      max_str_value = va_arg (args, gchar *);
+      if (min_str_value) {
+        g_value_set_string (&min_value, min_str_value);
+        min_p_value = &min_value;
+      }
+      if (max_str_value) {
+        g_value_set_string (&max_value, max_str_value);
+        max_p_value = &max_value;
+      }
+    } else if (key_type == G_TYPE_INT) {
+      min_int_value = va_arg (args, gint);
+      max_int_value = va_arg (args, gint);
+      if (min_int_value > G_MININT) {
+        g_value_set_int (&min_value, min_int_value);
+        min_p_value = &min_value;
+      }
+      if (max_int_value < G_MAXINT) {
+        g_value_set_int (&max_value, max_int_value);
+        max_p_value = &max_value;
+      }
+    } else {
+      GRL_WARNING ("Unexpected key type when setting up the filter");
+      success = FALSE;
+      skip = TRUE;
+    }
+
+    if (!skip) {
+      success &= grl_operation_options_set_key_range_filter_value (options,
+                                                                   next_key,
+                                                                   min_p_value,
+                                                                   max_p_value);
+    }
+
+    g_value_unset (&min_value);
+    g_value_unset (&max_value);
+    next_key = va_arg (args, GrlKeyID);
+  }
+
+  va_end (args);
+
+  return success;
+}
+
+void
+grl_operation_options_get_key_range_filter (GrlOperationOptions *options,
+                                            GrlKeyID key,
+                                            GValue **min_value,
+                                            GValue **max_value)
+{
+  GrlRangeValue *range =
+    (GrlRangeValue *) g_hash_table_lookup (options->priv->key_range_filter,
+                                           GRLKEYID_TO_POINTER (key));
+
+  if (min_value) {
+    if (range && range->min) {
+      *min_value = range->min;
+    } else {
+      *min_value = NULL;
+    }
+  }
+
+  if (max_value) {
+    if (range && range->max) {
+      *max_value = range->max;
+    } else {
+      *max_value = NULL;
+    }
+  }
+}
+
+/**
+ * grl_operation_options_get_key_range_filter_list:
+ * @options:
+ *
+ * Returns: (transfer container) (element-type GrlKeyID):
+ */
+GList *
+grl_operation_options_get_key_range_filter_list (GrlOperationOptions *options)
+{
+  return g_hash_table_get_keys (options->priv->key_range_filter);
+}
diff --git a/src/grl-operation-options.h b/src/grl-operation-options.h
index 5682ca1..ef4bf85 100644
--- a/src/grl-operation-options.h
+++ b/src/grl-operation-options.h
@@ -117,6 +117,22 @@ GValue *grl_operation_options_get_key_filter (GrlOperationOptions *options,
 
 GList *grl_operation_options_get_key_filter_list (GrlOperationOptions *options);
 
+gboolean grl_operation_options_set_key_range_filter_value (GrlOperationOptions *options,
+                                                           GrlKeyID key,
+                                                           GValue *min_value,
+                                                           GValue *max_value);
+
+gboolean grl_operation_options_set_key_range_filter (GrlOperationOptions *options,
+                                                     ...);
+
+void grl_operation_options_get_key_range_filter (GrlOperationOptions *options,
+                                                 GrlKeyID key,
+                                                 GValue **min_value,
+                                                 GValue **max_value);
+
+
+GList *grl_operation_options_get_key_range_filter_list (GrlOperationOptions *options);
+
 G_END_DECLS
 
 #endif /* _GRL_OPERATION_OPTIONS_H_ */
diff --git a/src/grl-range-value.c b/src/grl-range-value.c
new file mode 100644
index 0000000..6dfb4ab
--- /dev/null
+++ b/src/grl-range-value.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2011 Igalia S.L.
+ *
+ * Contact: Iago Toral Quiroga <itoral igalia com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+/**
+ * SECTION:grl-range-value
+ * @short_description: helpers to use Range Values
+ *
+ * This module provides helper functions to use Range Values easily. Inspired by
+ * libsoup's soup-value-utils:
+ * http://git.gnome.org/browse/libsoup/tree/libsoup/soup-value-utils.c
+ *
+ */
+
+#include <grl-range-value.h>
+#include <grl-value-helper.h>
+
+G_DEFINE_BOXED_TYPE (GrlRangeValue, grl_range_value,
+                     (GBoxedCopyFunc) grl_range_value_dup,
+                     (GBoxedFreeFunc) grl_range_value_free)
+
+
+GrlRangeValue *
+grl_range_value_new (GValue *min, GValue *max)
+{
+  GrlRangeValue *range;
+
+  range = g_slice_new0 (GrlRangeValue);
+  if (min) {
+    range->min = grl_g_value_dup (min);
+  }
+
+  if (max) {
+    range->max = grl_g_value_dup (max);
+  }
+
+  return range;
+}
+
+void
+grl_range_value_free (GrlRangeValue *range)
+{
+  if (range->min) {
+    grl_g_value_free (range->min);
+  }
+
+  if (range->max) {
+    grl_g_value_free (range->max);
+  }
+
+  g_slice_free (GrlRangeValue, range);
+}
+
+GHashTable *
+grl_range_value_hashtable_new (void)
+{
+  return g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)grl_range_value_free);
+}
+
+GrlRangeValue *
+grl_range_value_dup (const GrlRangeValue *range)
+{
+  return grl_range_value_new (range->min, range->max);
+}
+
+void
+grl_range_value_hashtable_insert (GHashTable *hash_table,
+                                  gpointer key,
+                                  GValue *min,
+                                  GValue *max)
+{
+  GrlRangeValue *range = grl_range_value_new (min, max);
+  g_hash_table_insert (hash_table, key, range);
+}
diff --git a/src/grl-range-value.h b/src/grl-range-value.h
new file mode 100644
index 0000000..5bce911
--- /dev/null
+++ b/src/grl-range-value.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 Igalia S.L.
+ *
+ * Contact: Iago Toral Quiroga <itoral igalia com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#if !defined (_GRILO_H_INSIDE_) && !defined (GRILO_COMPILATION)
+#error "Only <grilo.h> can be included directly."
+#endif
+
+#if !defined (_GRL_RANGE_VALUE_HELPER_H_)
+#define _GRL_RANGE_VALUE_HELPER_H_
+
+#include <glib-object.h>
+
+typedef struct {
+  GValue *min;
+  GValue *max;
+} GrlRangeValue;
+
+G_BEGIN_DECLS
+
+GrlRangeValue *grl_range_value_new (GValue *min,
+                                    GValue *max);
+
+void grl_range_value_free (GrlRangeValue *range);
+
+GHashTable *grl_range_value_hashtable_new (void);
+
+GrlRangeValue *grl_range_value_dup (const GrlRangeValue *range);
+
+void grl_range_value_hashtable_insert (GHashTable *hash_table,
+                                       gpointer key,
+                                       GValue *min,
+                                       GValue *max);
+
+GType grl_range_value_get_type (void);
+
+G_END_DECLS
+
+#endif /* _GRL_RANGE_VALUE_HELPER_H_ */
-- 
1.7.5.4



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]