summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Zeuthen <davidz@redhat.com>2008-12-15 19:15:05 -0500
committerDavid Zeuthen <davidz@redhat.com>2008-12-15 19:15:05 -0500
commit8b6011e7b4740a204d336f71810e2c3729819a62 (patch)
tree8801058f23eee1e7066032a29bf2cd504c6d04dc
parent8759f2a86ca44b8ca73fb182e880637595cbf231 (diff)
take a #GEqualFunc and add index_of() and friends
-rw-r--r--docs/eggdbus/eggdbus-sections.txt4
-rw-r--r--src/eggdbus/eggdbusarrayseq.c279
-rw-r--r--src/eggdbus/eggdbusarrayseq.h51
-rw-r--r--src/tests/testclient.c106
4 files changed, 358 insertions, 82 deletions
diff --git a/docs/eggdbus/eggdbus-sections.txt b/docs/eggdbus/eggdbus-sections.txt
index 8c1056d..a9b91ee 100644
--- a/docs/eggdbus/eggdbus-sections.txt
+++ b/docs/eggdbus/eggdbus-sections.txt
@@ -426,6 +426,7 @@ EggDBusArraySeq
egg_dbus_array_seq_new
egg_dbus_array_seq_new_full
egg_dbus_array_seq_get_flags
+egg_dbus_array_seq_set_equal_func
egg_dbus_array_seq_size
egg_dbus_array_seq_set_size
egg_dbus_array_seq_get_element_size
@@ -439,6 +440,9 @@ egg_dbus_array_seq_set
egg_dbus_array_seq_set_dup
egg_dbus_array_seq_add
egg_dbus_array_seq_add_dup
+egg_dbus_array_seq_index_of
+egg_dbus_array_seq_contains
+egg_dbus_array_seq_remove
egg_dbus_array_seq_steal_data
egg_dbus_array_seq_add_byte
egg_dbus_array_seq_add_int16
diff --git a/src/eggdbus/eggdbusarrayseq.c b/src/eggdbus/eggdbusarrayseq.c
index 1c9dfd6..286125a 100644
--- a/src/eggdbus/eggdbusarrayseq.c
+++ b/src/eggdbus/eggdbusarrayseq.c
@@ -37,20 +37,29 @@
*
* The array will automatically grow when elements are added and all accessor functions
* dealing with index-based access checks if the index is within bounds. If an index
- * is not within the bounds of the array a warning is issued on <literal>stderr</literal>
- * using g_error() (e.g. causing program termination).
+ * is not within the bounds of the array a warning is issued using g_error() (causing
+ * program termination).
*
- * When possible (e.g. for integral and #G_TYPE_OBJECT derived types), the array will
- * also check that the type of an inserted element matches the element type of the
- * array. If the check fails, a warning is issued using g_error().
+ * When possible (e.g. for integral types when the C convenience functions
+ * are used and #G_TYPE_OBJECT derived types), type checking will be performed to ensure
+ * an inserted element is compatible element type of the array. If the check fails, a
+ * warning is issued using g_error() (causing program termination).
*
* The array type has a notion of <emphasis>static elements</emphasis> that can be used
* to do away with copying/freeing data if certain assumptions can be made about the
* data passed in. See #EGG_DBUS_ARRAY_SEQ_FLAGS_STATIC for details.
*
+ * For implementing operations that involve comparing if two elements are equal (such
+ * as egg_dbus_array_seq_contains()), a #GEqualFunc is needed. For most types (such as
+ * #G_TYPE_STRING and #G_TYPE_INT), the default one is used but for e.g. #G_TYPE_OBJECT
+ * derived types one will need to be provided. Note that said operations are
+ * <emphasis>optional</emphasis> in the sense that if a #GEqualFunc is not provided
+ * other operations will still work; the operations needing the equality function
+ * will just fail and call g_error() (causing program termination).
+ *
* By default, the array takes ownership when inserting elements meaning that the
* programmer gives up his reference. In addition, there is convenience API to
- * make the array insert a copy of the item; see egg_dbus_array_seq_add_dup() for
+ * make the array insert a copy of the element; see egg_dbus_array_seq_add_dup() for
* example.
*
* Items extracted from the array are owned by the array. There is also convenience
@@ -64,15 +73,6 @@
*
* TODO:
*
- * To implement contains(), index_of() and remove() we need to get the user to pass
- * a #GEqualFunc. Sometimes we can infer this function directly (e.g. for strings) but
- * for boxed and object types we can't. Probably need a way to set the equal_func.
- * And also take it possibly from both constructors (passing %NULL would mean
- * use default; user can override with set_equal_func (NULL).
- * Also need a #EggDBusArraySeqFlags flag for whether we have an equal func. And document
- * that contains() + friends can fail runtime if we don't have an equal func (which is
- * fine).
- *
* Want to have the notion of a read-only array; for example, in a modern world
* #GVolumeMonitor would pass out read-only arrays of volumes (since the user
* can't add anything to them). Can easily be implemented with #EggDBusArraySeqFlags.
@@ -121,6 +121,10 @@ typedef struct
/* cached value of G_IS_OBJECT_TYPE() to avoid overhead on every insertion */
gboolean element_type_is_gobject_derived;
+ GEqualFunc equal_func;
+
+ EggDBusArraySeqFlags flags;
+
} EggDBusArraySeqPrivate;
enum
@@ -241,6 +245,26 @@ free_elem_static (EggDBusArraySeq *array_seq,
/* ---------------------------------------------------------------------------------------------------- */
+#define IMPL_EQUAL_FUNC(type) \
+ static gboolean \
+ _##type##_equal (gconstpointer v1, gconstpointer v2) \
+ { \
+ const type *a = v1; \
+ const type *b = v2; \
+ return *a == *b; \
+ }
+
+IMPL_EQUAL_FUNC (guchar);
+IMPL_EQUAL_FUNC (gint);
+IMPL_EQUAL_FUNC (gint64);
+IMPL_EQUAL_FUNC (gboolean);
+IMPL_EQUAL_FUNC (gdouble);
+IMPL_EQUAL_FUNC (glong);
+IMPL_EQUAL_FUNC (gfloat);
+IMPL_EQUAL_FUNC (gint16);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
static void
ensure_size (EggDBusArraySeq *array_seq,
guint minimum_size)
@@ -291,19 +315,17 @@ egg_dbus_array_seq_class_init (EggDBusArraySeqClass *klass)
/**
* egg_dbus_array_seq_new:
- * @element_type: A #GType.
+ * @element_type: The type of the elements in the array.
*
- * Creates a new array where inserted data is stolen by the array (unless methods like
- * egg_dbus_array_seq_set_dup() and egg_dbus_array_seq_add_dup() are used) and freed
- * when the array is finalized. Use egg_dbus_array_seq_new() to change this behavior.
+ * Creates a new array that holds elements of @element_type with the default (if any) function
+ * for comparing equality.
*
* Allowed values for @element_type include the types #EGG_DBUS_TYPE_INT16, #EGG_DBUS_TYPE_UINT16
* as well as any fundamental type known by the GObject library, and any type derived from any
* of the aforementioned types. Note that for #G_TYPE_INTERFACE, only instances deriving from
* #G_TYPE_OBJECT are supported.
*
- * See egg_dbus_array_seq_new() for a variant of this function with
- * more complicated options.
+ * See egg_dbus_array_seq_new() for a variant of this function with more complicated options.
*
* Returns: A new #EggDBusArraySeq. Free with g_object_unref().
**/
@@ -312,14 +334,16 @@ egg_dbus_array_seq_new (GType element_type)
{
return egg_dbus_array_seq_new_full (element_type,
EGG_DBUS_ARRAY_SEQ_FLAGS_NONE,
+ NULL,
0,
NULL);
}
/**
* egg_dbus_array_seq_new_full:
- * @element_type: A #GType.
+ * @element_type: The type of the elements in the array.
* @flags: A combination of flags from #EggDBusArraySeqFlags.
+ * @equal_func: A function that compares whether to elements are equal or %NULL to use default if one such exists.
* @size: The number of elements in the @data parameter or 0 if @data is %NULL.
* @data: Either %NULL (in which case @size must be 0) or raw memory to initialize the array with.
*
@@ -327,6 +351,13 @@ egg_dbus_array_seq_new (GType element_type)
* See egg_dbus_array_seq_new() for details on allowed values of @element_type and required memory
* layout of @data.
*
+ * If @equal_func is %NULL, the default equality function is used if one exists for @element_type
+ * (there is no natural equality function if @element_type is a subtype of #G_TYPE_OBJECT, #G_TYPE_INTERFACE
+ * or #G_TYPE_BOXED). Note that if the elements holds a fixed-size type (such as #G_TYPE_INT), the
+ * parameters passed to @equal_func will be the address of the element (e.g. a #gint<!-- -->*). Otherwise
+ * (for arrays holding non-fixed sizes) the pointer stored in the array is passed (e.g. a #GFile<!-- -->*
+ * if the array holds elements of #G_TYPE_FILE).
+ *
* If #EGG_DBUS_ARRAY_SEQ_FLAGS_STATIC is set in @flags, then elements are never copied (and methods like
* e.g. egg_dbus_array_seq_add_dup() will behave like egg_dbus_array_seq_add()) which can help with
* performance. On the other hand, if this flag is passed, you must guarantee that any elements inserted
@@ -337,28 +368,35 @@ egg_dbus_array_seq_new (GType element_type)
EggDBusArraySeq *
egg_dbus_array_seq_new_full (GType element_type,
EggDBusArraySeqFlags flags,
+ GEqualFunc equal_func,
guint size,
gconstpointer data)
{
+ GType fundamental_type;
EggDBusArraySeq *array_seq;
EggDBusArraySeqPrivate *priv;
- guint n;
gboolean not_supported;
gpointer *given_data;
- GType fundamental_type;
+ guint n;
array_seq = EGG_DBUS_ARRAY_SEQ (g_object_new (EGG_DBUS_TYPE_ARRAY_SEQ, NULL));
priv = EGG_DBUS_ARRAY_SEQ_GET_PRIVATE (array_seq);
- array_seq->flags = flags;
+ priv->flags = flags;
array_seq->size = size;
array_seq->element_type = element_type;
+ priv->equal_func = equal_func;
+
not_supported = FALSE;
- /* first compute copy_func, free_func and element_size; switch on fundamental type */
fundamental_type = G_TYPE_FUNDAMENTAL (array_seq->element_type);
+
+ if (flags & EGG_DBUS_ARRAY_SEQ_FLAGS_HAVE_EQUAL_FUNC)
+ g_error ("You cannot pass EGG_DBUS_ARRAY_SEQ_FLAGS_HAVE_EQUAL_FUNC in flags");
+
+ /* first compute copy_func, free_func, element_size and equal_func */
switch (fundamental_type)
{
case G_TYPE_OBJECT:
@@ -385,53 +423,67 @@ egg_dbus_array_seq_new_full (GType element_type,
priv->copy_func = copy_elem_string;
priv->free_func = free_elem_string;
array_seq->element_size = sizeof (gpointer);
+
+ if (priv->equal_func == NULL)
+ priv->equal_func = g_str_equal;
+
break;
case G_TYPE_UCHAR:
case G_TYPE_CHAR:
array_seq->element_size = sizeof (guchar);
+ if (priv->equal_func == NULL)
+ priv->equal_func = _guchar_equal;
break;
case G_TYPE_INT:
case G_TYPE_UINT:
array_seq->element_size = sizeof (gint);
+ if (priv->equal_func == NULL)
+ priv->equal_func = _gint_equal;
break;
case G_TYPE_INT64:
case G_TYPE_UINT64:
array_seq->element_size = sizeof (gint64);
+ if (priv->equal_func == NULL)
+ priv->equal_func = _gint64_equal;
break;
case G_TYPE_BOOLEAN:
array_seq->element_size = sizeof (gboolean);
+ if (priv->equal_func == NULL)
+ priv->equal_func = _gboolean_equal;
break;
case G_TYPE_DOUBLE:
array_seq->element_size = sizeof (gdouble);
+ if (priv->equal_func == NULL)
+ priv->equal_func = _gdouble_equal;
break;
case G_TYPE_LONG:
- array_seq->element_size = sizeof (glong);
- break;
-
case G_TYPE_ULONG:
- array_seq->element_size = sizeof (gulong);
+ array_seq->element_size = sizeof (glong);
+ if (priv->equal_func == NULL)
+ priv->equal_func = _glong_equal;
break;
case G_TYPE_FLOAT:
array_seq->element_size = sizeof (gfloat);
- break;
-
- case G_TYPE_POINTER:
- array_seq->element_size = sizeof (gpointer);
+ if (priv->equal_func == NULL)
+ priv->equal_func = _gfloat_equal;
break;
case G_TYPE_ENUM:
+ case G_TYPE_FLAGS:
array_seq->element_size = sizeof (gint);
+ if (priv->equal_func == NULL)
+ priv->equal_func = _gint_equal;
break;
- case G_TYPE_FLAGS:
- array_seq->element_size = sizeof (gint);
+ case G_TYPE_POINTER:
+ array_seq->element_size = sizeof (gpointer);
break;
default:
@@ -442,6 +494,8 @@ egg_dbus_array_seq_new_full (GType element_type,
array_seq->element_type == EGG_DBUS_TYPE_UINT16)
{
array_seq->element_size = sizeof (gint16);
+ if (priv->equal_func == NULL)
+ priv->equal_func = _gint16_equal;
}
else
{
@@ -450,14 +504,18 @@ egg_dbus_array_seq_new_full (GType element_type,
break;
}
- /* warn if STATIC was passed but element is a fixed-size type; this is a programmer-error */
- if (priv->copy_func == NULL && (array_seq->flags & EGG_DBUS_ARRAY_SEQ_FLAGS_STATIC))
+ /* warn/abort if STATIC was passed but element is a fixed-size type; this is a programmer-error */
+ if (priv->copy_func == NULL && (priv->flags & EGG_DBUS_ARRAY_SEQ_FLAGS_STATIC))
{
g_error ("Using EGG_DBUS_ARRAY_SEQ_FLAGS_STATIC doesn't make sense for "
"fixed-size type %s.",
g_type_name (array_seq->element_type));
}
+ /* sort out equal function */
+ if (priv->equal_func != NULL)
+ priv->flags |= EGG_DBUS_ARRAY_SEQ_FLAGS_HAVE_EQUAL_FUNC;
+
if (not_supported)
{
/* didn't recognize type; this is a programmer/user error; contract says we can only manage
@@ -468,7 +526,7 @@ egg_dbus_array_seq_new_full (GType element_type,
}
/* if the passed in objects are static; use non-op copy(), free() implementations */
- if (array_seq->flags & EGG_DBUS_ARRAY_SEQ_FLAGS_STATIC)
+ if (priv->flags & EGG_DBUS_ARRAY_SEQ_FLAGS_STATIC)
{
priv->copy_func = copy_elem_static;
priv->free_func = free_elem_static;
@@ -502,6 +560,45 @@ egg_dbus_array_seq_new_full (GType element_type,
return array_seq;
}
+/**
+ * egg_dbus_array_seq_set_equal_func:
+ * @array_seq: A #EggDBusArraySeq.
+ * @equal_func: A #GEqualFunc or %NULL.
+ *
+ * Sets the function for comparing equality.
+ **/
+void
+egg_dbus_array_seq_set_equal_func (EggDBusArraySeq *array_seq,
+ GEqualFunc equal_func)
+{
+ EggDBusArraySeqPrivate *priv;
+
+ priv = EGG_DBUS_ARRAY_SEQ_GET_PRIVATE (array_seq);
+
+ priv->equal_func = equal_func;
+
+ if (equal_func == NULL)
+ priv->flags &= ~EGG_DBUS_ARRAY_SEQ_FLAGS_HAVE_EQUAL_FUNC;
+ else
+ priv->flags |= EGG_DBUS_ARRAY_SEQ_FLAGS_HAVE_EQUAL_FUNC;
+}
+
+static gboolean
+check_have_equal_func (EggDBusArraySeq *array_seq)
+{
+ EggDBusArraySeqPrivate *priv;
+
+ priv = EGG_DBUS_ARRAY_SEQ_GET_PRIVATE (array_seq);
+
+ if (G_LIKELY (priv->equal_func != NULL))
+ return TRUE;
+
+ g_error ("no equal_func set for EggDBusArraySeq<%s>",
+ g_type_name (array_seq->element_type));
+
+ return FALSE;
+}
+
static gboolean
check_index (EggDBusArraySeq *array_seq,
gint index)
@@ -551,7 +648,7 @@ egg_dbus_array_seq_get_flags (EggDBusArraySeq *array_seq)
priv = EGG_DBUS_ARRAY_SEQ_GET_PRIVATE (array_seq);
- return array_seq->flags;
+ return priv->flags;
}
/**
@@ -868,7 +965,7 @@ egg_dbus_array_seq_set_internal (EggDBusArraySeq *array_seq,
* egg_dbus_array_seq_set:
* @array_seq: A #EggDBusArraySeq.
* @index: Zero-based index of element.
- * @value: The item to insert.
+ * @value: The value to insert.
*
* Replaces the element at @index in @array_seq with @value.
*
@@ -890,7 +987,7 @@ egg_dbus_array_seq_set (EggDBusArraySeq *array_seq,
* egg_dbus_array_seq_set_dup:
* @array_seq: A #EggDBusArraySeq.
* @index: Zero-based index of element.
- * @value: The item to insert.
+ * @value: The value to insert.
*
* Replaces the element at @index in @array_seq with a copy/reference of @value.
*
@@ -910,7 +1007,7 @@ egg_dbus_array_seq_set_dup (EggDBusArraySeq *array_seq,
/**
* egg_dbus_array_seq_add:
* @array_seq: A #EggDBusArraySeq.
- * @value: The item to insert.
+ * @value: The value to insert.
*
* Appends @value to the end of @array_seq. The size of @array_seq will grow by one.
*
@@ -937,7 +1034,7 @@ egg_dbus_array_seq_add (EggDBusArraySeq *array_seq,
/**
* egg_dbus_array_seq_add_dup:
* @array_seq: A #EggDBusArraySeq.
- * @value: The item to insert.
+ * @value: The value to insert.
*
* Appends a copy of @value to the end of @array_seq. The size of @array_seq will grow by one.
*
@@ -958,6 +1055,95 @@ egg_dbus_array_seq_add_dup (EggDBusArraySeq *array_seq,
return TRUE;
}
+/**
+ * egg_dbus_array_seq_index_of:
+ * @array_seq: A #EggDBusArraySeq.
+ * @value: The value to check for.
+ *
+ * Find the first occurence of an element equal to @value in @array_seq.
+ *
+ * This method is optional. It is a programing error to call this method on @array_seq
+ * if the flag #EGG_DBUS_ARRAY_SEQ_FLAGS_HAVE_EQUAL_FUNC isn't set.
+ *
+ * Returns: The index of the first occurence of an element equal to @value
+ * in @array_seq or -1 if no such elements exist.
+ **/
+gint
+egg_dbus_array_seq_index_of (EggDBusArraySeq *array_seq,
+ gconstpointer value)
+{
+ EggDBusArraySeqPrivate *priv;
+ guint n;
+
+ if (!check_have_equal_func (array_seq))
+ return -1;
+
+ priv = EGG_DBUS_ARRAY_SEQ_GET_PRIVATE (array_seq);
+
+ for (n = 0; n < array_seq->size; n++)
+ {
+ gboolean found;
+
+ if (priv->copy_func != NULL)
+ found = priv->equal_func (array_seq->data.v_ptr[n], value);
+ else
+ found = priv->equal_func (array_seq->data.v_byte + n * array_seq->element_size, value);
+
+ if (found)
+ break;
+ }
+
+ return n == array_seq->size ? -1 : (gint) n;
+}
+
+/**
+ * egg_dbus_array_seq_contains:
+ * @array_seq: A #EggDBusArraySeq.
+ * @value: The value to check for.
+ *
+ * Check if @array_seq contains an element equal to @value.
+ *
+ * This method is optional. It is a programing error to call this method on @array_seq
+ * if the flag #EGG_DBUS_ARRAY_SEQ_FLAGS_HAVE_EQUAL_FUNC isn't set.
+ *
+ * Returns: %TRUE if @array_seq contains one or more elements equal to @value.
+ **/
+gboolean
+egg_dbus_array_seq_contains (EggDBusArraySeq *array_seq,
+ gconstpointer value)
+{
+ return egg_dbus_array_seq_index_of (array_seq, value) != -1;
+}
+
+/**
+ * egg_dbus_array_seq_remove:
+ * @array_seq: A #EggDBusArraySeq.
+ * @value: The value to remove.
+ *
+ * Remove the first occurence of elements equal to @value from @array_seq.
+ *
+ * This method is optional. It is a programing error to call this method on @array_seq
+ * if the flag #EGG_DBUS_ARRAY_SEQ_FLAGS_HAVE_EQUAL_FUNC isn't set.
+ *
+ * Returns: %TRUE if an element was removed.
+ **/
+gboolean
+egg_dbus_array_seq_remove (EggDBusArraySeq *array_seq,
+ gconstpointer value)
+{
+ gint index;
+
+ index = egg_dbus_array_seq_index_of (array_seq, value);
+
+ if (index == -1)
+ return FALSE;
+
+ egg_dbus_array_seq_remove_at (array_seq, index);
+ return TRUE;
+}
+
+
+
/* ---------------------------------------------------------------------------------------------------- */
@@ -1140,7 +1326,7 @@ egg_dbus_array_seq_new_for_double (guint size,
#define EGG_DBUS_ARRAY_SEQ_NEW_FOR_VALIST(ctype, promoted_ctype, gtype) \
guint n = 0; \
promoted_ctype elem = first_value; \
- ctype *data = (ctype *) g_new0 (ctype, size); \
+ ctype *data = (ctype *) g_new0 (ctype, size); \
do \
{ \
data[n] = (ctype) elem; \
@@ -1148,7 +1334,7 @@ egg_dbus_array_seq_new_for_double (guint size,
n++; \
} \
while (n < size); \
- return egg_dbus_array_seq_new_full (gtype, 0, size, data);
+ return egg_dbus_array_seq_new_full (gtype, 0, NULL, size, data);
/**
@@ -1322,7 +1508,6 @@ egg_dbus_array_seq_new_for_double_valist (guint size,
EGG_DBUS_ARRAY_SEQ_NEW_FOR_VALIST (gdouble, gdouble, G_TYPE_DOUBLE);
}
-
/* ---------------------------------------------------------------------------------------------------- */
#define EGG_DBUS_ARRAY_SEQ_GET(name,failval) \
diff --git a/src/eggdbus/eggdbusarrayseq.h b/src/eggdbus/eggdbusarrayseq.h
index afd3e32..e3699b3 100644
--- a/src/eggdbus/eggdbusarrayseq.h
+++ b/src/eggdbus/eggdbusarrayseq.h
@@ -43,18 +43,19 @@ typedef struct _EggDBusArraySeqClass EggDBusArraySeqClass;
* EggDBusArraySeqFlags:
* @EGG_DBUS_ARRAY_SEQ_FLAGS_NONE: No flags set.
* @EGG_DBUS_ARRAY_SEQ_FLAGS_STATIC: Elements are never copied; users of the array must ensure that inserted elements are alive for the duration of the lifetime of the array.
+ * @EGG_DBUS_ARRAY_SEQ_FLAGS_HAVE_EQUAL_FUNC: Is set only if there's an equal function for comparing elements. If this flag is not set, certain operations such as egg_dbus_array_seq_contains() on the array are not supported. You can not pass this flag in any of the constructors.
*
* Flags that specify the behavior of an #EggDBusArraySeq instance.
*/
typedef enum
{
- EGG_DBUS_ARRAY_SEQ_FLAGS_NONE = 0,
- EGG_DBUS_ARRAY_SEQ_FLAGS_STATIC = (1<<0),
+ EGG_DBUS_ARRAY_SEQ_FLAGS_NONE = 0,
+ EGG_DBUS_ARRAY_SEQ_FLAGS_STATIC = (1<<0),
+ EGG_DBUS_ARRAY_SEQ_FLAGS_HAVE_EQUAL_FUNC = (1<<1),
} EggDBusArraySeqFlags;
/**
* EggDBusArraySeq:
- * @flags: Flags describing the behavior of the #EggDBusArraySeq instance.
* @size: Number of elements in the array.
* @element_type: The #GType of the elements in the array.
* @element_size: The size, in bytes, of each element.
@@ -85,7 +86,6 @@ struct _EggDBusArraySeq
GObject parent_instance;
/*< public >*/
- EggDBusArraySeqFlags flags;
guint size;
GType element_type;
gsize element_size;
@@ -133,11 +133,15 @@ EggDBusArraySeq *egg_dbus_array_seq_new (GType
EggDBusArraySeq *egg_dbus_array_seq_new_full (GType element_type,
EggDBusArraySeqFlags flags,
+ GEqualFunc equal_func,
guint size,
gconstpointer data) G_GNUC_WARN_UNUSED_RESULT;
EggDBusArraySeqFlags egg_dbus_array_seq_get_flags (EggDBusArraySeq *array_seq) G_GNUC_WARN_UNUSED_RESULT;
+void egg_dbus_array_seq_set_equal_func (EggDBusArraySeq *array_seq,
+ GEqualFunc equal_func);
+
guint egg_dbus_array_seq_size (EggDBusArraySeq *array_seq) G_GNUC_WARN_UNUSED_RESULT;
void egg_dbus_array_seq_set_size (EggDBusArraySeq *array_seq,
@@ -175,14 +179,19 @@ gboolean egg_dbus_array_seq_add (EggDBusArraySeq
gboolean egg_dbus_array_seq_add_dup (EggDBusArraySeq *array_seq,
gconstpointer value);
-/* C convenience functions for fixed-size arrays */
-
-gpointer egg_dbus_array_seq_steal_data (EggDBusArraySeq *array_seq) G_GNUC_WARN_UNUSED_RESULT;
+gint egg_dbus_array_seq_index_of (EggDBusArraySeq *array_seq,
+ gconstpointer value);
+gboolean egg_dbus_array_seq_contains (EggDBusArraySeq *array_seq,
+ gconstpointer value);
+gboolean egg_dbus_array_seq_remove (EggDBusArraySeq *array_seq,
+ gconstpointer value);
/* C convenience functions */
+gpointer egg_dbus_array_seq_steal_data (EggDBusArraySeq *array_seq) G_GNUC_WARN_UNUSED_RESULT;
+
gboolean egg_dbus_array_seq_add_byte (EggDBusArraySeq *array_seq,
guchar value);
gboolean egg_dbus_array_seq_add_int16 (EggDBusArraySeq *array_seq,
@@ -322,34 +331,6 @@ EggDBusArraySeq *egg_dbus_array_seq_new_for_double_valist (guint
gdouble first_value,
va_list va_args) G_GNUC_WARN_UNUSED_RESULT;
-
-/* TODO:
- *
- * - if we want to implement contains() (and index_of() and remove()) we can either
- * - require items to implement a new interface EggDBusEquals
- * - hmm, unsure this will work for boxed types...
- * - carry around a GEqual (need to be settable/gettable, we want constructors to take it too)
- * - should have a flag CAN_COMPARE_EQUALITY
- *
- * - It's fine for an an ArraySeq instance not to have CAN_COMPARE_EQUALITY,
- * it just means it's a programmer error and we'll issue a run-time warning
- * (similar to the unchecked UnsupportedOperationException mentioned here:
- * http://java.sun.com/j2se/1.5.0/docs/guide/collections/designfaq.html#2)
- *
- * - Ditto is it a progamming error if the user tries to modify an IMMUTABLE
- * or READ_ONLY array_seq; again, same argument; we'll just issue a run-time
- * warning
- *
- */
-
-/* TODO: algorithms?
- *
- * - foreach
- * - sort (requires equality tests)
- * - ...
- * - others?
- */
-
G_END_DECLS
#endif /* __ EGG_DBUS_ARRAY_SEQ_H */
diff --git a/src/tests/testclient.c b/src/tests/testclient.c
index b0a7861..5c8e471 100644
--- a/src/tests/testclient.c
+++ b/src/tests/testclient.c
@@ -3558,12 +3558,18 @@ test_egg_dbus_array_seq (void)
EggDBusArraySeq *a;
const gchar *some_strings[6] = {"zero", "one", "two", "three", "four", NULL};
gchar **string_array;
+ gint some_ints[8] = {0, 1, 2, 3, 2, 4, 2, 5};
+ gint int_2 = 2;
+ gint int_3 = 3;
+ GFile *file_2;
+ GFile *file_3;
/*
* First, check that all EggDBusArraySeq operations work
*/
a = egg_dbus_array_seq_new_full (G_TYPE_STRING,
0,
+ NULL,
5,
some_strings);
g_assert_cmpuint (egg_dbus_array_seq_get_element_type (a), ==, G_TYPE_STRING);
@@ -3648,6 +3654,7 @@ test_egg_dbus_array_seq (void)
*/
a = egg_dbus_array_seq_new_full (G_TYPE_STRING,
EGG_DBUS_ARRAY_SEQ_FLAGS_STATIC,
+ NULL,
5,
some_strings);
g_assert_cmpuint (egg_dbus_array_seq_get_element_type (a), ==, G_TYPE_STRING);
@@ -3822,6 +3829,8 @@ test_egg_dbus_array_seq (void)
g_strfreev (string_array);
g_object_unref (a);
+ /* -------------------------------------------------------------------------------- */
+
/* check that types deriving from boxed types work */
a = egg_dbus_array_seq_new (EGG_DBUS_TYPE_OBJECT_PATH_ARRAY);
egg_dbus_array_seq_add (a, g_strsplit ("/a/test/path", "/", 0));
@@ -3838,6 +3847,7 @@ test_egg_dbus_array_seq (void)
g_assert_cmpstr (a->data.v_strv[1][2], ==, "path");
g_object_unref (a);
+ /* -------------------------------------------------------------------------------- */
/* Arrays containing GObject derived instances are very similar to arrays containg boxed
* instances... so we don't need to test them very carefully since we've already tested
@@ -3862,6 +3872,7 @@ test_egg_dbus_array_seq (void)
g_test_trap_assert_stderr ("*Cannot insert an element of type GLocalFile into a EggDBusArraySeq<TestSubject>*");
g_object_unref (a);
+ /* -------------------------------------------------------------------------------- */
/* Check that an array of a type deriving from GInterface works (as long as the
* instances implenting the type are GObject derived). Since GFile is actually an interface
@@ -3875,6 +3886,100 @@ test_egg_dbus_array_seq (void)
g_assert_cmpuint (egg_dbus_array_seq_size (a), ==, 3);
g_object_unref (a);
+ /* -------------------------------------------------------------------------------- */
+
+ /* check that equal_func is properly inferred and works */
+ a = egg_dbus_array_seq_new (G_TYPE_STRING);
+ g_assert (egg_dbus_array_seq_get_flags (a) & EGG_DBUS_ARRAY_SEQ_FLAGS_HAVE_EQUAL_FUNC);
+ egg_dbus_array_seq_add_dup (a, "zero");
+ egg_dbus_array_seq_add_dup (a, "one");
+ egg_dbus_array_seq_add_dup (a, "two");
+ egg_dbus_array_seq_add_dup (a, "three");
+ egg_dbus_array_seq_add_dup (a, "two");
+ egg_dbus_array_seq_add_dup (a, "four");
+ egg_dbus_array_seq_add_dup (a, "two");
+ egg_dbus_array_seq_add_dup (a, "five");
+ g_assert_cmpint (egg_dbus_array_seq_index_of (a, "three"), ==, 3);
+ g_assert_cmpint (egg_dbus_array_seq_index_of (a, "two"), ==, 2);
+ g_assert (egg_dbus_array_seq_remove (a, "two"));
+ g_assert_cmpint (egg_dbus_array_seq_index_of (a, "two"), ==, 3);
+ g_assert (egg_dbus_array_seq_remove (a, "two"));
+ g_assert_cmpint (egg_dbus_array_seq_index_of (a, "two"), ==, 4);
+ g_assert (egg_dbus_array_seq_remove (a, "two"));
+ g_assert_cmpint (egg_dbus_array_seq_index_of (a, "two"), ==, -1);
+ g_assert (!egg_dbus_array_seq_remove (a, "two"));
+ g_object_unref (a);
+
+ /* -------------------------------------------------------------------------------- */
+
+ /* try for a fixed-size type as well (we don't provide C convenience for these (yet?)) */
+ a = egg_dbus_array_seq_new_full (G_TYPE_INT,
+ 0,
+ NULL,
+ 8,
+ some_ints);
+ g_assert_cmpint (egg_dbus_array_seq_get_int (a, 0), ==, 0);
+ g_assert_cmpint (egg_dbus_array_seq_get_int (a, 1), ==, 1);
+ g_assert_cmpint (egg_dbus_array_seq_get_int (a, 2), ==, 2);
+ g_assert_cmpint (egg_dbus_array_seq_get_int (a, 3), ==, 3);
+ g_assert_cmpint (egg_dbus_array_seq_get_int (a, 4), ==, 2);
+ g_assert_cmpint (egg_dbus_array_seq_get_int (a, 5), ==, 4);
+ g_assert_cmpint (egg_dbus_array_seq_get_int (a, 6), ==, 2);
+ g_assert_cmpint (egg_dbus_array_seq_get_int (a, 7), ==, 5);
+ g_assert_cmpint (egg_dbus_array_seq_index_of (a, &int_3), ==, 3);
+ g_assert_cmpint (egg_dbus_array_seq_index_of (a, &int_2), ==, 2);
+ g_assert (egg_dbus_array_seq_remove (a, &int_2));
+ g_assert_cmpint (egg_dbus_array_seq_index_of (a, &int_2), ==, 3);
+ g_assert (egg_dbus_array_seq_remove (a, &int_2));
+ g_assert_cmpint (egg_dbus_array_seq_index_of (a, &int_2), ==, 4);
+ g_assert (egg_dbus_array_seq_remove (a, &int_2));
+ g_assert_cmpint (egg_dbus_array_seq_index_of (a, &int_2), ==, -1);
+ g_assert (!egg_dbus_array_seq_remove (a, &int_2));
+ g_object_unref (a);
+
+ /* -------------------------------------------------------------------------------- */
+
+ /* check there is no equal_func by default for GObject types */
+ a = egg_dbus_array_seq_new (G_TYPE_FILE);
+ g_assert (! (egg_dbus_array_seq_get_flags (a) & EGG_DBUS_ARRAY_SEQ_FLAGS_HAVE_EQUAL_FUNC));
+ egg_dbus_array_seq_add (a, g_file_new_for_path ("0.txt"));
+ egg_dbus_array_seq_add (a, g_file_new_for_path ("1.txt"));
+ egg_dbus_array_seq_add (a, g_file_new_for_path ("2.txt"));
+ egg_dbus_array_seq_add (a, g_file_new_for_path ("3.txt"));
+ egg_dbus_array_seq_add (a, g_file_new_for_path ("2.txt"));
+ egg_dbus_array_seq_add (a, g_file_new_for_path ("4.txt"));
+ egg_dbus_array_seq_add (a, g_file_new_for_path ("2.txt"));
+ egg_dbus_array_seq_add (a, g_file_new_for_path ("5.txt"));
+ /* we only check that index_of don't work (contains() and remove() are trivial when we
+ * have index_of() and remove_at() already)
+ */
+ if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR))
+ {
+ gint index;
+ index = egg_dbus_array_seq_index_of (a, g_file_new_for_path ("/somewhere/file.txt"));
+ }
+ g_test_trap_assert_failed ();
+ g_test_trap_assert_stderr ("*no equal_func set for EggDBusArraySeq<GFile>*");
+ /* check we can set an equal_func post construction and that the equal func works*/
+ egg_dbus_array_seq_set_equal_func (a, (GEqualFunc) g_file_equal);
+ g_assert (egg_dbus_array_seq_get_flags (a) & EGG_DBUS_ARRAY_SEQ_FLAGS_HAVE_EQUAL_FUNC);
+ file_2 = g_file_new_for_path ("2.txt");
+ file_3 = g_file_new_for_path ("3.txt");
+ g_assert_cmpint (egg_dbus_array_seq_index_of (a, file_3), ==, 3);
+ g_assert_cmpint (egg_dbus_array_seq_index_of (a, file_2), ==, 2);
+ g_assert (egg_dbus_array_seq_remove (a, file_2));
+ g_assert_cmpint (egg_dbus_array_seq_index_of (a, file_2), ==, 3);
+ g_assert (egg_dbus_array_seq_remove (a, file_2));
+ g_assert_cmpint (egg_dbus_array_seq_index_of (a, file_2), ==, 4);
+ g_assert (egg_dbus_array_seq_remove (a, file_2));
+ g_assert_cmpint (egg_dbus_array_seq_index_of (a, file_2), ==, -1);
+ g_assert (!egg_dbus_array_seq_remove (a, file_2));
+ g_object_unref (file_2);
+ g_object_unref (file_3);
+ egg_dbus_array_seq_set_equal_func (a, NULL);
+ g_assert (! (egg_dbus_array_seq_get_flags (a) & EGG_DBUS_ARRAY_SEQ_FLAGS_HAVE_EQUAL_FUNC));
+ g_object_unref (a);
+
}
/* ---------------------------------------------------------------------------------------------------- */
@@ -3894,6 +3999,7 @@ main (int argc, char *argv[])
GPid server_pid;
g_type_init ();
+ //g_test_init (&argc, &argv, NULL);
/* TODO: launch our own session bus */