diff options
author | David Zeuthen <davidz@redhat.com> | 2008-12-17 14:35:04 -0500 |
---|---|---|
committer | David Zeuthen <davidz@redhat.com> | 2008-12-17 14:35:04 -0500 |
commit | be92ac30da13698e0ccaa90801caf490cfe6f696 (patch) | |
tree | fb2a85b2c937e378936adbf6fccd444167883a9d | |
parent | 9f7a46b0e675aaa8b0b60507b4b4654013131502 (diff) |
minor changes to ArraySeq
-rw-r--r-- | src/eggdbus/eggdbusarrayseq.c | 735 | ||||
-rw-r--r-- | src/eggdbus/eggdbusarrayseq.h | 68 | ||||
-rw-r--r-- | src/tests/testclient.c | 238 |
3 files changed, 519 insertions, 522 deletions
diff --git a/src/eggdbus/eggdbusarrayseq.c b/src/eggdbus/eggdbusarrayseq.c index 6e5e010..2df4876 100644 --- a/src/eggdbus/eggdbusarrayseq.c +++ b/src/eggdbus/eggdbusarrayseq.c @@ -32,110 +32,52 @@ * @title: EggDBusArraySeq * @short_description: Arrays * - * An array type that can store elements of (virtually) any type known by the GObject - * library. See egg_dbus_array_seq_new() for details. + * An array type that can store elements of a given #GType. See egg_dbus_array_seq_new() for details. * * 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 using g_error() (causing * program termination). * - * When possible 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. + * When possible (when the elements are derived from #GObject) type checking will be performed to + * ensure an inserted element is compatible with the element type of the array. If the check fails, + * a warning is issued using g_error() (causing program termination). * - * 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 + * For implementing operations that involve comparing elements (such as egg_dbus_array_seq_contains()), + * a #GEqualFunc is needed. For most types (such as #G_TYPE_STRING and #G_TYPE_INT), the natural + * #GEqualFunc 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 equal 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 element; see egg_dbus_array_seq_add_dup() for - * example. - * - * Items extracted from the array are owned by the array. There is also convenience - * API to get a copy of the item, see egg_dbus_array_seq_get_dup() for an example. + * By default, the array takes ownership when inserting elements meaning that the programmer gives + * up his reference. Elements extracted from the array are owned by the array. There is also convenience + * API to get a copy of the item, see egg_dbus_array_seq_get_copy(). * * Note that this class exposes a number of implementation details directly in the class * instance structure for efficient and convenient access when used from the C programming * language. Use with caution. For the same reasons, this class also provides a number of - * convenience functions such as egg_dbus_array_seq_add_int(), egg_dbus_array_seq_set_int(), - * egg_dbus_array_seq_get_int() and egg_dbus_array_seq_new_for_int(). - * - * TODO: - * - * 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. - * Then need to document that write-ops can fail with warnings (which is fine - * too). In constrast, libgee has #GeeReadOnlyList etc. This will not scale for the - * reasons outlined in <ulink url="http://java.sun.com/j2se/1.5.0/docs/guide/collections/designfaq.html">Java Collections API Design FAQ</ulink>. Also want a convenience method that constructs a - * read-only array from a given array. - * - * Maybe we want convenience constructors that take a #GSList and #GList. No need for - * constructors for #GPtrArray and #GArray, the user can do this just as easily - * by using the regular constructors. - * - * Also want minor convenience like add_all() etc.; I'm probably missing something. - * See Java and .NET collection APIs for details. - * - * Maybe we want convenience methods that constructs #GList, #GSList, #GPtrArray - * and #GArray from the given data. - * - * We also want to have proper GInterfaces like in libgee (#EggDBusArraySeq is designed - * to very easily implement #GeeCollection and #GeeList), see - * <ulink url="http://bugzilla.gnome.org/show_bug.cgi?id=560061">bgo 560061</ulink> - * for the gory detalis and prospect of having that in GLib. It doesn't make - * sense, however, to make #EggDBusArraySeq implement any interfaces shipped with - * the EggDBus package; the point of having collection interfaces is that everyone - * should be using the same stuff (and we'd also want those interfaces to support - * e.g. #EggDBusArraySeqFlags or similar since it's an useful thing). And at this - * point it's fine; we'll always be handing out arrays _anyway_ (due to how the - * D-Bus protocol); however it would perhaps be useful for the user to pass in, - * say, a #EggDBusListSeq since it might be easier on his side to construct - * a doubly-linked list than an array. So there. - * - * Want to implement at least a few algorithms like for_each() and sort(). This - * should probably wait until we have proper GInterfaces. And then some concerted - * effort around that. + * convenience functions for dealing with fixed-size integral and floating point numbers. */ typedef struct { /* if element_type is a fixed-size type, these are both NULL */ - gpointer (*copy_func) (EggDBusArraySeq *array_seq, gconstpointer element); - void (*free_func) (EggDBusArraySeq *array_seq, gpointer element); + gpointer (*copy_func) (EggDBusArraySeq *array_seq, gconstpointer element); + GDestroyNotify free_func; + GEqualFunc equal_func; + GBoxedCopyFunc user_copy_func; guint capacity; /* cached value of G_IS_OBJECT_TYPE() to avoid overhead on every insertion */ gboolean element_type_is_gobject_derived; - GEqualFunc equal_func; - - EggDBusArraySeqFlags flags; - + /* cached value to determine if it's a fixed size array */ + gboolean element_type_is_fixed_size; } EggDBusArraySeqPrivate; -enum -{ - PROP_0, - PROP_FLAGS, - PROP_ELEMENT_TYPE, - PROP_SIZE, - PROP_ELEMENTS, - PROP_ELEMENT_SIZE, -}; - #define EGG_DBUS_ARRAY_SEQ_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), EGG_DBUS_TYPE_ARRAY_SEQ, EggDBusArraySeqPrivate)) G_DEFINE_TYPE (EggDBusArraySeq, egg_dbus_array_seq, G_TYPE_OBJECT); @@ -160,7 +102,8 @@ egg_dbus_array_seq_finalize (GObject *object) if (priv->free_func != NULL) for (n = 0; n < array_seq->size; n++) - priv->free_func (array_seq, array_seq->data.v_ptr[n]); + if (array_seq->data.v_ptr[n] != NULL) + priv->free_func (array_seq->data.v_ptr[n]); g_free (array_seq->data.data); G_OBJECT_CLASS (egg_dbus_array_seq_parent_class)->finalize (object); @@ -169,21 +112,23 @@ egg_dbus_array_seq_finalize (GObject *object) /* ---------------------------------------------------------------------------------------------------- */ static gpointer -copy_elem_object (EggDBusArraySeq *array_seq, - gconstpointer element) +copy_via_user_copy_func (EggDBusArraySeq *array_seq, + gconstpointer element) { - return element == NULL ? NULL : g_object_ref ((gpointer) element); + EggDBusArraySeqPrivate *priv; + + priv = EGG_DBUS_ARRAY_SEQ_GET_PRIVATE (array_seq); + + return element == NULL ? NULL : priv->user_copy_func ((gpointer) element); } -static void -free_elem_object (EggDBusArraySeq *array_seq, - gpointer element) +static gpointer +copy_elem_object (EggDBusArraySeq *array_seq, + gconstpointer element) { - if (element != NULL) - g_object_unref (element); + return element == NULL ? NULL : g_object_ref ((gpointer) element); } - static gpointer copy_elem_string (EggDBusArraySeq *array_seq, gconstpointer element) @@ -191,13 +136,6 @@ copy_elem_string (EggDBusArraySeq *array_seq, return g_strdup (element); } -static void -free_elem_string (EggDBusArraySeq *array_seq, - gpointer element) -{ - g_free (element); -} - static gpointer copy_elem_boxed (EggDBusArraySeq *array_seq, gconstpointer element) @@ -205,14 +143,6 @@ copy_elem_boxed (EggDBusArraySeq *array_seq, return element == NULL ? NULL : g_boxed_copy (array_seq->element_type, element); } -static void -free_elem_boxed (EggDBusArraySeq *array_seq, - gpointer element) -{ - if (element != NULL) - g_boxed_free (array_seq->element_type, element); -} - static gpointer copy_elem_param_spec (EggDBusArraySeq *array_seq, gconstpointer element) @@ -220,28 +150,6 @@ copy_elem_param_spec (EggDBusArraySeq *array_seq, return element == NULL ? NULL : g_param_spec_ref ((gpointer) element); } -static void -free_elem_param_spec (EggDBusArraySeq *array_seq, - gpointer element) -{ - if (element != NULL) - g_param_spec_unref (element); -} - -static gpointer -copy_elem_static (EggDBusArraySeq *array_seq, - gconstpointer element) -{ - return (gpointer) element; -} - -static void -free_elem_static (EggDBusArraySeq *array_seq, - gpointer element) -{ - /* intentionally left blank */ -} - /* ---------------------------------------------------------------------------------------------------- */ #define IMPL_EQUAL_FUNC(type) \ @@ -273,10 +181,13 @@ ensure_size (EggDBusArraySeq *array_seq, guint old_capacity; guint old_size; + if (array_seq->size >= minimum_size) + return; + priv = EGG_DBUS_ARRAY_SEQ_GET_PRIVATE (array_seq); - /* always allocated in 8-element increments */ - minimum_capacity = (guint) (((((guint64) minimum_size) * G_GINT64_CONSTANT (8)) + G_GINT64_CONSTANT (8)) / G_GINT64_CONSTANT (8)); + /* always allocate 8 elements at a time */ + minimum_capacity = (guint) ((minimum_size + 7) / 8) * 8; old_capacity = priv->capacity; old_size = array_seq->size; @@ -311,116 +222,122 @@ egg_dbus_array_seq_class_init (EggDBusArraySeqClass *klass) g_type_class_add_private (klass, sizeof (EggDBusArraySeqPrivate)); } - /** * egg_dbus_array_seq_new: * @element_type: The type of the elements in the array. + * @free_func: Function to be used to free elements or %NULL. + * @copy_func: Function to be used to copy elements or %NULL to use the default copy function. + * @equal_func: Function to be used for comparing equality or %NULL to use the default equality function. * - * Creates a new array that holds elements of @element_type with the default (if any) function - * for comparing equality. + * Creates a new array that holds elements of @element_type and uses @free_func to free + * elements when they are no longer in use (e.g. when removed from the array either directly + * by calling e.g. egg_dbus_array_seq_remove_at() or if replaced by another element through + * egg_dbus_array_seq_set()). If @free_func is %NULL, then it is the responsibility of the owner + * of the array to free the elements when they are no longer used. * - * 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. - * - * Returns: A new #EggDBusArraySeq. Free with g_object_unref(). - **/ -EggDBusArraySeq * -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: 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. - * - * Creates a new array and optionally initializes with it with @size elements copied from @data. - * See egg_dbus_array_seq_new() for details on allowed values of @element_type and required memory - * layout of @data. + * If @copy_func is %NULL, the default copy function is used if one exists for @element_type + * (for example there is no default copy function if @element_type is #G_TYPE_POINTER). Note + * that <emphasis>optional</emphasis> methods such as egg_dbus_array_seq_get_copy() won't + * work if there is no copy function. * * 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 - * into the returned array are alive for the lifetime of the returned array. Use with caution. + * (for example there is no default equality function if @element_type is a subtype of + * #G_TYPE_OBJECT, #G_TYPE_INTERFACE or #G_TYPE_BOXED). Note that <emphasis>optional</emphasis> + * methods such as egg_dbus_array_seq_contains() won't work if there is no equality function. + * + * If the type of elements is not a fixed-size type (such as #GObject derived types), the array + * will store pointers and all value pointers to and from this class are to the actual elements + * (the array is simply an array of pointers). For example, to implement @equal_func when + * @element_type is #G_TYPE_FILE, one would do the following: + * + * <programlisting> + * static gboolean + * my_file_equal_func (gconstpointer _a, gconstpointer _b) + * { + * GVolume *a = G_FILE (_a); + * GVolume *b = G_FILE (_b) + * gboolean is_equal; + * + * /<!-- -->* compute is_equal by comparing a and b *<!-- -->/ + * + * return is_equal; + * } + * </programlisting> + * + * or, in this specific case, just pass g_file_equal() as @equal_func. + * + * If the type of the elements is a fixed-size type (such as #G_TYPE_INT, #G_TYPE_DOUBLE or a + * #G_TYPE_ENUM derived type), all value pointers used throughout this class is for the address + * of where the fixed-size value is stored inside the array. This is because the raw value are stored + * in the array; as such no pointers to elements are ever used (in addition, this means that @free_func + * and @copy_func are never used on such arrays). For example, for #G_TYPE_DOUBLE, you'd define + * @equal_func like this: + * + * <programlisting> + * static gboolean + * my_double_equal_func (gconstpointer _a, gconstpointer _b) + * { + * gdouble a = *((gdouble *) _a); + * gdouble b = *((gdouble *) _b); + * gboolean is_equal; + * + * /<!-- -->* compute is_equal by comparing a and b *<!-- -->/ + * + * return is_equal; + * } + * </programlisting> + * + * Note that the default equality functions for integral and floating point types should + * be good enough for all but exotic corner cases. * * Returns: A new #EggDBusArraySeq. Free with g_object_unref(). **/ EggDBusArraySeq * -egg_dbus_array_seq_new_full (GType element_type, - EggDBusArraySeqFlags flags, - GEqualFunc equal_func, - guint size, - gconstpointer data) +egg_dbus_array_seq_new (GType element_type, + GDestroyNotify free_func, + GBoxedCopyFunc copy_func, + GEqualFunc equal_func) { GType fundamental_type; EggDBusArraySeq *array_seq; EggDBusArraySeqPrivate *priv; gboolean not_supported; - gpointer *given_data; - 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); - priv->flags = flags; - array_seq->size = size; array_seq->element_type = element_type; priv->equal_func = equal_func; + priv->free_func = free_func; not_supported = FALSE; 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: case G_TYPE_INTERFACE: priv->copy_func = copy_elem_object; - priv->free_func = free_elem_object; array_seq->element_size = sizeof (gpointer); priv->element_type_is_gobject_derived = TRUE; break; case G_TYPE_BOXED: priv->copy_func = copy_elem_boxed; - priv->free_func = free_elem_boxed; array_seq->element_size = sizeof (gpointer); break; case G_TYPE_PARAM: priv->copy_func = copy_elem_param_spec; - priv->free_func = free_elem_param_spec; array_seq->element_size = sizeof (gpointer); break; case G_TYPE_STRING: priv->copy_func = copy_elem_string; - priv->free_func = free_elem_string; array_seq->element_size = sizeof (gpointer); if (priv->equal_func == NULL) @@ -430,6 +347,7 @@ egg_dbus_array_seq_new_full (GType element_type, case G_TYPE_UCHAR: case G_TYPE_CHAR: + priv->element_type_is_fixed_size = TRUE; array_seq->element_size = sizeof (guchar); if (priv->equal_func == NULL) priv->equal_func = _guchar_equal; @@ -437,6 +355,7 @@ egg_dbus_array_seq_new_full (GType element_type, case G_TYPE_INT: case G_TYPE_UINT: + priv->element_type_is_fixed_size = TRUE; array_seq->element_size = sizeof (gint); if (priv->equal_func == NULL) priv->equal_func = _gint_equal; @@ -444,18 +363,21 @@ egg_dbus_array_seq_new_full (GType element_type, case G_TYPE_INT64: case G_TYPE_UINT64: + priv->element_type_is_fixed_size = TRUE; array_seq->element_size = sizeof (gint64); if (priv->equal_func == NULL) priv->equal_func = _gint64_equal; break; case G_TYPE_BOOLEAN: + priv->element_type_is_fixed_size = TRUE; array_seq->element_size = sizeof (gboolean); if (priv->equal_func == NULL) priv->equal_func = _gboolean_equal; break; case G_TYPE_DOUBLE: + priv->element_type_is_fixed_size = TRUE; array_seq->element_size = sizeof (gdouble); if (priv->equal_func == NULL) priv->equal_func = _gdouble_equal; @@ -463,12 +385,14 @@ egg_dbus_array_seq_new_full (GType element_type, case G_TYPE_LONG: case G_TYPE_ULONG: + priv->element_type_is_fixed_size = TRUE; array_seq->element_size = sizeof (glong); if (priv->equal_func == NULL) priv->equal_func = _glong_equal; break; case G_TYPE_FLOAT: + priv->element_type_is_fixed_size = TRUE; array_seq->element_size = sizeof (gfloat); if (priv->equal_func == NULL) priv->equal_func = _gfloat_equal; @@ -476,6 +400,7 @@ egg_dbus_array_seq_new_full (GType element_type, case G_TYPE_ENUM: case G_TYPE_FLAGS: + priv->element_type_is_fixed_size = TRUE; array_seq->element_size = sizeof (gint); if (priv->equal_func == NULL) priv->equal_func = _gint_equal; @@ -487,11 +412,12 @@ egg_dbus_array_seq_new_full (GType element_type, default: /* can't have 16bit types in the switch since they're not constant - * (Thanks GObject for not have GType for these) + * (Thanks GObject for not having a GType for these) */ if (array_seq->element_type == EGG_DBUS_TYPE_INT16 || array_seq->element_type == EGG_DBUS_TYPE_UINT16) { + priv->element_type_is_fixed_size = TRUE; array_seq->element_size = sizeof (gint16); if (priv->equal_func == NULL) priv->equal_func = _gint16_equal; @@ -503,96 +429,63 @@ egg_dbus_array_seq_new_full (GType element_type, break; } - /* 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)) + if (priv->element_type_is_fixed_size && free_func != NULL) { - g_error ("Using EGG_DBUS_ARRAY_SEQ_FLAGS_STATIC doesn't make sense for " - "fixed-size type %s.", + g_error ("Meaningless to specify free_func for EggDBusArraySeq<%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) + if (priv->element_type_is_fixed_size && copy_func != NULL) { - /* didn't recognize type; this is a programmer/user error; contract says we can only manage - * boxed or GObject-derived types - */ - g_error ("Unsupported type %s used as element type for EggDBusArraySeq.", + g_error ("Meaningless to specify copy_func for EggDBusArraySeq<%s>.", g_type_name (array_seq->element_type)); } - /* if the passed in objects are static; use non-op copy(), free() implementations */ - if (priv->flags & EGG_DBUS_ARRAY_SEQ_FLAGS_STATIC) + if (copy_func != NULL) { - priv->copy_func = copy_elem_static; - priv->free_func = free_elem_static; + priv->user_copy_func = copy_func; + priv->copy_func = copy_via_user_copy_func; } - /* take the passed in elements */ - given_data = (gpointer *) data; - array_seq->data.v_ptr = NULL; - - /* ... allocate data to store element copies */ - ensure_size (array_seq, array_seq->size); - - /* ... and copy the passed in data if applicable */ - if (given_data != NULL && array_seq->size > 0) + if (not_supported) { - if (priv->copy_func != NULL) - { - /* elements are pointers; have to copy them one by one */ - for (n = 0; n < array_seq->size; n++) - { - array_seq->data.v_ptr[n] = priv->copy_func (array_seq, given_data[n]); - } - } - else - { - /* for arrays of fixed size, copy the whole lot at once */ - memcpy (array_seq->data.v_ptr, given_data, array_seq->size * array_seq->element_size); - } + /* didn't recognize type; this is a programmer/user error; contract says we can only manage + * boxed or GObject-derived types + */ + g_error ("Unsupported type %s used as element type for EggDBusArraySeq.", + g_type_name (array_seq->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) +static gboolean +check_have_equal_func (EggDBusArraySeq *array_seq) { EggDBusArraySeqPrivate *priv; priv = EGG_DBUS_ARRAY_SEQ_GET_PRIVATE (array_seq); - priv->equal_func = equal_func; + if (G_LIKELY (priv->equal_func != NULL)) + return TRUE; - 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; + g_error ("no equal_func set for EggDBusArraySeq<%s>", + g_type_name (array_seq->element_type)); + + return FALSE; } static gboolean -check_have_equal_func (EggDBusArraySeq *array_seq) +check_have_copy_func (EggDBusArraySeq *array_seq) { EggDBusArraySeqPrivate *priv; priv = EGG_DBUS_ARRAY_SEQ_GET_PRIVATE (array_seq); - if (G_LIKELY (priv->equal_func != NULL)) + if (G_LIKELY (priv->copy_func != NULL)) return TRUE; - g_error ("no equal_func set for EggDBusArraySeq<%s>", + g_error ("no copy_func set for EggDBusArraySeq<%s>", g_type_name (array_seq->element_type)); return FALSE; @@ -633,25 +526,7 @@ check_element_type (EggDBusArraySeq *array_seq, } /** - * egg_dbus_array_seq_get_flags: - * @array_seq: A #EggDBusArraySeq. - * - * Gets the flags that specify the behavior of @array_seq. - * - * Returns: Flags from #EggDBusArraySeqFlags that specify the behavior of @array_seq. - **/ -EggDBusArraySeqFlags -egg_dbus_array_seq_get_flags (EggDBusArraySeq *array_seq) -{ - EggDBusArraySeqPrivate *priv; - - priv = EGG_DBUS_ARRAY_SEQ_GET_PRIVATE (array_seq); - - return priv->flags; -} - -/** - * egg_dbus_array_seq_size: + * egg_dbus_array_seq_get_size: * @array_seq: A #EggDBusArraySeq. * * Gets the size of @array_seq. @@ -659,7 +534,7 @@ egg_dbus_array_seq_get_flags (EggDBusArraySeq *array_seq) * Returns: The number of elements in @array_seq. **/ guint -egg_dbus_array_seq_size (EggDBusArraySeq *array_seq) +egg_dbus_array_seq_get_size (EggDBusArraySeq *array_seq) { EggDBusArraySeqPrivate *priv; @@ -704,7 +579,8 @@ egg_dbus_array_seq_set_size (EggDBusArraySeq *array_seq, if (priv->free_func != NULL) { for (n = size; n < old_size; n++) - priv->free_func (array_seq, array_seq->data.v_ptr[n]); + if (array_seq->data.v_ptr[n] != NULL) + priv->free_func (array_seq->data.v_ptr[n]); } /* set new size */ @@ -726,7 +602,7 @@ egg_dbus_array_seq_set_size (EggDBusArraySeq *array_seq, * If @array_seq contains elements on non-fixed size, <literal>sizeof</literal> #gpointer * is returned. * - * Returns: The size, in byes, of each element. + * Returns: The size, in bytes, of each element. **/ gsize egg_dbus_array_seq_get_element_size (EggDBusArraySeq *array_seq) @@ -753,32 +629,42 @@ egg_dbus_array_seq_get_element_type (EggDBusArraySeq *array_seq) } /** - * egg_dbus_array_seq_steal_data: + * egg_dbus_array_seq_have_copy_func: * @array_seq: A #EggDBusArraySeq. * - * Steals the data backing @array_seq. The effect is the same as calling - * egg_dbus_array_seq_clear(), e.g. no elements will remain in the array - * when this function returns. Use with caution. + * Checks if @array_seq have a copy function. * - * Returns: A pointer to the elements of @array_seq. It is your - * responsibility to free the returned data depending on the element - * type of @array_seq. + * Returns: %TRUE only if there is a copy function for @array_seq. **/ -gpointer -egg_dbus_array_seq_steal_data (EggDBusArraySeq *array_seq) +gboolean +egg_dbus_array_seq_have_copy_func (EggDBusArraySeq *array_seq) { EggDBusArraySeqPrivate *priv; - gpointer result; priv = EGG_DBUS_ARRAY_SEQ_GET_PRIVATE (array_seq); - result = array_seq->data.v_ptr; - array_seq->data.v_ptr = NULL; - array_seq->size = 0; + return priv->copy_func != NULL; +} - return result; +/** + * egg_dbus_array_seq_get_equal_func: + * @array_seq: A #EggDBusArraySeq. + * + * Gets the #GEqualFunc used for comparing equality of elements. + * + * Returns: A #GEqualFunc. + **/ +GEqualFunc +egg_dbus_array_seq_get_equal_func (EggDBusArraySeq *array_seq) +{ + EggDBusArraySeqPrivate *priv; + + priv = EGG_DBUS_ARRAY_SEQ_GET_PRIVATE (array_seq); + + return priv->equal_func; } + /** * egg_dbus_array_seq_remove_at: * @array_seq: A #EggDBusArraySeq. @@ -823,7 +709,8 @@ egg_dbus_array_seq_remove_range_at (EggDBusArraySeq *array_seq, if (priv->free_func != NULL) { for (n = index; n < index + size; n++) - priv->free_func (array_seq, array_seq->data.v_ptr[n]); + if (array_seq->data.v_ptr[n] != NULL) + priv->free_func (array_seq->data.v_ptr[n]); } /* move data (this works for both pointers and primitive types) */ @@ -864,8 +751,8 @@ egg_dbus_array_seq_clear (EggDBusArraySeq *array_seq) * Gets the element at @index from @array_seq. * * Note that the returned element is owned by @array_seq and may be invalid if - * later removed from the array. If you want your own reference use - * egg_dbus_array_seq_get_dup(). + * later removed from the array. If you want a copy, use egg_dbus_array_seq_get_copy() + * instead. * * This is a constant-time operation. * @@ -884,25 +771,31 @@ egg_dbus_array_seq_get (EggDBusArraySeq *array_seq, priv = EGG_DBUS_ARRAY_SEQ_GET_PRIVATE (array_seq); - if (priv->copy_func != NULL) + if (! priv->element_type_is_fixed_size) return array_seq->data.v_ptr[index]; else return array_seq->data.v_byte + index * array_seq->element_size; } /** - * egg_dbus_array_seq_get_dup: + * egg_dbus_array_seq_get_copy: * @array_seq: A #EggDBusArraySeq. * @index: Zero-based index of element. * - * Gets a copy/reference of the element at @index from @array_seq. If you don't want your - * own copy/reference use egg_dbus_array_seq_get(). + * Gets a copy of the element at @index from @array_seq. If you don't want your + * own copy use egg_dbus_array_seq_get() instead. * - * Returns: A copy/reference of the requested element. Free with the appropriate + * This method is <emphasis>optional</emphasis> as some element types (for example #G_TYPE_POINTER + * and derived types) have no natural copy function and one might not have been set when @array_seq + * was constructed. It is a programming error to call this method on @array_seq if there + * is no copy function on @array_seq (a warning will be printed using g_error() causing program + * termination). + * + * Returns: A copy of the requested element. Free with the appropriate * function depending on the element type of @array_seq. **/ gpointer -egg_dbus_array_seq_get_dup (EggDBusArraySeq *array_seq, +egg_dbus_array_seq_get_copy (EggDBusArraySeq *array_seq, gint index) { EggDBusArraySeqPrivate *priv; @@ -912,20 +805,38 @@ egg_dbus_array_seq_get_dup (EggDBusArraySeq *array_seq, if (!check_index (array_seq, index)) return NULL; + if (!check_have_copy_func (array_seq)) + return NULL; + priv = EGG_DBUS_ARRAY_SEQ_GET_PRIVATE (array_seq); - if (priv->copy_func != NULL) - return priv->copy_func (array_seq, array_seq->data.v_ptr[index]); + if (! priv->element_type_is_fixed_size) + { + return priv->copy_func (array_seq, array_seq->data.v_ptr[index]); + } else - return g_memdup (array_seq->data.v_byte + index * array_seq->element_size, - array_seq->element_size); + { + return g_memdup (array_seq->data.v_byte + index * array_seq->element_size, + array_seq->element_size); + } } -static void -egg_dbus_array_seq_set_internal (EggDBusArraySeq *array_seq, - gint index, - gconstpointer value, - gboolean steal_value) +/** + * egg_dbus_array_seq_set: + * @array_seq: A #EggDBusArraySeq. + * @index: Zero-based index of element. + * @value: The value to insert. + * + * Replaces the element at @index in @array_seq with @value. + * + * Note that this function <emphasis>steals</emphasis> your reference to @value. + * + * This is a constant-time operation. + **/ +void +egg_dbus_array_seq_set (EggDBusArraySeq *array_seq, + gint index, + gconstpointer value) { EggDBusArraySeqPrivate *priv; @@ -942,15 +853,13 @@ egg_dbus_array_seq_set_internal (EggDBusArraySeq *array_seq, /* out with the old... */ if (priv->free_func != NULL) - priv->free_func (array_seq, array_seq->data.v_ptr[index]); + if (array_seq->data.v_ptr[index] != NULL) + priv->free_func (array_seq->data.v_ptr[index]); /* and in with the new.. */ - if (priv->copy_func != NULL) + if (! priv->element_type_is_fixed_size) { - if (steal_value) - array_seq->data.v_ptr[index] = (gpointer) value; - else - array_seq->data.v_ptr[index] = priv->copy_func (array_seq, value); + array_seq->data.v_ptr[index] = (gpointer) value; } else { @@ -961,58 +870,13 @@ 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 value to insert. - * - * Replaces the element at @index in @array_seq with @value. - * - * Note that this function <emphasis>steals</emphasis> your reference to @value to - * avoid copying/reffing it. If this is unwanted use egg_dbus_array_seq_set_dup() to - * hold on to your reference. - * - * This is a constant-time operation. - **/ -void -egg_dbus_array_seq_set (EggDBusArraySeq *array_seq, - gint index, - gconstpointer value) -{ - egg_dbus_array_seq_set_internal (array_seq, index, value, TRUE); -} - -/** - * egg_dbus_array_seq_set_dup: - * @array_seq: A #EggDBusArraySeq. - * @index: Zero-based index of element. - * @value: The value to insert. - * - * Replaces the element at @index in @array_seq with a copy/reference of @value. - * - * Note that @value is copied/reffed and you still own a reference to @value that - * you must free yourself. If this is unwanted use egg_dbus_array_seq_set() instead. - * - * This is a constant-time operation. - **/ -void -egg_dbus_array_seq_set_dup (EggDBusArraySeq *array_seq, - gint index, - gconstpointer value) -{ - egg_dbus_array_seq_set_internal (array_seq, index, value, FALSE); -} - -/** * egg_dbus_array_seq_add: * @array_seq: A #EggDBusArraySeq. * @value: The value to append. * * Appends @value to the end of @array_seq. The size of @array_seq will grow by one. * - * Note that this function <emphasis>steals</emphasis> your reference to @value to - * avoid copying/reffing it. If this is unwanted use egg_dbus_array_seq_add_dup() to - * hold on to your reference. + * Note that this function <emphasis>steals</emphasis> your reference to @value. * * This is a constant time operation. * @@ -1024,34 +888,53 @@ egg_dbus_array_seq_add (EggDBusArraySeq *array_seq, { /* grow, then add a copy of the element */ ensure_size (array_seq, array_seq->size + 1); - egg_dbus_array_seq_set_dup (array_seq, - array_seq->size - 1, - value); + egg_dbus_array_seq_set (array_seq, + array_seq->size - 1, + value); return TRUE; } /** - * egg_dbus_array_seq_add_dup: + * egg_dbus_array_seq_insert: * @array_seq: A #EggDBusArraySeq. + * @index: Zero-based index of element. * @value: The value to append. * - * Appends a copy of @value to the end of @array_seq. The size of @array_seq will grow by one. - * - * Note that @value is copied/reffed and you still own a reference to @value that - * you must free yourself. If this is unwanted use egg_dbus_array_seq_add() instead. + * Inserts @value at @index of @array_seq. All elements currently at or after @index will + * be shifted up by one and the size of @array_seq will grow by one. * - * Returns: Always %TRUE. + * Note that this function <emphasis>steals</emphasis> your reference to @value. **/ -gboolean -egg_dbus_array_seq_add_dup (EggDBusArraySeq *array_seq, - gconstpointer value) +void +egg_dbus_array_seq_insert (EggDBusArraySeq *array_seq, + gint index, + gconstpointer value) { - /* grow, then add stolen element */ + EggDBusArraySeqPrivate *priv; + guint old_size; + + if (!check_index (array_seq, index)) + return; + + priv = EGG_DBUS_ARRAY_SEQ_GET_PRIVATE (array_seq); + + old_size = array_seq->size; ensure_size (array_seq, array_seq->size + 1); - egg_dbus_array_seq_set_dup (array_seq, - array_seq->size - 1, - value); - return TRUE; + + if (old_size - index > 0) + { + g_memmove (array_seq->data.v_byte + (index + 1) * array_seq->element_size, /* dst */ + array_seq->data.v_byte + index * array_seq->element_size, /* src */ + (old_size - index) * array_seq->element_size); + } + + memset (array_seq->data.v_byte + index * array_seq->element_size, + 0, + array_seq->element_size); + + egg_dbus_array_seq_set (array_seq, + index, + value); } /** @@ -1061,8 +944,9 @@ egg_dbus_array_seq_add_dup (EggDBusArraySeq *array_seq, * * 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. + * This method is <emphasis>optional</emphasis>. It is a programing error to call this + * method on @array_seq if there is no #GEqualFunc set for @array_seq (a warning will be + * printed using g_error() causing program termination). * * Returns: The index of the first occurence of an element equal to @value * in @array_seq or -1 if no such elements exist. @@ -1083,7 +967,7 @@ egg_dbus_array_seq_index_of (EggDBusArraySeq *array_seq, { gboolean found; - if (priv->copy_func != NULL) + if (! priv->element_type_is_fixed_size) 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); @@ -1102,8 +986,9 @@ egg_dbus_array_seq_index_of (EggDBusArraySeq *array_seq, * * 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. + * This method is <emphasis>optional</emphasis>. It is a programing error to call this + * method on @array_seq if there is no #GEqualFunc set for @array_seq (a warning will be + * printed using g_error() causing program termination). * * Returns: %TRUE if @array_seq contains one or more elements equal to @value. **/ @@ -1121,8 +1006,9 @@ egg_dbus_array_seq_contains (EggDBusArraySeq *array_seq, * * 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. + * This method is <emphasis>optional</emphasis>. It is a programing error to call this method + * on @array_seq if there is no #GEqualFunc set for @array_seq (a warning will be + * printed using g_error() causing program termination). * * Returns: %TRUE if an element was removed. **/ @@ -1176,7 +1062,7 @@ egg_dbus_array_seq_add_fixed (EggDBusArraySeq *array_seq, case G_TYPE_INT: case G_TYPE_UINT: v_int = value; - egg_dbus_array_seq_add (array_seq, &v_int16); + egg_dbus_array_seq_add (array_seq, &v_int); break; case G_TYPE_INT64: @@ -1346,6 +1232,107 @@ egg_dbus_array_seq_set_float (EggDBusArraySeq *array_seq, } /** + * egg_dbus_array_seq_insert_fixed: + * @array_seq: A #EggDBusArraySeq. + * @index: Zero-based index of element. + * @value: The value to append. + * + * Inserts @value at @index of @array_seq. All elements currently at or after @index will + * be shifted up by one and the size of @array_seq will grow by one. + * + * This is a C convenience function for fixed-size integral types such as #G_TYPE_UCHAR, #G_TYPE_INT and so on. + **/ +void +egg_dbus_array_seq_insert_fixed (EggDBusArraySeq *array_seq, + gint index, + guint64 value) +{ + guchar v_byte; + guint16 v_int16; + guint v_int; + gulong v_long; + + switch (array_seq->element_type) + { + case G_TYPE_UCHAR: + case G_TYPE_CHAR: + v_byte = value; + egg_dbus_array_seq_insert (array_seq, index, &v_byte); + break; + + case G_TYPE_INT: + case G_TYPE_UINT: + v_int = value; + egg_dbus_array_seq_insert (array_seq, index, &v_int); + break; + + case G_TYPE_INT64: + case G_TYPE_UINT64: + egg_dbus_array_seq_insert (array_seq, index, &value); + break; + + case G_TYPE_LONG: + case G_TYPE_ULONG: + v_long = value; + egg_dbus_array_seq_insert (array_seq, index, &v_long); + break; + + default: + /* can't have 16bit types in the switch since they're not constant + */ + if (array_seq->element_type == EGG_DBUS_TYPE_INT16 || + array_seq->element_type == EGG_DBUS_TYPE_UINT16) + { + v_int16 = value; + egg_dbus_array_seq_insert (array_seq, index, &v_int16); + } + else + { + g_error ("Cannot use egg_dbus_array_seq_insert_fixed() on EggDBusArraySeq<%s>", + g_type_name (array_seq->element_type)); + } + break; + } +} + +/** + * egg_dbus_array_seq_insert_float: + * @array_seq: A #EggDBusArraySeq. + * @index: Zero-based index of element. + * @value: The value to append. + * + * Inserts @value at @index of @array_seq. All elements currently at or after @index will + * be shifted up by one and the size of @array_seq will grow by one. + * + * This is a C convenience function for the floating point types #G_TYPE_FLOAT and #G_TYPE_DOUBLE. + **/ +void +egg_dbus_array_seq_insert_float (EggDBusArraySeq *array_seq, + gint index, + gdouble value) +{ + gfloat v_float; + + switch (array_seq->element_type) + { + case G_TYPE_FLOAT: + v_float = value; + egg_dbus_array_seq_insert (array_seq, index, &v_float); + break; + + case G_TYPE_DOUBLE: + egg_dbus_array_seq_insert (array_seq, index, &value); + break; + + default: + g_error ("Cannot use egg_dbus_array_seq_insert_float() on EggDBusArraySeq<%s>", + g_type_name (array_seq->element_type)); + break; + } +} + + +/** * egg_dbus_array_seq_get_fixed: * @array_seq: A #EggDBusArraySeq. * @index: Zero-based index of element. diff --git a/src/eggdbus/eggdbusarrayseq.h b/src/eggdbus/eggdbusarrayseq.h index 830cc4c..d51d390 100644 --- a/src/eggdbus/eggdbusarrayseq.h +++ b/src/eggdbus/eggdbusarrayseq.h @@ -40,21 +40,6 @@ G_BEGIN_DECLS 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_HAVE_EQUAL_FUNC = (1<<1), -} EggDBusArraySeqFlags; - -/** * EggDBusArraySeq: * @size: Number of elements in the array. * @element_type: The #GType of the elements in the array. @@ -129,55 +114,48 @@ struct _EggDBusArraySeqClass GType egg_dbus_array_seq_get_type (void) G_GNUC_CONST; -EggDBusArraySeq *egg_dbus_array_seq_new (GType element_type) G_GNUC_WARN_UNUSED_RESULT; +EggDBusArraySeq *egg_dbus_array_seq_new (GType element_type, + GDestroyNotify free_func, + GBoxedCopyFunc copy_func, + GEqualFunc equal_func) G_GNUC_WARN_UNUSED_RESULT; +gsize egg_dbus_array_seq_get_element_size (EggDBusArraySeq *array_seq); -EggDBusArraySeq *egg_dbus_array_seq_new_full (GType element_type, - EggDBusArraySeqFlags flags, - GEqualFunc equal_func, - guint size, - gconstpointer data) G_GNUC_WARN_UNUSED_RESULT; +GType egg_dbus_array_seq_get_element_type (EggDBusArraySeq *array_seq) G_GNUC_WARN_UNUSED_RESULT; -EggDBusArraySeqFlags egg_dbus_array_seq_get_flags (EggDBusArraySeq *array_seq) G_GNUC_WARN_UNUSED_RESULT; +GEqualFunc egg_dbus_array_seq_get_equal_func (EggDBusArraySeq *array_seq) G_GNUC_WARN_UNUSED_RESULT; -void egg_dbus_array_seq_set_equal_func (EggDBusArraySeq *array_seq, - GEqualFunc equal_func); +gboolean egg_dbus_array_seq_have_copy_func (EggDBusArraySeq *array_seq) G_GNUC_WARN_UNUSED_RESULT; -guint egg_dbus_array_seq_size (EggDBusArraySeq *array_seq) G_GNUC_WARN_UNUSED_RESULT; +guint egg_dbus_array_seq_get_size (EggDBusArraySeq *array_seq) G_GNUC_WARN_UNUSED_RESULT; void egg_dbus_array_seq_set_size (EggDBusArraySeq *array_seq, guint size); -gsize egg_dbus_array_seq_get_element_size (EggDBusArraySeq *array_seq); - -GType egg_dbus_array_seq_get_element_type (EggDBusArraySeq *array_seq) G_GNUC_WARN_UNUSED_RESULT; - -void egg_dbus_array_seq_remove_at (EggDBusArraySeq *array_seq, - gint index); - -void egg_dbus_array_seq_remove_range_at (EggDBusArraySeq *array_seq, - gint index, - guint size); - void egg_dbus_array_seq_clear (EggDBusArraySeq *array_seq); gpointer egg_dbus_array_seq_get (EggDBusArraySeq *array_seq, gint index) G_GNUC_WARN_UNUSED_RESULT; -gpointer egg_dbus_array_seq_get_dup (EggDBusArraySeq *array_seq, +gpointer egg_dbus_array_seq_get_copy (EggDBusArraySeq *array_seq, gint index) G_GNUC_WARN_UNUSED_RESULT; void egg_dbus_array_seq_set (EggDBusArraySeq *array_seq, gint index, gconstpointer value); -void egg_dbus_array_seq_set_dup (EggDBusArraySeq *array_seq, +void egg_dbus_array_seq_insert (EggDBusArraySeq *array_seq, gint index, gconstpointer value); gboolean egg_dbus_array_seq_add (EggDBusArraySeq *array_seq, gconstpointer value); -gboolean egg_dbus_array_seq_add_dup (EggDBusArraySeq *array_seq, - gconstpointer value); + +void egg_dbus_array_seq_remove_at (EggDBusArraySeq *array_seq, + gint index); + +void egg_dbus_array_seq_remove_range_at (EggDBusArraySeq *array_seq, + gint index, + guint size); gint egg_dbus_array_seq_index_of (EggDBusArraySeq *array_seq, gconstpointer value); @@ -190,9 +168,6 @@ gboolean egg_dbus_array_seq_remove (EggDBusArraySeq /* C convenience functions */ -gpointer egg_dbus_array_seq_steal_data (EggDBusArraySeq *array_seq) G_GNUC_WARN_UNUSED_RESULT; - - gboolean egg_dbus_array_seq_add_fixed (EggDBusArraySeq *array_seq, guint64 value); gboolean egg_dbus_array_seq_add_float (EggDBusArraySeq *array_seq, @@ -205,6 +180,13 @@ void egg_dbus_array_seq_set_float (EggDBusArraySeq gint index, gdouble value); +void egg_dbus_array_seq_insert_fixed (EggDBusArraySeq *array_seq, + gint index, + guint64 value); +void egg_dbus_array_seq_insert_float (EggDBusArraySeq *array_seq, + gint index, + gdouble value); + guint64 egg_dbus_array_seq_get_fixed (EggDBusArraySeq *array_seq, gint index) G_GNUC_WARN_UNUSED_RESULT; gdouble egg_dbus_array_seq_get_float (EggDBusArraySeq *array_seq, diff --git a/src/tests/testclient.c b/src/tests/testclient.c index 4853b52..39844a6 100644 --- a/src/tests/testclient.c +++ b/src/tests/testclient.c @@ -3565,18 +3565,16 @@ test_egg_dbus_array_seq (void) GFile *file_3; guint64 some_uint64_numbers[3] = {G_MAXINT64 - 10, G_MAXINT * G_GINT64_CONSTANT (2), G_GINT64_CONSTANT (42)}; guchar some_prime_numbers[7] = {1, 2, 3, 5, 7, 11, 13}; - + guint n; /* * First, check that all EggDBusArraySeq operations work */ - a = egg_dbus_array_seq_new_full (G_TYPE_STRING, - 0, - NULL, - 5, - some_strings); + a = egg_dbus_array_seq_new (G_TYPE_STRING, g_free, NULL, NULL); + for (n = 0; n < 5; n++) + egg_dbus_array_seq_add (a, g_strdup (some_strings[n])); g_assert_cmpuint (egg_dbus_array_seq_get_element_type (a), ==, G_TYPE_STRING); - g_assert_cmpuint (egg_dbus_array_seq_size (a), ==, 5); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 5); g_assert_cmpstr (egg_dbus_array_seq_get (a, 0), ==, "zero"); g_assert_cmpstr (egg_dbus_array_seq_get (a, 1), ==, "one"); g_assert_cmpstr (egg_dbus_array_seq_get (a, 2), ==, "two"); @@ -3584,14 +3582,30 @@ test_egg_dbus_array_seq (void) g_assert_cmpstr (egg_dbus_array_seq_get (a, 4), ==, "four"); /* address SHOULDN'T be the same since it's a copy */ g_assert (egg_dbus_array_seq_get (a, 0) != some_strings[0]); - /* try adding elements; this will automatically grow the array */ - egg_dbus_array_seq_add_dup (a, "five"); - g_assert_cmpuint (egg_dbus_array_seq_size (a), ==, 6); + /* try inserting elements, that should shift elements up */ + egg_dbus_array_seq_insert (a, 3, g_strdup ("two-and-a-half")); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 6); + g_assert_cmpstr (egg_dbus_array_seq_get (a, 0), ==, "zero"); + g_assert_cmpstr (egg_dbus_array_seq_get (a, 1), ==, "one"); + g_assert_cmpstr (egg_dbus_array_seq_get (a, 2), ==, "two"); + g_assert_cmpstr (egg_dbus_array_seq_get (a, 3), ==, "two-and-a-half"); + g_assert_cmpstr (egg_dbus_array_seq_get (a, 4), ==, "three"); + g_assert_cmpstr (egg_dbus_array_seq_get (a, 5), ==, "four"); + egg_dbus_array_seq_remove_at (a, 3); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 5); + g_assert_cmpstr (egg_dbus_array_seq_get (a, 0), ==, "zero"); + g_assert_cmpstr (egg_dbus_array_seq_get (a, 1), ==, "one"); + g_assert_cmpstr (egg_dbus_array_seq_get (a, 2), ==, "two"); + g_assert_cmpstr (egg_dbus_array_seq_get (a, 3), ==, "three"); + g_assert_cmpstr (egg_dbus_array_seq_get (a, 4), ==, "four"); + /* Try adding elements; this will automatically grow the array */ + egg_dbus_array_seq_add (a, g_strdup ("five")); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 6); g_assert_cmpstr (egg_dbus_array_seq_get (a, 5), ==, "five"); /* this would be a buffer overflow; verify that we catch it and warn/abort */ if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR)) { - egg_dbus_array_seq_set_dup (a, 7, "seven"); + egg_dbus_array_seq_set (a, 7, g_strdup ("seven")); } g_test_trap_assert_failed (); g_test_trap_assert_stderr ("*index 7 is out of bounds on EggDBusArraySeq<gchararray> of size 6*"); @@ -3600,15 +3614,15 @@ test_egg_dbus_array_seq (void) * Note that this creates a hole at index 6. Also check that. */ egg_dbus_array_seq_set_size (a, 8); - egg_dbus_array_seq_set_dup (a, 7, "seven"); - g_assert_cmpuint (egg_dbus_array_seq_size (a), ==, 8); + egg_dbus_array_seq_set (a, 7, g_strdup ("seven")); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 8); g_assert (egg_dbus_array_seq_get (a, 6) == NULL); g_assert_cmpstr (egg_dbus_array_seq_get (a, 7), ==, "seven"); /* replace elements */ - egg_dbus_array_seq_set_dup (a, 1, "better one"); /* get it? ;-) */ + egg_dbus_array_seq_set (a, 1, g_strdup ("better one")); /* get it? ;-) */ /* removing elements */ egg_dbus_array_seq_remove_at (a, 2); - g_assert_cmpuint (egg_dbus_array_seq_size (a), ==, 7); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 7); g_assert_cmpstr (egg_dbus_array_seq_get (a, 0), ==, "zero"); g_assert_cmpstr (egg_dbus_array_seq_get (a, 1), ==, "better one"); g_assert_cmpstr (egg_dbus_array_seq_get (a, 2), ==, "three"); @@ -3617,13 +3631,13 @@ test_egg_dbus_array_seq (void) g_assert (egg_dbus_array_seq_get (a, 5) == NULL); g_assert_cmpstr (egg_dbus_array_seq_get (a, 6), ==, "seven"); egg_dbus_array_seq_remove_range_at (a, 1, 3); - g_assert_cmpuint (egg_dbus_array_seq_size (a), ==, 4); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 4); g_assert_cmpstr (egg_dbus_array_seq_get (a, 0), ==, "zero"); g_assert_cmpstr (egg_dbus_array_seq_get (a, 1), ==, "five"); g_assert (egg_dbus_array_seq_get (a, 2) == NULL); g_assert_cmpstr (egg_dbus_array_seq_get (a, 3), ==, "seven"); egg_dbus_array_seq_remove_at (a, 2); - g_assert_cmpuint (egg_dbus_array_seq_size (a), ==, 3); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 3); g_assert_cmpstr (egg_dbus_array_seq_get (a, 0), ==, "zero"); g_assert_cmpstr (egg_dbus_array_seq_get (a, 1), ==, "five"); g_assert_cmpstr (egg_dbus_array_seq_get (a, 2), ==, "seven"); @@ -3644,24 +3658,20 @@ test_egg_dbus_array_seq (void) g_test_trap_assert_stderr ("*index -2 is out of bounds on EggDBusArraySeq<gchararray> of size 3*"); /* check we that downsizing the array works */ egg_dbus_array_seq_set_size (a, 2); - g_assert_cmpuint (egg_dbus_array_seq_size (a), ==, 2); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 2); /* check that clear works */ egg_dbus_array_seq_clear (a); - g_assert_cmpuint (egg_dbus_array_seq_size (a), ==, 0); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 0); g_object_unref (a); /* -------------------------------------------------------------------------------- */ - /* now, check that EGG_DBUS_ARRAY_SEQ_FLAGS_STATIC is honored; e.g. that - * no copies elements are ever made - */ - a = egg_dbus_array_seq_new_full (G_TYPE_STRING, - EGG_DBUS_ARRAY_SEQ_FLAGS_STATIC, - NULL, - 5, - some_strings); + /* now, check the same without a free function */ + a = egg_dbus_array_seq_new (G_TYPE_STRING, NULL, NULL, NULL); + for (n = 0; n < 5; n++) + egg_dbus_array_seq_add (a, some_strings[n]); g_assert_cmpuint (egg_dbus_array_seq_get_element_type (a), ==, G_TYPE_STRING); - g_assert_cmpuint (egg_dbus_array_seq_size (a), ==, 5); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 5); g_assert_cmpstr (egg_dbus_array_seq_get (a, 0), ==, "zero"); g_assert_cmpstr (egg_dbus_array_seq_get (a, 1), ==, "one"); g_assert_cmpstr (egg_dbus_array_seq_get (a, 2), ==, "two"); @@ -3669,35 +3679,16 @@ test_egg_dbus_array_seq (void) g_assert_cmpstr (egg_dbus_array_seq_get (a, 4), ==, "four"); /* address SHOULD be the same since it's not a copy */ g_assert (egg_dbus_array_seq_get (a, 0) == some_strings[0]); - /* elements inserted after constuction shouldn't be copied either even if _dup() is used */ - egg_dbus_array_seq_set_dup (a, 1, some_strings[0]); - g_assert_cmpstr (egg_dbus_array_seq_get (a, 1), ==, "zero"); - g_assert (egg_dbus_array_seq_get (a, 1) == some_strings[0]); - /* check we can steal the data; first terminate with NULL so g_strv_length() works */ - egg_dbus_array_seq_add (a, NULL); - string_array = (gchar **) egg_dbus_array_seq_steal_data (a); - g_assert_cmpuint (egg_dbus_array_seq_size (a), ==, 0); g_object_unref (a); - /* no need to free strings in the array, these are static strings */ - g_assert_cmpuint (g_strv_length (string_array), ==, 5); - g_assert_cmpstr (string_array[0], ==, "zero"); - g_assert_cmpstr (string_array[1], ==, "zero"); - g_assert_cmpstr (string_array[2], ==, "two"); - g_assert_cmpstr (string_array[3], ==, "three"); - g_assert_cmpstr (string_array[4], ==, "four"); - g_assert (string_array[4] == some_strings[4]); - g_free (string_array); /* -------------------------------------------------------------------------------- */ /* check that fixed size types work (through C convenience interface) */ - a = egg_dbus_array_seq_new_full (G_TYPE_UCHAR, - 0, /* flags */ - NULL, - 7, - some_prime_numbers); + a = egg_dbus_array_seq_new (G_TYPE_UCHAR, NULL, NULL, NULL); + for (n = 0; n < 7; n++) + egg_dbus_array_seq_add_fixed (a, some_prime_numbers[n]); g_assert_cmpuint (egg_dbus_array_seq_get_element_type (a), ==, G_TYPE_UCHAR); - g_assert_cmpuint (egg_dbus_array_seq_size (a), ==, 7); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 7); /* check that direct access works */ g_assert_cmpint (a->data.v_byte[0], ==, 1); g_assert_cmpint (a->data.v_byte[1], ==, 2); @@ -3714,6 +3705,26 @@ test_egg_dbus_array_seq (void) g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 4), ==, 7); g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 5), ==, 11); g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 6), ==, 13); + /* check we can insert items in the middle */ + egg_dbus_array_seq_insert_fixed (a, 5, 9); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 8); + g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 0), ==, 1); + g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 1), ==, 2); + g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 2), ==, 3); + g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 3), ==, 5); + g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 4), ==, 7); + g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 5), ==, 9); + g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 6), ==, 11); + g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 7), ==, 13); + egg_dbus_array_seq_remove_at (a, 5); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 7); + g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 0), ==, 1); + g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 1), ==, 2); + g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 2), ==, 3); + g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 3), ==, 5); + g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 4), ==, 7); + g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 5), ==, 11); + g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 6), ==, 13); /* check that we're getting runtime errors / abort for out-of-bounds access */ if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR)) { @@ -3724,7 +3735,7 @@ test_egg_dbus_array_seq (void) g_test_trap_assert_stderr ("*index 10 is out of bounds on EggDBusArraySeq<guchar> of size 7*"); /* check we can set elements */ egg_dbus_array_seq_set_fixed (a, 4, 9); /* prime intruder! */ - g_assert_cmpuint (egg_dbus_array_seq_size (a), ==, 7); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 7); g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 0), ==, 1); g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 1), ==, 2); g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 2), ==, 3); @@ -3735,7 +3746,7 @@ test_egg_dbus_array_seq (void) /* check that we can remove elements */ egg_dbus_array_seq_remove_at (a, 2); egg_dbus_array_seq_remove_at (a, 4); - g_assert_cmpuint (egg_dbus_array_seq_size (a), ==, 5); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 5); g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 0), ==, 1); g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 1), ==, 2); g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 2), ==, 5); @@ -3743,18 +3754,18 @@ test_egg_dbus_array_seq (void) g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 4), ==, 13); /* check we can add stuff */ egg_dbus_array_seq_add_fixed (a, 0xff); - g_assert_cmpuint (egg_dbus_array_seq_size (a), ==, 6); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 6); g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 5), ==, 0xff); g_object_unref (a); + /* -------------------------------------------------------------------------------- */ + /* check another fixed size type just for kicks */ - a = egg_dbus_array_seq_new_full (G_TYPE_INT64, - 0, /* flags */ - NULL, - 3, - some_uint64_numbers); + a = egg_dbus_array_seq_new (G_TYPE_INT64, NULL, NULL, NULL); + for (n = 0; n < 3; n++) + egg_dbus_array_seq_add_fixed (a, some_uint64_numbers[n]); g_assert_cmpuint (egg_dbus_array_seq_get_element_type (a), ==, G_TYPE_INT64); - g_assert_cmpuint (egg_dbus_array_seq_size (a), ==, 3); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 3); /* check that direct access works */ g_assert_cmpint (a->data.v_int64[0], ==, G_MAXINT64 - 10); g_assert_cmpint (a->data.v_int64[1], ==, G_MAXINT * G_GINT64_CONSTANT (2)); @@ -3762,12 +3773,12 @@ test_egg_dbus_array_seq (void) /* check we can remove stuff */ egg_dbus_array_seq_remove_at (a, 1); /* check that C convenience getters work */ - g_assert_cmpuint (egg_dbus_array_seq_size (a), ==, 2); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 2); g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 0), ==, G_MAXINT64 - 10); g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 1), ==, 42); /* check we can add stuff */ egg_dbus_array_seq_add_fixed (a, G_MAXINT * G_GINT64_CONSTANT (3)); - g_assert_cmpuint (egg_dbus_array_seq_size (a), ==, 3); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 3); g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 0), ==, G_MAXINT64 - 10); g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 1), ==, 42); g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 2), ==, G_MAXINT * G_GINT64_CONSTANT (3)); @@ -3776,11 +3787,11 @@ test_egg_dbus_array_seq (void) /* -------------------------------------------------------------------------------- */ /* now check that boxed types works */ - a = egg_dbus_array_seq_new (G_TYPE_STRV); + a = egg_dbus_array_seq_new (G_TYPE_STRV, (GDestroyNotify) g_strfreev, NULL, NULL); egg_dbus_array_seq_add (a, g_strsplit ("a test string", " ", 0)); egg_dbus_array_seq_add (a, g_strsplit ("another string", " ", 0)); - egg_dbus_array_seq_add_dup (a, some_strings); - g_assert_cmpuint (egg_dbus_array_seq_size (a), ==, 3); + egg_dbus_array_seq_add (a, g_strdupv ((gchar **) some_strings)); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 3); g_assert_cmpuint (g_strv_length (egg_dbus_array_seq_get (a, 0)), ==, 3); g_assert_cmpstr (a->data.v_strv[0][0], ==, "a"); g_assert_cmpstr (a->data.v_strv[0][1], ==, "test"); @@ -3795,14 +3806,6 @@ test_egg_dbus_array_seq (void) g_assert_cmpstr (a->data.v_strv[2][3], ==, "three"); g_assert_cmpstr (a->data.v_strv[2][4], ==, "four"); /* adding stuff of a wrong type should cause a run-time warning / abort; check that - * - * (Unfortunately we can't check types if the the regular array_seq_add() - * is used (a boxed instance or string could be passed) though the program - * is very likely to crash if this happens. - * - * One way to get around this is to abolish array_seq_add() completely and - * replace it with the types we care about (str, strv, object, boxed)... - * TODO: consider if that's a good idea. */ if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR)) { @@ -3812,13 +3815,13 @@ test_egg_dbus_array_seq (void) g_test_trap_assert_stderr ("*Cannot use egg_dbus_array_seq_add_fixed() on EggDBusArraySeq<GStrv>*"); /* check we can remove stuff; we only bother check the first element this time */ egg_dbus_array_seq_remove_at (a, 1); - g_assert_cmpuint (egg_dbus_array_seq_size (a), ==, 2); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 2); g_assert_cmpuint (g_strv_length (egg_dbus_array_seq_get (a, 0)), ==, 3); g_assert_cmpstr (a->data.v_strv[0][0], ==, "a"); g_assert_cmpuint (g_strv_length (egg_dbus_array_seq_get (a, 1)), ==, 5); g_assert_cmpstr (a->data.v_strv[1][0], ==, "zero"); - /* check that dup works */ - string_array = egg_dbus_array_seq_get_dup (a, 1); + /* check that copying works */ + string_array = egg_dbus_array_seq_get_copy (a, 1); g_assert_cmpuint (g_strv_length (string_array), ==, 5); g_assert_cmpstr (string_array[0], ==, "zero"); g_assert_cmpstr (string_array[1], ==, "one"); @@ -3831,10 +3834,10 @@ test_egg_dbus_array_seq (void) /* -------------------------------------------------------------------------------- */ /* check that types deriving from boxed types work */ - a = egg_dbus_array_seq_new (EGG_DBUS_TYPE_OBJECT_PATH_ARRAY); + a = egg_dbus_array_seq_new (EGG_DBUS_TYPE_OBJECT_PATH_ARRAY, (GDestroyNotify) g_strfreev, NULL, NULL); egg_dbus_array_seq_add (a, g_strsplit ("/a/test/path", "/", 0)); egg_dbus_array_seq_add (a, g_strsplit ("/another/path", "/", 0)); - g_assert_cmpuint (egg_dbus_array_seq_size (a), ==, 2); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 2); g_assert_cmpuint (g_strv_length (egg_dbus_array_seq_get (a, 0)), ==, 4); g_assert_cmpstr (a->data.v_strv[0][0], ==, ""); g_assert_cmpstr (a->data.v_strv[0][1], ==, "a"); @@ -3853,10 +3856,10 @@ test_egg_dbus_array_seq (void) * arrays of boxed instances. However, there's one additional check that is done; namely * type checking: */ - a = egg_dbus_array_seq_new (TEST_TYPE_SUBJECT); + a = egg_dbus_array_seq_new (TEST_TYPE_SUBJECT, g_object_unref, NULL, NULL); egg_dbus_array_seq_add (a, test_subject_new (TEST_SUBJECT_KIND_HUMAN, "davidz", "eggs", "blue")); egg_dbus_array_seq_add (a, test_subject_new (TEST_SUBJECT_KIND_HUMAN, "krh", "<undisclosed>", "<classified>")); - g_assert_cmpuint (egg_dbus_array_seq_size (a), ==, 2); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 2); if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR)) { egg_dbus_array_seq_add_fixed (a, 0xcafebabe); @@ -3878,26 +3881,26 @@ test_egg_dbus_array_seq (void) * (implemented by GLocalFile and (if gvfs is installed) and GDaemonFile) use that for * our test case. */ - a = egg_dbus_array_seq_new (G_TYPE_FILE); + a = egg_dbus_array_seq_new (G_TYPE_FILE, g_object_unref, NULL, NULL); egg_dbus_array_seq_add (a, g_file_new_for_path ("a.txt")); egg_dbus_array_seq_add (a, g_file_new_for_path ("b.txt")); egg_dbus_array_seq_add (a, g_file_new_for_path ("c.txt")); - g_assert_cmpuint (egg_dbus_array_seq_size (a), ==, 3); + g_assert_cmpuint (egg_dbus_array_seq_get_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"); + a = egg_dbus_array_seq_new (G_TYPE_STRING, g_free, NULL, NULL); + g_assert (egg_dbus_array_seq_get_equal_func (a) != NULL); + egg_dbus_array_seq_add (a, g_strdup ("zero")); + egg_dbus_array_seq_add (a, g_strdup ("one")); + egg_dbus_array_seq_add (a, g_strdup ("two")); + egg_dbus_array_seq_add (a, g_strdup ("three")); + egg_dbus_array_seq_add (a, g_strdup ("two")); + egg_dbus_array_seq_add (a, g_strdup ("four")); + egg_dbus_array_seq_add (a, g_strdup ("two")); + egg_dbus_array_seq_add (a, g_strdup ("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")); @@ -3911,12 +3914,11 @@ test_egg_dbus_array_seq (void) /* -------------------------------------------------------------------------------- */ - /* 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); + /* try for a fixed-size type as well */ + a = egg_dbus_array_seq_new (G_TYPE_INT, NULL, NULL, NULL); + for (n = 0; n < 8; n++) + egg_dbus_array_seq_add_fixed (a, some_ints[n]); + g_assert_cmpuint (egg_dbus_array_seq_get_size (a), ==, 8); g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 0), ==, 0); g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 1), ==, 1); g_assert_cmpint (egg_dbus_array_seq_get_fixed (a, 2), ==, 2); @@ -3939,8 +3941,8 @@ test_egg_dbus_array_seq (void) /* -------------------------------------------------------------------------------- */ /* 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)); + a = egg_dbus_array_seq_new (G_TYPE_FILE, g_object_unref, NULL, NULL); + g_assert (egg_dbus_array_seq_get_equal_func (a) == NULL); 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")); @@ -3959,9 +3961,18 @@ test_egg_dbus_array_seq (void) } 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); + g_object_unref (a); + /* now check again with an equal func */ + a = egg_dbus_array_seq_new (G_TYPE_FILE, g_object_unref, NULL, (GEqualFunc) g_file_equal); + g_assert (egg_dbus_array_seq_get_equal_func (a) != NULL); + 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")); 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); @@ -3975,8 +3986,25 @@ test_egg_dbus_array_seq (void) 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); + + /* -------------------------------------------------------------------------------- */ + + /* check we can handle raw pointer types */ + a = egg_dbus_array_seq_new (G_TYPE_POINTER, NULL, NULL, NULL); + g_assert (egg_dbus_array_seq_get_equal_func (a) == NULL); + 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")); + g_object_unref (a->data.v_ptr[0]); + g_object_unref (a->data.v_ptr[1]); + /* check that attempting to copy items will cause a runtime error */ + if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR)) + { + gpointer ptr; + ptr = egg_dbus_array_seq_get_copy (a, 0); + } + g_test_trap_assert_failed (); + g_test_trap_assert_stderr ("*no copy_func set for EggDBusArraySeq<gpointer>*"); g_object_unref (a); } |