Add basic object system
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Thu, 12 Mar 2015 20:14:31 +0000 (16:14 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Tue, 17 Mar 2015 02:24:30 +0000 (22:24 -0400)
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
include/Makefile.am
include/babeltrace/objects.h [new file with mode: 0644]
lib/Makefile.am
lib/objects.c [new file with mode: 0644]

index 9f106c967096911682517f177d90b2b2c632aaf4..2928f7575228496a50045d99abb2f7b04afd523a 100644 (file)
@@ -5,7 +5,8 @@ babeltraceinclude_HEADERS = \
        babeltrace/iterator.h \
        babeltrace/trace-handle.h \
        babeltrace/list.h \
-       babeltrace/clock-types.h
+       babeltrace/clock-types.h \
+       babeltrace/objects.h
 
 babeltracectfinclude_HEADERS = \
        babeltrace/ctf/events.h \
diff --git a/include/babeltrace/objects.h b/include/babeltrace/objects.h
new file mode 100644 (file)
index 0000000..3b66cec
--- /dev/null
@@ -0,0 +1,878 @@
+#ifndef _BABELTRACE_OBJECTS_H
+#define _BABELTRACE_OBJECTS_H
+
+/*
+ * Babeltrace
+ *
+ * Basic object system
+ *
+ * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation
+ * Copyright (c) 2015 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * @file objects.h
+ * @brief Basic object system
+ *
+ * This is a basic object system API. The following functions allow you
+ * to create, modify, and destroy:
+ *
+ *   - \link bt_object_null null objects\endlink
+ *   - \link bt_object_bool_create() boolean objects\endlink
+ *   - \link bt_object_integer_create() integer objects\endlink
+ *   - \link bt_object_float_create() floating point number
+ *     objects\endlink
+ *   - \link bt_object_string_create() string objects\endlink
+ *   - \link bt_object_array_create() array objects\endlink,
+ *     containing zero or more objects
+ *   - \link bt_object_map_create() map objects\endlink, mapping
+ *     string keys to objects
+ *
+ * All the object types above, except for null objects (which always
+ * point to the same \link bt_object_null singleton\endlink), have a
+ * reference count property. Once an object is created, its reference
+ * count is set to 1. When \link bt_object_array_append() appending an
+ * object to an array object\endlink, or \link bt_object_map_insert()
+ * inserting an object into a map object\endlink, its reference count
+ * is incremented, as well as when getting an object back from those
+ * structures. The bt_object_get() and bt_object_put() functions exist
+ * to deal with reference counting. Once you are done with an object,
+ * pass it to bt_object_put().
+ *
+ * A common action with objects is to create or get one, do something
+ * with it, and then put it. To avoid putting it a second time later
+ * (if an error occurs, for example), the variable is often reset to
+ * \c NULL after putting the object it points to. Since this is so
+ * common, you can use the BT_OBJECT_PUT() macro, which does just that:
+ *
+ * \code{.c}
+ *     struct bt_object *int_obj = bt_object_integer_create_init(34);
+ *
+ *     if (!int_obj) {
+ *         goto error;
+ *     }
+ *
+ *     // stuff, which could jump to error
+ *
+ *     BT_OBJECT_PUT(int_obj);
+ *
+ *     // stuff, which could jump to error
+ *
+ *     return 0;
+ *
+ * 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
+ * from one variable to another: since the reference count is not
+ * incremented, and since, to avoid errors, two variables should not
+ * point to same object without each of them having their own reference,
+ * it is best practice to set the original variable to \c NULL. This
+ * too can be accomplished in a single step using the BT_OBJECT_MOVE()
+ * macro:
+ *
+ * \code{.c}
+ *     struct bt_object *int_obj2 = NULL;
+ *     struct bt_object *int_obj = bt_object_integer_create_init(-23);
+ *
+ *     if (!int_obj) {
+ *         goto error;
+ *     }
+ *
+ *     // stuff, which could jump to error
+ *
+ *     BT_OBJECT_MOVE(int_obj2, int_obj);
+ *
+ *     // stuff, which could jump to error
+ *
+ *     return 0;
+ *
+ * error:
+ *     // safe, since only one of int_obj/int_obj2 (or none)
+ *     // points to the object
+ *     BT_OBJECT_PUT(int_obj);
+ *     BT_OBJECT_PUT(int_obj2);
+ * \endcode
+ *
+ * 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().
+ *
+ * @author     Philippe Proulx <pproulx@efficios.com>
+ * @bug                No known bugs
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Object type.
+ */
+enum bt_object_type {
+       /** Unknown object, used as an error code. */
+       BT_OBJECT_TYPE_UNKNOWN =        -1,
+
+       /** Null object. */
+       BT_OBJECT_TYPE_NULL =           0,
+
+       /** Boolean object (holds \c true or \c false). */
+       BT_OBJECT_TYPE_BOOL =           1,
+
+       /** Integer (holds a signed 64-bit integer value). */
+       BT_OBJECT_TYPE_INTEGER =        2,
+
+       /**
+        * Floating point number object (holds a \c double value).
+        */
+       BT_OBJECT_TYPE_FLOAT =          3,
+
+       /** String object. */
+       BT_OBJECT_TYPE_STRING =         4,
+
+       /** Array object. */
+       BT_OBJECT_TYPE_ARRAY =          5,
+
+       /** Map object. */
+       BT_OBJECT_TYPE_MAP =            6,
+};
+
+/**
+ * Object.
+ */
+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().
+ *
+ * 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.
+ */
+extern struct bt_object *bt_object_null;
+
+/**
+ * User function type for bt_object_map_foreach().
+ *
+ * \p object is a \i weak reference; you must pass it to
+ * bt_object_get() to get your own reference.
+ *
+ * Return \c true to continue the loop, or \c false to break it.
+ *
+ * @param key          Key of map entry
+ * @param object       Object of map entry (weak reference)
+ * @param data         User data
+ * @returns            \c true to continue the loop
+ */
+typedef bool (* bt_object_map_foreach_cb)(const char *key,
+       struct bt_object *object, void *data);
+
+/**
+ * Puts the object \p _object (calls bt_object_put() on it), and resets
+ * the variable to \c NULL.
+ *
+ * This is something that is often done when putting and object;
+ * resetting the variable to \c NULL makes sure it cannot be put a
+ * second time later.
+ *
+ * @param _object      Object to put
+ *
+ * @see BT_OBJECT_MOVE() (moves an object from one variable to the other
+ *                      without putting it)
+ */
+#define BT_OBJECT_PUT(_object)                         \
+       do {                                            \
+               bt_object_put(_object);                 \
+               (_object) = NULL;                       \
+       } while (0)
+
+/**
+ * Moves the object referenced by the variable \p _src_object to the
+ * \p _dst_object variable, then resets \p _src_object to \c NULL.
+ *
+ * The object's reference count is <b>not changed</b>. Resetting
+ * \p _src_object to \c NULL ensures the object will not be put
+ * twice later; its ownership is indeed \i moved from the source
+ * variable to the destination variable.
+ *
+ * @param _src_object  Source object variable
+ * @param _dst_object  Destination object variable
+ */
+#define BT_OBJECT_MOVE(_dst_object, _src_object)       \
+       do {                                            \
+               (_dst_object) = (_src_object);          \
+               (_src_object) = NULL;                   \
+       } while (0)
+
+/**
+ * Increments the reference count of \p object.
+ *
+ * @param object       Object of which to increment the reference count
+ */
+extern void bt_object_get(struct bt_object *object);
+
+/**
+ * Decrements the reference count of \p object, destroying it when this
+ * count reaches 0.
+ *
+ * @param object       Object of which to decrement the reference count
+ *
+ * @see BT_OBJECT_PUT() (puts an object and resets the variable to
+ *                     \c NULL)
+ */
+extern void bt_object_put(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
+ *                     on error
+ *
+ * @see enum bt_object_type (object types)
+ */
+extern enum bt_object_type bt_object_get_type(const struct bt_object *object);
+
+/**
+ * Checks whether \p object is a null object. The only valid null
+ * object is \ref bt_object_null.
+ *
+ * @param object       Object to check
+ * @returns            \c true if \p object is a null object
+ */
+bool bt_object_is_null(const struct bt_object *object)
+{
+       return bt_object_get_type(object) == BT_OBJECT_TYPE_NULL;
+}
+
+/**
+ * Checks whether \p object is a boolean object.
+ *
+ * @param object       Object to check
+ * @returns            \c true if \p object is a boolean object
+ */
+bool bt_object_is_bool(const struct bt_object *object)
+{
+       return bt_object_get_type(object) == BT_OBJECT_TYPE_BOOL;
+}
+
+/**
+ * Checks whether \p object is an integer object.
+ *
+ * @param object       Object to check
+ * @returns            \c true if \p object is an integer object
+ */
+bool bt_object_is_integer(const struct bt_object *object)
+{
+       return bt_object_get_type(object) == BT_OBJECT_TYPE_INTEGER;
+}
+
+/**
+ * Checks whether \p object is a floating point number object.
+ *
+ * @param object       Object to check
+ * @returns            \c true if \p object is a floating point number object
+ */
+bool bt_object_is_float(const struct bt_object *object)
+{
+       return bt_object_get_type(object) == BT_OBJECT_TYPE_FLOAT;
+}
+
+/**
+ * Checks whether \p object is a string object.
+ *
+ * @param object       Object to check
+ * @returns            \c true if \p object is a string object
+ */
+bool bt_object_is_string(const struct bt_object *object)
+{
+       return bt_object_get_type(object) == BT_OBJECT_TYPE_STRING;
+}
+
+/**
+ * Checks whether \p object is an array object.
+ *
+ * @param object       Object to check
+ * @returns            \c true if \p object is an array object
+ */
+bool bt_object_is_array(const struct bt_object *object)
+{
+       return bt_object_get_type(object) == BT_OBJECT_TYPE_ARRAY;
+}
+
+/**
+ * Checks whether \p object is a map object.
+ *
+ * @param object       Object to check
+ * @returns            \c true if \p object is a map object
+ */
+bool bt_object_is_map(const struct bt_object *object)
+{
+       return bt_object_get_type(object) == BT_OBJECT_TYPE_MAP;
+}
+
+/**
+ * Creates a boolean object. The created boolean object's initial value
+ * is \c false.
+ *
+ * The created object's reference count is set to 1.
+ *
+ * @returns    Created object on success, or \c NULL on error
+ */
+extern struct bt_object *bt_object_bool_create(void);
+
+/**
+ * Creates a boolean object with its initial value set to \p val.
+ *
+ * The created object's reference count is set to 1.
+ *
+ * @param val  Initial value
+ * @returns    Created object on success, or \c NULL on error
+ */
+extern struct bt_object *bt_object_bool_create_init(bool val);
+
+/**
+ * Creates an integer object. The created integer object's initial value
+ * is 0.
+ *
+ * The created object's reference count is set to 1.
+ *
+ * @returns    Created object on success, or \c NULL on error
+ */
+extern struct bt_object *bt_object_integer_create(void);
+
+/**
+ * Creates an integer object with its initial value set to \p val.
+ *
+ * The created object's reference count is set to 1.
+ *
+ * @param val  Initial value
+ * @returns    Created object on success, or \c NULL on error
+ */
+extern struct bt_object *bt_object_integer_create_init(int64_t val);
+
+/**
+ * Creates a floating point number object. The created floating point
+ * number object's initial value is 0.
+ *
+ * The created object's reference count is set to 1.
+ *
+ * @returns    Created object on success, or \c NULL on error
+ */
+extern struct bt_object *bt_object_float_create(void);
+
+/**
+ * Creates a floating point number object with its initial value set
+ * to \p val.
+ *
+ * The created object's reference count is set to 1.
+ *
+ * @param val  Initial value
+ * @returns    Created object on success, or \c NULL on error
+ */
+extern struct bt_object *bt_object_float_create_init(double val);
+
+/**
+ * Creates a string object. The string object is initially empty.
+ *
+ * The created object's reference count is set to 1.
+ *
+ * @returns    Created object on success, or \c NULL on error
+ */
+extern struct bt_object *bt_object_string_create(void);
+
+/**
+ * Creates a string object with its initial value set to \p val.
+ *
+ * \p val is copied.
+ *
+ * The created object's reference count is set to 1.
+ *
+ * @param val  Initial value (will be copied)
+ * @returns    Created object on success, or \c NULL on error
+ */
+extern struct bt_object *bt_object_string_create_init(const char *val);
+
+/**
+ * Creates an empty array object.
+ *
+ * The created object's reference count is set to 1.
+ *
+ * @returns    Created object on success, or \c NULL on error
+ */
+extern struct bt_object *bt_object_array_create(void);
+
+/**
+ * Creates an empty map object.
+ *
+ * The created object's reference count is set to 1.
+ *
+ * @returns    Created object on success, or \c NULL on error
+ */
+extern struct bt_object *bt_object_map_create(void);
+
+/**
+ * Gets the boolean value of the boolean objet \p bool_obj.
+ *
+ * @param bool_obj     Boolean object
+ * @param val          Returned boolean value
+ * @returns            0 on success, negative value on error
+ */
+extern int 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
+ */
+extern int bt_object_bool_set(struct bt_object *bool_obj, bool val);
+
+/**
+ * Gets the integer value of the integer objet \p integer_obj.
+ *
+ * @param integer_obj  Integer object
+ * @param val          Returned integer value
+ * @returns            0 on success, negative value on error
+ */
+extern int 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
+ * \p val.
+ *
+ * @param integer_obj  Integer object
+ * @param val          New integer value
+ * @returns            0 on success, negative value on error
+ */
+extern int 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.
+ *
+ * @param float_obj    Floating point number object
+ * @param val          Returned floating point number value
+ * @returns            0 on success, negative value on error
+ */
+extern int bt_object_float_get(const struct bt_object *float_obj, double *val);
+
+/**
+ * Sets the floating point number value of the floating point number
+ * object \p float_obj to \p val.
+ *
+ * @param float_obj    Floating point number object
+ * @param val          New floating point number value
+ * @returns            0 on success, negative value on error
+ */
+extern int bt_object_float_set(struct bt_object *float_obj, double val);
+
+/**
+ * Gets the string value of the string objet \p string_obj. The
+ * returned string is valid as long as this object exists and is not
+ * modified.
+ *
+ * @param string_obj   String object
+ * @returns            String value, or \c NULL on error
+ */
+extern const char *bt_object_string_get(const struct bt_object *string_obj);
+
+/**
+ * Sets the string value of the string object \p string_obj to
+ * \p val.
+ *
+ * \p val is copied.
+ *
+ * @param string_obj   String object
+ * @param val          New string value (copied)
+ * @returns            0 on success, negative value on error
+ */
+extern int 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
+ */
+extern int bt_object_array_size(const struct bt_object *array_obj);
+
+/**
+ * Returns \c true if the array object \p array_obj.
+ *
+ * @param array_obj    Array object
+ * @returns            \c true if \p array_obj is empty
+ */
+extern bool bt_object_array_is_empty(const struct bt_object *array_obj);
+
+/**
+ * Gets the element object of the array object \p array_obj at the
+ * index \p index.
+ *
+ * The returned object's reference count is incremented, unless it's
+ * a null object.
+ *
+ * @param array_obj    Array object
+ * @param index                Index of element to get
+ * @returns            Element object at index \p index on success,
+ *                     or \c NULL on error
+ */
+extern struct bt_object *bt_object_array_get(const struct bt_object *array_obj,
+       size_t index);
+
+/**
+ * Appends the element object \p element_obj to the array object
+ * \p array_obj.
+ *
+ * The appended object's reference count is incremented, unless it's
+ * a null object.
+ *
+ * @param array_obj    Array object
+ * @param element_obj  Element object to append
+ * @returns            0 on success, or a negative value on error
+ */
+extern int bt_object_array_append(struct bt_object *array_obj,
+       struct bt_object *element_obj);
+
+/**
+ * Appends the boolean value \p val to the array object \p array_obj.
+ * This is a convenience function which creates the underlying boolean
+ * object before appending it.
+ *
+ * The created boolean object's reference count is set to 1.
+ *
+ * @param array_obj    Array object
+ * @param val          Boolean value to append
+ * @returns            0 on success, or a negative value on error
+ */
+extern int 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.
+ * This is a convenience function which creates the underlying integer
+ * object before appending it.
+ *
+ * The created integer object's reference count is set to 1.
+ *
+ * @param array_obj    Array object
+ * @param val          Integer value to append
+ * @returns            0 on success, or a negative value on error
+ */
+extern int 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
+ * \p array_obj. This is a convenience function which creates the
+ * underlying floating point number object before appending it.
+ *
+ * The created floating point number object's reference count is
+ * set to 1.
+ *
+ * @param array_obj    Array object
+ * @param val          Floating point number value to append
+ * @returns            0 on success, or a negative value on error
+ */
+extern int 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.
+ * This is a convenience function which creates the underlying string
+ * object before appending it.
+ *
+ * \p val is copied.
+ *
+ * The created string object's reference count is set to 1.
+ *
+ * @param array_obj    Array object
+ * @param val          String value to append (copied)
+ * @returns            0 on success, or a negative value on error
+ */
+extern int 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.
+ * This is a convenience function which creates the underlying array
+ * object before appending it.
+ *
+ * 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
+ */
+extern int bt_object_array_append_array(struct bt_object *array_obj);
+
+/**
+ * Appends an empty map object to the array object \p array_obj. This
+ * is a convenience function which creates the underlying map object
+ * before appending it.
+ *
+ * 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
+ */
+extern int bt_object_array_append_map(struct bt_object *array_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
+ */
+extern int bt_object_map_size(const struct bt_object *map_obj);
+
+/**
+ * Returns \c true if the map object \p map_obj.
+ *
+ * @param map_obj      Map object
+ * @returns            \c true if \p map_obj is empty
+ */
+extern bool bt_object_map_is_empty(const struct bt_object *map_obj);
+
+/**
+ * Gets the element object associated with the key \p key within the
+ * map object \p map_obj.
+ *
+ * The returned object's reference count is incremented, unless it's
+ * a null object.
+ *
+ * @param map_obj      Map object
+ * @param key          Key of the element to get
+ * @returns            Element object associated with the key \p key
+ *                     on success, or \c NULL on error
+ */
+extern struct bt_object *bt_object_map_get(const struct bt_object *map_obj,
+       const char *key);
+
+/**
+ * Calls a provided user function \p cb for each element of the map
+ * object \p map_obj.
+ *
+ * The object passed to the user function is a <b>weak reference</b>:
+ * you must call bt_object_get() on it to obtain your own reference.
+ *
+ * The key passed to the user function is only valid in the scope of
+ * this user function.
+ *
+ * The user function must return \c true to continue the loop, or
+ * \c false to break it.
+ *
+ * @param map_obj      Map object
+ * @param cb           User function to call back
+ * @param data         User data passed to the user function
+ * @returns            0 on success, or a negative value on error
+ *                     (the user function breaking the loop is \b not
+ *                     considered an error here)
+ */
+extern int bt_object_map_foreach(const struct bt_object *map_obj,
+       bt_object_map_foreach_cb cb, void *data);
+
+/**
+ * Returns whether or not the map object \p map_obj contains the
+ * key \p key.
+ *
+ * @param map_obj      Map object
+ * @param key          Key to check
+ * @returns            \c true if \p map_obj contains the key \p key,
+ *                     or \c false if it doesn't have \p key or
+ *                     on error
+ */
+extern bool bt_object_map_has_key(const struct bt_object *map_obj,
+       const char *key);
+
+/**
+ * Inserts the element object \p element_obj associated with the key
+ * \p key into the map object \p map_obj. If \p key exists in
+ * \p map_obj, the associated element object is first put, and then
+ * replaced by \p element_obj.
+ *
+ * \p key is copied.
+ *
+ * The inserted object's reference count is incremented, unless it's
+ * a null object.
+ *
+ * @param map_obj      Map object
+ * @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
+ */
+extern int 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
+ * the map object \p map_obj. This is a convenience function which
+ * creates the underlying boolean object before inserting it.
+ *
+ * \p key is copied.
+ *
+ * The created boolean object's reference count is set to 1.
+ *
+ * @param map_obj      Map object
+ * @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
+ */
+extern int 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
+ * the map object \p map_obj. This is a convenience function which
+ * creates the underlying integer object before inserting it.
+ *
+ * \p key is copied.
+ *
+ * The created integer object's reference count is set to 1.
+ *
+ * @param map_obj      Map object
+ * @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
+ */
+extern int 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
+ * key \p key into the map object \p map_obj. This is a convenience
+ * function which creates the underlying floating point number object
+ * before inserting it.
+ *
+ * \p key is copied.
+ *
+ * The created floating point number object's reference count is
+ * set to 1.
+ *
+ * @param map_obj      Map object
+ * @param key          Key (copied) of floating point number value to
+ *                     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
+ */
+extern int 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
+ * the map object \p map_obj. This is a convenience function which
+ * creates the underlying string object before inserting it.
+ *
+ * \p val and \p key are copied.
+ *
+ * The created string object's reference count is set to 1.
+ *
+ * @param map_obj      Map object
+ * @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
+ */
+extern int 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
+ * the map object \p map_obj. This is a convenience function which
+ * creates the underlying array object before inserting it.
+ *
+ * \p key is copied.
+ *
+ * The created array object's reference count is set to 1.
+ *
+ * @param map_obj      Map object
+ * @param key          Key (copied) of empty array to insert
+ * @returns            0 on success, or a negative value on error
+ */
+extern int 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
+ * the map object \p map_obj. This is a convenience function which
+ * creates the underlying map object before inserting it.
+ *
+ * \p key is copied.
+ *
+ * The created map object's reference count is set to 1.
+ *
+ * @param map_obj      Map object
+ * @param key          Key (copied) of empty map to insert
+ * @returns            0 on success, or a negative value on error
+ */
+extern int bt_object_map_insert_map(struct bt_object *map_obj,
+       const char *key);
+
+/**
+ * Creates a deep copy of the object \p object.
+ *
+ * The created object's reference count is set to 1, unless
+ * \p object is a null object.
+ *
+ * @param object       Object to copy
+ * @returns            Deep copy of \p object on success, or \c NULL
+ *                     on error
+ */
+extern struct bt_object *bt_object_copy(const struct bt_object *object);
+
+/**
+ * Compares the objects \p object_a and \p object_b and returns \c true
+ * if they have the same content.
+ *
+ * @param object_a     Object A
+ * @param object_B     Object B
+ * @returns            \c true if \p object_a and \p object_b have the
+ *                     same content, or \c false if they differ or on
+ *                     error
+ */
+extern bool bt_object_compare(const struct bt_object *object_a,
+       const struct bt_object *object_b);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _BABELTRACE_OBJECTS_H */
index 348b0a9b2611977040911a3f8c13c195f0370026..8fe87f34fde01a7acdebcc5604b63168f1e8c0f4 100644 (file)
@@ -9,7 +9,8 @@ libbabeltrace_la_SOURCES = babeltrace.c \
                           context.c \
                           trace-handle.c \
                           trace-collection.c \
-                          registry.c
+                          registry.c \
+                          objects.c
 
 libbabeltrace_la_LDFLAGS = -version-info $(BABELTRACE_LIBRARY_VERSION)
 
diff --git a/lib/objects.c b/lib/objects.c
new file mode 100644 (file)
index 0000000..7fb3484
--- /dev/null
@@ -0,0 +1,1092 @@
+/*
+ * objects.c: basic object system
+ *
+ * Babeltrace Library
+ *
+ * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation
+ * Copyright (c) 2015 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <string.h>
+#include <babeltrace/ctf-writer/ref-internal.h>
+#include <babeltrace/compiler.h>
+#include <glib.h>
+#include <babeltrace/objects.h>
+
+#define BT_OBJECT_FROM_CONCRETE(_concrete) ((struct bt_object *) (_concrete))
+#define BT_OBJECT_TO_BOOL(_base) ((struct bt_object_bool *) (_base))
+#define BT_OBJECT_TO_INTEGER(_base) ((struct bt_object_integer *) (_base))
+#define BT_OBJECT_TO_FLOAT(_base) ((struct bt_object_float *) (_base))
+#define BT_OBJECT_TO_STRING(_base) ((struct bt_object_string *) (_base))
+#define BT_OBJECT_TO_ARRAY(_base) ((struct bt_object_array *) (_base))
+#define BT_OBJECT_TO_MAP(_base) ((struct bt_object_map *) (_base))
+
+struct bt_object {
+       enum bt_object_type type;
+       struct bt_ctf_ref ref_count;
+};
+
+static
+struct bt_object bt_object_null_instance = {
+       .type = BT_OBJECT_TYPE_NULL,
+};
+
+struct bt_object *bt_object_null = &bt_object_null_instance;
+
+struct bt_object_bool {
+       struct bt_object base;
+       bool value;
+};
+
+struct bt_object_integer {
+       struct bt_object base;
+       int64_t value;
+};
+
+struct bt_object_float {
+       struct bt_object base;
+       double value;
+};
+
+struct bt_object_string {
+       struct bt_object base;
+       GString *gstr;
+};
+
+struct bt_object_array {
+       struct bt_object base;
+       GArray *garray;
+};
+
+struct bt_object_map {
+       struct bt_object base;
+       GHashTable *ght;
+};
+
+static
+void bt_object_string_destroy(struct bt_object *object)
+{
+       struct bt_object_string *string_obj = BT_OBJECT_TO_STRING(object);
+
+       g_string_free(string_obj->gstr, TRUE);
+}
+
+static
+void bt_object_array_destroy(struct bt_object *object)
+{
+       int x;
+       struct bt_object_array *array_obj = BT_OBJECT_TO_ARRAY(object);
+
+       for (x = 0; x < array_obj->garray->len; ++x) {
+               struct bt_object *el_obj;
+
+               el_obj = g_array_index(array_obj->garray,
+                       struct bt_object *, x);
+               bt_object_put(el_obj);
+       }
+
+       g_array_free(array_obj->garray, TRUE);
+}
+
+static
+void bt_object_map_destroy(struct bt_object *object)
+{
+       struct bt_object_map *map = BT_OBJECT_TO_MAP(object);
+
+       /*
+        * Hash table's registered value destructor will take care of
+        * putting each contained object. Keys are GQuarks and cannot
+        * be destroyed anyway.
+        */
+       g_hash_table_destroy(map->ght);
+}
+
+static
+void (* const destroy_funcs[])(struct bt_object *) = {
+       [BT_OBJECT_TYPE_NULL] =         NULL,
+       [BT_OBJECT_TYPE_BOOL] =         NULL,
+       [BT_OBJECT_TYPE_INTEGER] =      NULL,
+       [BT_OBJECT_TYPE_FLOAT] =        NULL,
+       [BT_OBJECT_TYPE_STRING] =       bt_object_string_destroy,
+       [BT_OBJECT_TYPE_ARRAY] =        bt_object_array_destroy,
+       [BT_OBJECT_TYPE_MAP] =          bt_object_map_destroy,
+};
+
+static
+struct bt_object *bt_object_null_copy(const struct bt_object *null_obj)
+{
+       return bt_object_null;
+}
+
+static
+struct bt_object *bt_object_bool_copy(const struct bt_object *bool_obj)
+{
+       return bt_object_bool_create_init(BT_OBJECT_TO_BOOL(bool_obj)->value);
+}
+
+static
+struct bt_object *bt_object_integer_copy(const struct bt_object *integer_obj)
+{
+       return bt_object_integer_create_init(
+               BT_OBJECT_TO_INTEGER(integer_obj)->value);
+}
+
+static
+struct bt_object *bt_object_float_copy(const struct bt_object *float_obj)
+{
+       return bt_object_float_create_init(
+               BT_OBJECT_TO_FLOAT(float_obj)->value);
+}
+
+static
+struct bt_object *bt_object_string_copy(const struct bt_object *string_obj)
+{
+       return bt_object_string_create_init(
+               BT_OBJECT_TO_STRING(string_obj)->gstr->str);
+}
+
+static
+struct bt_object *bt_object_array_copy(const struct bt_object *array_obj)
+{
+       int x;
+       int ret;
+       struct bt_object *copy_obj;
+       struct bt_object_array *typed_array_obj;
+
+       typed_array_obj = BT_OBJECT_TO_ARRAY(array_obj);
+       copy_obj = bt_object_array_create();
+
+       if (!copy_obj) {
+               goto end;
+       }
+
+       for (x = 0; x < typed_array_obj->garray->len; ++x) {
+               struct bt_object *element_obj_copy;
+               struct bt_object *element_obj =
+                       bt_object_array_get(array_obj, x);
+
+               if (!element_obj) {
+                       BT_OBJECT_PUT(copy_obj);
+                       goto end;
+               }
+
+               element_obj_copy = bt_object_copy(element_obj);
+               BT_OBJECT_PUT(element_obj);
+
+               if (!element_obj_copy) {
+                       BT_OBJECT_PUT(copy_obj);
+                       goto end;
+               }
+
+               ret = bt_object_array_append(copy_obj, element_obj_copy);
+               BT_OBJECT_PUT(element_obj_copy);
+
+               if (ret) {
+                       BT_OBJECT_PUT(copy_obj);
+                       goto end;
+               }
+       }
+
+end:
+       return copy_obj;
+}
+
+static
+struct bt_object *bt_object_map_copy(const struct bt_object *map_obj)
+{
+       int ret;
+       GHashTableIter iter;
+       gpointer key, element_obj;
+       struct bt_object *copy_obj;
+       struct bt_object *element_obj_copy;
+       struct bt_object_map *typed_map_obj;
+
+       typed_map_obj = BT_OBJECT_TO_MAP(map_obj);
+       copy_obj = bt_object_map_create();
+
+       if (!copy_obj) {
+               goto end;
+       }
+
+       g_hash_table_iter_init(&iter, typed_map_obj->ght);
+
+       while (g_hash_table_iter_next(&iter, &key, &element_obj)) {
+               const char *key_str = g_quark_to_string((unsigned long) key);
+
+               element_obj_copy = bt_object_copy(element_obj);
+
+               if (!element_obj_copy) {
+                       BT_OBJECT_PUT(copy_obj);
+                       goto end;
+               }
+
+               ret = bt_object_map_insert(copy_obj, key_str, element_obj_copy);
+               BT_OBJECT_PUT(element_obj_copy);
+
+               if (ret) {
+                       BT_OBJECT_PUT(copy_obj);
+                       goto end;
+               }
+       }
+
+end:
+       return copy_obj;
+}
+
+static
+struct bt_object *(* const copy_funcs[])(const struct bt_object *) = {
+       [BT_OBJECT_TYPE_NULL] =         bt_object_null_copy,
+       [BT_OBJECT_TYPE_BOOL] =         bt_object_bool_copy,
+       [BT_OBJECT_TYPE_INTEGER] =      bt_object_integer_copy,
+       [BT_OBJECT_TYPE_FLOAT] =        bt_object_float_copy,
+       [BT_OBJECT_TYPE_STRING] =       bt_object_string_copy,
+       [BT_OBJECT_TYPE_ARRAY] =        bt_object_array_copy,
+       [BT_OBJECT_TYPE_MAP] =          bt_object_map_copy,
+};
+
+static
+bool bt_object_null_compare(const struct bt_object *object_a,
+               const struct bt_object *object_b)
+{
+       /*
+        * Always true since bt_object_compare() already checks if both
+        * object_a and object_b have the same type, and in the case of
+        * null objects, they're always the same if it is so.
+        */
+       return true;
+}
+
+static
+bool bt_object_bool_compare(const struct bt_object *object_a,
+               const struct bt_object *object_b)
+{
+       return BT_OBJECT_TO_BOOL(object_a)->value ==
+               BT_OBJECT_TO_BOOL(object_b)->value;
+}
+
+static
+bool bt_object_integer_compare(const struct bt_object *object_a,
+               const struct bt_object *object_b)
+{
+       return BT_OBJECT_TO_INTEGER(object_a)->value ==
+               BT_OBJECT_TO_INTEGER(object_b)->value;
+}
+
+static
+bool bt_object_float_compare(const struct bt_object *object_a,
+               const struct bt_object *object_b)
+{
+       return BT_OBJECT_TO_FLOAT(object_a)->value ==
+               BT_OBJECT_TO_FLOAT(object_b)->value;
+}
+
+static
+bool bt_object_string_compare(const struct bt_object *object_a,
+               const struct bt_object *object_b)
+{
+       return !strcmp(BT_OBJECT_TO_STRING(object_a)->gstr->str,
+               BT_OBJECT_TO_STRING(object_b)->gstr->str);
+}
+
+static
+bool bt_object_array_compare(const struct bt_object *object_a,
+               const struct bt_object *object_b)
+{
+       int x;
+       bool ret = true;
+       const struct bt_object_array *array_obj_a =
+               BT_OBJECT_TO_ARRAY(object_a);
+
+       if (bt_object_array_size(object_a) != bt_object_array_size(object_b)) {
+               ret = false;
+               goto end;
+       }
+
+       for (x = 0; x < array_obj_a->garray->len; ++x) {
+               struct bt_object *element_obj_a;
+               struct bt_object *element_obj_b;
+
+               element_obj_a = bt_object_array_get(object_a, x);
+               element_obj_b = bt_object_array_get(object_b, x);
+
+               if (!bt_object_compare(element_obj_a, element_obj_b)) {
+                       BT_OBJECT_PUT(element_obj_a);
+                       BT_OBJECT_PUT(element_obj_b);
+                       ret = false;
+                       goto end;
+               }
+
+               BT_OBJECT_PUT(element_obj_a);
+               BT_OBJECT_PUT(element_obj_b);
+       }
+
+end:
+       return ret;
+}
+
+static
+bool bt_object_map_compare(const struct bt_object *object_a,
+               const struct bt_object *object_b)
+{
+       bool ret = true;
+       GHashTableIter iter;
+       gpointer key, element_obj_a;
+       const struct bt_object_map *map_obj_a = BT_OBJECT_TO_MAP(object_a);
+
+       if (bt_object_map_size(object_a) != bt_object_map_size(object_b)) {
+               ret = false;
+               goto end;
+       }
+
+       g_hash_table_iter_init(&iter, map_obj_a->ght);
+
+       while (g_hash_table_iter_next(&iter, &key, &element_obj_a)) {
+               struct bt_object *element_obj_b;
+               const char *key_str = g_quark_to_string((unsigned long) key);
+
+               element_obj_b = bt_object_map_get(object_b, key_str);
+
+               if (!bt_object_compare(element_obj_a, element_obj_b)) {
+                       BT_OBJECT_PUT(element_obj_b);
+                       ret = false;
+                       goto end;
+               }
+
+               BT_OBJECT_PUT(element_obj_b);
+       }
+
+end:
+       return ret;
+}
+
+static
+bool (* const compare_funcs[])(const struct bt_object *,
+               const struct bt_object *) = {
+       [BT_OBJECT_TYPE_NULL] =         bt_object_null_compare,
+       [BT_OBJECT_TYPE_BOOL] =         bt_object_bool_compare,
+       [BT_OBJECT_TYPE_INTEGER] =      bt_object_integer_compare,
+       [BT_OBJECT_TYPE_FLOAT] =        bt_object_float_compare,
+       [BT_OBJECT_TYPE_STRING] =       bt_object_string_compare,
+       [BT_OBJECT_TYPE_ARRAY] =        bt_object_array_compare,
+       [BT_OBJECT_TYPE_MAP] =          bt_object_map_compare,
+};
+
+static
+void bt_object_destroy(struct bt_ctf_ref *ref_count)
+{
+       struct bt_object *object;
+
+       object = container_of(ref_count, struct bt_object, ref_count);
+       assert(object->type != BT_OBJECT_TYPE_UNKNOWN);
+
+       if (bt_object_is_null(object)) {
+               return;
+       }
+
+       if (destroy_funcs[object->type]) {
+               destroy_funcs[object->type](object);
+       }
+
+       g_free(object);
+}
+
+void bt_object_get(struct bt_object *object)
+{
+       if (!object) {
+               goto skip;
+       }
+
+       bt_ctf_ref_get(&object->ref_count);
+
+skip:
+       return;
+}
+
+void bt_object_put(struct bt_object *object)
+{
+       if (!object) {
+               goto skip;
+       }
+
+       bt_ctf_ref_put(&object->ref_count, bt_object_destroy);
+
+skip:
+       return;
+}
+
+enum bt_object_type bt_object_get_type(const struct bt_object *object)
+{
+       if (!object) {
+               return BT_OBJECT_TYPE_UNKNOWN;
+       }
+
+       return object->type;
+}
+
+static
+struct bt_object bt_object_create_base(enum bt_object_type type)
+{
+       struct bt_object base;
+
+       base.type = type;
+       bt_ctf_ref_init(&base.ref_count);
+
+       return base;
+}
+
+struct bt_object *bt_object_bool_create_init(bool val)
+{
+       struct bt_object_bool *bool_obj;
+
+       bool_obj = g_new0(struct bt_object_bool, 1);
+
+       if (!bool_obj) {
+               goto end;
+       }
+
+       bool_obj->base = bt_object_create_base(BT_OBJECT_TYPE_BOOL);
+       bool_obj->value = val;
+
+end:
+       return BT_OBJECT_FROM_CONCRETE(bool_obj);
+}
+
+struct bt_object *bt_object_bool_create(void)
+{
+       return bt_object_bool_create_init(false);
+}
+
+struct bt_object *bt_object_integer_create_init(int64_t val)
+{
+       struct bt_object_integer *integer_obj;
+
+       integer_obj = g_new0(struct bt_object_integer, 1);
+
+       if (!integer_obj) {
+               goto end;
+       }
+
+       integer_obj->base = bt_object_create_base(BT_OBJECT_TYPE_INTEGER);
+       integer_obj->value = val;
+
+end:
+       return BT_OBJECT_FROM_CONCRETE(integer_obj);
+}
+
+struct bt_object *bt_object_integer_create(void)
+{
+       return bt_object_integer_create_init(0);
+}
+
+struct bt_object *bt_object_float_create_init(double val)
+{
+       struct bt_object_float *float_obj;
+
+       float_obj = g_new0(struct bt_object_float, 1);
+
+       if (!float_obj) {
+               goto end;
+       }
+
+       float_obj->base = bt_object_create_base(BT_OBJECT_TYPE_FLOAT);
+       float_obj->value = val;
+
+end:
+       return BT_OBJECT_FROM_CONCRETE(float_obj);
+}
+
+struct bt_object *bt_object_float_create(void)
+{
+       return bt_object_float_create_init(0.);
+}
+
+struct bt_object *bt_object_string_create_init(const char *val)
+{
+       struct bt_object_string *string_obj = NULL;
+
+       if (!val) {
+               goto end;
+       }
+
+       string_obj = g_new0(struct bt_object_string, 1);
+
+       if (!string_obj) {
+               goto end;
+       }
+
+       string_obj->base = bt_object_create_base(BT_OBJECT_TYPE_STRING);
+       string_obj->gstr = g_string_new(val);
+
+       if (!string_obj->gstr) {
+               g_free(string_obj);
+               string_obj = NULL;
+               goto end;
+       }
+
+end:
+       return BT_OBJECT_FROM_CONCRETE(string_obj);
+}
+
+struct bt_object *bt_object_string_create(void)
+{
+       return bt_object_string_create_init("");
+}
+
+struct bt_object *bt_object_array_create(void)
+{
+       struct bt_object_array *array_obj;
+
+       array_obj = g_new0(struct bt_object_array, 1);
+
+       if (!array_obj) {
+               goto end;
+       }
+
+       array_obj->base = bt_object_create_base(BT_OBJECT_TYPE_ARRAY);
+       array_obj->garray = g_array_new(FALSE, FALSE,
+               sizeof(struct bt_object *));
+
+       if (!array_obj->garray) {
+               g_free(array_obj);
+               array_obj = NULL;
+               goto end;
+       }
+
+end:
+       return BT_OBJECT_FROM_CONCRETE(array_obj);
+}
+
+struct bt_object *bt_object_map_create(void)
+{
+       struct bt_object_map *map_obj;
+
+       map_obj = g_new0(struct bt_object_map, 1);
+
+       if (!map_obj) {
+               goto end;
+       }
+
+       map_obj->base = bt_object_create_base(BT_OBJECT_TYPE_MAP);
+       map_obj->ght = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+               NULL, (GDestroyNotify) bt_object_put);
+
+       if (!map_obj->ght) {
+               g_free(map_obj);
+               map_obj = NULL;
+               goto end;
+       }
+
+end:
+       return BT_OBJECT_FROM_CONCRETE(map_obj);
+}
+
+int bt_object_bool_get(const struct bt_object *bool_obj, bool *val)
+{
+       int ret = 0;
+       struct bt_object_bool *typed_bool_obj = BT_OBJECT_TO_BOOL(bool_obj);
+
+       if (!bool_obj || !bt_object_is_bool(bool_obj)) {
+               ret = -1;
+               goto end;
+       }
+
+       *val = typed_bool_obj->value;
+
+end:
+       return ret;
+}
+
+int bt_object_bool_set(struct bt_object *bool_obj, bool val)
+{
+       int ret = 0;
+       struct bt_object_bool *typed_bool_obj = BT_OBJECT_TO_BOOL(bool_obj);
+
+       if (!bool_obj || !bt_object_is_bool(bool_obj)) {
+               ret = -1;
+               goto end;
+       }
+
+       typed_bool_obj->value = val;
+
+end:
+       return ret;
+}
+
+int bt_object_integer_get(const struct bt_object *integer_obj, int64_t *val)
+{
+       int ret = 0;
+       struct bt_object_integer *typed_integer_obj =
+               BT_OBJECT_TO_INTEGER(integer_obj);
+
+       if (!integer_obj || !bt_object_is_integer(integer_obj)) {
+               ret = -1;
+               goto end;
+       }
+
+       *val = typed_integer_obj->value;
+
+end:
+       return ret;
+}
+
+int bt_object_integer_set(struct bt_object *integer_obj, int64_t val)
+{
+       int ret = 0;
+       struct bt_object_integer *typed_integer_obj =
+               BT_OBJECT_TO_INTEGER(integer_obj);
+
+       if (!integer_obj || !bt_object_is_integer(integer_obj)) {
+               ret = -1;
+               goto end;
+       }
+
+       typed_integer_obj->value = val;
+
+end:
+       return ret;
+}
+
+int bt_object_float_get(const struct bt_object *float_obj, double *val)
+{
+       int ret = 0;
+       struct bt_object_float *typed_float_obj =
+               BT_OBJECT_TO_FLOAT(float_obj);
+
+       if (!float_obj || !bt_object_is_float(float_obj)) {
+               ret = -1;
+               goto end;
+       }
+
+       *val = typed_float_obj->value;
+
+end:
+       return ret;
+}
+
+int bt_object_float_set(struct bt_object *float_obj, double val)
+{
+       int ret = 0;
+       struct bt_object_float *typed_float_obj =
+               BT_OBJECT_TO_FLOAT(float_obj);
+
+       if (!float_obj || !bt_object_is_float(float_obj)) {
+               ret = -1;
+               goto end;
+       }
+
+       typed_float_obj->value = val;
+
+end:
+       return ret;
+}
+
+const char *bt_object_string_get(const struct bt_object *string_obj)
+{
+       const char *ret;
+       struct bt_object_string *typed_string_obj =
+               BT_OBJECT_TO_STRING(string_obj);
+
+       if (!string_obj || !bt_object_is_string(string_obj)) {
+               ret = NULL;
+               goto end;
+       }
+
+       ret = typed_string_obj->gstr->str;
+
+end:
+       return ret;
+}
+
+int bt_object_string_set(struct bt_object *string_obj, const char *val)
+{
+       int ret = 0;
+       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;
+               goto end;
+       }
+
+       g_string_assign(typed_string_obj->gstr, val);
+
+end:
+       return ret;
+}
+
+int bt_object_array_size(const struct bt_object *array_obj)
+{
+       int ret = 0;
+       struct bt_object_array *typed_array_obj =
+               BT_OBJECT_TO_ARRAY(array_obj);
+
+       if (!array_obj || !bt_object_is_array(array_obj)) {
+               ret = -1;
+               goto end;
+       }
+
+       ret = (int) typed_array_obj->garray->len;
+
+end:
+       return ret;
+}
+
+bool bt_object_array_is_empty(const struct bt_object *array_obj)
+{
+       return bt_object_array_size(array_obj) == 0;
+}
+
+struct bt_object *bt_object_array_get(const struct bt_object *array_obj,
+       size_t index)
+{
+       struct bt_object *ret;
+       struct bt_object_array *typed_array_obj =
+               BT_OBJECT_TO_ARRAY(array_obj);
+
+       if (!array_obj || !bt_object_is_array(array_obj) ||
+                       index >= typed_array_obj->garray->len) {
+               ret = NULL;
+               goto end;
+       }
+
+       ret = g_array_index(typed_array_obj->garray,
+               struct bt_object *, index);
+       bt_object_get(ret);
+
+end:
+       return ret;
+}
+
+int bt_object_array_append(struct bt_object *array_obj,
+       struct bt_object *element_obj)
+{
+       int ret = 0;
+       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;
+               goto end;
+       }
+
+       g_array_append_val(typed_array_obj->garray, element_obj);
+       bt_object_get(element_obj);
+
+end:
+       return ret;
+}
+
+int bt_object_array_append_bool(struct bt_object *array_obj, bool val)
+{
+       int ret;
+       struct bt_object *bool_obj = NULL;
+
+       bool_obj = bt_object_bool_create_init(val);
+       ret = bt_object_array_append(array_obj, bool_obj);
+       bt_object_put(bool_obj);
+
+       return ret;
+}
+
+int bt_object_array_append_integer(struct bt_object *array_obj, int64_t val)
+{
+       int ret;
+       struct bt_object *integer_obj = NULL;
+
+       integer_obj = bt_object_integer_create_init(val);
+       ret = bt_object_array_append(array_obj, integer_obj);
+       bt_object_put(integer_obj);
+
+       return ret;
+}
+
+int bt_object_array_append_float(struct bt_object *array_obj, double val)
+{
+       int ret;
+       struct bt_object *float_obj = NULL;
+
+       float_obj = bt_object_float_create_init(val);
+       ret = bt_object_array_append(array_obj, float_obj);
+       bt_object_put(float_obj);
+
+       return ret;
+}
+
+int bt_object_array_append_string(struct bt_object *array_obj, const char *val)
+{
+       int ret;
+       struct bt_object *string_obj = NULL;
+
+       string_obj = bt_object_string_create_init(val);
+       ret = bt_object_array_append(array_obj, string_obj);
+       bt_object_put(string_obj);
+
+       return ret;
+}
+
+int bt_object_array_append_array(struct bt_object *array_obj)
+{
+       int ret;
+       struct bt_object *empty_array_obj = NULL;
+
+       empty_array_obj = bt_object_array_create();
+       ret = bt_object_array_append(array_obj, empty_array_obj);
+       bt_object_put(empty_array_obj);
+
+       return ret;
+}
+
+int bt_object_array_append_map(struct bt_object *array_obj)
+{
+       int ret;
+       struct bt_object *map_obj = NULL;
+
+       map_obj = bt_object_map_create();
+       ret = bt_object_array_append(array_obj, map_obj);
+       bt_object_put(map_obj);
+
+       return ret;
+}
+
+int bt_object_map_size(const struct bt_object *map_obj)
+{
+       int ret;
+       struct bt_object_map *typed_map_obj = BT_OBJECT_TO_MAP(map_obj);
+
+       if (!map_obj || !bt_object_is_map(map_obj)) {
+               ret = -1;
+               goto end;
+       }
+
+       ret = (int) g_hash_table_size(typed_map_obj->ght);
+
+end:
+       return ret;
+}
+
+bool bt_object_map_is_empty(const struct bt_object *map_obj)
+{
+       return bt_object_map_size(map_obj) == 0;
+}
+
+struct bt_object *bt_object_map_get(const struct bt_object *map_obj,
+       const char *key)
+{
+       GQuark quark;
+       struct bt_object *ret;
+       struct bt_object_map *typed_map_obj = BT_OBJECT_TO_MAP(map_obj);
+
+       if (!map_obj || !bt_object_is_map(map_obj) || !key) {
+               ret = NULL;
+               goto end;
+       }
+
+       quark = g_quark_from_string(key);
+       ret = g_hash_table_lookup(typed_map_obj->ght, GUINT_TO_POINTER(quark));
+
+       if (ret) {
+               bt_object_get(ret);
+       }
+
+end:
+       return ret;
+}
+
+bool bt_object_map_has_key(const struct bt_object *map_obj, const char *key)
+{
+       bool ret;
+       GQuark quark;
+       struct bt_object_map *typed_map_obj = BT_OBJECT_TO_MAP(map_obj);
+
+       if (!map_obj || !bt_object_is_map(map_obj) || !key) {
+               ret = false;
+               goto end;
+       }
+
+       quark = g_quark_from_string(key);
+       ret = g_hash_table_contains(typed_map_obj->ght,
+               GUINT_TO_POINTER(quark));
+
+end:
+       return ret;
+}
+
+int bt_object_map_insert(struct bt_object *map_obj, const char *key,
+       struct bt_object *element_obj)
+{
+       int ret = 0;
+       GQuark quark;
+       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;
+               goto end;
+       }
+
+       quark = g_quark_from_string(key);
+       g_hash_table_insert(typed_map_obj->ght,
+               GUINT_TO_POINTER(quark), element_obj);
+       bt_object_get(element_obj);
+
+end:
+       return ret;
+}
+
+int bt_object_map_insert_bool(struct bt_object *map_obj,
+       const char *key, bool val)
+{
+       int ret;
+       struct bt_object *bool_obj = NULL;
+
+       bool_obj = bt_object_bool_create_init(val);
+       ret = bt_object_map_insert(map_obj, key, bool_obj);
+       bt_object_put(bool_obj);
+
+       return ret;
+}
+
+int bt_object_map_insert_integer(struct bt_object *map_obj,
+       const char *key, int64_t val)
+{
+       int ret;
+       struct bt_object *integer_obj = NULL;
+
+       integer_obj = bt_object_integer_create_init(val);
+       ret = bt_object_map_insert(map_obj, key, integer_obj);
+       bt_object_put(integer_obj);
+
+       return ret;
+}
+
+int bt_object_map_insert_float(struct bt_object *map_obj,
+       const char *key, double val)
+{
+       int ret;
+       struct bt_object *float_obj = NULL;
+
+       float_obj = bt_object_float_create_init(val);
+       ret = bt_object_map_insert(map_obj, key, float_obj);
+       bt_object_put(float_obj);
+
+       return ret;
+}
+
+int bt_object_map_insert_string(struct bt_object *map_obj,
+       const char *key, const char *val)
+{
+       int ret;
+       struct bt_object *string_obj = NULL;
+
+       string_obj = bt_object_string_create_init(val);
+       ret = bt_object_map_insert(map_obj, key, string_obj);
+       bt_object_put(string_obj);
+
+       return ret;
+}
+
+int bt_object_map_insert_array(struct bt_object *map_obj,
+       const char *key)
+{
+       int ret;
+       struct bt_object *array_obj = NULL;
+
+       array_obj = bt_object_array_create();
+       ret = bt_object_map_insert(map_obj, key, array_obj);
+       bt_object_put(array_obj);
+
+       return ret;
+}
+
+int bt_object_map_insert_map(struct bt_object *map_obj,
+       const char *key)
+{
+       int ret;
+       struct bt_object *empty_map_obj = NULL;
+
+       empty_map_obj = bt_object_map_create();
+       ret = bt_object_map_insert(map_obj, key, empty_map_obj);
+       bt_object_put(empty_map_obj);
+
+       return ret;
+}
+
+int bt_object_map_foreach(const struct bt_object *map_obj,
+       bt_object_map_foreach_cb cb, void *data)
+{
+       int ret = 0;
+       gpointer key, element_obj;
+       GHashTableIter iter;
+       struct bt_object_map *typed_map_obj = BT_OBJECT_TO_MAP(map_obj);
+
+       if (!map_obj || !bt_object_is_map(map_obj) || !cb) {
+               ret = -1;
+               goto end;
+       }
+
+       g_hash_table_iter_init(&iter, typed_map_obj->ght);
+
+       while (g_hash_table_iter_next(&iter, &key, &element_obj)) {
+               const char *key_str = g_quark_to_string((unsigned long) key);
+
+               if (!cb(key_str, element_obj, data)) {
+                       break;
+               }
+       }
+
+end:
+       return ret;
+}
+
+struct bt_object *bt_object_copy(const struct bt_object *object)
+{
+       struct bt_object *copy_obj = NULL;
+
+       if (!object) {
+               goto end;
+       }
+
+       copy_obj = copy_funcs[object->type](object);
+
+end:
+       return copy_obj;
+}
+
+bool bt_object_compare(const struct bt_object *object_a,
+       const struct bt_object *object_b)
+{
+       bool ret = false;
+
+       if (!object_a || !object_b) {
+               goto end;
+       }
+
+       if (object_a->type != object_b->type) {
+               goto end;
+       }
+
+       ret = compare_funcs[object_a->type](object_a, object_b);
+
+end:
+       return ret;
+}
This page took 0.042125 seconds and 4 git commands to generate.