objects: add bt_object_freeze() and more statuses
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Thu, 19 Mar 2015 02:12:19 +0000 (22:12 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 19 Mar 2015 18:18:10 +0000 (14:18 -0400)
This patch adds the possibility to freeze an object.
By doing this, it introduces a new status code,
BT_OBJECT_STATUS_FROZEN, which is returned when trying
to alter a frozen object. Thus, all functions returning
either 0 or -1 are modified to return an
enum bt_object_status value instead.

The status code BT_OBJECT_STATUS_INVAL is also introduced
to signal invalid arguments, to differentiate this error
from other errors.

Finally, this patch adapts the objects tests and the
documentation to the changes.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
include/babeltrace/objects.h
lib/objects.c
tests/lib/test_bt_objects.c

index 48e4cfd504c0fdb689530e1b6b7d48b4c0ab7642..77be607c054b3abfe07c4b86da11ad97fe0533e0 100644 (file)
@@ -81,6 +81,8 @@
  * error:
  *     // safe, even if int_obj is NULL
  *     BT_OBJECT_PUT(int_obj);
+ *
+ *     // ...
  * \endcode
  *
  * Another common manipulation is to move the ownership of an object
  *     // points to the object
  *     BT_OBJECT_PUT(int_obj);
  *     BT_OBJECT_PUT(int_obj2);
+ *
+ *     // ...
  * \endcode
  *
+ * Most functions return a status code, one of the values in
+ * #bt_object_status.
+ *
  * You can create a deep copy of any object using the bt_object_copy()
  * function. You can compare two given objects using
  * bt_object_compare().
  *
+ * Any object may be frozen using bt_object_freeze(). You may get the
+ * value of a frozen object, but you cannot modify it. Reference
+ * counting still works on frozen objects. You may also copy and compare
+ * frozen objects.
+ *
  * @author     Philippe Proulx <pproulx@efficios.com>
  * @bug                No known bugs
  */
@@ -162,13 +174,20 @@ enum bt_object_type {
 };
 
 /**
- * Status (return value of some functions).
+ * Status code.
  */
 enum bt_object_status {
+       /** Object cannot be altered because it's frozen. */
+       BT_OBJECT_STATUS_FROZEN =       -4,
+
        /** Operation cancelled. */
-       BT_OBJECT_STATUS_CANCELLED =    -2,
+       BT_OBJECT_STATUS_CANCELLED =    -3,
+
+       /** Invalid arguments. */
+       /* -22 for compatibility with -EINVAL */
+       BT_OBJECT_STATUS_INVAL =        -22,
 
-       /** Error. */
+       /** General error. */
        BT_OBJECT_STATUS_ERROR =        -1,
 
        /** Okay, no error. */
@@ -183,15 +202,14 @@ struct bt_object;
 /**
  * The null object singleton.
  *
- * Use this everytime you need a null objet. The null objet singleton
- * has no reference count; there's only one. You may compare any object
- * to the null singleton to find out if it's a null object, or otherwise
- * use bt_object_is_null().
+ * Use this everytime you need a null object. The null object singleton
+ * has no reference count; there's only one. You may directly compare
+ * any object to the null singleton to find out if it's a null object,
+ * or otherwise use bt_object_is_null().
  *
  * Functions of this API return this when the object is actually a
- * null object (of type \link bt_object_type::BT_OBJECT_TYPE_NULL
- * <code>BT_OBJECT_TYPE_NULL</code>\endlink), whereas \c NULL means an error
- * of some sort.
+ * null object (of type #BT_OBJECT_TYPE_NULL), whereas \c NULL means an
+ * error of some sort.
  */
 extern struct bt_object *bt_object_null;
 
@@ -266,16 +284,37 @@ extern void bt_object_get(struct bt_object *object);
  */
 extern void bt_object_put(struct bt_object *object);
 
+/**
+ * Recursively freezes the object \p object.
+ *
+ * A frozen object cannot be modified; it is considered immutable.
+ * Reference counting still works on a frozen object though: you may
+ * pass a frozen object to bt_object_get() and bt_object_put().
+ *
+ * @param object       Object to freeze
+ * @returns            One of #bt_object_status values; if \p object
+ *                     is already frozen, though, #BT_OBJECT_STATUS_OK
+ *                     is returned anyway (i.e. this function never
+ *                     returns #BT_OBJECT_STATUS_FROZEN)
+ */
+extern enum bt_object_status bt_object_freeze(struct bt_object *object);
+
+/**
+ * Checks whether \p object is frozen or not.
+ *
+ * @param object       Object to check
+ * @returns            \c true if \p object is frozen
+ */
+extern bool bt_object_is_frozen(const struct bt_object *object);
+
 /**
  * Returns the type of \p object.
  *
  * @param object       Object of which to get the type
- * @returns            Object's type, or
- *                     \link bt_object_type::BT_OBJECT_TYPE_NULL
- *                     <code>BT_OBJECT_TYPE_UNKNOWN</code>\endlink
+ * @returns            Object's type, or #BT_OBJECT_TYPE_UNKNOWN
  *                     on error
  *
- * @see enum bt_object_type (object types)
+ * @see #bt_object_type (object types)
  */
 extern enum bt_object_type bt_object_get_type(const struct bt_object *object);
 
@@ -465,32 +504,34 @@ extern struct bt_object *bt_object_array_create(void);
 extern struct bt_object *bt_object_map_create(void);
 
 /**
- * Gets the boolean value of the boolean objet \p bool_obj.
+ * Gets the boolean value of the boolean object \p bool_obj.
  *
  * @param bool_obj     Boolean object
  * @param val          Returned boolean value
- * @returns            0 on success, negative value on error
+ * @returns            One of #bt_object_status values
  */
-extern int bt_object_bool_get(const struct bt_object *bool_obj, bool *val);
+extern enum bt_object_status bt_object_bool_get(
+       const struct bt_object *bool_obj, bool *val);
 
 /**
  * Sets the boolean value of the boolean object \p bool_obj to \p val.
  *
  * @param bool_obj     Boolean object
  * @param val          New boolean value
- * @returns            0 on success, negative value on error
+ * @returns            One of #bt_object_status values
  */
-extern int bt_object_bool_set(struct bt_object *bool_obj, bool val);
+extern enum bt_object_status bt_object_bool_set(struct bt_object *bool_obj,
+       bool val);
 
 /**
- * Gets the integer value of the integer objet \p integer_obj.
+ * Gets the integer value of the integer object \p integer_obj.
  *
  * @param integer_obj  Integer object
  * @param val          Returned integer value
- * @returns            0 on success, negative value on error
+ * @returns            One of #bt_object_status values
  */
-extern int bt_object_integer_get(const struct bt_object *integer_obj,
-       int64_t *val);
+extern enum bt_object_status bt_object_integer_get(
+       const struct bt_object *integer_obj, int64_t *val);
 
 /**
  * Sets the integer value of the integer object \p integer_obj to
@@ -498,19 +539,21 @@ extern int bt_object_integer_get(const struct bt_object *integer_obj,
  *
  * @param integer_obj  Integer object
  * @param val          New integer value
- * @returns            0 on success, negative value on error
+ * @returns            One of #bt_object_status values
  */
-extern int bt_object_integer_set(struct bt_object *integer_obj, int64_t val);
+extern enum bt_object_status bt_object_integer_set(
+       struct bt_object *integer_obj, int64_t val);
 
 /**
  * Gets the floating point number value of the floating point number
- * objet \p float_obj.
+ * object \p float_obj.
  *
  * @param float_obj    Floating point number object
  * @param val          Returned floating point number value
- * @returns            0 on success, negative value on error
+ * @returns            One of #bt_object_status values
  */
-extern int bt_object_float_get(const struct bt_object *float_obj, double *val);
+extern enum bt_object_status bt_object_float_get(
+       const struct bt_object *float_obj, double *val);
 
 /**
  * Sets the floating point number value of the floating point number
@@ -518,19 +561,23 @@ extern int bt_object_float_get(const struct bt_object *float_obj, double *val);
  *
  * @param float_obj    Floating point number object
  * @param val          New floating point number value
- * @returns            0 on success, negative value on error
+ * @returns            One of #bt_object_status values
  */
-extern int bt_object_float_set(struct bt_object *float_obj, double val);
+extern enum bt_object_status bt_object_float_set(
+       struct bt_object *float_obj, double val);
 
 /**
- * Gets the string value of the string objet \p string_obj. The
+ * Gets the string value of the string object \p string_obj. The
  * returned string is valid as long as this object exists and is not
- * modified.
+ * modified. The ownership of the returned string is \em not
+ * transferred to the caller.
  *
  * @param string_obj   String object
- * @returns            String value, or \c NULL on error
+ * @param val          Returned string value
+ * @returns            One of #bt_object_status values
  */
-extern const char *bt_object_string_get(const struct bt_object *string_obj);
+extern enum bt_object_status bt_object_string_get(
+       const struct bt_object *string_obj, const char **val);
 
 /**
  * Sets the string value of the string object \p string_obj to
@@ -540,16 +587,19 @@ extern const char *bt_object_string_get(const struct bt_object *string_obj);
  *
  * @param string_obj   String object
  * @param val          New string value (copied)
- * @returns            0 on success, negative value on error
+ * @returns            One of #bt_object_status values
  */
-extern int bt_object_string_set(struct bt_object *string_obj, const char *val);
+extern enum bt_object_status bt_object_string_set(struct bt_object *string_obj,
+       const char *val);
 
 /**
  * Gets the size of the array object \p array_obj, that is, the number
  * of elements contained in \p array_obj.
  *
  * @param array_obj    Array object
- * @returns            Array size, or a negative value on error
+ * @returns            Array size if the return value is 0 (empty) or a
+ *                     positive value, or one of
+ *                     #bt_object_status negative values otherwise
  */
 extern int bt_object_array_size(const struct bt_object *array_obj);
 
@@ -585,9 +635,9 @@ extern struct bt_object *bt_object_array_get(const struct bt_object *array_obj,
  *
  * @param array_obj    Array object
  * @param element_obj  Element object to append
- * @returns            0 on success, or a negative value on error
+ * @returns            One of #bt_object_status values
  */
-extern int bt_object_array_append(struct bt_object *array_obj,
+extern enum bt_object_status bt_object_array_append(struct bt_object *array_obj,
        struct bt_object *element_obj);
 
 /**
@@ -599,9 +649,10 @@ extern int bt_object_array_append(struct bt_object *array_obj,
  *
  * @param array_obj    Array object
  * @param val          Boolean value to append
- * @returns            0 on success, or a negative value on error
+ * @returns            One of #bt_object_status values
  */
-extern int bt_object_array_append_bool(struct bt_object *array_obj, bool val);
+extern enum bt_object_status bt_object_array_append_bool(
+       struct bt_object *array_obj, bool val);
 
 /**
  * Appends the integer value \p val to the array object \p array_obj.
@@ -612,10 +663,10 @@ extern int bt_object_array_append_bool(struct bt_object *array_obj, bool val);
  *
  * @param array_obj    Array object
  * @param val          Integer value to append
- * @returns            0 on success, or a negative value on error
+ * @returns            One of #bt_object_status values
  */
-extern int bt_object_array_append_integer(struct bt_object *array_obj,
-       int64_t val);
+extern enum bt_object_status bt_object_array_append_integer(
+       struct bt_object *array_obj, int64_t val);
 
 /**
  * Appends the floating point number value \p val to the array object
@@ -627,10 +678,10 @@ extern int bt_object_array_append_integer(struct bt_object *array_obj,
  *
  * @param array_obj    Array object
  * @param val          Floating point number value to append
- * @returns            0 on success, or a negative value on error
+ * @returns            One of #bt_object_status values
  */
-extern int bt_object_array_append_float(struct bt_object *array_obj,
-       double val);
+extern enum bt_object_status bt_object_array_append_float(
+       struct bt_object *array_obj, double val);
 
 /**
  * Appends the string value \p val to the array object \p array_obj.
@@ -643,10 +694,10 @@ extern int bt_object_array_append_float(struct bt_object *array_obj,
  *
  * @param array_obj    Array object
  * @param val          String value to append (copied)
- * @returns            0 on success, or a negative value on error
+ * @returns            One of #bt_object_status values
  */
-extern int bt_object_array_append_string(struct bt_object *array_obj,
-       const char *val);
+extern enum bt_object_status bt_object_array_append_string(
+       struct bt_object *array_obj, const char *val);
 
 /**
  * Appends an empty array object to the array object \p array_obj.
@@ -656,9 +707,10 @@ extern int bt_object_array_append_string(struct bt_object *array_obj,
  * The created array object's reference count is set to 1.
  *
  * @param array_obj    Array object
- * @returns            0 on success, or a negative value on error
+ * @returns            One of #bt_object_status values
  */
-extern int bt_object_array_append_array(struct bt_object *array_obj);
+extern enum bt_object_status bt_object_array_append_array(
+       struct bt_object *array_obj);
 
 /**
  * Appends an empty map object to the array object \p array_obj. This
@@ -668,9 +720,10 @@ extern int bt_object_array_append_array(struct bt_object *array_obj);
  * The created map object's reference count is set to 1.
  *
  * @param array_obj    Array object
- * @returns            0 on success, or a negative value on error
+ * @returns            One of #bt_object_status values
  */
-extern int bt_object_array_append_map(struct bt_object *array_obj);
+extern enum bt_object_status bt_object_array_append_map(
+       struct bt_object *array_obj);
 
 /**
  * Replaces the element object at index \p index of the array object
@@ -684,17 +737,19 @@ extern int bt_object_array_append_map(struct bt_object *array_obj);
  * @param index                Index of element object to replace
  * @param element_obj  New element object at position \p index of
  *                     \p array_obj
- * @returns            0 on success, or a negative value on error
+ * @returns            One of #bt_object_status values
  */
-extern int bt_object_array_set(struct bt_object *array_obj, size_t index,
-       struct bt_object *element_obj);
+extern enum bt_object_status bt_object_array_set(struct bt_object *array_obj,
+       size_t index, struct bt_object *element_obj);
 
 /**
  * Gets the size of a map object, that is, the number of elements
  * contained in a map object.
  *
  * @param map_obj      Map object
- * @returns            Map size, or a negative value on error
+ * @returns            Map size if the return value is 0 (empty) or a
+ *                     positive value, or one of
+ *                     #bt_object_status negative values otherwise
  */
 extern int bt_object_map_size(const struct bt_object *map_obj);
 
@@ -737,17 +792,10 @@ extern struct bt_object *bt_object_map_get(const struct bt_object *map_obj,
  * @param map_obj      Map object
  * @param cb           User function to call back
  * @param data         User data passed to the user function
- * @returns            \link bt_object_status::BT_OBJECT_STATUS_OK
- *                     <code>BT_OBJECT_STATUS_OK</code>\endlink if
- *                     there's no error and the traversal was not
- *                     cancelled by the user function,
- *                     \link bt_object_status::BT_OBJECT_STATUS_CANCELLED
- *                     <code>BT_OBJECT_STATUS_CANCELLED</code>\endlink
- *                     if the function was cancelled by the user
- *                     function, or
- *                     \link bt_object_status::BT_OBJECT_STATUS_ERROR
- *                     <code>BT_OBJECT_STATUS_ERROR</code>\endlink on
- *                     any other error
+ * @returns            One of #bt_object_status values; more
+ *                     specifically, #BT_OBJECT_STATUS_CANCELLED is
+ *                     returned if the loop was cancelled by the user
+ *                     function
  */
 extern enum bt_object_status bt_object_map_foreach(
        const struct bt_object *map_obj, bt_object_map_foreach_cb cb,
@@ -781,10 +829,11 @@ extern bool bt_object_map_has_key(const struct bt_object *map_obj,
  * @param key          Key (copied) of object to insert
  * @param element_obj  Element object to insert, associated with the
  *                     key \p key
- * @returns            0 on success, or a negative value on error
+ * @returns            One of #bt_object_status values
  */
-extern int bt_object_map_insert(struct bt_object *map_obj,
-       const char *key, struct bt_object *element_obj);
+extern enum bt_object_status bt_object_map_insert(
+       struct bt_object *map_obj, const char *key,
+       struct bt_object *element_obj);
 
 /**
  * Inserts the boolean value \p val associated with the key \p key into
@@ -799,10 +848,10 @@ extern int bt_object_map_insert(struct bt_object *map_obj,
  * @param key          Key (copied) of boolean value to insert
  * @param val          Boolean value to insert, associated with the
  *                     key \p key
- * @returns            0 on success, or a negative value on error
+ * @returns            One of #bt_object_status values
  */
-extern int bt_object_map_insert_bool(struct bt_object *map_obj,
-       const char *key, bool val);
+extern enum bt_object_status bt_object_map_insert_bool(
+       struct bt_object *map_obj, const char *key, bool val);
 
 /**
  * Inserts the integer value \p val associated with the key \p key into
@@ -817,10 +866,10 @@ extern int bt_object_map_insert_bool(struct bt_object *map_obj,
  * @param key          Key (copied) of integer value to insert
  * @param val          Integer value to insert, associated with the
  *                     key \p key
- * @returns            0 on success, or a negative value on error
+ * @returns            One of #bt_object_status values
  */
-extern int bt_object_map_insert_integer(struct bt_object *map_obj,
-       const char *key, int64_t val);
+extern enum bt_object_status bt_object_map_insert_integer(
+       struct bt_object *map_obj, const char *key, int64_t val);
 
 /**
  * Inserts the floating point number value \p val associated with the
@@ -838,10 +887,10 @@ extern int bt_object_map_insert_integer(struct bt_object *map_obj,
  *                     insert
  * @param val          Floating point number value to insert,
  *                     associated with the key \p key
- * @returns            0 on success, or a negative value on error
+ * @returns            One of #bt_object_status values
  */
-extern int bt_object_map_insert_float(struct bt_object *map_obj,
-       const char *key, double val);
+extern enum bt_object_status bt_object_map_insert_float(
+       struct bt_object *map_obj, const char *key, double val);
 
 /**
  * Inserts the string value \p val associated with the key \p key into
@@ -856,10 +905,10 @@ extern int bt_object_map_insert_float(struct bt_object *map_obj,
  * @param key          Key (copied) of string value to insert
  * @param val          String value to insert, associated with the
  *                     key \p key
- * @returns            0 on success, or a negative value on error
+ * @returns            One of #bt_object_status values
  */
-extern int bt_object_map_insert_string(struct bt_object *map_obj,
-       const char *key, const char *val);
+extern enum bt_object_status bt_object_map_insert_string(
+       struct bt_object *map_obj, const char *key, const char *val);
 
 /**
  * Inserts an empty array object associated with the key \p key into
@@ -872,10 +921,10 @@ extern int bt_object_map_insert_string(struct bt_object *map_obj,
  *
  * @param map_obj      Map object
  * @param key          Key (copied) of empty array to insert
- * @returns            0 on success, or a negative value on error
+ * @returns            One of #bt_object_status values
  */
-extern int bt_object_map_insert_array(struct bt_object *map_obj,
-       const char *key);
+extern enum bt_object_status bt_object_map_insert_array(
+       struct bt_object *map_obj, const char *key);
 
 /**
  * Inserts an empty map object associated with the key \p key into
@@ -888,10 +937,10 @@ extern int bt_object_map_insert_array(struct bt_object *map_obj,
  *
  * @param map_obj      Map object
  * @param key          Key (copied) of empty map to insert
- * @returns            0 on success, or a negative value on error
+ * @returns            One of #bt_object_status values
  */
-extern int bt_object_map_insert_map(struct bt_object *map_obj,
-       const char *key);
+extern enum bt_object_status bt_object_map_insert_map(
+       struct bt_object *map_obj, const char *key);
 
 /**
  * Creates a deep copy of the object \p object.
index f59d84dc139069b0126a76abd7de21e0c2f767a2..4f4670d18c3ea65d42b5a7585e5bf0fd27eba0d3 100644 (file)
 struct bt_object {
        enum bt_object_type type;
        struct bt_ctf_ref ref_count;
+       bool is_frozen;
 };
 
 static
 struct bt_object bt_object_null_instance = {
        .type = BT_OBJECT_TYPE_NULL,
+       .is_frozen = true,
 };
 
 struct bt_object *bt_object_null = &bt_object_null_instance;
@@ -381,6 +383,57 @@ bool (* const compare_funcs[])(const struct bt_object *,
        [BT_OBJECT_TYPE_MAP] =          bt_object_map_compare,
 };
 
+void bt_object_null_freeze(struct bt_object *object)
+{
+}
+
+void bt_object_generic_freeze(struct bt_object *object)
+{
+       object->is_frozen = true;
+}
+
+void bt_object_array_freeze(struct bt_object *object)
+{
+       int x;
+       struct bt_object_array *typed_array_obj =
+               BT_OBJECT_TO_ARRAY(object);
+
+       for (x = 0; x < typed_array_obj->garray->len; ++x) {
+               struct bt_object *element_obj =
+                       g_ptr_array_index(typed_array_obj->garray, x);
+
+               bt_object_freeze(element_obj);
+       }
+
+       bt_object_generic_freeze(object);
+}
+
+void bt_object_map_freeze(struct bt_object *object)
+{
+       GHashTableIter iter;
+       gpointer key, element_obj;
+       const struct bt_object_map *map_obj = BT_OBJECT_TO_MAP(object);
+
+       g_hash_table_iter_init(&iter, map_obj->ght);
+
+       while (g_hash_table_iter_next(&iter, &key, &element_obj)) {
+               bt_object_freeze(element_obj);
+       }
+
+       bt_object_generic_freeze(object);
+}
+
+static
+void (* const freeze_funcs[])(struct bt_object *) = {
+       [BT_OBJECT_TYPE_NULL] =         bt_object_null_freeze,
+       [BT_OBJECT_TYPE_BOOL] =         bt_object_generic_freeze,
+       [BT_OBJECT_TYPE_INTEGER] =      bt_object_generic_freeze,
+       [BT_OBJECT_TYPE_FLOAT] =        bt_object_generic_freeze,
+       [BT_OBJECT_TYPE_STRING] =       bt_object_generic_freeze,
+       [BT_OBJECT_TYPE_ARRAY] =        bt_object_array_freeze,
+       [BT_OBJECT_TYPE_MAP] =          bt_object_map_freeze,
+};
+
 static
 void bt_object_destroy(struct bt_ctf_ref *ref_count)
 {
@@ -424,6 +477,26 @@ skip:
        return;
 }
 
+enum bt_object_status bt_object_freeze(struct bt_object *object)
+{
+       enum bt_object_status ret = BT_OBJECT_STATUS_OK;
+
+       if (!object) {
+               ret = BT_OBJECT_STATUS_INVAL;
+               goto end;
+       }
+
+       freeze_funcs[object->type](object);
+
+end:
+       return ret;
+}
+
+bool bt_object_is_frozen(const struct bt_object *object)
+{
+       return object && object->is_frozen;
+}
+
 enum bt_object_type bt_object_get_type(const struct bt_object *object)
 {
        if (!object) {
@@ -439,6 +512,7 @@ struct bt_object bt_object_create_base(enum bt_object_type type)
        struct bt_object base;
 
        base.type = type;
+       base.is_frozen = false;
        bt_ctf_ref_init(&base.ref_count);
 
        return base;
@@ -590,13 +664,14 @@ end:
        return BT_OBJECT_FROM_CONCRETE(map_obj);
 }
 
-int bt_object_bool_get(const struct bt_object *bool_obj, bool *val)
+enum bt_object_status bt_object_bool_get(const struct bt_object *bool_obj,
+       bool *val)
 {
-       int ret = 0;
+       enum bt_object_status ret = BT_OBJECT_STATUS_OK;
        struct bt_object_bool *typed_bool_obj = BT_OBJECT_TO_BOOL(bool_obj);
 
-       if (!bool_obj || !bt_object_is_bool(bool_obj)) {
-               ret = -1;
+       if (!bool_obj || !bt_object_is_bool(bool_obj) || !val) {
+               ret = BT_OBJECT_STATUS_INVAL;
                goto end;
        }
 
@@ -606,13 +681,18 @@ end:
        return ret;
 }
 
-int bt_object_bool_set(struct bt_object *bool_obj, bool val)
+enum bt_object_status bt_object_bool_set(struct bt_object *bool_obj, bool val)
 {
-       int ret = 0;
+       enum bt_object_status ret = BT_OBJECT_STATUS_OK;
        struct bt_object_bool *typed_bool_obj = BT_OBJECT_TO_BOOL(bool_obj);
 
        if (!bool_obj || !bt_object_is_bool(bool_obj)) {
-               ret = -1;
+               ret = BT_OBJECT_STATUS_INVAL;
+               goto end;
+       }
+
+       if (bool_obj->is_frozen) {
+               ret = BT_OBJECT_STATUS_FROZEN;
                goto end;
        }
 
@@ -622,14 +702,15 @@ end:
        return ret;
 }
 
-int bt_object_integer_get(const struct bt_object *integer_obj, int64_t *val)
+enum bt_object_status bt_object_integer_get(const struct bt_object *integer_obj,
+       int64_t *val)
 {
-       int ret = 0;
+       enum bt_object_status ret = BT_OBJECT_STATUS_OK;
        struct bt_object_integer *typed_integer_obj =
                BT_OBJECT_TO_INTEGER(integer_obj);
 
-       if (!integer_obj || !bt_object_is_integer(integer_obj)) {
-               ret = -1;
+       if (!integer_obj || !bt_object_is_integer(integer_obj) || !val) {
+               ret = BT_OBJECT_STATUS_INVAL;
                goto end;
        }
 
@@ -639,14 +720,20 @@ end:
        return ret;
 }
 
-int bt_object_integer_set(struct bt_object *integer_obj, int64_t val)
+enum bt_object_status bt_object_integer_set(struct bt_object *integer_obj,
+       int64_t val)
 {
-       int ret = 0;
+       enum bt_object_status ret = BT_OBJECT_STATUS_OK;
        struct bt_object_integer *typed_integer_obj =
                BT_OBJECT_TO_INTEGER(integer_obj);
 
        if (!integer_obj || !bt_object_is_integer(integer_obj)) {
-               ret = -1;
+               ret = BT_OBJECT_STATUS_INVAL;
+               goto end;
+       }
+
+       if (integer_obj->is_frozen) {
+               ret = BT_OBJECT_STATUS_FROZEN;
                goto end;
        }
 
@@ -656,14 +743,15 @@ end:
        return ret;
 }
 
-int bt_object_float_get(const struct bt_object *float_obj, double *val)
+enum bt_object_status bt_object_float_get(const struct bt_object *float_obj,
+       double *val)
 {
-       int ret = 0;
+       enum bt_object_status ret = BT_OBJECT_STATUS_OK;
        struct bt_object_float *typed_float_obj =
                BT_OBJECT_TO_FLOAT(float_obj);
 
-       if (!float_obj || !bt_object_is_float(float_obj)) {
-               ret = -1;
+       if (!float_obj || !bt_object_is_float(float_obj) || !val) {
+               ret = BT_OBJECT_STATUS_INVAL;
                goto end;
        }
 
@@ -673,14 +761,20 @@ end:
        return ret;
 }
 
-int bt_object_float_set(struct bt_object *float_obj, double val)
+enum bt_object_status bt_object_float_set(struct bt_object *float_obj,
+       double val)
 {
-       int ret = 0;
+       enum bt_object_status ret = BT_OBJECT_STATUS_OK;
        struct bt_object_float *typed_float_obj =
                BT_OBJECT_TO_FLOAT(float_obj);
 
        if (!float_obj || !bt_object_is_float(float_obj)) {
-               ret = -1;
+               ret = BT_OBJECT_STATUS_INVAL;
+               goto end;
+       }
+
+       if (float_obj->is_frozen) {
+               ret = BT_OBJECT_STATUS_FROZEN;
                goto end;
        }
 
@@ -690,31 +784,38 @@ end:
        return ret;
 }
 
-const char *bt_object_string_get(const struct bt_object *string_obj)
+enum bt_object_status bt_object_string_get(const struct bt_object *string_obj,
+       const char **val)
 {
-       const char *ret;
+       enum bt_object_status ret = BT_OBJECT_STATUS_OK;
        struct bt_object_string *typed_string_obj =
                BT_OBJECT_TO_STRING(string_obj);
 
-       if (!string_obj || !bt_object_is_string(string_obj)) {
-               ret = NULL;
+       if (!string_obj || !bt_object_is_string(string_obj) || !val) {
+               ret = BT_OBJECT_STATUS_INVAL;
                goto end;
        }
 
-       ret = typed_string_obj->gstr->str;
+       *val = typed_string_obj->gstr->str;
 
 end:
        return ret;
 }
 
-int bt_object_string_set(struct bt_object *string_obj, const char *val)
+enum bt_object_status bt_object_string_set(struct bt_object *string_obj,
+       const char *val)
 {
-       int ret = 0;
+       enum bt_object_status ret = BT_OBJECT_STATUS_OK;
        struct bt_object_string *typed_string_obj =
                BT_OBJECT_TO_STRING(string_obj);
 
        if (!string_obj || !bt_object_is_string(string_obj) || !val) {
-               ret = -1;
+               ret = BT_OBJECT_STATUS_INVAL;
+               goto end;
+       }
+
+       if (string_obj->is_frozen) {
+               ret = BT_OBJECT_STATUS_FROZEN;
                goto end;
        }
 
@@ -726,12 +827,12 @@ end:
 
 int bt_object_array_size(const struct bt_object *array_obj)
 {
-       int ret = 0;
+       int ret;
        struct bt_object_array *typed_array_obj =
                BT_OBJECT_TO_ARRAY(array_obj);
 
        if (!array_obj || !bt_object_is_array(array_obj)) {
-               ret = -1;
+               ret = BT_OBJECT_STATUS_INVAL;
                goto end;
        }
 
@@ -766,15 +867,20 @@ end:
        return ret;
 }
 
-int bt_object_array_append(struct bt_object *array_obj,
+enum bt_object_status bt_object_array_append(struct bt_object *array_obj,
        struct bt_object *element_obj)
 {
-       int ret = 0;
+       enum bt_object_status ret = BT_OBJECT_STATUS_OK;
        struct bt_object_array *typed_array_obj =
                BT_OBJECT_TO_ARRAY(array_obj);
 
        if (!array_obj || !bt_object_is_array(array_obj) || !element_obj) {
-               ret = -1;
+               ret = BT_OBJECT_STATUS_INVAL;
+               goto end;
+       }
+
+       if (array_obj->is_frozen) {
+               ret = BT_OBJECT_STATUS_FROZEN;
                goto end;
        }
 
@@ -785,9 +891,10 @@ end:
        return ret;
 }
 
-int bt_object_array_append_bool(struct bt_object *array_obj, bool val)
+enum bt_object_status bt_object_array_append_bool(struct bt_object *array_obj,
+       bool val)
 {
-       int ret;
+       enum bt_object_status ret;
        struct bt_object *bool_obj = NULL;
 
        bool_obj = bt_object_bool_create_init(val);
@@ -797,9 +904,10 @@ int bt_object_array_append_bool(struct bt_object *array_obj, bool val)
        return ret;
 }
 
-int bt_object_array_append_integer(struct bt_object *array_obj, int64_t val)
+enum bt_object_status bt_object_array_append_integer(
+       struct bt_object *array_obj, int64_t val)
 {
-       int ret;
+       enum bt_object_status ret;
        struct bt_object *integer_obj = NULL;
 
        integer_obj = bt_object_integer_create_init(val);
@@ -809,9 +917,10 @@ int bt_object_array_append_integer(struct bt_object *array_obj, int64_t val)
        return ret;
 }
 
-int bt_object_array_append_float(struct bt_object *array_obj, double val)
+enum bt_object_status bt_object_array_append_float(struct bt_object *array_obj,
+       double val)
 {
-       int ret;
+       enum bt_object_status ret;
        struct bt_object *float_obj = NULL;
 
        float_obj = bt_object_float_create_init(val);
@@ -821,9 +930,10 @@ int bt_object_array_append_float(struct bt_object *array_obj, double val)
        return ret;
 }
 
-int bt_object_array_append_string(struct bt_object *array_obj, const char *val)
+enum bt_object_status bt_object_array_append_string(struct bt_object *array_obj,
+       const char *val)
 {
-       int ret;
+       enum bt_object_status ret;
        struct bt_object *string_obj = NULL;
 
        string_obj = bt_object_string_create_init(val);
@@ -833,9 +943,9 @@ int bt_object_array_append_string(struct bt_object *array_obj, const char *val)
        return ret;
 }
 
-int bt_object_array_append_array(struct bt_object *array_obj)
+enum bt_object_status bt_object_array_append_array(struct bt_object *array_obj)
 {
-       int ret;
+       enum bt_object_status ret;
        struct bt_object *empty_array_obj = NULL;
 
        empty_array_obj = bt_object_array_create();
@@ -845,9 +955,9 @@ int bt_object_array_append_array(struct bt_object *array_obj)
        return ret;
 }
 
-int bt_object_array_append_map(struct bt_object *array_obj)
+enum bt_object_status bt_object_array_append_map(struct bt_object *array_obj)
 {
-       int ret;
+       enum bt_object_status ret;
        struct bt_object *map_obj = NULL;
 
        map_obj = bt_object_map_create();
@@ -857,16 +967,21 @@ int bt_object_array_append_map(struct bt_object *array_obj)
        return ret;
 }
 
-int bt_object_array_set(struct bt_object *array_obj, size_t index,
-       struct bt_object *element_obj)
+enum bt_object_status bt_object_array_set(struct bt_object *array_obj,
+       size_t index, struct bt_object *element_obj)
 {
-       int ret = 0;
+       enum bt_object_status ret = BT_OBJECT_STATUS_OK;
        struct bt_object_array *typed_array_obj =
                BT_OBJECT_TO_ARRAY(array_obj);
 
        if (!array_obj || !bt_object_is_array(array_obj) || !element_obj ||
                        index >= typed_array_obj->garray->len) {
-               ret = -1;
+               ret = BT_OBJECT_STATUS_INVAL;
+               goto end;
+       }
+
+       if (array_obj->is_frozen) {
+               ret = BT_OBJECT_STATUS_FROZEN;
                goto end;
        }
 
@@ -884,7 +999,7 @@ int bt_object_map_size(const struct bt_object *map_obj)
        struct bt_object_map *typed_map_obj = BT_OBJECT_TO_MAP(map_obj);
 
        if (!map_obj || !bt_object_is_map(map_obj)) {
-               ret = -1;
+               ret = BT_OBJECT_STATUS_INVAL;
                goto end;
        }
 
@@ -941,15 +1056,20 @@ end:
        return ret;
 }
 
-int bt_object_map_insert(struct bt_object *map_obj, const char *key,
-       struct bt_object *element_obj)
+enum bt_object_status bt_object_map_insert(struct bt_object *map_obj,
+       const char *key, struct bt_object *element_obj)
 {
-       int ret = 0;
        GQuark quark;
+       enum bt_object_status ret = BT_OBJECT_STATUS_OK;
        struct bt_object_map *typed_map_obj = BT_OBJECT_TO_MAP(map_obj);
 
        if (!map_obj || !bt_object_is_map(map_obj) || !key || !element_obj) {
-               ret = -1;
+               ret = BT_OBJECT_STATUS_INVAL;
+               goto end;
+       }
+
+       if (map_obj->is_frozen) {
+               ret = BT_OBJECT_STATUS_FROZEN;
                goto end;
        }
 
@@ -962,10 +1082,10 @@ end:
        return ret;
 }
 
-int bt_object_map_insert_bool(struct bt_object *map_obj,
+enum bt_object_status bt_object_map_insert_bool(struct bt_object *map_obj,
        const char *key, bool val)
 {
-       int ret;
+       enum bt_object_status ret;
        struct bt_object *bool_obj = NULL;
 
        bool_obj = bt_object_bool_create_init(val);
@@ -975,10 +1095,10 @@ int bt_object_map_insert_bool(struct bt_object *map_obj,
        return ret;
 }
 
-int bt_object_map_insert_integer(struct bt_object *map_obj,
+enum bt_object_status bt_object_map_insert_integer(struct bt_object *map_obj,
        const char *key, int64_t val)
 {
-       int ret;
+       enum bt_object_status ret;
        struct bt_object *integer_obj = NULL;
 
        integer_obj = bt_object_integer_create_init(val);
@@ -988,10 +1108,10 @@ int bt_object_map_insert_integer(struct bt_object *map_obj,
        return ret;
 }
 
-int bt_object_map_insert_float(struct bt_object *map_obj,
+enum bt_object_status bt_object_map_insert_float(struct bt_object *map_obj,
        const char *key, double val)
 {
-       int ret;
+       enum bt_object_status ret;
        struct bt_object *float_obj = NULL;
 
        float_obj = bt_object_float_create_init(val);
@@ -1001,10 +1121,10 @@ int bt_object_map_insert_float(struct bt_object *map_obj,
        return ret;
 }
 
-int bt_object_map_insert_string(struct bt_object *map_obj,
+enum bt_object_status bt_object_map_insert_string(struct bt_object *map_obj,
        const char *key, const char *val)
 {
-       int ret;
+       enum bt_object_status ret;
        struct bt_object *string_obj = NULL;
 
        string_obj = bt_object_string_create_init(val);
@@ -1014,10 +1134,10 @@ int bt_object_map_insert_string(struct bt_object *map_obj,
        return ret;
 }
 
-int bt_object_map_insert_array(struct bt_object *map_obj,
+enum bt_object_status bt_object_map_insert_array(struct bt_object *map_obj,
        const char *key)
 {
-       int ret;
+       enum bt_object_status ret;
        struct bt_object *array_obj = NULL;
 
        array_obj = bt_object_array_create();
@@ -1027,10 +1147,10 @@ int bt_object_map_insert_array(struct bt_object *map_obj,
        return ret;
 }
 
-int bt_object_map_insert_map(struct bt_object *map_obj,
+enum bt_object_status bt_object_map_insert_map(struct bt_object *map_obj,
        const char *key)
 {
-       int ret;
+       enum bt_object_status ret;
        struct bt_object *empty_map_obj = NULL;
 
        empty_map_obj = bt_object_map_create();
@@ -1040,7 +1160,7 @@ int bt_object_map_insert_map(struct bt_object *map_obj,
        return ret;
 }
 
-int bt_object_map_foreach(const struct bt_object *map_obj,
+enum bt_object_status bt_object_map_foreach(const struct bt_object *map_obj,
        bt_object_map_foreach_cb cb, void *data)
 {
        enum bt_object_status ret = BT_OBJECT_STATUS_OK;
@@ -1049,7 +1169,7 @@ int bt_object_map_foreach(const struct bt_object *map_obj,
        struct bt_object_map *typed_map_obj = BT_OBJECT_TO_MAP(map_obj);
 
        if (!map_obj || !bt_object_is_map(map_obj) || !cb) {
-               ret = BT_OBJECT_STATUS_ERROR;
+               ret = BT_OBJECT_STATUS_INVAL;
                goto end;
        }
 
index 07774e45652bc5d0b1446fbff1b0c0a0a5d26035..389938b74d82da9d1d4cb0eeb52fd191930d5435 100644 (file)
@@ -62,10 +62,16 @@ void test_bool(void)
        ok(!ret && !value, "default boolean object value is false");
 
        ret = bt_object_bool_set(NULL, true);
-       ok(ret, "bt_object_bool_set() fails with an object set to NULL");
+       ok(ret == BT_OBJECT_STATUS_INVAL,
+               "bt_object_bool_set() fails with an object set to NULL");
        ret = bt_object_bool_get(NULL, &value);
-       ok(ret, "bt_object_bool_get() fails with an object set to NULL");
+       ok(ret == BT_OBJECT_STATUS_INVAL,
+               "bt_object_bool_get() fails with an object set to NULL");
+       ret = bt_object_bool_get(obj, NULL);
+       ok(ret == BT_OBJECT_STATUS_INVAL,
+               "bt_object_bool_get() fails with a return value set to NULL");
 
+       assert(!bt_object_bool_set(obj, false));
        ret = bt_object_bool_set(obj, true);
        ok(!ret, "bt_object_bool_set() succeeds");
        ret = bt_object_bool_get(obj, &value);
@@ -74,6 +80,7 @@ void test_bool(void)
        BT_OBJECT_PUT(obj);
        pass("putting an existing boolean object does not cause a crash")
 
+       value = false;
        obj = bt_object_bool_create_init(true);
        ok(obj && bt_object_is_bool(obj),
                "bt_object_bool_create_init() returns a boolean object");
@@ -81,6 +88,14 @@ void test_bool(void)
        ok(!ret && value,
                "bt_object_bool_create_init() sets the appropriate initial value");
 
+       assert(!bt_object_freeze(obj));
+       ok(bt_object_bool_set(obj, false) == BT_OBJECT_STATUS_FROZEN,
+               "bt_object_bool_set() cannot be called on a frozen boolean object");
+       value = false;
+       ret = bt_object_bool_get(obj, &value);
+       ok(!ret && value,
+               "bt_object_bool_set() does not alter a frozen floating point number object");
+
        BT_OBJECT_PUT(obj);
 }
 
@@ -96,18 +111,23 @@ void test_integer(void)
                "bt_object_integer_create() returns an integer object");
 
        ret = bt_object_integer_set(NULL, -12345);
-       ok(ret, "bt_object_integer_set() fails with an object set to NULL");
+       ok(ret == BT_OBJECT_STATUS_INVAL,
+               "bt_object_integer_set() fails with an object set to NULL");
        ret = bt_object_integer_get(NULL, &value);
-       ok(ret, "bt_object_integer_get() fails with an object set to NULL");
+       ok(ret == BT_OBJECT_STATUS_INVAL,
+               "bt_object_integer_get() fails with an object set to NULL");
+       ret = bt_object_integer_get(obj, NULL);
+       ok(ret == BT_OBJECT_STATUS_INVAL,
+               "bt_object_integer_get() fails with a return value set to NULL");
 
        value = 1961;
        ret = bt_object_integer_get(obj, &value);
        ok(!ret && value == 0, "default integer object value is 0");
 
-       ret = bt_object_integer_set(obj, -12345);
+       ret = bt_object_integer_set(obj, -98765);
        ok(!ret, "bt_object_integer_set() succeeds");
        ret = bt_object_integer_get(obj, &value);
-       ok(!ret && value == -12345, "bt_object_integer_set() works");
+       ok(!ret && value == -98765, "bt_object_integer_set() works");
 
        BT_OBJECT_PUT(obj);
        pass("putting an existing integer object does not cause a crash")
@@ -119,6 +139,14 @@ void test_integer(void)
        ok(!ret && value == 321456987,
                "bt_object_integer_create_init() sets the appropriate initial value");
 
+       assert(!bt_object_freeze(obj));
+       ok(bt_object_integer_set(obj, 18276) == BT_OBJECT_STATUS_FROZEN,
+               "bt_object_integer_set() cannot be called on a frozen integer object");
+       value = 17;
+       ret = bt_object_integer_get(obj, &value);
+       ok(!ret && value == 321456987,
+               "bt_object_integer_set() does not alter a frozen integer object");
+
        BT_OBJECT_PUT(obj);
 }
 
@@ -134,13 +162,19 @@ void test_float(void)
                "bt_object_float_create() returns a floating point number object");
 
        ret = bt_object_float_set(NULL, 1.2345);
-       ok(ret, "bt_object_float_set() fails with an object set to NULL");
+       ok(ret == BT_OBJECT_STATUS_INVAL,
+               "bt_object_float_set() fails with an object set to NULL");
        ret = bt_object_float_get(NULL, &value);
-       ok(ret, "bt_object_float_get() fails with an object set to NULL");
+       ok(ret == BT_OBJECT_STATUS_INVAL,
+               "bt_object_float_get() fails with an object set to NULL");
+       ret = bt_object_float_get(obj, NULL);
+       ok(ret == BT_OBJECT_STATUS_INVAL,
+               "bt_object_float_get() fails with a return value set to NULL");
 
        value = 17.34;
        ret = bt_object_float_get(obj, &value);
-       ok(!ret && value == 0., "default floating point number object value is 0");
+       ok(!ret && value == 0.,
+               "default floating point number object value is 0");
 
        ret = bt_object_float_set(obj, -3.1416);
        ok(!ret, "bt_object_float_set() succeeds");
@@ -157,6 +191,14 @@ void test_float(void)
        ok(!ret && value == 33.1649758,
                "bt_object_float_create_init() sets the appropriate initial value");
 
+       assert(!bt_object_freeze(obj));
+       ok(bt_object_float_set(obj, 17.88) == BT_OBJECT_STATUS_FROZEN,
+               "bt_object_float_set() fails with a frozen floating point number object");
+       value = 1.2;
+       ret = bt_object_float_get(obj, &value);
+       ok(!ret && value == 33.1649758,
+               "bt_object_float_set() does not alter a frozen floating point number object");
+
        BT_OBJECT_PUT(obj);
 }
 
@@ -172,21 +214,27 @@ void test_string(void)
                "bt_object_string_create() returns a string object");
 
        ret = bt_object_string_set(NULL, "hoho");
-       ok(ret, "bt_object_string_set() fails with an object set to NULL");
-       value = bt_object_string_get(NULL);
-       ok(!value, "bt_object_string_get() fails with an object set to NULL");
-
-       value = bt_object_string_get(obj);
-       ok(value && !strcmp(value, ""),
+       ok(ret == BT_OBJECT_STATUS_INVAL,
+               "bt_object_string_set() fails with an object set to NULL");
+       ret = bt_object_string_set(obj, NULL);
+       ok(ret == BT_OBJECT_STATUS_INVAL,
+               "bt_object_string_set() fails with a value set to NULL");
+       ret = bt_object_string_get(NULL, &value);
+       ok(ret == BT_OBJECT_STATUS_INVAL,
+               "bt_object_string_get() fails with an object set to NULL");
+       ret = bt_object_string_get(obj, NULL);
+       ok(ret == BT_OBJECT_STATUS_INVAL,
+               "bt_object_string_get() fails with a return value set to NULL");
+
+       ret = bt_object_string_get(obj, &value);
+       ok(!ret && value && !strcmp(value, ""),
                "default string object value is \"\"");
 
        ret = bt_object_string_set(obj, "hello worldz");
        ok(!ret, "bt_object_string_set() succeeds");
-       value = bt_object_string_get(obj);
-       ok(value && !strcmp(value, "hello worldz"),
-               "bt_object_string_set() works");
-       ret = bt_object_string_set(obj, NULL);
-       ok(ret, "bt_object_string_set() does not accept a NULL value");
+       ret = bt_object_string_get(obj, &value);
+       ok(!ret && value && !strcmp(value, "hello worldz"),
+               "bt_object_string_get() works");
 
        BT_OBJECT_PUT(obj);
        pass("putting an existing string object does not cause a crash")
@@ -196,10 +244,18 @@ void test_string(void)
        obj = bt_object_string_create_init("initial value");
        ok(obj && bt_object_is_string(obj),
                "bt_object_string_create_init() returns a string object");
-       value = bt_object_string_get(obj);
-       ok(value && !strcmp(value, "initial value"),
+       ret = bt_object_string_get(obj, &value);
+       ok(!ret && value && !strcmp(value, "initial value"),
                "bt_object_string_create_init() sets the appropriate initial value");
 
+       assert(!bt_object_freeze(obj));
+       ok(bt_object_string_set(obj, "new value") == BT_OBJECT_STATUS_FROZEN,
+               "bt_object_string_set() fails with a frozen string object");
+       value = "";
+       ret = bt_object_string_get(obj, &value);
+       ok(!ret && value && !strcmp(value, "initial value"),
+               "bt_object_string_set() does not alter a frozen string object");
+
        BT_OBJECT_PUT(obj);
 }
 
@@ -217,13 +273,18 @@ void test_array(void)
        array_obj = bt_object_array_create();
        ok(array_obj && bt_object_is_array(array_obj),
                "bt_object_array_create() returns an array object");
+       ok(bt_object_array_is_empty(NULL) == false,
+               "bt_object_array_is_empty() returns false with an object set to NULL");
        ok(bt_object_array_is_empty(array_obj),
                "initial array object size is 0");
-       ok(bt_object_array_size(NULL) < 0,
+       ok(bt_object_array_size(NULL) == BT_OBJECT_STATUS_INVAL,
                "bt_object_array_size() fails with an array object set to NULL");
 
-       ok(bt_object_array_append(NULL, bt_object_null),
+       ok(bt_object_array_append(NULL, bt_object_null)
+               == BT_OBJECT_STATUS_INVAL,
                "bt_object_array_append() fails with an array object set to NULL");
+       ok(bt_object_array_append(array_obj, NULL) == BT_OBJECT_STATUS_INVAL,
+               "bt_object_array_append() fails with a value set to NULL");
 
        obj = bt_object_integer_create_init(345);
        ret = bt_object_array_append(array_obj, obj);
@@ -236,10 +297,6 @@ void test_array(void)
        BT_OBJECT_PUT(obj);
        ret |= bt_object_array_append(array_obj, bt_object_null);
        ok(!ret, "bt_object_array_append() succeeds");
-       ret = bt_object_array_append(NULL, bt_object_null);
-       ok(ret, "bt_object_array_append() fails with an array object set to NULL");
-       ret = bt_object_array_append(array_obj, NULL);
-       ok(ret, "bt_object_array_append() fails with an element object set to NULL");
        ok(bt_object_array_size(array_obj) == 4,
                "appending an element to an array object increment its size");
 
@@ -276,11 +333,13 @@ void test_array(void)
        ok(obj == bt_object_null,
                "bt_object_array_get() returns an object with the appropriate type (null)");
 
-       ok(bt_object_array_set(NULL, 0, bt_object_null),
+       ok(bt_object_array_set(NULL, 0, bt_object_null) ==
+               BT_OBJECT_STATUS_INVAL,
                "bt_object_array_set() fails with an array object set to NULL");
-       ok(bt_object_array_set(array_obj, 0, NULL),
+       ok(bt_object_array_set(array_obj, 0, NULL) == BT_OBJECT_STATUS_INVAL,
                "bt_object_array_set() fails with an element object set to NULL");
-       ok(bt_object_array_set(array_obj, 4, bt_object_null),
+       ok(bt_object_array_set(array_obj, 4, bt_object_null) ==
+               BT_OBJECT_STATUS_INVAL,
                "bt_object_array_set() fails with an invalid index");
        obj = bt_object_integer_create_init(1001);
        assert(obj);
@@ -298,28 +357,31 @@ void test_array(void)
 
        ret = bt_object_array_append_bool(array_obj, false);
        ok(!ret, "bt_object_array_append_bool() succeeds");
-       ret = bt_object_array_append_bool(NULL, true);
-       ok(ret, "bt_object_array_append_bool() fails with an array object set to NULL");
+       ok(bt_object_array_append_bool(NULL, true) == BT_OBJECT_STATUS_INVAL,
+               "bt_object_array_append_bool() fails with an array object set to NULL");
        ret = bt_object_array_append_integer(array_obj, 98765);
        ok(!ret, "bt_object_array_append_integer() succeeds");
-       ret = bt_object_array_append_integer(NULL, 18765);
-       ok(ret, "bt_object_array_append_integer() fails with an array object set to NULL");
+       ok(bt_object_array_append_integer(NULL, 18765) ==
+               BT_OBJECT_STATUS_INVAL,
+               "bt_object_array_append_integer() fails with an array object set to NULL");
        ret = bt_object_array_append_float(array_obj, 2.49578);
        ok(!ret, "bt_object_array_append_float() succeeds");
-       ret = bt_object_array_append_float(NULL, 1.49578);
-       ok(ret, "bt_object_array_append_float() fails with an array object set to NULL");
+       ok(bt_object_array_append_float(NULL, 1.49578) ==
+               BT_OBJECT_STATUS_INVAL,
+               "bt_object_array_append_float() fails with an array object set to NULL");
        ret = bt_object_array_append_string(array_obj, "bt_object");
        ok(!ret, "bt_object_array_append_string() succeeds");
-       ret = bt_object_array_append_string(NULL, "bt_obj");
-       ok(ret, "bt_object_array_append_string() fails with an array object set to NULL");
+       ok(bt_object_array_append_string(NULL, "bt_obj") ==
+               BT_OBJECT_STATUS_INVAL,
+               "bt_object_array_append_string() fails with an array object set to NULL");
        ret = bt_object_array_append_array(array_obj);
        ok(!ret, "bt_object_array_append_array() succeeds");
-       ret = bt_object_array_append_array(NULL);
-       ok(ret, "bt_object_array_append_array() fails with an array object set to NULL");
+       ok(bt_object_array_append_array(NULL) == BT_OBJECT_STATUS_INVAL,
+               "bt_object_array_append_array() fails with an array object set to NULL");
        ret = bt_object_array_append_map(array_obj);
        ok(!ret, "bt_object_array_append_map() succeeds");
-       ret = bt_object_array_append_map(NULL);
-       ok(ret, "bt_object_array_append_map() fails with an array object set to NULL");
+       ok(bt_object_array_append_map(NULL) == BT_OBJECT_STATUS_INVAL,
+               "bt_object_array_append_map() fails with an array object set to NULL");
 
        ok(bt_object_array_size(array_obj) == 10,
                "the bt_object_array_append_*() functions increment the array object's size");
@@ -350,8 +412,8 @@ void test_array(void)
        obj = bt_object_array_get(array_obj, 7);
        ok(obj && bt_object_is_string(obj),
                "bt_object_array_append_string() appends a string object");
-       string_value = bt_object_string_get(obj);
-       ok(string_value && !strcmp(string_value, "bt_object"),
+       ret = bt_object_string_get(obj, &string_value);
+       ok(!ret && string_value && !strcmp(string_value, "bt_object"),
                "bt_object_array_append_string() appends the appropriate value");
        BT_OBJECT_PUT(obj);
        obj = bt_object_array_get(array_obj, 8);
@@ -367,6 +429,39 @@ void test_array(void)
                "bt_object_array_append_map() an empty map object");
        BT_OBJECT_PUT(obj);
 
+       assert(!bt_object_freeze(array_obj));
+       ok(bt_object_array_append(array_obj, bt_object_null) ==
+               BT_OBJECT_STATUS_FROZEN,
+               "bt_object_array_append() fails with a frozen array object");
+       ok(bt_object_array_append_bool(array_obj, false) ==
+               BT_OBJECT_STATUS_FROZEN,
+               "bt_object_array_append_bool() fails with a frozen array object");
+       ok(bt_object_array_append_integer(array_obj, 23) ==
+               BT_OBJECT_STATUS_FROZEN,
+               "bt_object_array_append_integer() fails with a frozen array object");
+       ok(bt_object_array_append_float(array_obj, 2.34) ==
+               BT_OBJECT_STATUS_FROZEN,
+               "bt_object_array_append_float() fails with a frozen array object");
+       ok(bt_object_array_append_string(array_obj, "yayayayaya") ==
+               BT_OBJECT_STATUS_FROZEN,
+               "bt_object_array_append_string() fails with a frozen array object");
+       ok(bt_object_array_append_array(array_obj) ==
+               BT_OBJECT_STATUS_FROZEN,
+               "bt_object_array_append_array() fails with a frozen array object");
+       ok(bt_object_array_append_map(array_obj) ==
+               BT_OBJECT_STATUS_FROZEN,
+               "bt_object_array_append_map() fails with a frozen array object");
+       ok(bt_object_array_set(array_obj, 2, bt_object_null) ==
+               BT_OBJECT_STATUS_FROZEN,
+               "bt_object_array_set() fails with a frozen array object");
+       ok(bt_object_array_size(array_obj) == 10,
+               "appending to a frozen array object does not change its size");
+
+       assert(obj = bt_object_array_get(array_obj, 1));
+       ok(bt_object_float_set(obj, 14.52) == BT_OBJECT_STATUS_FROZEN,
+               "freezing an array object also freezes its elements");
+       BT_OBJECT_PUT(obj);
+
        BT_OBJECT_PUT(array_obj);
        pass("putting an existing array object does not cause a crash")
 }
@@ -418,6 +513,8 @@ bool test_map_foreach_cb_check(const char *key, struct bt_object *object,
                        if (val) {
                                pass("test_map_foreach_cb_check(): \"bool\" object has the right value");
                                checklist->bool1 = true;
+                       } else {
+                               fail("test_map_foreach_cb_check(): \"bool\" object has the wrong value");
                        }
                }
        } else if (!strcmp(key, "int")) {
@@ -432,6 +529,8 @@ bool test_map_foreach_cb_check(const char *key, struct bt_object *object,
                        if (val == 19457) {
                                pass("test_map_foreach_cb_check(): \"int\" object has the right value");
                                checklist->int1 = true;
+                       } else {
+                               fail("test_map_foreach_cb_check(): \"int\" object has the wrong value");
                        }
                }
        } else if (!strcmp(key, "float")) {
@@ -446,6 +545,8 @@ bool test_map_foreach_cb_check(const char *key, struct bt_object *object,
                        if (val == 5.444) {
                                pass("test_map_foreach_cb_check(): \"float\" object has the right value");
                                checklist->float1 = true;
+                       } else {
+                               fail("test_map_foreach_cb_check(): \"float\" object has the wrong value");
                        }
                }
        } else if (!strcmp(key, "null")) {
@@ -467,6 +568,8 @@ bool test_map_foreach_cb_check(const char *key, struct bt_object *object,
                        if (val) {
                                pass("test_map_foreach_cb_check(): \"bool2\" object has the right value");
                                checklist->bool2 = true;
+                       } else {
+                               fail("test_map_foreach_cb_check(): \"bool2\" object has the wrong value");
                        }
                }
        } else if (!strcmp(key, "int2")) {
@@ -481,6 +584,8 @@ bool test_map_foreach_cb_check(const char *key, struct bt_object *object,
                        if (val == 98765) {
                                pass("test_map_foreach_cb_check(): \"int2\" object has the right value");
                                checklist->int2 = true;
+                       } else {
+                               fail("test_map_foreach_cb_check(): \"int2\" object has the wrong value");
                        }
                }
        } else if (!strcmp(key, "float2")) {
@@ -495,19 +600,24 @@ bool test_map_foreach_cb_check(const char *key, struct bt_object *object,
                        if (val == -49.0001) {
                                pass("test_map_foreach_cb_check(): \"float2\" object has the right value");
                                checklist->float2 = true;
+                       } else {
+                               fail("test_map_foreach_cb_check(): \"float2\" object has the wrong value");
                        }
                }
        } else if (!strcmp(key, "string2")) {
                if (checklist->string2) {
                        fail("test_map_foreach_cb_check(): duplicate key \"string2\"");
                } else {
-                       const char *val = bt_object_string_get(object);
+                       const char *val;
 
-                       ok(val, "test_map_foreach_cb_check(): success getting \"string2\" value");
+                       ret = bt_object_string_get(object, &val);
+                       ok(!ret, "test_map_foreach_cb_check(): success getting \"string2\" value");
 
                        if (val && !strcmp(val, "bt_object")) {
                                pass("test_map_foreach_cb_check(): \"string2\" object has the right value");
                                checklist->string2 = true;
+                       } else {
+                               fail("test_map_foreach_cb_check(): \"string2\" object has the wrong value");
                        }
                }
        } else if (!strcmp(key, "array2")) {
@@ -529,9 +639,7 @@ bool test_map_foreach_cb_check(const char *key, struct bt_object *object,
                        checklist->map2 = true;
                }
        } else {
-               diag("test_map_foreach_cb_check(): unknown map key \"%s\"",
-                       key);
-               fail("test_map_foreach_cb_check(): unknown map key");
+               fail("test_map_foreach_cb_check(): unknown map key \"%s\"", key);
        }
 
        return true;
@@ -554,15 +662,17 @@ void test_map(void)
                "bt_object_map_create() returns a map object");
        ok(bt_object_map_size(map_obj) == 0,
                "initial map object size is 0");
-       ok(bt_object_map_size(NULL) < 0,
+       ok(bt_object_map_size(NULL) == BT_OBJECT_STATUS_INVAL,
                "bt_object_map_size() fails with a map object set to NULL");
 
-       ok(bt_object_map_insert(NULL, "hello", bt_object_null),
+       ok(bt_object_map_insert(NULL, "hello", bt_object_null) ==
+               BT_OBJECT_STATUS_INVAL,
                "bt_object_array_insert() fails with a map object set to NULL");
-
-       ok(bt_object_map_insert(map_obj, NULL, bt_object_null),
+       ok(bt_object_map_insert(map_obj, NULL, bt_object_null) ==
+               BT_OBJECT_STATUS_INVAL,
                "bt_object_array_insert() fails with a key set to NULL");
-       ok(bt_object_map_insert(map_obj, "yeah", NULL),
+       ok(bt_object_map_insert(map_obj, "yeah", NULL) ==
+               BT_OBJECT_STATUS_INVAL,
                "bt_object_array_insert() fails with an element object set to NULL");
 
        obj = bt_object_integer_create_init(19457);
@@ -618,28 +728,32 @@ void test_map(void)
 
        ret = bt_object_map_insert_bool(map_obj, "bool2", true);
        ok(!ret, "bt_object_map_insert_bool() succeeds");
-       ret = bt_object_map_insert_bool(NULL, "bool2", false);
-       ok(ret, "bt_object_map_insert_bool() fails with a map object set to NULL");
+       ok(bt_object_map_insert_bool(NULL, "bool2", false) ==
+               BT_OBJECT_STATUS_INVAL,
+               "bt_object_map_insert_bool() fails with a map object set to NULL");
        ret = bt_object_map_insert_integer(map_obj, "int2", 98765);
        ok(!ret, "bt_object_map_insert_integer() succeeds");
-       ret = bt_object_map_insert_integer(NULL, "int2", 1001);
-       ok(ret, "bt_object_map_insert_integer() fails with a map object set to NULL");
+       ok(bt_object_map_insert_integer(NULL, "int2", 1001) ==
+               BT_OBJECT_STATUS_INVAL,
+               "bt_object_map_insert_integer() fails with a map object set to NULL");
        ret = bt_object_map_insert_float(map_obj, "float2", -49.0001);
        ok(!ret, "bt_object_map_insert_float() succeeds");
-       ret = bt_object_map_insert_float(NULL, "float2", 495);
-       ok(ret, "bt_object_map_insert_float() fails with a map object set to NULL");
+       ok(bt_object_map_insert_float(NULL, "float2", 495) ==
+               BT_OBJECT_STATUS_INVAL,
+               "bt_object_map_insert_float() fails with a map object set to NULL");
        ret = bt_object_map_insert_string(map_obj, "string2", "bt_object");
        ok(!ret, "bt_object_map_insert_string() succeeds");
-       ret = bt_object_map_insert_string(NULL, "string2", "bt_obj");
-       ok(ret, "bt_object_map_insert_string() fails with a map object set to NULL");
+       ok(bt_object_map_insert_string(NULL, "string2", "bt_obj") ==
+               BT_OBJECT_STATUS_INVAL,
+               "bt_object_map_insert_string() fails with a map object set to NULL");
        ret = bt_object_map_insert_array(map_obj, "array2");
        ok(!ret, "bt_object_map_insert_array() succeeds");
-       ret = bt_object_map_insert_array(NULL, "array2");
-       ok(ret, "bt_object_map_insert_array() fails with a map object set to NULL");
+       ok(bt_object_map_insert_array(NULL, "array2") == BT_OBJECT_STATUS_INVAL,
+               "bt_object_map_insert_array() fails with a map object set to NULL");
        ret = bt_object_map_insert_map(map_obj, "map2");
        ok(!ret, "bt_object_map_insert_map() succeeds");
-       ret = bt_object_map_insert_map(NULL, "map2");
-       ok(ret, "bt_object_map_insert_map() fails with a map object set to NULL");
+       ok(bt_object_map_insert_map(NULL, "map2") == BT_OBJECT_STATUS_INVAL,
+               "bt_object_map_insert_map() fails with a map object set to NULL");
 
        ok(bt_object_map_size(map_obj) == 10,
                "the bt_object_map_insert*() functions increment the map object's size");
@@ -667,11 +781,11 @@ void test_map(void)
        ok(bt_object_map_has_key(map_obj, "map2"),
                "map object has key \"map2\"");
 
-       ret = bt_object_map_foreach(NULL, test_map_foreach_cb_count, &count);
-       ok(ret == BT_OBJECT_STATUS_ERROR,
+       ok(bt_object_map_foreach(NULL, test_map_foreach_cb_count, &count) ==
+               BT_OBJECT_STATUS_INVAL,
                "bt_object_map_foreach() fails with a map object set to NULL");
-       ret = bt_object_map_foreach(map_obj, NULL, &count);
-       ok(ret == BT_OBJECT_STATUS_ERROR,
+       ok(bt_object_map_foreach(map_obj, NULL, &count) ==
+               BT_OBJECT_STATUS_INVAL,
                "bt_object_map_foreach() fails with a user function set to NULL");
        ret = bt_object_map_foreach(map_obj, test_map_foreach_cb_count, &count);
        ok(ret == BT_OBJECT_STATUS_CANCELLED && count == 3,
@@ -688,6 +802,31 @@ void test_map(void)
                checklist.array2 && checklist.map2,
                "bt_object_map_foreach() iterates over all the map object's elements");
 
+       assert(!bt_object_freeze(map_obj));
+       ok(bt_object_map_insert(map_obj, "allo", bt_object_null) ==
+               BT_OBJECT_STATUS_FROZEN,
+               "bt_object_map_insert() fails with a frozen map object");
+       ok(bt_object_map_insert_bool(map_obj, "duh", false) ==
+               BT_OBJECT_STATUS_FROZEN,
+               "bt_object_map_insert_bool() fails with a frozen array object");
+       ok(bt_object_map_insert_integer(map_obj, "duh", 23) ==
+               BT_OBJECT_STATUS_FROZEN,
+               "bt_object_map_insert_integer() fails with a frozen array object");
+       ok(bt_object_map_insert_float(map_obj, "duh", 2.34) ==
+               BT_OBJECT_STATUS_FROZEN,
+               "bt_object_map_insert_float() fails with a frozen array object");
+       ok(bt_object_map_insert_string(map_obj, "duh", "yayayayaya") ==
+               BT_OBJECT_STATUS_FROZEN,
+               "bt_object_map_insert_string() fails with a frozen array object");
+       ok(bt_object_map_insert_array(map_obj, "duh") ==
+               BT_OBJECT_STATUS_FROZEN,
+               "bt_object_map_insert_array() fails with a frozen array object");
+       ok(bt_object_map_insert_map(map_obj, "duh") ==
+               BT_OBJECT_STATUS_FROZEN,
+               "bt_object_map_insert_map() fails with a frozen array object");
+       ok(bt_object_map_size(map_obj) == 10,
+               "appending to a frozen map object does not change its size");
+
        BT_OBJECT_PUT(map_obj);
        pass("putting an existing map object does not cause a crash")
 }
@@ -987,11 +1126,37 @@ void test_macros(void)
        BT_OBJECT_PUT(dst);
 }
 
+static
+void test_freeze(void)
+{
+       struct bt_object *obj;
+
+       ok(bt_object_freeze(NULL) == BT_OBJECT_STATUS_INVAL,
+               "bt_object_freeze() fails with an object set to NULL");
+       ok(!bt_object_freeze(bt_object_null),
+               "bt_object_freeze() succeeds with a null object");
+
+       ok(!bt_object_is_frozen(NULL), "NULL is not frozen");
+       ok(bt_object_is_frozen(bt_object_null),
+               "the null singleton is frozen");
+       assert(obj = bt_object_integer_create());
+       ok(!bt_object_is_frozen(obj),
+               "bt_object_is_frozen() returns false with a fresh object");
+       assert(!bt_object_freeze(obj));
+       ok(!bt_object_freeze(obj),
+               "bt_object_freeze() passes with a frozen object");
+       ok(bt_object_is_frozen(obj),
+               "bt_object_is_frozen() returns true with a frozen object");
+
+       BT_OBJECT_PUT(obj);
+}
+
 int main(void)
 {
        plan_no_plan();
 
        test_macros();
+       test_freeze();
        test_types();
        test_compare();
        test_copy();
This page took 0.047348 seconds and 4 git commands to generate.