From: Philippe Proulx Date: Thu, 23 Jul 2015 21:11:27 +0000 (-0400) Subject: Rename bt_object to bt_value X-Git-Tag: v2.0.0-pre1~1206 X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=commitdiff_plain;h=dac5c838a2e15f0da9acd223a119ae7962dbc79a Rename bt_object to bt_value Signed-off-by: Philippe Proulx Signed-off-by: Jérémie Galarneau --- diff --git a/formats/ctf/ir/attributes.c b/formats/ctf/ir/attributes.c index 619b28ed..409ae6bb 100644 --- a/formats/ctf/ir/attributes.c +++ b/formats/ctf/ir/attributes.c @@ -26,18 +26,18 @@ */ #include -#include +#include #define BT_CTF_ATTR_NAME_INDEX 0 #define BT_CTF_ATTR_VALUE_INDEX 1 BT_HIDDEN -struct bt_object *bt_ctf_attributes_create(void) +struct bt_value *bt_ctf_attributes_create(void) { /* - * Attributes: array object of array objects, each one - * containing two entries: a string object (attributes field - * name), and an object (attributes field value). + * Attributes: array value object of array value objects, each one + * containing two entries: a string value object (attributes + * field name), and a value object (attributes field value). * * Example (JSON representation): * @@ -48,96 +48,96 @@ struct bt_object *bt_ctf_attributes_create(void) * ["tracer_minor", 5] * ] */ - return bt_object_array_create(); + return bt_value_array_create(); } BT_HIDDEN -void bt_ctf_attributes_destroy(struct bt_object *attr_obj) +void bt_ctf_attributes_destroy(struct bt_value *attr_obj) { - bt_object_put(attr_obj); + bt_value_put(attr_obj); } BT_HIDDEN -int bt_ctf_attributes_get_count(struct bt_object *attr_obj) +int bt_ctf_attributes_get_count(struct bt_value *attr_obj) { - return bt_object_array_size(attr_obj); + return bt_value_array_size(attr_obj); } BT_HIDDEN -const char *bt_ctf_attributes_get_field_name(struct bt_object *attr_obj, +const char *bt_ctf_attributes_get_field_name(struct bt_value *attr_obj, int index) { int rc; const char *ret = NULL; - struct bt_object *attr_field_obj = NULL; - struct bt_object *attr_field_name_obj = NULL; + struct bt_value *attr_field_obj = NULL; + struct bt_value *attr_field_name_obj = NULL; if (!attr_obj || index < 0) { goto end; } - attr_field_obj = bt_object_array_get(attr_obj, index); + attr_field_obj = bt_value_array_get(attr_obj, index); if (!attr_field_obj) { goto end; } - attr_field_name_obj = bt_object_array_get(attr_field_obj, + attr_field_name_obj = bt_value_array_get(attr_field_obj, BT_CTF_ATTR_NAME_INDEX); if (!attr_field_name_obj) { goto end; } - rc = bt_object_string_get(attr_field_name_obj, &ret); + rc = bt_value_string_get(attr_field_name_obj, &ret); if (rc) { ret = NULL; } end: - BT_OBJECT_PUT(attr_field_name_obj); - BT_OBJECT_PUT(attr_field_obj); + BT_VALUE_PUT(attr_field_name_obj); + BT_VALUE_PUT(attr_field_obj); return ret; } BT_HIDDEN -struct bt_object *bt_ctf_attributes_get_field_value(struct bt_object *attr_obj, +struct bt_value *bt_ctf_attributes_get_field_value(struct bt_value *attr_obj, int index) { - struct bt_object *value_obj = NULL; - struct bt_object *attr_field_obj = NULL; + struct bt_value *value_obj = NULL; + struct bt_value *attr_field_obj = NULL; if (!attr_obj || index < 0) { goto end; } - attr_field_obj = bt_object_array_get(attr_obj, index); + attr_field_obj = bt_value_array_get(attr_obj, index); if (!attr_field_obj) { goto end; } - value_obj = bt_object_array_get(attr_field_obj, + value_obj = bt_value_array_get(attr_field_obj, BT_CTF_ATTR_VALUE_INDEX); end: - BT_OBJECT_PUT(attr_field_obj); + BT_VALUE_PUT(attr_field_obj); return value_obj; } static -struct bt_object *bt_ctf_attributes_get_field_by_name( - struct bt_object *attr_obj, const char *name) +struct bt_value *bt_ctf_attributes_get_field_by_name( + struct bt_value *attr_obj, const char *name) { int i; int attr_size; - struct bt_object *value_obj = NULL; - struct bt_object *attr_field_name_obj = NULL; + struct bt_value *value_obj = NULL; + struct bt_value *attr_field_name_obj = NULL; - attr_size = bt_object_array_size(attr_obj); + attr_size = bt_value_array_size(attr_obj); if (attr_size < 0) { goto error; @@ -147,47 +147,47 @@ struct bt_object *bt_ctf_attributes_get_field_by_name( int ret; const char *field_name; - value_obj = bt_object_array_get(attr_obj, i); + value_obj = bt_value_array_get(attr_obj, i); if (!value_obj) { goto error; } - attr_field_name_obj = bt_object_array_get(value_obj, 0); + attr_field_name_obj = bt_value_array_get(value_obj, 0); if (!attr_field_name_obj) { goto error; } - ret = bt_object_string_get(attr_field_name_obj, &field_name); + ret = bt_value_string_get(attr_field_name_obj, &field_name); if (ret) { goto error; } if (!strcmp(field_name, name)) { - BT_OBJECT_PUT(attr_field_name_obj); + BT_VALUE_PUT(attr_field_name_obj); break; } - BT_OBJECT_PUT(attr_field_name_obj); - BT_OBJECT_PUT(value_obj); + BT_VALUE_PUT(attr_field_name_obj); + BT_VALUE_PUT(value_obj); } return value_obj; error: - BT_OBJECT_PUT(attr_field_name_obj); - BT_OBJECT_PUT(value_obj); + BT_VALUE_PUT(attr_field_name_obj); + BT_VALUE_PUT(value_obj); return value_obj; } BT_HIDDEN -int bt_ctf_attributes_set_field_value(struct bt_object *attr_obj, - const char *name, struct bt_object *value_obj) +int bt_ctf_attributes_set_field_value(struct bt_value *attr_obj, + const char *name, struct bt_value *value_obj) { int ret = 0; - struct bt_object *attr_field_obj = NULL; + struct bt_value *attr_field_obj = NULL; if (!attr_obj || !name || !value_obj) { ret = -1; @@ -197,39 +197,39 @@ int bt_ctf_attributes_set_field_value(struct bt_object *attr_obj, attr_field_obj = bt_ctf_attributes_get_field_by_name(attr_obj, name); if (attr_field_obj) { - ret = bt_object_array_set(attr_field_obj, + ret = bt_value_array_set(attr_field_obj, BT_CTF_ATTR_VALUE_INDEX, value_obj); goto end; } - attr_field_obj = bt_object_array_create(); + attr_field_obj = bt_value_array_create(); if (!attr_field_obj) { ret = -1; goto end; } - ret = bt_object_array_append_string(attr_field_obj, name); - ret |= bt_object_array_append(attr_field_obj, value_obj); + ret = bt_value_array_append_string(attr_field_obj, name); + ret |= bt_value_array_append(attr_field_obj, value_obj); if (ret) { goto end; } - ret = bt_object_array_append(attr_obj, attr_field_obj); + ret = bt_value_array_append(attr_obj, attr_field_obj); end: - BT_OBJECT_PUT(attr_field_obj); + BT_VALUE_PUT(attr_field_obj); return ret; } BT_HIDDEN -struct bt_object *bt_ctf_attributes_get_field_value_by_name( - struct bt_object *attr_obj, const char *name) +struct bt_value *bt_ctf_attributes_get_field_value_by_name( + struct bt_value *attr_obj, const char *name) { - struct bt_object *value_obj = NULL; - struct bt_object *attr_field_obj = NULL; + struct bt_value *value_obj = NULL; + struct bt_value *attr_field_obj = NULL; if (!attr_obj || !name) { goto end; @@ -241,17 +241,17 @@ struct bt_object *bt_ctf_attributes_get_field_value_by_name( goto end; } - value_obj = bt_object_array_get(attr_field_obj, + value_obj = bt_value_array_get(attr_field_obj, BT_CTF_ATTR_VALUE_INDEX); end: - BT_OBJECT_PUT(attr_field_obj); + BT_VALUE_PUT(attr_field_obj); return value_obj; } BT_HIDDEN -int bt_ctf_attributes_freeze(struct bt_object *attr_obj) +int bt_ctf_attributes_freeze(struct bt_value *attr_obj) { int i; int count; @@ -262,7 +262,7 @@ int bt_ctf_attributes_freeze(struct bt_object *attr_obj) goto end; } - count = bt_object_array_size(attr_obj); + count = bt_value_array_size(attr_obj); if (count < 0) { ret = -1; @@ -270,12 +270,12 @@ int bt_ctf_attributes_freeze(struct bt_object *attr_obj) } /* - * We do not freeze the array itself here, since internal - * stuff could need to modify/add attributes. Each attribute - * is frozen one by one. + * We do not freeze the array value object itself here, since + * internal stuff could need to modify/add attributes. Each + * attribute is frozen one by one. */ for (i = 0; i < count; ++i) { - struct bt_object *obj = NULL; + struct bt_value *obj = NULL; obj = bt_ctf_attributes_get_field_value(attr_obj, i); @@ -284,8 +284,8 @@ int bt_ctf_attributes_freeze(struct bt_object *attr_obj) goto end; } - bt_object_freeze(obj); - BT_OBJECT_PUT(obj); + bt_value_freeze(obj); + BT_VALUE_PUT(obj); } end: diff --git a/formats/ctf/ir/event.c b/formats/ctf/ir/event.c index 6cb9f2d5..82499417 100644 --- a/formats/ctf/ir/event.c +++ b/formats/ctf/ir/event.c @@ -51,7 +51,7 @@ int set_integer_field_value(struct bt_ctf_field *field, uint64_t value); struct bt_ctf_event_class *bt_ctf_event_class_create(const char *name) { int ret; - struct bt_object *obj = NULL; + struct bt_value *obj = NULL; struct bt_ctf_event_class *event_class = NULL; if (bt_ctf_validate_identifier(name)) { @@ -74,7 +74,7 @@ struct bt_ctf_event_class *bt_ctf_event_class_create(const char *name) goto error; } - obj = bt_object_integer_create_init(-1); + obj = bt_value_integer_create_init(-1); if (!obj) { goto error; } @@ -85,9 +85,9 @@ struct bt_ctf_event_class *bt_ctf_event_class_create(const char *name) goto error; } - BT_OBJECT_PUT(obj); + BT_VALUE_PUT(obj); - obj = bt_object_string_create_init(name); + obj = bt_value_string_create_init(name); if (!obj) { goto error; } @@ -98,7 +98,7 @@ struct bt_ctf_event_class *bt_ctf_event_class_create(const char *name) goto error; } - BT_OBJECT_PUT(obj); + BT_VALUE_PUT(obj); return event_class; @@ -107,14 +107,14 @@ error: bt_ctf_event_class_put(event_class); } - BT_OBJECT_PUT(obj); + BT_VALUE_PUT(obj); return NULL; } const char *bt_ctf_event_class_get_name(struct bt_ctf_event_class *event_class) { - struct bt_object *obj = NULL; + struct bt_value *obj = NULL; const char *name = NULL; if (!event_class) { @@ -127,19 +127,19 @@ const char *bt_ctf_event_class_get_name(struct bt_ctf_event_class *event_class) goto end; } - if (bt_object_string_get(obj, &name)) { + if (bt_value_string_get(obj, &name)) { name = NULL; } end: - BT_OBJECT_PUT(obj); + BT_VALUE_PUT(obj); return name; } int64_t bt_ctf_event_class_get_id(struct bt_ctf_event_class *event_class) { - struct bt_object *obj = NULL; + struct bt_value *obj = NULL; int64_t ret = 0; if (!event_class) { @@ -153,7 +153,7 @@ int64_t bt_ctf_event_class_get_id(struct bt_ctf_event_class *event_class) goto end; } - if (bt_object_integer_get(obj, &ret)) { + if (bt_value_integer_get(obj, &ret)) { ret = -1; } @@ -164,7 +164,7 @@ int64_t bt_ctf_event_class_get_id(struct bt_ctf_event_class *event_class) } end: - BT_OBJECT_PUT(obj); + BT_VALUE_PUT(obj); return ret; } @@ -173,7 +173,7 @@ int bt_ctf_event_class_set_id(struct bt_ctf_event_class *event_class, uint32_t id) { int ret = 0; - struct bt_object *obj = NULL; + struct bt_value *obj = NULL; if (!event_class) { ret = -1; @@ -195,20 +195,20 @@ int bt_ctf_event_class_set_id(struct bt_ctf_event_class *event_class, goto end; } - if (bt_object_integer_set(obj, id)) { + if (bt_value_integer_set(obj, id)) { ret = -1; goto end; } end: - BT_OBJECT_PUT(obj); + BT_VALUE_PUT(obj); return ret; } int bt_ctf_event_class_set_attribute( struct bt_ctf_event_class *event_class, const char *name, - struct bt_object *value) + struct bt_value *value) { int ret = 0; @@ -218,12 +218,12 @@ int bt_ctf_event_class_set_attribute( } if (!strcmp(name, "id") || !strcmp(name, "loglevel")) { - if (!bt_object_is_integer(value)) { + if (!bt_value_is_integer(value)) { ret = -1; goto end; } } else if (!strcmp(name, "name") || !strcmp(name, "model.emf.uri")) { - if (!bt_object_is_string(value)) { + if (!bt_value_is_string(value)) { ret = -1; goto end; } @@ -237,7 +237,7 @@ int bt_ctf_event_class_set_attribute( if (!strcmp(name, "id")) { int64_t val; - ret = bt_object_integer_get(value, &val); + ret = bt_value_integer_get(value, &val); if (ret) { goto end; @@ -289,11 +289,11 @@ end: return ret; } -struct bt_object * +struct bt_value * bt_ctf_event_class_get_attribute_value(struct bt_ctf_event_class *event_class, int index) { - struct bt_object *ret; + struct bt_value *ret; if (!event_class) { ret = NULL; @@ -306,11 +306,11 @@ end: return ret; } -struct bt_object * +struct bt_value * bt_ctf_event_class_get_attribute_value_by_name( struct bt_ctf_event_class *event_class, const char *name) { - struct bt_object *ret; + struct bt_value *ret; if (!event_class || !name) { ret = NULL; @@ -525,9 +525,9 @@ int bt_ctf_event_class_set_stream_id(struct bt_ctf_event_class *event_class, uint32_t stream_id) { int ret = 0; - struct bt_object *obj; + struct bt_value *obj; - obj = bt_object_integer_create_init(stream_id); + obj = bt_value_integer_create_init(stream_id); if (!obj) { ret = -1; @@ -538,7 +538,7 @@ int bt_ctf_event_class_set_stream_id(struct bt_ctf_event_class *event_class, "stream_id", obj); end: - BT_OBJECT_PUT(obj); + BT_VALUE_PUT(obj); return ret; } @@ -1031,7 +1031,7 @@ int bt_ctf_event_class_serialize(struct bt_ctf_event_class *event_class, int i; int count; int ret = 0; - struct bt_object *attr_value = NULL; + struct bt_value *attr_value = NULL; assert(event_class); assert(context); @@ -1059,12 +1059,12 @@ int bt_ctf_event_class_serialize(struct bt_ctf_event_class *event_class, goto end; } - switch (bt_object_get_type(attr_value)) { - case BT_OBJECT_TYPE_INTEGER: + switch (bt_value_get_type(attr_value)) { + case BT_VALUE_TYPE_INTEGER: { int64_t value; - ret = bt_object_integer_get(attr_value, &value); + ret = bt_value_integer_get(attr_value, &value); if (ret) { goto end; @@ -1075,11 +1075,11 @@ int bt_ctf_event_class_serialize(struct bt_ctf_event_class *event_class, break; } - case BT_OBJECT_TYPE_STRING: + case BT_VALUE_TYPE_STRING: { const char *value; - ret = bt_object_string_get(attr_value, &value); + ret = bt_value_string_get(attr_value, &value); if (ret) { goto end; @@ -1096,7 +1096,7 @@ int bt_ctf_event_class_serialize(struct bt_ctf_event_class *event_class, break; } - BT_OBJECT_PUT(attr_value); + BT_VALUE_PUT(attr_value); } if (event_class->context) { @@ -1121,7 +1121,7 @@ int bt_ctf_event_class_serialize(struct bt_ctf_event_class *event_class, g_string_append(context->string, "};\n\n"); end: context->current_indentation_level = 0; - BT_OBJECT_PUT(attr_value); + BT_VALUE_PUT(attr_value); return ret; } diff --git a/formats/ctf/ir/trace.c b/formats/ctf/ir/trace.c index d5786d33..8ff6371b 100644 --- a/formats/ctf/ir/trace.c +++ b/formats/ctf/ir/trace.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #define DEFAULT_IDENTIFIER_SIZE 128 #define DEFAULT_METADATA_STRING_SIZE 4096 @@ -188,13 +188,13 @@ error: } int bt_ctf_trace_set_environment_field(struct bt_ctf_trace *trace, - const char *name, struct bt_object *value) + const char *name, struct bt_value *value) { int ret = 0; if (!trace || !name || !value || bt_ctf_validate_identifier(name) || - !(bt_object_is_integer(value) || bt_object_is_string(value))) { + !(bt_value_is_integer(value) || bt_value_is_string(value))) { ret = -1; goto end; } @@ -211,17 +211,17 @@ int bt_ctf_trace_set_environment_field(struct bt_ctf_trace *trace, * * The object passed is frozen like all other attributes. */ - struct bt_object *attribute = + struct bt_value *attribute = bt_ctf_attributes_get_field_value_by_name( trace->environment, name); if (attribute) { - BT_OBJECT_PUT(attribute); + BT_VALUE_PUT(attribute); ret = -1; goto end; } - bt_object_freeze(value); + bt_value_freeze(value); } ret = bt_ctf_attributes_set_field_value(trace->environment, name, @@ -235,7 +235,7 @@ int bt_ctf_trace_set_environment_field_string(struct bt_ctf_trace *trace, const char *name, const char *value) { int ret = 0; - struct bt_object *env_value_string_obj = NULL; + struct bt_value *env_value_string_obj = NULL; if (!trace || !name || !value) { ret = -1; @@ -247,18 +247,18 @@ int bt_ctf_trace_set_environment_field_string(struct bt_ctf_trace *trace, * New environment fields may be added to a frozen trace, * but existing fields may not be changed. */ - struct bt_object *attribute = + struct bt_value *attribute = bt_ctf_attributes_get_field_value_by_name( trace->environment, name); if (attribute) { - BT_OBJECT_PUT(attribute); + BT_VALUE_PUT(attribute); ret = -1; goto end; } } - env_value_string_obj = bt_object_string_create_init(value); + env_value_string_obj = bt_value_string_create_init(value); if (!env_value_string_obj) { ret = -1; @@ -266,13 +266,13 @@ int bt_ctf_trace_set_environment_field_string(struct bt_ctf_trace *trace, } if (trace->frozen) { - bt_object_freeze(env_value_string_obj); + bt_value_freeze(env_value_string_obj); } ret = bt_ctf_trace_set_environment_field(trace, name, env_value_string_obj); end: - BT_OBJECT_PUT(env_value_string_obj); + BT_VALUE_PUT(env_value_string_obj); return ret; } @@ -281,7 +281,7 @@ int bt_ctf_trace_set_environment_field_integer(struct bt_ctf_trace *trace, const char *name, int64_t value) { int ret = 0; - struct bt_object *env_value_integer_obj = NULL; + struct bt_value *env_value_integer_obj = NULL; if (!trace || !name) { ret = -1; @@ -293,18 +293,18 @@ int bt_ctf_trace_set_environment_field_integer(struct bt_ctf_trace *trace, * New environment fields may be added to a frozen trace, * but existing fields may not be changed. */ - struct bt_object *attribute = + struct bt_value *attribute = bt_ctf_attributes_get_field_value_by_name( trace->environment, name); if (attribute) { - BT_OBJECT_PUT(attribute); + BT_VALUE_PUT(attribute); ret = -1; goto end; } } - env_value_integer_obj = bt_object_integer_create_init(value); + env_value_integer_obj = bt_value_integer_create_init(value); if (!env_value_integer_obj) { ret = -1; goto end; @@ -313,10 +313,10 @@ int bt_ctf_trace_set_environment_field_integer(struct bt_ctf_trace *trace, ret = bt_ctf_trace_set_environment_field(trace, name, env_value_integer_obj); if (trace->frozen) { - bt_object_freeze(env_value_integer_obj); + bt_value_freeze(env_value_integer_obj); } end: - BT_OBJECT_PUT(env_value_integer_obj); + BT_VALUE_PUT(env_value_integer_obj); return ret; } @@ -352,10 +352,10 @@ end: return ret; } -struct bt_object *bt_ctf_trace_get_environment_field_value( +struct bt_value *bt_ctf_trace_get_environment_field_value( struct bt_ctf_trace *trace, int index) { - struct bt_object *ret = NULL; + struct bt_value *ret = NULL; if (!trace) { goto end; @@ -367,10 +367,10 @@ end: return ret; } -struct bt_object *bt_ctf_trace_get_environment_field_value_by_name( +struct bt_value *bt_ctf_trace_get_environment_field_value_by_name( struct bt_ctf_trace *trace, const char *name) { - struct bt_object *ret = NULL; + struct bt_value *ret = NULL; if (!trace || !name) { goto end; @@ -649,7 +649,7 @@ void append_env_metadata(struct bt_ctf_trace *trace, g_string_append(context->string, "env {\n"); for (i = 0; i < env_size; ++i) { - struct bt_object *env_field_value_obj = NULL; + struct bt_value *env_field_value_obj = NULL; const char *entry_name; entry_name = bt_ctf_attributes_get_field_name( @@ -661,13 +661,13 @@ void append_env_metadata(struct bt_ctf_trace *trace, goto loop_next; } - switch (bt_object_get_type(env_field_value_obj)) { - case BT_OBJECT_TYPE_INTEGER: + switch (bt_value_get_type(env_field_value_obj)) { + case BT_VALUE_TYPE_INTEGER: { int ret; int64_t int_value; - ret = bt_object_integer_get(env_field_value_obj, + ret = bt_value_integer_get(env_field_value_obj, &int_value); if (ret) { @@ -679,13 +679,13 @@ void append_env_metadata(struct bt_ctf_trace *trace, int_value); break; } - case BT_OBJECT_TYPE_STRING: + case BT_VALUE_TYPE_STRING: { int ret; const char *str_value; char *escaped_str = NULL; - ret = bt_object_string_get(env_field_value_obj, + ret = bt_value_string_get(env_field_value_obj, &str_value); if (ret) { @@ -709,7 +709,7 @@ void append_env_metadata(struct bt_ctf_trace *trace, } loop_next: - BT_OBJECT_PUT(env_field_value_obj); + BT_VALUE_PUT(env_field_value_obj); } g_string_append(context->string, "};\n\n"); diff --git a/include/Makefile.am b/include/Makefile.am index b70ee7e6..b852ed15 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -6,7 +6,7 @@ babeltraceinclude_HEADERS = \ babeltrace/trace-handle.h \ babeltrace/list.h \ babeltrace/clock-types.h \ - babeltrace/objects.h + babeltrace/values.h babeltracectfinclude_HEADERS = \ babeltrace/ctf/events.h \ diff --git a/include/babeltrace/ctf-ir/attributes-internal.h b/include/babeltrace/ctf-ir/attributes-internal.h index e383c28d..b6a15a8c 100644 --- a/include/babeltrace/ctf-ir/attributes-internal.h +++ b/include/babeltrace/ctf-ir/attributes-internal.h @@ -33,35 +33,35 @@ extern "C" { #endif #include -#include +#include BT_HIDDEN -struct bt_object *bt_ctf_attributes_create(void); +struct bt_value *bt_ctf_attributes_create(void); BT_HIDDEN -void bt_ctf_attributes_destroy(struct bt_object *attr_obj); +void bt_ctf_attributes_destroy(struct bt_value *attr_obj); BT_HIDDEN -int bt_ctf_attributes_get_count(struct bt_object *attr_obj); +int bt_ctf_attributes_get_count(struct bt_value *attr_obj); BT_HIDDEN -const char *bt_ctf_attributes_get_field_name(struct bt_object *attr_obj, +const char *bt_ctf_attributes_get_field_name(struct bt_value *attr_obj, int index); BT_HIDDEN -struct bt_object *bt_ctf_attributes_get_field_value(struct bt_object *attr_obj, +struct bt_value *bt_ctf_attributes_get_field_value(struct bt_value *attr_obj, int index); BT_HIDDEN -int bt_ctf_attributes_set_field_value(struct bt_object *attr_obj, - const char *name, struct bt_object *value_obj); +int bt_ctf_attributes_set_field_value(struct bt_value *attr_obj, + const char *name, struct bt_value *value_obj); BT_HIDDEN -struct bt_object *bt_ctf_attributes_get_field_value_by_name( - struct bt_object *attr_obj, const char *name); +struct bt_value *bt_ctf_attributes_get_field_value_by_name( + struct bt_value *attr_obj, const char *name); BT_HIDDEN -int bt_ctf_attributes_freeze(struct bt_object *attr_obj); +int bt_ctf_attributes_freeze(struct bt_value *attr_obj); #ifdef __cplusplus } diff --git a/include/babeltrace/ctf-ir/event-internal.h b/include/babeltrace/ctf-ir/event-internal.h index 9b2e2075..db98771f 100644 --- a/include/babeltrace/ctf-ir/event-internal.h +++ b/include/babeltrace/ctf-ir/event-internal.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -42,7 +42,7 @@ struct bt_ctf_event_class { struct bt_ctf_base base; - struct bt_object *attributes; + struct bt_value *attributes; /* * Weak reference; an event class does not have ownership of a * stream class. diff --git a/include/babeltrace/ctf-ir/event.h b/include/babeltrace/ctf-ir/event.h index 4c90a2eb..e871902d 100644 --- a/include/babeltrace/ctf-ir/event.h +++ b/include/babeltrace/ctf-ir/event.h @@ -32,7 +32,7 @@ #include #include -#include +#include #ifdef __cplusplus extern "C" { @@ -118,7 +118,7 @@ extern int bt_ctf_event_class_set_id( */ extern int bt_ctf_event_class_set_attribute( struct bt_ctf_event_class *event_class, const char *name, - struct bt_object *value); + struct bt_value *value); /* * bt_ctf_event_class_get_attribute_count: get the number of attributes @@ -154,14 +154,14 @@ bt_ctf_event_class_get_attribute_name( * * Get an attribute's value (an object). The returned object's * reference count is incremented. When done with the object, the caller - * must call bt_object_put() on it. + * must call bt_value_put() on it. * * @param event_class Event class. * @param index Index of the attribute. * * Returns the attribute's object value, NULL on error. */ -extern struct bt_object * +extern struct bt_value * bt_ctf_event_class_get_attribute_value(struct bt_ctf_event_class *event_class, int index); @@ -171,14 +171,14 @@ bt_ctf_event_class_get_attribute_value(struct bt_ctf_event_class *event_class, * * Get an attribute's value (an object) by its name. The returned object's * reference count is incremented. When done with the object, the caller - * must call bt_object_put() on it. + * must call bt_value_put() on it. * * @param event_class Event class. * @param name Attribute's name * * Returns the attribute's object value, NULL on error. */ -extern struct bt_object * +extern struct bt_value * bt_ctf_event_class_get_attribute_value_by_name( struct bt_ctf_event_class *event_class, const char *name); diff --git a/include/babeltrace/ctf-ir/trace-internal.h b/include/babeltrace/ctf-ir/trace-internal.h index 4a76c1a1..b8a3d8c8 100644 --- a/include/babeltrace/ctf-ir/trace-internal.h +++ b/include/babeltrace/ctf-ir/trace-internal.h @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include @@ -52,7 +52,7 @@ struct bt_ctf_trace { int frozen; uuid_t uuid; int byte_order; /* A value defined in Babeltrace's "endian.h" */ - struct bt_object *environment; + struct bt_value *environment; GPtrArray *clocks; /* Array of pointers to bt_ctf_clock */ GPtrArray *stream_classes; /* Array of ptrs to bt_ctf_stream_class */ GPtrArray *streams; /* Array of ptrs to bt_ctf_stream */ diff --git a/include/babeltrace/ctf-ir/trace.h b/include/babeltrace/ctf-ir/trace.h index cc628a5b..d85a4bea 100644 --- a/include/babeltrace/ctf-ir/trace.h +++ b/include/babeltrace/ctf-ir/trace.h @@ -31,7 +31,7 @@ */ #include -#include +#include #include #ifdef __cplusplus @@ -84,8 +84,8 @@ extern struct bt_ctf_stream *bt_ctf_trace_create_stream( * If a value exists in the environment for the specified name, it is * replaced by the new value. * - * The value parameter _must_ be either an integer object or a - * string object. Other object types are not supported. + * The value parameter _must_ be either an integer value object or a + * string value object. Other object types are not supported. * * @param trace Trace instance. * @param name Name of the environment field (will be copied). @@ -95,7 +95,7 @@ extern struct bt_ctf_stream *bt_ctf_trace_create_stream( */ extern int bt_ctf_trace_set_environment_field( struct bt_ctf_trace *trace, const char *name, - struct bt_object *value); + struct bt_value *value); /* * bt_ctf_trace_set_environment_field_string: sets a string environment @@ -167,14 +167,14 @@ bt_ctf_trace_get_environment_field_name(struct bt_ctf_trace *trace, * * Get an environment field's value (an object). The returned object's * reference count is incremented. When done with the object, the caller - * must call bt_object_put() on it. + * must call bt_value_put() on it. * * @param trace Trace instance. * @param index Index of the environment field. * * Returns the environment field's object value, NULL on error. */ -extern struct bt_object * +extern struct bt_value * bt_ctf_trace_get_environment_field_value(struct bt_ctf_trace *trace, int index); @@ -184,14 +184,14 @@ bt_ctf_trace_get_environment_field_value(struct bt_ctf_trace *trace, * * Get an environment field's value (an object) by its field name. The * returned object's reference count is incremented. When done with the - * object, the caller must call bt_object_put() on it. + * object, the caller must call bt_value_put() on it. * * @param trace Trace instance. * @param name Environment field's name * * Returns the environment field's object value, NULL on error. */ -extern struct bt_object * +extern struct bt_value * bt_ctf_trace_get_environment_field_value_by_name(struct bt_ctf_trace *trace, const char *name); diff --git a/include/babeltrace/ctf-ir/utils.h b/include/babeltrace/ctf-ir/utils.h index e574bd60..d661ed88 100644 --- a/include/babeltrace/ctf-ir/utils.h +++ b/include/babeltrace/ctf-ir/utils.h @@ -34,8 +34,6 @@ extern "C" { #endif -#include - /* * bt_ctf_validate_identifier: validate an identifier against the CTF spec. * diff --git a/include/babeltrace/objects.h b/include/babeltrace/objects.h deleted file mode 100644 index 420bd628..00000000 --- a/include/babeltrace/objects.h +++ /dev/null @@ -1,1083 +0,0 @@ -#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 - * - * 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 - * - * 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 - * @bug No known bugs - */ - -#include -#include -#include - -#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 object (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, -}; - -/** - * 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 = -3, - - /** Invalid arguments. */ - /* -22 for compatibility with -EINVAL */ - BT_OBJECT_STATUS_INVAL = -22, - - /** General error. */ - BT_OBJECT_STATUS_ERROR = -1, - - /** Okay, no error. */ - BT_OBJECT_STATUS_OK = 0, -}; - -/** - * Object. - */ -struct bt_object; - -/** - * The null object singleton. - * - * 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 object singleton to - * find out if it's a null object, or otherwise use bt_object_is_null(). - * - * The null object singleton is always frozen (see bt_object_freeze() - * and bt_object_is_frozen()). - * - * Functions of this API return this when the object is actually a - * null object (of type #BT_OBJECT_TYPE_NULL), 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 \em 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 not changed. Resetting - * \p _src_object to \c NULL ensures the object will not be put - * twice later; its ownership is indeed \em 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 - * - * @see bt_object_put() - */ -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) - * @see bt_object_get() - */ -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) - * - * @see bt_object_is_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 - * - * @see bt_object_freeze() - */ -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 #BT_OBJECT_TYPE_UNKNOWN - * on error - * - * @see #bt_object_type (object types) - * @see bt_object_is_null() - * @see bt_object_is_bool() - * @see bt_object_is_integer() - * @see bt_object_is_float() - * @see bt_object_is_string() - * @see bt_object_is_array() - * @see bt_object_is_map() - */ -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 - * - * @see bt_object_get_type() - */ -static inline -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 - * - * @see bt_object_get_type() - */ -static inline -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 - * - * @see bt_object_get_type() - */ -static inline -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 - * - * @see bt_object_get_type() - */ -static inline -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 - * - * @see bt_object_get_type() - */ -static inline -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 - * - * @see bt_object_get_type() - */ -static inline -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 - * - * @see bt_object_get_type() - */ -static inline -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 - * - * @see bt_object_bool_create_init() (creates an initialized - * boolean object) - */ -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 - * - * @see bt_object_integer_create_init() (creates an initialized - * integer object) - */ -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 - * - * @see bt_object_float_create_init() (creates an initialized floating - * point number object) - */ -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 - * - * @see bt_object_string_create_init() (creates an initialized - * string object) - */ -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 object \p bool_obj. - * - * @param bool_obj Boolean object - * @param val Returned boolean value - * @returns One of #bt_object_status values - * - * @see bt_object_bool_set() - */ -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 One of #bt_object_status values - * - * @see bt_object_bool_get() - */ -extern enum bt_object_status bt_object_bool_set(struct bt_object *bool_obj, - bool val); - -/** - * Gets the integer value of the integer object \p integer_obj. - * - * @param integer_obj Integer object - * @param val Returned integer value - * @returns One of #bt_object_status values - * - * @see bt_object_integer_set() - */ -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 - * \p val. - * - * @param integer_obj Integer object - * @param val New integer value - * @returns One of #bt_object_status values - * - * @see bt_object_integer_get() - */ -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 - * object \p float_obj. - * - * @param float_obj Floating point number object - * @param val Returned floating point number value - * @returns One of #bt_object_status values - * - * @see bt_object_float_set() - */ -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 - * object \p float_obj to \p val. - * - * @param float_obj Floating point number object - * @param val New floating point number value - * @returns One of #bt_object_status values - * - * @see bt_object_float_get() - */ -extern enum bt_object_status bt_object_float_set( - struct bt_object *float_obj, double val); - -/** - * 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. The ownership of the returned string is \em not - * transferred to the caller. - * - * @param string_obj String object - * @param val Returned string value - * @returns One of #bt_object_status values - * - * @see bt_object_string_set() - */ -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 - * \p val. - * - * \p val is copied. - * - * @param string_obj String object - * @param val New string value (copied) - * @returns One of #bt_object_status values - * - * @see bt_object_string_get() - */ -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 if the return value is 0 (empty) or a - * positive value, or one of - * #bt_object_status negative values otherwise - * - * @see bt_object_array_is_empty() - */ -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 - * - * @see bt_object_array_size() - */ -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 One of #bt_object_status values - * - * @see bt_object_array_append_bool() - * @see bt_object_array_append_integer() - * @see bt_object_array_append_float() - * @see bt_object_array_append_string() - * @see bt_object_array_append_array() - * @see bt_object_array_append_map() - */ -extern enum bt_object_status 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 One of #bt_object_status values - * - * @see bt_object_array_append() - */ -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. - * 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 One of #bt_object_status values - * - * @see bt_object_array_append() - */ -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 - * \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 One of #bt_object_status values - * - * @see bt_object_array_append() - */ -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. - * 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 One of #bt_object_status values - * - * @see bt_object_array_append() - */ -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. - * 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 One of #bt_object_status values - * - * @see bt_object_array_append() - */ -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 - * 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 One of #bt_object_status values - * - * @see bt_object_array_append() - */ -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 - * \p array_obj by \p element_obj. - * - * The replaced object's reference count is decremented, unless it's - * a null object. The reference count of \p element_obj is incremented, - * unless it's a null object. - * - * @param array_obj Array object - * @param index Index of element object to replace - * @param element_obj New element object at position \p index of - * \p array_obj - * @returns One of #bt_object_status values - */ -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 if the return value is 0 (empty) or a - * positive value, or one of - * #bt_object_status negative values otherwise - * - * @see bt_object_map_is_empty() - */ -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 - * - * @see bt_object_map_size() - */ -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 weak reference: - * 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 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, - 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 One of #bt_object_status values - * - * @see bt_object_map_insert_bool() - * @see bt_object_map_insert_integer() - * @see bt_object_map_insert_float() - * @see bt_object_map_insert_string() - * @see bt_object_map_insert_array() - * @see bt_object_map_insert_map() - */ -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 - * 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 One of #bt_object_status values - * - * @see bt_object_map_insert() - */ -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 - * 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 One of #bt_object_status values - * - * @see bt_object_map_insert() - */ -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 - * 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 One of #bt_object_status values - * - * @see bt_object_map_insert() - */ -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 - * 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 One of #bt_object_status values - * - * @see bt_object_map_insert() - */ -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 - * 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 One of #bt_object_status values - * - * @see bt_object_map_insert() - */ -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 - * 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 One of #bt_object_status values - * - * @see bt_object_map_insert() - */ -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. - * - * The created object's reference count is set to 1, unless - * \p object is a null object. - * - * Copying a frozen object is allowed: the resulting copy is not frozen. - * - * @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 */ diff --git a/include/babeltrace/values.h b/include/babeltrace/values.h new file mode 100644 index 00000000..c0a3fa45 --- /dev/null +++ b/include/babeltrace/values.h @@ -0,0 +1,1032 @@ +#ifndef _BABELTRACE_VALUES_H +#define _BABELTRACE_VALUES_H + +/* + * Babeltrace - Value objects + * + * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation + * Copyright (c) 2015 Philippe Proulx + * + * 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 values.h + * @brief Value objects + * + * This is a set of value objects. The following functions allow you + * to create, modify, and destroy: + * + * - \link bt_value_null null value objects\endlink + * - \link bt_value_bool_create() boolean value objects\endlink + * - \link bt_value_integer_create() integer value objects\endlink + * - \link bt_value_float_create() floating point number + * value objects\endlink + * - \link bt_value_string_create() string value objects\endlink + * - \link bt_value_array_create() array value objects\endlink, + * containing zero or more value objects + * - \link bt_value_map_create() map value objects\endlink, mapping + * string keys to value objects + * + * All the value object types above, except for null values (which + * always point to the same \link bt_value_null singleton\endlink), have + * a reference count property. Once a value object is created, its + * reference count is set to 1. When \link bt_value_array_append() + * appending a value to an array value object\endlink, or + * \link bt_value_map_insert() inserting a value object into a map + * value object\endlink, its reference count is incremented, as well as + * when getting a value object back from those structures. The + * bt_value_get() and bt_value_put() functions exist to deal with + * reference counting. Once you are done with a value object, pass it to + * bt_value_put(). + * + * Most functions of this API return a status code, one of the values in + * #bt_value_status. + * + * You can create a deep copy of any value object using the + * bt_value_copy() function. You can compare two given value objects + * using bt_value_compare(). + * + * Any value object may be frozen using bt_value_freeze(). You may get + * the raw value of a frozen value object, but you cannot modify it. + * Reference counting still works on frozen value objects. You may also + * copy and compare frozen value objects. + * + * @author Philippe Proulx + * @bug No known bugs + */ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Value object type. + */ +enum bt_value_type { + /** Unknown value object, used as an error code. */ + BT_VALUE_TYPE_UNKNOWN = -1, + + /** Null value object. */ + BT_VALUE_TYPE_NULL = 0, + + /** Boolean value object (holds \c true or \c false). */ + BT_VALUE_TYPE_BOOL = 1, + + /** Integer value object (holds a signed 64-bit integer raw value). */ + BT_VALUE_TYPE_INTEGER = 2, + + /** Floating point number value object (holds a \c double raw value). */ + BT_VALUE_TYPE_FLOAT = 3, + + /** String value object. */ + BT_VALUE_TYPE_STRING = 4, + + /** Array value object. */ + BT_VALUE_TYPE_ARRAY = 5, + + /** Map value object. */ + BT_VALUE_TYPE_MAP = 6, +}; + +/** + * Status codes. + */ +enum bt_value_status { + /** Value object cannot be altered because it's frozen. */ + BT_VALUE_STATUS_FROZEN = -4, + + /** Operation cancelled. */ + BT_VALUE_STATUS_CANCELLED = -3, + + /** Invalid arguments. */ + /* -22 for compatibility with -EINVAL */ + BT_VALUE_STATUS_INVAL = -22, + + /** General error. */ + BT_VALUE_STATUS_ERROR = -1, + + /** Okay, no error. */ + BT_VALUE_STATUS_OK = 0, +}; + +/** + * Value object. + */ +struct bt_value; + +/** + * The null value object singleton. + * + * Use this everytime you need a null value object. + * + * The null value object singleton has no reference count; there's only + * one. You may directly compare any value object to the null value + * object singleton to find out if it's a null value object, or + * otherwise use bt_value_is_null(). + * + * The null value object singleton is always frozen (see + * bt_value_freeze() and bt_value_is_frozen()). + * + * Functions of this API return this when the value object is actually a + * null value object (of type #BT_VALUE_TYPE_NULL), whereas \c NULL + * means an error of some sort. + */ +extern struct bt_value *bt_value_null; + +/** + * User function type for bt_value_map_foreach(). + * + * \p object is a \em weak reference; you must pass it to + * bt_value_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 Value object of map entry (weak reference) + * @param data User data + * @returns \c true to continue the loop + */ +typedef bool (* bt_value_map_foreach_cb)(const char *key, + struct bt_value *object, void *data); + +/** + * Puts the value object \p _object (calls bt_value_put() on it), and + * resets the variable to \c NULL. + * + * This is something that is often done when putting a value object; + * resetting the variable to \c NULL makes sure it cannot be put a + * second time later. + * + * @param _object Value object to put + * + * @see BT_VALUE_MOVE() (moves a value object from one variable to the + * other without putting it) + */ +#define BT_VALUE_PUT(_object) \ + do { \ + bt_value_put(_object); \ + (_object) = NULL; \ + } while (0) + +/** + * Moves the value object referenced by the variable \p _src_object to + * the \p _dst_object variable, then resets \p _src_object to \c NULL. + * + * The value object's reference count is not changed. Resetting + * \p _src_object to \c NULL ensures the value object will not be put + * twice later; its ownership is indeed \em moved from the source + * variable to the destination variable. + * + * @param _src_object Source value object variable + * @param _dst_object Destination value object variable + */ +#define BT_VALUE_MOVE(_dst_object, _src_object) \ + do { \ + (_dst_object) = (_src_object); \ + (_src_object) = NULL; \ + } while (0) + +/** + * Increments the reference count of \p object. + * + * @param object Value object of which to increment the reference count + * + * @see bt_value_put() + */ +extern void bt_value_get(struct bt_value *object); + +/** + * Decrements the reference count of \p object, destroying it when this + * count reaches 0. + * + * @param object Value object of which to decrement the reference count + * + * @see bt_value_get() + */ +extern void bt_value_put(struct bt_value *object); + +/** + * Recursively freezes the value object \p object. + * + * A frozen value object cannot be modified; it is considered immutable. + * Reference counting still works on a frozen value object though: you + * may pass a frozen value object to bt_value_get() and bt_value_put(). + * + * @param object Value object to freeze + * @returns One of #bt_value_status values; if \p object + * is already frozen, though, #BT_VALUE_STATUS_OK + * is returned anyway (i.e. this function never + * returns #BT_VALUE_STATUS_FROZEN) + * + * @see bt_value_is_frozen() + */ +extern enum bt_value_status bt_value_freeze(struct bt_value *object); + +/** + * Checks whether \p object is frozen or not. + * + * @param object Value object to check + * @returns \c true if \p object is frozen + * + * @see bt_value_freeze() + */ +extern bool bt_value_is_frozen(const struct bt_value *object); + +/** + * Returns the type of \p object. + * + * @param object Value object of which to get the type + * @returns Value object's type, or #BT_VALUE_TYPE_UNKNOWN + * on error + * + * @see #bt_value_type (value object types) + * @see bt_value_is_null() + * @see bt_value_is_bool() + * @see bt_value_is_integer() + * @see bt_value_is_float() + * @see bt_value_is_string() + * @see bt_value_is_array() + * @see bt_value_is_map() + */ +extern enum bt_value_type bt_value_get_type(const struct bt_value *object); + +/** + * Checks whether \p object is a null value object. The only valid null + * value object is \ref bt_value_null. + * + * @param object Value object to check + * @returns \c true if \p object is a null value object + * + * @see bt_value_get_type() + */ +static inline +bool bt_value_is_null(const struct bt_value *object) +{ + return bt_value_get_type(object) == BT_VALUE_TYPE_NULL; +} + +/** + * Checks whether \p object is a boolean value object. + * + * @param object Value object to check + * @returns \c true if \p object is a boolean value object + * + * @see bt_value_get_type() + */ +static inline +bool bt_value_is_bool(const struct bt_value *object) +{ + return bt_value_get_type(object) == BT_VALUE_TYPE_BOOL; +} + +/** + * Checks whether \p object is an integer value object. + * + * @param object Value object to check + * @returns \c true if \p object is an integer value object + * + * @see bt_value_get_type() + */ +static inline +bool bt_value_is_integer(const struct bt_value *object) +{ + return bt_value_get_type(object) == BT_VALUE_TYPE_INTEGER; +} + +/** + * Checks whether \p object is a floating point number value object. + * + * @param object Value object to check + * @returns \c true if \p object is a floating point + * number value object + * + * @see bt_value_get_type() + */ +static inline +bool bt_value_is_float(const struct bt_value *object) +{ + return bt_value_get_type(object) == BT_VALUE_TYPE_FLOAT; +} + +/** + * Checks whether \p object is a string value object. + * + * @param object Value object to check + * @returns \c true if \p object is a string value object + * + * @see bt_value_get_type() + */ +static inline +bool bt_value_is_string(const struct bt_value *object) +{ + return bt_value_get_type(object) == BT_VALUE_TYPE_STRING; +} + +/** + * Checks whether \p object is an array value object. + * + * @param object Value object to check + * @returns \c true if \p object is an array value object + * + * @see bt_value_get_type() + */ +static inline +bool bt_value_is_array(const struct bt_value *object) +{ + return bt_value_get_type(object) == BT_VALUE_TYPE_ARRAY; +} + +/** + * Checks whether \p object is a map value object. + * + * @param object Value object to check + * @returns \c true if \p object is a map value object + * + * @see bt_value_get_type() + */ +static inline +bool bt_value_is_map(const struct bt_value *object) +{ + return bt_value_get_type(object) == BT_VALUE_TYPE_MAP; +} + +/** + * Creates a boolean value object. The created boolean value object's + * initial raw value is \c false. + * + * The created value object's reference count is set to 1. + * + * @returns Created value object on success, or \c NULL on error + * + * @see bt_value_bool_create_init() (creates an initialized + * boolean value object) + */ +extern struct bt_value *bt_value_bool_create(void); + +/** + * Creates a boolean value object with its initial raw value set to + * \p val. + * + * The created value object's reference count is set to 1. + * + * @param val Initial raw value + * @returns Created value object on success, or \c NULL on error + */ +extern struct bt_value *bt_value_bool_create_init(bool val); + +/** + * Creates an integer value object. The created integer value object's + * initial raw value is 0. + * + * The created value object's reference count is set to 1. + * + * @returns Created value object on success, or \c NULL on error + * + * @see bt_value_integer_create_init() (creates an initialized + * integer value object) + */ +extern struct bt_value *bt_value_integer_create(void); + +/** + * Creates an integer value object with its initial raw value set to + * \p val. + * + * The created value object's reference count is set to 1. + * + * @param val Initial raw value + * @returns Created value object on success, or \c NULL on error + */ +extern struct bt_value *bt_value_integer_create_init(int64_t val); + +/** + * Creates a floating point number value object. The created floating + * point number value object's initial raw value is 0. + * + * The created value object's reference count is set to 1. + * + * @returns Created value object on success, or \c NULL on error + * + * @see bt_value_float_create_init() (creates an initialized floating + * point number value object) + */ +extern struct bt_value *bt_value_float_create(void); + +/** + * Creates a floating point number value object with its initial raw + * value set to \p val. + * + * The created value object's reference count is set to 1. + * + * @param val Initial raw value + * @returns Created value object on success, or \c NULL on error + */ +extern struct bt_value *bt_value_float_create_init(double val); + +/** + * Creates a string value object. The string value object is initially + * empty. + * + * The created value object's reference count is set to 1. + * + * @returns Created value object on success, or \c NULL on error + * + * @see bt_value_string_create_init() (creates an initialized + * string value object) + */ +extern struct bt_value *bt_value_string_create(void); + +/** + * Creates a string value object with its initial raw value set to + * \p val. + * + * On success, \p val is \em copied. + * + * The created value object's reference count is set to 1. + * + * @param val Initial raw value (copied on success) + * @returns Created value object on success, or \c NULL on error + */ +extern struct bt_value *bt_value_string_create_init(const char *val); + +/** + * Creates an empty array value object. + * + * The created value object's reference count is set to 1. + * + * @returns Created value object on success, or \c NULL on error + */ +extern struct bt_value *bt_value_array_create(void); + +/** + * Creates an empty map value object. + * + * The created value object's reference count is set to 1. + * + * @returns Created value object on success, or \c NULL on error + */ +extern struct bt_value *bt_value_map_create(void); + +/** + * Gets the boolean raw value of the boolean value object \p bool_obj. + * + * @param bool_obj Boolean value object + * @param val Returned boolean raw value + * @returns One of #bt_value_status values + * + * @see bt_value_bool_set() + */ +extern enum bt_value_status bt_value_bool_get( + const struct bt_value *bool_obj, bool *val); + +/** + * Sets the boolean raw value of the boolean value object \p bool_obj + * to \p val. + * + * @param bool_obj Boolean value object + * @param val New boolean raw value + * @returns One of #bt_value_status values + * + * @see bt_value_bool_get() + */ +extern enum bt_value_status bt_value_bool_set(struct bt_value *bool_obj, + bool val); + +/** + * Gets the integer raw value of the integer value object + * \p integer_obj. + * + * @param integer_obj Integer value object + * @param val Returned integer raw value + * @returns One of #bt_value_status values + * + * @see bt_value_integer_set() + */ +extern enum bt_value_status bt_value_integer_get( + const struct bt_value *integer_obj, int64_t *val); + +/** + * Sets the integer raw value of the integer value object \p integer_obj + * to \p val. + * + * @param integer_obj Integer value object + * @param val New integer raw value + * @returns One of #bt_value_status values + * + * @see bt_value_integer_get() + */ +extern enum bt_value_status bt_value_integer_set( + struct bt_value *integer_obj, int64_t val); + +/** + * Gets the floating point number raw value of the floating point number + * value object \p float_obj. + * + * @param float_obj Floating point number value object + * @param val Returned floating point number raw value + * @returns One of #bt_value_status values + * + * @see bt_value_float_set() + */ +extern enum bt_value_status bt_value_float_get( + const struct bt_value *float_obj, double *val); + +/** + * Sets the floating point number raw value of the floating point number + * value object \p float_obj to \p val. + * + * @param float_obj Floating point number value object + * @param val New floating point number raw value + * @returns One of #bt_value_status values + * + * @see bt_value_float_get() + */ +extern enum bt_value_status bt_value_float_set( + struct bt_value *float_obj, double val); + +/** + * Gets the string raw value of the string value object \p string_obj. + * The returned string is valid as long as this value object exists and + * is not modified. The ownership of the returned string is \em not + * transferred to the caller. + * + * @param string_obj String value object + * @param val Returned string raw value + * @returns One of #bt_value_status values + * + * @see bt_value_string_set() + */ +extern enum bt_value_status bt_value_string_get( + const struct bt_value *string_obj, const char **val); + +/** + * Sets the string raw value of the string value object \p string_obj to + * \p val. + * + * On success, \p val is \em copied. + * + * @param string_obj String value object + * @param val New string raw value (copied on successf) + * @returns One of #bt_value_status values + * + * @see bt_value_string_get() + */ +extern enum bt_value_status bt_value_string_set(struct bt_value *string_obj, + const char *val); + +/** + * Gets the size of the array value object \p array_obj, that is, the + * number of value objects contained in \p array_obj. + * + * @param array_obj Array value object + * @returns Array size if the return value is 0 (empty) or a + * positive value, or one of + * #bt_value_status negative values otherwise + * + * @see bt_value_array_is_empty() + */ +extern int bt_value_array_size(const struct bt_value *array_obj); + +/** + * Returns \c true if the array value object \p array_obj is empty. + * + * @param array_obj Array value object + * @returns \c true if \p array_obj is empty + * + * @see bt_value_array_size() + */ +extern bool bt_value_array_is_empty(const struct bt_value *array_obj); + +/** + * Gets the value object of the array value object \p array_obj at the + * index \p index. + * + * The returned value object's reference count is incremented, unless + * it's a null value object. + * + * @param array_obj Array value object + * @param index Index of value object to get + * @returns Value object at index \p index on + * success, or \c NULL on error + */ +extern struct bt_value *bt_value_array_get(const struct bt_value *array_obj, + size_t index); + +/** + * Appends the value object \p element_obj to the array value + * object \p array_obj. + * + * The appended value object's reference count is incremented, unless + * it's a null object. + * + * @param array_obj Array value object + * @param element_obj Value object to append + * @returns One of #bt_value_status values + * + * @see bt_value_array_append_bool() + * @see bt_value_array_append_integer() + * @see bt_value_array_append_float() + * @see bt_value_array_append_string() + * @see bt_value_array_append_array() + * @see bt_value_array_append_map() + */ +extern enum bt_value_status bt_value_array_append(struct bt_value *array_obj, + struct bt_value *element_obj); + +/** + * Appends the boolean raw value \p val to the array value object + * \p array_obj. This is a convenience function which creates the + * underlying boolean value object before appending it. + * + * The created boolean value object's reference count is set to 1. + * + * @param array_obj Array value object + * @param val Boolean raw value to append + * @returns One of #bt_value_status values + * + * @see bt_value_array_append() + */ +extern enum bt_value_status bt_value_array_append_bool( + struct bt_value *array_obj, bool val); + +/** + * Appends the integer raw value \p val to the array value object + * \p array_obj. This is a convenience function which creates the + * underlying integer value object before appending it. + * + * The created integer value object's reference count is set to 1. + * + * @param array_obj Array value object + * @param val Integer raw value to append + * @returns One of #bt_value_status values + * + * @see bt_value_array_append() + */ +extern enum bt_value_status bt_value_array_append_integer( + struct bt_value *array_obj, int64_t val); + +/** + * Appends the floating point number raw value \p val to the array value + * object \p array_obj. This is a convenience function which creates the + * underlying floating point number value object before appending it. + * + * The created floating point number value object's reference count is + * set to 1. + * + * @param array_obj Array value object + * @param val Floating point number raw value to append + * @returns One of #bt_value_status values + * + * @see bt_value_array_append() + */ +extern enum bt_value_status bt_value_array_append_float( + struct bt_value *array_obj, double val); + +/** + * Appends the string raw value \p val to the array value object + * \p array_obj. This is a convenience function which creates the + * underlying string value object before appending it. + * + * On success, \p val is \em copied. + * + * The created string value object's reference count is set to 1. + * + * @param array_obj Array value object + * @param val String raw value to append (copied on success) + * @returns One of #bt_value_status values + * + * @see bt_value_array_append() + */ +extern enum bt_value_status bt_value_array_append_string( + struct bt_value *array_obj, const char *val); + +/** + * Appends an empty array value object to the array value object + * \p array_obj. This is a convenience function which creates the + * underlying array value object before appending it. + * + * The created array value object's reference count is set to 1. + * + * @param array_obj Array value object + * @returns One of #bt_value_status values + * + * @see bt_value_array_append() + */ +extern enum bt_value_status bt_value_array_append_array( + struct bt_value *array_obj); + +/** + * Appends an empty map value object to the array value object + * \p array_obj. This is a convenience function which creates the + * underlying map value object before appending it. + * + * The created map value object's reference count is set to 1. + * + * @param array_obj Array value object + * @returns One of #bt_value_status values + * + * @see bt_value_array_append() + */ +extern enum bt_value_status bt_value_array_append_map( + struct bt_value *array_obj); + +/** + * Replaces the value object at index \p index of the array + * value object \p array_obj by \p element_obj. + * + * The replaced value object's reference count is decremented, unless + * it's a null value object. The reference count of \p element_obj is + * incremented, unless it's a null value object. + * + * @param array_obj Array value object + * @param index Index of value object to replace + * @param element_obj New value object at position \p index of + * \p array_obj + * @returns One of #bt_value_status values + */ +extern enum bt_value_status bt_value_array_set(struct bt_value *array_obj, + size_t index, struct bt_value *element_obj); + +/** + * Gets the size of a map value object, that is, the number of entries + * contained in a map value object. + * + * @param map_obj Map value object + * @returns Map size if the return value is 0 (empty) or a + * positive value, or one of + * #bt_value_status negative values otherwise + * + * @see bt_value_map_is_empty() + */ +extern int bt_value_map_size(const struct bt_value *map_obj); + +/** + * Returns \c true if the map value object \p map_obj is empty. + * + * @param map_obj Map value object + * @returns \c true if \p map_obj is empty + * + * @see bt_value_map_size() + */ +extern bool bt_value_map_is_empty(const struct bt_value *map_obj); + +/** + * Gets the value object associated with the key \p key within the + * map value object \p map_obj. + * + * The returned value object's reference count is incremented, unless + * it's a null value object. + * + * @param map_obj Map value object + * @param key Key of the value object to get + * @returns Value object associated with the key \p key + * on success, or \c NULL on error + */ +extern struct bt_value *bt_value_map_get(const struct bt_value *map_obj, + const char *key); + +/** + * Calls a provided user function \p cb for each value object of the map + * value object \p map_obj. + * + * The value object passed to the user function is a + * weak reference: you must call bt_value_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 call. + * + * The user function must return \c true to continue the loop, or + * \c false to break it. + * + * @param map_obj Map value object + * @param cb User function to call back + * @param data User data passed to the user function + * @returns One of #bt_value_status values; more + * specifically, #BT_VALUE_STATUS_CANCELLED is + * returned if the loop was cancelled by the user + * function + */ +extern enum bt_value_status bt_value_map_foreach( + const struct bt_value *map_obj, bt_value_map_foreach_cb cb, + void *data); + +/** + * Returns whether or not the map value object \p map_obj contains the + * key \p key. + * + * @param map_obj Map value 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_value_map_has_key(const struct bt_value *map_obj, + const char *key); + +/** + * Inserts the value object \p element_obj associated with the key + * \p key into the map value object \p map_obj. If \p key exists in + * \p map_obj, the associated value object is first put, and then + * replaced by \p element_obj. + * + * On success, \p key is \em copied. + * + * The inserted value object's reference count is incremented, unless + * it's a null value object. + * + * @param map_obj Map value object + * @param key Key (copied on success) of value object to insert + * @param element_obj Value object to insert, associated with the + * key \p key + * @returns One of #bt_value_status values + * + * @see bt_value_map_insert_bool() + * @see bt_value_map_insert_integer() + * @see bt_value_map_insert_float() + * @see bt_value_map_insert_string() + * @see bt_value_map_insert_array() + * @see bt_value_map_insert_map() + */ +extern enum bt_value_status bt_value_map_insert( + struct bt_value *map_obj, const char *key, + struct bt_value *element_obj); + +/** + * Inserts the boolean raw value \p val associated with the key \p key + * into the map value object \p map_obj. This is a convenience function + * which creates the underlying boolean value object before + * inserting it. + * + * On success, \p key is \em copied. + * + * The created boolean value object's reference count is set to 1. + * + * @param map_obj Map value object + * @param key Key (copied on success) of boolean value object + * to insert + * @param val Boolean raw value to insert, associated with + * the key \p key + * @returns One of #bt_value_status values + * + * @see bt_value_map_insert() + */ +extern enum bt_value_status bt_value_map_insert_bool( + struct bt_value *map_obj, const char *key, bool val); + +/** + * Inserts the integer raw value \p val associated with the key \p key + * into the map value object \p map_obj. This is a convenience function + * which creates the underlying integer value object before inserting it. + * + * On success, \p key is \em copied. + * + * The created integer value object's reference count is set to 1. + * + * @param map_obj Map value object + * @param key Key (copied on success) of integer value object + * to insert + * @param val Integer raw value to insert, associated with + * the key \p key + * @returns One of #bt_value_status values + * + * @see bt_value_map_insert() + */ +extern enum bt_value_status bt_value_map_insert_integer( + struct bt_value *map_obj, const char *key, int64_t val); + +/** + * Inserts the floating point number raw value \p val associated with + * the key \p key into the map value object \p map_obj. This is a + * convenience function which creates the underlying floating point + * number value object before inserting it. + * + * On success, \p key is \em copied. + * + * The created floating point number value object's reference count is + * set to 1. + * + * @param map_obj Map value object + * @param key Key (copied on success) of floating point number + * value object to insert + * @param val Floating point number raw value to insert, + * associated with the key \p key + * @returns One of #bt_value_status values + * + * @see bt_value_map_insert() + */ +extern enum bt_value_status bt_value_map_insert_float( + struct bt_value *map_obj, const char *key, double val); + +/** + * Inserts the string raw value \p val associated with the key \p key + * into the map value object \p map_obj. This is a convenience function + * which creates the underlying string value object before inserting it. + * + * On success, \p val and \p key are \em copied. + * + * The created string value object's reference count is set to 1. + * + * @param map_obj Map value object + * @param key Key (copied on success) of string value object + * to insert + * @param val String raw value to insert (copied on success), + * associated with the key \p key + * @returns One of #bt_value_status values + * + * @see bt_value_map_insert() + */ +extern enum bt_value_status bt_value_map_insert_string( + struct bt_value *map_obj, const char *key, const char *val); + +/** + * Inserts an empty array value object associated with the key \p key + * into the map value object \p map_obj. This is a convenience function + * which creates the underlying array value object before inserting it. + * + * On success, \p key is \em copied. + * + * The created array value object's reference count is set to 1. + * + * @param map_obj Map value object + * @param key Key (copied on success) of empty array value + * object to insert + * @returns One of #bt_value_status values + * + * @see bt_value_map_insert() + */ +extern enum bt_value_status bt_value_map_insert_array( + struct bt_value *map_obj, const char *key); + +/** + * Inserts an empty map value object associated with the key \p key into + * the map value object \p map_obj. This is a convenience function which + * creates the underlying map value object before inserting it. + * + * On success, \p key is \em copied. + * + * The created map value object's reference count is set to 1. + * + * @param map_obj Map value object + * @param key Key (copied on success) of empty map value + * object to insert + * @returns One of #bt_value_status values + * + * @see bt_value_map_insert() + */ +extern enum bt_value_status bt_value_map_insert_map( + struct bt_value *map_obj, const char *key); + +/** + * Creates a deep copy of the value object \p object. + * + * The created value object's reference count is set to 1, unless + * \p object is a null value object. + * + * Copying a frozen value object is allowed: the resulting copy is + * \em not frozen. + * + * @param object Value object to copy + * @returns Deep copy of \p object on success, or \c NULL + * on error + */ +extern struct bt_value *bt_value_copy(const struct bt_value *object); + +/** + * Compares the value objects \p object_a and \p object_b and returns + * \c true if they have the same \em content (raw values). + * + * @param object_a Value object A + * @param object_b Value 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_value_compare(const struct bt_value *object_a, + const struct bt_value *object_b); + +#ifdef __cplusplus +} +#endif + +#endif /* _BABELTRACE_VALUES_H */ diff --git a/lib/Makefile.am b/lib/Makefile.am index 8fe87f34..54d065fb 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -10,7 +10,7 @@ libbabeltrace_la_SOURCES = babeltrace.c \ trace-handle.c \ trace-collection.c \ registry.c \ - objects.c + values.c libbabeltrace_la_LDFLAGS = -version-info $(BABELTRACE_LIBRARY_VERSION) diff --git a/lib/objects.c b/lib/objects.c deleted file mode 100644 index 8a0bc650..00000000 --- a/lib/objects.c +++ /dev/null @@ -1,1217 +0,0 @@ -/* - * objects.c: basic object system - * - * Babeltrace Library - * - * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation - * Copyright (c) 2015 Philippe Proulx - * - * 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 -#include -#include -#include -#include -#include -#include -#include - -#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_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; - -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; - GPtrArray *garray; -}; - -struct bt_object_map { - struct bt_object base; - GHashTable *ght; -}; - -static -void bt_object_destroy(struct bt_ref *ref_count); - -static -void bt_object_string_destroy(struct bt_object *object) -{ - g_string_free(BT_OBJECT_TO_STRING(object)->gstr, TRUE); -} - -static -void bt_object_array_destroy(struct bt_object *object) -{ - /* - * Pointer array's registered value destructor will take care - * of putting each contained object. - */ - g_ptr_array_free(BT_OBJECT_TO_ARRAY(object)->garray, TRUE); -} - -static -void bt_object_map_destroy(struct bt_object *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(BT_OBJECT_TO_MAP(object)->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 i; - 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 (i = 0; i < typed_array_obj->garray->len; ++i) { - struct bt_object *element_obj_copy; - struct bt_object *element_obj = - bt_object_array_get(array_obj, i); - - 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 i; - 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 (i = 0; i < array_obj_a->garray->len; ++i) { - struct bt_object *element_obj_a; - struct bt_object *element_obj_b; - - element_obj_a = bt_object_array_get(object_a, i); - element_obj_b = bt_object_array_get(object_b, i); - - 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, -}; - -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 i; - struct bt_object_array *typed_array_obj = - BT_OBJECT_TO_ARRAY(object); - - for (i = 0; i < typed_array_obj->garray->len; ++i) { - struct bt_object *element_obj = - g_ptr_array_index(typed_array_obj->garray, i); - - 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_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 && !bt_object_is_null(object)) { - bt_ref_get(&object->ref_count); - } - - return; -} - -void bt_object_put(struct bt_object *object) -{ - if (object && !bt_object_is_null(object)) { - bt_ref_put(&object->ref_count); - } -} - -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) { - 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; - base.is_frozen = false; - bt_ref_init(&base.ref_count, bt_object_destroy); - - 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_ptr_array_new_full(0, - (GDestroyNotify) bt_object_put); - - 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); -} - -enum bt_object_status bt_object_bool_get(const struct bt_object *bool_obj, - bool *val) -{ - 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) || !val) { - ret = BT_OBJECT_STATUS_INVAL; - goto end; - } - - *val = typed_bool_obj->value; - -end: - return ret; -} - -enum bt_object_status bt_object_bool_set(struct bt_object *bool_obj, bool val) -{ - 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 = BT_OBJECT_STATUS_INVAL; - goto end; - } - - if (bool_obj->is_frozen) { - ret = BT_OBJECT_STATUS_FROZEN; - goto end; - } - - typed_bool_obj->value = val; - -end: - return ret; -} - -enum bt_object_status bt_object_integer_get(const struct bt_object *integer_obj, - int64_t *val) -{ - 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) || !val) { - ret = BT_OBJECT_STATUS_INVAL; - goto end; - } - - *val = typed_integer_obj->value; - -end: - return ret; -} - -enum bt_object_status bt_object_integer_set(struct bt_object *integer_obj, - int64_t val) -{ - 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 = BT_OBJECT_STATUS_INVAL; - goto end; - } - - if (integer_obj->is_frozen) { - ret = BT_OBJECT_STATUS_FROZEN; - goto end; - } - - typed_integer_obj->value = val; - -end: - return ret; -} - -enum bt_object_status bt_object_float_get(const struct bt_object *float_obj, - double *val) -{ - 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) || !val) { - ret = BT_OBJECT_STATUS_INVAL; - goto end; - } - - *val = typed_float_obj->value; - -end: - return ret; -} - -enum bt_object_status bt_object_float_set(struct bt_object *float_obj, - double val) -{ - 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 = BT_OBJECT_STATUS_INVAL; - goto end; - } - - if (float_obj->is_frozen) { - ret = BT_OBJECT_STATUS_FROZEN; - goto end; - } - - typed_float_obj->value = val; - -end: - return ret; -} - -enum bt_object_status bt_object_string_get(const struct bt_object *string_obj, - const char **val) -{ - 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 = BT_OBJECT_STATUS_INVAL; - goto end; - } - - *val = typed_string_obj->gstr->str; - -end: - return ret; -} - -enum bt_object_status bt_object_string_set(struct bt_object *string_obj, - const char *val) -{ - 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 = BT_OBJECT_STATUS_INVAL; - goto end; - } - - if (string_obj->is_frozen) { - ret = BT_OBJECT_STATUS_FROZEN; - 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; - struct bt_object_array *typed_array_obj = - BT_OBJECT_TO_ARRAY(array_obj); - - if (!array_obj || !bt_object_is_array(array_obj)) { - ret = BT_OBJECT_STATUS_INVAL; - 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_ptr_array_index(typed_array_obj->garray, index); - bt_object_get(ret); - -end: - return ret; -} - -enum bt_object_status bt_object_array_append(struct bt_object *array_obj, - struct bt_object *element_obj) -{ - 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 = BT_OBJECT_STATUS_INVAL; - goto end; - } - - if (array_obj->is_frozen) { - ret = BT_OBJECT_STATUS_FROZEN; - goto end; - } - - g_ptr_array_add(typed_array_obj->garray, element_obj); - bt_object_get(element_obj); - -end: - return ret; -} - -enum bt_object_status bt_object_array_append_bool(struct bt_object *array_obj, - bool val) -{ - enum bt_object_status 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; -} - -enum bt_object_status bt_object_array_append_integer( - struct bt_object *array_obj, int64_t val) -{ - enum bt_object_status 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; -} - -enum bt_object_status bt_object_array_append_float(struct bt_object *array_obj, - double val) -{ - enum bt_object_status 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; -} - -enum bt_object_status bt_object_array_append_string(struct bt_object *array_obj, - const char *val) -{ - enum bt_object_status 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; -} - -enum bt_object_status bt_object_array_append_array(struct bt_object *array_obj) -{ - enum bt_object_status 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; -} - -enum bt_object_status bt_object_array_append_map(struct bt_object *array_obj) -{ - enum bt_object_status 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; -} - -enum bt_object_status bt_object_array_set(struct bt_object *array_obj, - size_t index, struct bt_object *element_obj) -{ - 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 = BT_OBJECT_STATUS_INVAL; - goto end; - } - - if (array_obj->is_frozen) { - ret = BT_OBJECT_STATUS_FROZEN; - goto end; - } - - bt_object_put(g_ptr_array_index(typed_array_obj->garray, index)); - g_ptr_array_index(typed_array_obj->garray, index) = element_obj; - bt_object_get(element_obj); - -end: - 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 = BT_OBJECT_STATUS_INVAL; - 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; -} - -enum bt_object_status bt_object_map_insert(struct bt_object *map_obj, - const char *key, struct bt_object *element_obj) -{ - 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 = BT_OBJECT_STATUS_INVAL; - goto end; - } - - if (map_obj->is_frozen) { - ret = BT_OBJECT_STATUS_FROZEN; - 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; -} - -enum bt_object_status bt_object_map_insert_bool(struct bt_object *map_obj, - const char *key, bool val) -{ - enum bt_object_status 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; -} - -enum bt_object_status bt_object_map_insert_integer(struct bt_object *map_obj, - const char *key, int64_t val) -{ - enum bt_object_status 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; -} - -enum bt_object_status bt_object_map_insert_float(struct bt_object *map_obj, - const char *key, double val) -{ - enum bt_object_status 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; -} - -enum bt_object_status bt_object_map_insert_string(struct bt_object *map_obj, - const char *key, const char *val) -{ - enum bt_object_status 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; -} - -enum bt_object_status bt_object_map_insert_array(struct bt_object *map_obj, - const char *key) -{ - enum bt_object_status 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; -} - -enum bt_object_status bt_object_map_insert_map(struct bt_object *map_obj, - const char *key) -{ - enum bt_object_status 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; -} - -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; - 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 = BT_OBJECT_STATUS_INVAL; - 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)) { - ret = BT_OBJECT_STATUS_CANCELLED; - 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; -} diff --git a/lib/values.c b/lib/values.c new file mode 100644 index 00000000..f926ccbf --- /dev/null +++ b/lib/values.c @@ -0,0 +1,1216 @@ +/* + * values.c: value objects + * + * Babeltrace Library + * + * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation + * Copyright (c) 2015 Philippe Proulx + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#define BT_VALUE_FROM_CONCRETE(_concrete) ((struct bt_value *) (_concrete)) +#define BT_VALUE_TO_BOOL(_base) ((struct bt_value_bool *) (_base)) +#define BT_VALUE_TO_INTEGER(_base) ((struct bt_value_integer *) (_base)) +#define BT_VALUE_TO_FLOAT(_base) ((struct bt_value_float *) (_base)) +#define BT_VALUE_TO_STRING(_base) ((struct bt_value_string *) (_base)) +#define BT_VALUE_TO_ARRAY(_base) ((struct bt_value_array *) (_base)) +#define BT_VALUE_TO_MAP(_base) ((struct bt_value_map *) (_base)) + +struct bt_value { + enum bt_value_type type; + struct bt_ref ref_count; + bool is_frozen; +}; + +static +struct bt_value bt_value_null_instance = { + .type = BT_VALUE_TYPE_NULL, + .is_frozen = true, +}; + +struct bt_value *bt_value_null = &bt_value_null_instance; + +struct bt_value_bool { + struct bt_value base; + bool value; +}; + +struct bt_value_integer { + struct bt_value base; + int64_t value; +}; + +struct bt_value_float { + struct bt_value base; + double value; +}; + +struct bt_value_string { + struct bt_value base; + GString *gstr; +}; + +struct bt_value_array { + struct bt_value base; + GPtrArray *garray; +}; + +struct bt_value_map { + struct bt_value base; + GHashTable *ght; +}; + +static +void bt_value_destroy(struct bt_ref *ref_count); + +static +void bt_value_string_destroy(struct bt_value *object) +{ + g_string_free(BT_VALUE_TO_STRING(object)->gstr, TRUE); +} + +static +void bt_value_array_destroy(struct bt_value *object) +{ + /* + * Pointer array's registered value destructor will take care + * of putting each contained object. + */ + g_ptr_array_free(BT_VALUE_TO_ARRAY(object)->garray, TRUE); +} + +static +void bt_value_map_destroy(struct bt_value *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(BT_VALUE_TO_MAP(object)->ght); +} + +static +void (* const destroy_funcs[])(struct bt_value *) = { + [BT_VALUE_TYPE_NULL] = NULL, + [BT_VALUE_TYPE_BOOL] = NULL, + [BT_VALUE_TYPE_INTEGER] = NULL, + [BT_VALUE_TYPE_FLOAT] = NULL, + [BT_VALUE_TYPE_STRING] = bt_value_string_destroy, + [BT_VALUE_TYPE_ARRAY] = bt_value_array_destroy, + [BT_VALUE_TYPE_MAP] = bt_value_map_destroy, +}; + +static +struct bt_value *bt_value_null_copy(const struct bt_value *null_obj) +{ + return bt_value_null; +} + +static +struct bt_value *bt_value_bool_copy(const struct bt_value *bool_obj) +{ + return bt_value_bool_create_init(BT_VALUE_TO_BOOL(bool_obj)->value); +} + +static +struct bt_value *bt_value_integer_copy(const struct bt_value *integer_obj) +{ + return bt_value_integer_create_init( + BT_VALUE_TO_INTEGER(integer_obj)->value); +} + +static +struct bt_value *bt_value_float_copy(const struct bt_value *float_obj) +{ + return bt_value_float_create_init( + BT_VALUE_TO_FLOAT(float_obj)->value); +} + +static +struct bt_value *bt_value_string_copy(const struct bt_value *string_obj) +{ + return bt_value_string_create_init( + BT_VALUE_TO_STRING(string_obj)->gstr->str); +} + +static +struct bt_value *bt_value_array_copy(const struct bt_value *array_obj) +{ + int i; + int ret; + struct bt_value *copy_obj; + struct bt_value_array *typed_array_obj; + + typed_array_obj = BT_VALUE_TO_ARRAY(array_obj); + copy_obj = bt_value_array_create(); + + if (!copy_obj) { + goto end; + } + + for (i = 0; i < typed_array_obj->garray->len; ++i) { + struct bt_value *element_obj_copy; + struct bt_value *element_obj = bt_value_array_get(array_obj, i); + + if (!element_obj) { + BT_VALUE_PUT(copy_obj); + goto end; + } + + element_obj_copy = bt_value_copy(element_obj); + BT_VALUE_PUT(element_obj); + + if (!element_obj_copy) { + BT_VALUE_PUT(copy_obj); + goto end; + } + + ret = bt_value_array_append(copy_obj, element_obj_copy); + BT_VALUE_PUT(element_obj_copy); + + if (ret) { + BT_VALUE_PUT(copy_obj); + goto end; + } + } + +end: + return copy_obj; +} + +static +struct bt_value *bt_value_map_copy(const struct bt_value *map_obj) +{ + int ret; + GHashTableIter iter; + gpointer key, element_obj; + struct bt_value *copy_obj; + struct bt_value *element_obj_copy; + struct bt_value_map *typed_map_obj; + + typed_map_obj = BT_VALUE_TO_MAP(map_obj); + copy_obj = bt_value_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_value_copy(element_obj); + + if (!element_obj_copy) { + BT_VALUE_PUT(copy_obj); + goto end; + } + + ret = bt_value_map_insert(copy_obj, key_str, element_obj_copy); + BT_VALUE_PUT(element_obj_copy); + + if (ret) { + BT_VALUE_PUT(copy_obj); + goto end; + } + } + +end: + return copy_obj; +} + +static +struct bt_value *(* const copy_funcs[])(const struct bt_value *) = { + [BT_VALUE_TYPE_NULL] = bt_value_null_copy, + [BT_VALUE_TYPE_BOOL] = bt_value_bool_copy, + [BT_VALUE_TYPE_INTEGER] = bt_value_integer_copy, + [BT_VALUE_TYPE_FLOAT] = bt_value_float_copy, + [BT_VALUE_TYPE_STRING] = bt_value_string_copy, + [BT_VALUE_TYPE_ARRAY] = bt_value_array_copy, + [BT_VALUE_TYPE_MAP] = bt_value_map_copy, +}; + +static +bool bt_value_null_compare(const struct bt_value *object_a, + const struct bt_value *object_b) +{ + /* + * Always true since bt_value_compare() already checks if both + * object_a and object_b have the same type, and in the case of + * null value objects, they're always the same if it is so. + */ + return true; +} + +static +bool bt_value_bool_compare(const struct bt_value *object_a, + const struct bt_value *object_b) +{ + return BT_VALUE_TO_BOOL(object_a)->value == + BT_VALUE_TO_BOOL(object_b)->value; +} + +static +bool bt_value_integer_compare(const struct bt_value *object_a, + const struct bt_value *object_b) +{ + return BT_VALUE_TO_INTEGER(object_a)->value == + BT_VALUE_TO_INTEGER(object_b)->value; +} + +static +bool bt_value_float_compare(const struct bt_value *object_a, + const struct bt_value *object_b) +{ + return BT_VALUE_TO_FLOAT(object_a)->value == + BT_VALUE_TO_FLOAT(object_b)->value; +} + +static +bool bt_value_string_compare(const struct bt_value *object_a, + const struct bt_value *object_b) +{ + return !strcmp(BT_VALUE_TO_STRING(object_a)->gstr->str, + BT_VALUE_TO_STRING(object_b)->gstr->str); +} + +static +bool bt_value_array_compare(const struct bt_value *object_a, + const struct bt_value *object_b) +{ + int i; + bool ret = true; + const struct bt_value_array *array_obj_a = + BT_VALUE_TO_ARRAY(object_a); + + if (bt_value_array_size(object_a) != bt_value_array_size(object_b)) { + ret = false; + goto end; + } + + for (i = 0; i < array_obj_a->garray->len; ++i) { + struct bt_value *element_obj_a; + struct bt_value *element_obj_b; + + element_obj_a = bt_value_array_get(object_a, i); + element_obj_b = bt_value_array_get(object_b, i); + + if (!bt_value_compare(element_obj_a, element_obj_b)) { + BT_VALUE_PUT(element_obj_a); + BT_VALUE_PUT(element_obj_b); + ret = false; + goto end; + } + + BT_VALUE_PUT(element_obj_a); + BT_VALUE_PUT(element_obj_b); + } + +end: + return ret; +} + +static +bool bt_value_map_compare(const struct bt_value *object_a, + const struct bt_value *object_b) +{ + bool ret = true; + GHashTableIter iter; + gpointer key, element_obj_a; + const struct bt_value_map *map_obj_a = BT_VALUE_TO_MAP(object_a); + + if (bt_value_map_size(object_a) != bt_value_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_value *element_obj_b; + const char *key_str = g_quark_to_string((unsigned long) key); + + element_obj_b = bt_value_map_get(object_b, key_str); + + if (!bt_value_compare(element_obj_a, element_obj_b)) { + BT_VALUE_PUT(element_obj_b); + ret = false; + goto end; + } + + BT_VALUE_PUT(element_obj_b); + } + +end: + return ret; +} + +static +bool (* const compare_funcs[])(const struct bt_value *, + const struct bt_value *) = { + [BT_VALUE_TYPE_NULL] = bt_value_null_compare, + [BT_VALUE_TYPE_BOOL] = bt_value_bool_compare, + [BT_VALUE_TYPE_INTEGER] = bt_value_integer_compare, + [BT_VALUE_TYPE_FLOAT] = bt_value_float_compare, + [BT_VALUE_TYPE_STRING] = bt_value_string_compare, + [BT_VALUE_TYPE_ARRAY] = bt_value_array_compare, + [BT_VALUE_TYPE_MAP] = bt_value_map_compare, +}; + +void bt_value_null_freeze(struct bt_value *object) +{ +} + +void bt_value_generic_freeze(struct bt_value *object) +{ + object->is_frozen = true; +} + +void bt_value_array_freeze(struct bt_value *object) +{ + int i; + struct bt_value_array *typed_array_obj = + BT_VALUE_TO_ARRAY(object); + + for (i = 0; i < typed_array_obj->garray->len; ++i) { + struct bt_value *element_obj = + g_ptr_array_index(typed_array_obj->garray, i); + + bt_value_freeze(element_obj); + } + + bt_value_generic_freeze(object); +} + +void bt_value_map_freeze(struct bt_value *object) +{ + GHashTableIter iter; + gpointer key, element_obj; + const struct bt_value_map *map_obj = BT_VALUE_TO_MAP(object); + + g_hash_table_iter_init(&iter, map_obj->ght); + + while (g_hash_table_iter_next(&iter, &key, &element_obj)) { + bt_value_freeze(element_obj); + } + + bt_value_generic_freeze(object); +} + +static +void (* const freeze_funcs[])(struct bt_value *) = { + [BT_VALUE_TYPE_NULL] = bt_value_null_freeze, + [BT_VALUE_TYPE_BOOL] = bt_value_generic_freeze, + [BT_VALUE_TYPE_INTEGER] = bt_value_generic_freeze, + [BT_VALUE_TYPE_FLOAT] = bt_value_generic_freeze, + [BT_VALUE_TYPE_STRING] = bt_value_generic_freeze, + [BT_VALUE_TYPE_ARRAY] = bt_value_array_freeze, + [BT_VALUE_TYPE_MAP] = bt_value_map_freeze, +}; + +static +void bt_value_destroy(struct bt_ref *ref_count) +{ + struct bt_value *object; + + object = container_of(ref_count, struct bt_value, ref_count); + assert(object->type != BT_VALUE_TYPE_UNKNOWN); + + if (bt_value_is_null(object)) { + return; + } + + if (destroy_funcs[object->type]) { + destroy_funcs[object->type](object); + } + + g_free(object); +} + +void bt_value_get(struct bt_value *object) +{ + if (object && !bt_value_is_null(object)) { + bt_ref_get(&object->ref_count); + } + + return; +} + +void bt_value_put(struct bt_value *object) +{ + if (object && !bt_value_is_null(object)) { + bt_ref_put(&object->ref_count); + } +} + +enum bt_value_status bt_value_freeze(struct bt_value *object) +{ + enum bt_value_status ret = BT_VALUE_STATUS_OK; + + if (!object) { + ret = BT_VALUE_STATUS_INVAL; + goto end; + } + + freeze_funcs[object->type](object); + +end: + return ret; +} + +bool bt_value_is_frozen(const struct bt_value *object) +{ + return object && object->is_frozen; +} + +enum bt_value_type bt_value_get_type(const struct bt_value *object) +{ + if (!object) { + return BT_VALUE_TYPE_UNKNOWN; + } + + return object->type; +} + +static +struct bt_value bt_value_create_base(enum bt_value_type type) +{ + struct bt_value base; + + base.type = type; + base.is_frozen = false; + bt_ref_init(&base.ref_count, bt_value_destroy); + + return base; +} + +struct bt_value *bt_value_bool_create_init(bool val) +{ + struct bt_value_bool *bool_obj; + + bool_obj = g_new0(struct bt_value_bool, 1); + + if (!bool_obj) { + goto end; + } + + bool_obj->base = bt_value_create_base(BT_VALUE_TYPE_BOOL); + bool_obj->value = val; + +end: + return BT_VALUE_FROM_CONCRETE(bool_obj); +} + +struct bt_value *bt_value_bool_create(void) +{ + return bt_value_bool_create_init(false); +} + +struct bt_value *bt_value_integer_create_init(int64_t val) +{ + struct bt_value_integer *integer_obj; + + integer_obj = g_new0(struct bt_value_integer, 1); + + if (!integer_obj) { + goto end; + } + + integer_obj->base = bt_value_create_base(BT_VALUE_TYPE_INTEGER); + integer_obj->value = val; + +end: + return BT_VALUE_FROM_CONCRETE(integer_obj); +} + +struct bt_value *bt_value_integer_create(void) +{ + return bt_value_integer_create_init(0); +} + +struct bt_value *bt_value_float_create_init(double val) +{ + struct bt_value_float *float_obj; + + float_obj = g_new0(struct bt_value_float, 1); + + if (!float_obj) { + goto end; + } + + float_obj->base = bt_value_create_base(BT_VALUE_TYPE_FLOAT); + float_obj->value = val; + +end: + return BT_VALUE_FROM_CONCRETE(float_obj); +} + +struct bt_value *bt_value_float_create(void) +{ + return bt_value_float_create_init(0.); +} + +struct bt_value *bt_value_string_create_init(const char *val) +{ + struct bt_value_string *string_obj = NULL; + + if (!val) { + goto end; + } + + string_obj = g_new0(struct bt_value_string, 1); + + if (!string_obj) { + goto end; + } + + string_obj->base = bt_value_create_base(BT_VALUE_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_VALUE_FROM_CONCRETE(string_obj); +} + +struct bt_value *bt_value_string_create(void) +{ + return bt_value_string_create_init(""); +} + +struct bt_value *bt_value_array_create(void) +{ + struct bt_value_array *array_obj; + + array_obj = g_new0(struct bt_value_array, 1); + + if (!array_obj) { + goto end; + } + + array_obj->base = bt_value_create_base(BT_VALUE_TYPE_ARRAY); + array_obj->garray = g_ptr_array_new_full(0, + (GDestroyNotify) bt_value_put); + + if (!array_obj->garray) { + g_free(array_obj); + array_obj = NULL; + goto end; + } + +end: + return BT_VALUE_FROM_CONCRETE(array_obj); +} + +struct bt_value *bt_value_map_create(void) +{ + struct bt_value_map *map_obj; + + map_obj = g_new0(struct bt_value_map, 1); + + if (!map_obj) { + goto end; + } + + map_obj->base = bt_value_create_base(BT_VALUE_TYPE_MAP); + map_obj->ght = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, (GDestroyNotify) bt_value_put); + + if (!map_obj->ght) { + g_free(map_obj); + map_obj = NULL; + goto end; + } + +end: + return BT_VALUE_FROM_CONCRETE(map_obj); +} + +enum bt_value_status bt_value_bool_get(const struct bt_value *bool_obj, + bool *val) +{ + enum bt_value_status ret = BT_VALUE_STATUS_OK; + struct bt_value_bool *typed_bool_obj = BT_VALUE_TO_BOOL(bool_obj); + + if (!bool_obj || !bt_value_is_bool(bool_obj) || !val) { + ret = BT_VALUE_STATUS_INVAL; + goto end; + } + + *val = typed_bool_obj->value; + +end: + return ret; +} + +enum bt_value_status bt_value_bool_set(struct bt_value *bool_obj, bool val) +{ + enum bt_value_status ret = BT_VALUE_STATUS_OK; + struct bt_value_bool *typed_bool_obj = BT_VALUE_TO_BOOL(bool_obj); + + if (!bool_obj || !bt_value_is_bool(bool_obj)) { + ret = BT_VALUE_STATUS_INVAL; + goto end; + } + + if (bool_obj->is_frozen) { + ret = BT_VALUE_STATUS_FROZEN; + goto end; + } + + typed_bool_obj->value = val; + +end: + return ret; +} + +enum bt_value_status bt_value_integer_get(const struct bt_value *integer_obj, + int64_t *val) +{ + enum bt_value_status ret = BT_VALUE_STATUS_OK; + struct bt_value_integer *typed_integer_obj = + BT_VALUE_TO_INTEGER(integer_obj); + + if (!integer_obj || !bt_value_is_integer(integer_obj) || !val) { + ret = BT_VALUE_STATUS_INVAL; + goto end; + } + + *val = typed_integer_obj->value; + +end: + return ret; +} + +enum bt_value_status bt_value_integer_set(struct bt_value *integer_obj, + int64_t val) +{ + enum bt_value_status ret = BT_VALUE_STATUS_OK; + struct bt_value_integer *typed_integer_obj = + BT_VALUE_TO_INTEGER(integer_obj); + + if (!integer_obj || !bt_value_is_integer(integer_obj)) { + ret = BT_VALUE_STATUS_INVAL; + goto end; + } + + if (integer_obj->is_frozen) { + ret = BT_VALUE_STATUS_FROZEN; + goto end; + } + + typed_integer_obj->value = val; + +end: + return ret; +} + +enum bt_value_status bt_value_float_get(const struct bt_value *float_obj, + double *val) +{ + enum bt_value_status ret = BT_VALUE_STATUS_OK; + struct bt_value_float *typed_float_obj = + BT_VALUE_TO_FLOAT(float_obj); + + if (!float_obj || !bt_value_is_float(float_obj) || !val) { + ret = BT_VALUE_STATUS_INVAL; + goto end; + } + + *val = typed_float_obj->value; + +end: + return ret; +} + +enum bt_value_status bt_value_float_set(struct bt_value *float_obj, + double val) +{ + enum bt_value_status ret = BT_VALUE_STATUS_OK; + struct bt_value_float *typed_float_obj = + BT_VALUE_TO_FLOAT(float_obj); + + if (!float_obj || !bt_value_is_float(float_obj)) { + ret = BT_VALUE_STATUS_INVAL; + goto end; + } + + if (float_obj->is_frozen) { + ret = BT_VALUE_STATUS_FROZEN; + goto end; + } + + typed_float_obj->value = val; + +end: + return ret; +} + +enum bt_value_status bt_value_string_get(const struct bt_value *string_obj, + const char **val) +{ + enum bt_value_status ret = BT_VALUE_STATUS_OK; + struct bt_value_string *typed_string_obj = + BT_VALUE_TO_STRING(string_obj); + + if (!string_obj || !bt_value_is_string(string_obj) || !val) { + ret = BT_VALUE_STATUS_INVAL; + goto end; + } + + *val = typed_string_obj->gstr->str; + +end: + return ret; +} + +enum bt_value_status bt_value_string_set(struct bt_value *string_obj, + const char *val) +{ + enum bt_value_status ret = BT_VALUE_STATUS_OK; + struct bt_value_string *typed_string_obj = + BT_VALUE_TO_STRING(string_obj); + + if (!string_obj || !bt_value_is_string(string_obj) || !val) { + ret = BT_VALUE_STATUS_INVAL; + goto end; + } + + if (string_obj->is_frozen) { + ret = BT_VALUE_STATUS_FROZEN; + goto end; + } + + g_string_assign(typed_string_obj->gstr, val); + +end: + return ret; +} + +int bt_value_array_size(const struct bt_value *array_obj) +{ + int ret; + struct bt_value_array *typed_array_obj = + BT_VALUE_TO_ARRAY(array_obj); + + if (!array_obj || !bt_value_is_array(array_obj)) { + ret = BT_VALUE_STATUS_INVAL; + goto end; + } + + ret = (int) typed_array_obj->garray->len; + +end: + return ret; +} + +bool bt_value_array_is_empty(const struct bt_value *array_obj) +{ + return bt_value_array_size(array_obj) == 0; +} + +struct bt_value *bt_value_array_get(const struct bt_value *array_obj, + size_t index) +{ + struct bt_value *ret; + struct bt_value_array *typed_array_obj = + BT_VALUE_TO_ARRAY(array_obj); + + if (!array_obj || !bt_value_is_array(array_obj) || + index >= typed_array_obj->garray->len) { + ret = NULL; + goto end; + } + + ret = g_ptr_array_index(typed_array_obj->garray, index); + bt_value_get(ret); + +end: + return ret; +} + +enum bt_value_status bt_value_array_append(struct bt_value *array_obj, + struct bt_value *element_obj) +{ + enum bt_value_status ret = BT_VALUE_STATUS_OK; + struct bt_value_array *typed_array_obj = + BT_VALUE_TO_ARRAY(array_obj); + + if (!array_obj || !bt_value_is_array(array_obj) || !element_obj) { + ret = BT_VALUE_STATUS_INVAL; + goto end; + } + + if (array_obj->is_frozen) { + ret = BT_VALUE_STATUS_FROZEN; + goto end; + } + + g_ptr_array_add(typed_array_obj->garray, element_obj); + bt_value_get(element_obj); + +end: + return ret; +} + +enum bt_value_status bt_value_array_append_bool(struct bt_value *array_obj, + bool val) +{ + enum bt_value_status ret; + struct bt_value *bool_obj = NULL; + + bool_obj = bt_value_bool_create_init(val); + ret = bt_value_array_append(array_obj, bool_obj); + bt_value_put(bool_obj); + + return ret; +} + +enum bt_value_status bt_value_array_append_integer( + struct bt_value *array_obj, int64_t val) +{ + enum bt_value_status ret; + struct bt_value *integer_obj = NULL; + + integer_obj = bt_value_integer_create_init(val); + ret = bt_value_array_append(array_obj, integer_obj); + bt_value_put(integer_obj); + + return ret; +} + +enum bt_value_status bt_value_array_append_float(struct bt_value *array_obj, + double val) +{ + enum bt_value_status ret; + struct bt_value *float_obj = NULL; + + float_obj = bt_value_float_create_init(val); + ret = bt_value_array_append(array_obj, float_obj); + bt_value_put(float_obj); + + return ret; +} + +enum bt_value_status bt_value_array_append_string(struct bt_value *array_obj, + const char *val) +{ + enum bt_value_status ret; + struct bt_value *string_obj = NULL; + + string_obj = bt_value_string_create_init(val); + ret = bt_value_array_append(array_obj, string_obj); + bt_value_put(string_obj); + + return ret; +} + +enum bt_value_status bt_value_array_append_array(struct bt_value *array_obj) +{ + enum bt_value_status ret; + struct bt_value *empty_array_obj = NULL; + + empty_array_obj = bt_value_array_create(); + ret = bt_value_array_append(array_obj, empty_array_obj); + bt_value_put(empty_array_obj); + + return ret; +} + +enum bt_value_status bt_value_array_append_map(struct bt_value *array_obj) +{ + enum bt_value_status ret; + struct bt_value *map_obj = NULL; + + map_obj = bt_value_map_create(); + ret = bt_value_array_append(array_obj, map_obj); + bt_value_put(map_obj); + + return ret; +} + +enum bt_value_status bt_value_array_set(struct bt_value *array_obj, + size_t index, struct bt_value *element_obj) +{ + enum bt_value_status ret = BT_VALUE_STATUS_OK; + struct bt_value_array *typed_array_obj = + BT_VALUE_TO_ARRAY(array_obj); + + if (!array_obj || !bt_value_is_array(array_obj) || !element_obj || + index >= typed_array_obj->garray->len) { + ret = BT_VALUE_STATUS_INVAL; + goto end; + } + + if (array_obj->is_frozen) { + ret = BT_VALUE_STATUS_FROZEN; + goto end; + } + + bt_value_put(g_ptr_array_index(typed_array_obj->garray, index)); + g_ptr_array_index(typed_array_obj->garray, index) = element_obj; + bt_value_get(element_obj); + +end: + return ret; +} + +int bt_value_map_size(const struct bt_value *map_obj) +{ + int ret; + struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj); + + if (!map_obj || !bt_value_is_map(map_obj)) { + ret = BT_VALUE_STATUS_INVAL; + goto end; + } + + ret = (int) g_hash_table_size(typed_map_obj->ght); + +end: + return ret; +} + +bool bt_value_map_is_empty(const struct bt_value *map_obj) +{ + return bt_value_map_size(map_obj) == 0; +} + +struct bt_value *bt_value_map_get(const struct bt_value *map_obj, + const char *key) +{ + GQuark quark; + struct bt_value *ret; + struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj); + + if (!map_obj || !bt_value_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_value_get(ret); + } + +end: + return ret; +} + +bool bt_value_map_has_key(const struct bt_value *map_obj, const char *key) +{ + bool ret; + GQuark quark; + struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj); + + if (!map_obj || !bt_value_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; +} + +enum bt_value_status bt_value_map_insert(struct bt_value *map_obj, + const char *key, struct bt_value *element_obj) +{ + GQuark quark; + enum bt_value_status ret = BT_VALUE_STATUS_OK; + struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj); + + if (!map_obj || !bt_value_is_map(map_obj) || !key || !element_obj) { + ret = BT_VALUE_STATUS_INVAL; + goto end; + } + + if (map_obj->is_frozen) { + ret = BT_VALUE_STATUS_FROZEN; + goto end; + } + + quark = g_quark_from_string(key); + g_hash_table_insert(typed_map_obj->ght, + GUINT_TO_POINTER(quark), element_obj); + bt_value_get(element_obj); + +end: + return ret; +} + +enum bt_value_status bt_value_map_insert_bool(struct bt_value *map_obj, + const char *key, bool val) +{ + enum bt_value_status ret; + struct bt_value *bool_obj = NULL; + + bool_obj = bt_value_bool_create_init(val); + ret = bt_value_map_insert(map_obj, key, bool_obj); + bt_value_put(bool_obj); + + return ret; +} + +enum bt_value_status bt_value_map_insert_integer(struct bt_value *map_obj, + const char *key, int64_t val) +{ + enum bt_value_status ret; + struct bt_value *integer_obj = NULL; + + integer_obj = bt_value_integer_create_init(val); + ret = bt_value_map_insert(map_obj, key, integer_obj); + bt_value_put(integer_obj); + + return ret; +} + +enum bt_value_status bt_value_map_insert_float(struct bt_value *map_obj, + const char *key, double val) +{ + enum bt_value_status ret; + struct bt_value *float_obj = NULL; + + float_obj = bt_value_float_create_init(val); + ret = bt_value_map_insert(map_obj, key, float_obj); + bt_value_put(float_obj); + + return ret; +} + +enum bt_value_status bt_value_map_insert_string(struct bt_value *map_obj, + const char *key, const char *val) +{ + enum bt_value_status ret; + struct bt_value *string_obj = NULL; + + string_obj = bt_value_string_create_init(val); + ret = bt_value_map_insert(map_obj, key, string_obj); + bt_value_put(string_obj); + + return ret; +} + +enum bt_value_status bt_value_map_insert_array(struct bt_value *map_obj, + const char *key) +{ + enum bt_value_status ret; + struct bt_value *array_obj = NULL; + + array_obj = bt_value_array_create(); + ret = bt_value_map_insert(map_obj, key, array_obj); + bt_value_put(array_obj); + + return ret; +} + +enum bt_value_status bt_value_map_insert_map(struct bt_value *map_obj, + const char *key) +{ + enum bt_value_status ret; + struct bt_value *empty_map_obj = NULL; + + empty_map_obj = bt_value_map_create(); + ret = bt_value_map_insert(map_obj, key, empty_map_obj); + bt_value_put(empty_map_obj); + + return ret; +} + +enum bt_value_status bt_value_map_foreach(const struct bt_value *map_obj, + bt_value_map_foreach_cb cb, void *data) +{ + enum bt_value_status ret = BT_VALUE_STATUS_OK; + gpointer key, element_obj; + GHashTableIter iter; + struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj); + + if (!map_obj || !bt_value_is_map(map_obj) || !cb) { + ret = BT_VALUE_STATUS_INVAL; + 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)) { + ret = BT_VALUE_STATUS_CANCELLED; + break; + } + } + +end: + return ret; +} + +struct bt_value *bt_value_copy(const struct bt_value *object) +{ + struct bt_value *copy_obj = NULL; + + if (!object) { + goto end; + } + + copy_obj = copy_funcs[object->type](object); + +end: + return copy_obj; +} + +bool bt_value_compare(const struct bt_value *object_a, + const struct bt_value *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; +} diff --git a/tests/lib/Makefile.am b/tests/lib/Makefile.am index d11ac545..f5e836f6 100644 --- a/tests/lib/Makefile.am +++ b/tests/lib/Makefile.am @@ -20,15 +20,15 @@ test_ctf_writer_LDADD = $(LIBTAP) \ $(top_builddir)/lib/libbabeltrace.la \ $(top_builddir)/formats/ctf/libbabeltrace-ctf.la -test_bt_objects_LDADD = $(LIBTAP) \ +test_bt_values_LDADD = $(LIBTAP) \ $(top_builddir)/lib/libbabeltrace.la -noinst_PROGRAMS = test_seek test_bitfield test_ctf_writer test_bt_objects +noinst_PROGRAMS = test_seek test_bitfield test_ctf_writer test_bt_values test_seek_SOURCES = test_seek.c test_bitfield_SOURCES = test_bitfield.c test_ctf_writer_SOURCES = test_ctf_writer.c -test_bt_objects_SOURCES = test_bt_objects.c +test_bt_values_SOURCES = test_bt_values.c SCRIPT_LIST = test_seek_big_trace \ test_seek_empty_packet \ diff --git a/tests/lib/test_bt_objects.c b/tests/lib/test_bt_objects.c deleted file mode 100644 index 97131361..00000000 --- a/tests/lib/test_bt_objects.c +++ /dev/null @@ -1,1167 +0,0 @@ -/* - * test_bt_objects.c - * - * Babeltrace basic object system tests - * - * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation - * Copyright (c) 2015 Philippe Proulx - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; under version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#define _GNU_SOURCE -#include -#include -#include -#include "tap/tap.h" - -static -void test_null(void) -{ - ok(bt_object_null, "bt_object_null is not NULL"); - ok(bt_object_is_null(bt_object_null), - "bt_object_null is a null object"); - bt_object_get(bt_object_null); - pass("getting bt_object_null does not cause a crash"); - bt_object_put(bt_object_null); - pass("putting bt_object_null does not cause a crash"); - - bt_object_get(NULL); - pass("getting NULL does not cause a crash"); - bt_object_put(NULL); - pass("putting NULL does not cause a crash"); - - ok(bt_object_get_type(NULL) == BT_OBJECT_TYPE_UNKNOWN, - "bt_object_get_type(NULL) returns BT_OBJECT_TYPE_UNKNOWN"); -} - -static -void test_bool(void) -{ - int ret; - bool value; - struct bt_object *obj; - - obj = bt_object_bool_create(); - ok(obj && bt_object_is_bool(obj), - "bt_object_bool_create() returns a boolean object"); - - value = true; - ret = bt_object_bool_get(obj, &value); - ok(!ret && !value, "default boolean object value is false"); - - ret = bt_object_bool_set(NULL, true); - 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_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); - ok(!ret && value, "bt_object_bool_set() works"); - - 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"); - ret = bt_object_bool_get(obj, &value); - 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); -} - -static -void test_integer(void) -{ - int ret; - int64_t value; - struct bt_object *obj; - - obj = bt_object_integer_create(); - ok(obj && bt_object_is_integer(obj), - "bt_object_integer_create() returns an integer object"); - - ret = bt_object_integer_set(NULL, -12345); - 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_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, -98765); - ok(!ret, "bt_object_integer_set() succeeds"); - ret = bt_object_integer_get(obj, &value); - ok(!ret && value == -98765, "bt_object_integer_set() works"); - - BT_OBJECT_PUT(obj); - pass("putting an existing integer object does not cause a crash") - - obj = bt_object_integer_create_init(321456987); - ok(obj && bt_object_is_integer(obj), - "bt_object_integer_create_init() returns an integer object"); - ret = bt_object_integer_get(obj, &value); - 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); -} - -static -void test_float(void) -{ - int ret; - double value; - struct bt_object *obj; - - obj = bt_object_float_create(); - ok(obj && bt_object_is_float(obj), - "bt_object_float_create() returns a floating point number object"); - - ret = bt_object_float_set(NULL, 1.2345); - 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_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"); - - ret = bt_object_float_set(obj, -3.1416); - ok(!ret, "bt_object_float_set() succeeds"); - ret = bt_object_float_get(obj, &value); - ok(!ret && value == -3.1416, "bt_object_float_set() works"); - - BT_OBJECT_PUT(obj); - pass("putting an existing floating point number object does not cause a crash") - - obj = bt_object_float_create_init(33.1649758); - ok(obj && bt_object_is_float(obj), - "bt_object_float_create_init() returns a floating point number object"); - ret = bt_object_float_get(obj, &value); - 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); -} - -static -void test_string(void) -{ - int ret; - const char *value; - struct bt_object *obj; - - obj = bt_object_string_create(); - ok(obj && bt_object_is_string(obj), - "bt_object_string_create() returns a string object"); - - ret = bt_object_string_set(NULL, "hoho"); - 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"); - 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") - - obj = bt_object_string_create_init(NULL); - ok(!obj, "bt_object_string_create_init() fails with an initial value set to NULL"); - obj = bt_object_string_create_init("initial value"); - ok(obj && bt_object_is_string(obj), - "bt_object_string_create_init() returns a string object"); - 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); -} - -static -void test_array(void) -{ - int ret; - bool bool_value; - int64_t int_value; - double float_value; - struct bt_object *obj; - const char *string_value; - struct bt_object *array_obj; - - 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) == 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) - == 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); - BT_OBJECT_PUT(obj); - obj = bt_object_float_create_init(-17.45); - ret |= bt_object_array_append(array_obj, obj); - BT_OBJECT_PUT(obj); - obj = bt_object_bool_create_init(true); - ret |= bt_object_array_append(array_obj, obj); - BT_OBJECT_PUT(obj); - ret |= bt_object_array_append(array_obj, bt_object_null); - ok(!ret, "bt_object_array_append() succeeds"); - ok(bt_object_array_size(array_obj) == 4, - "appending an element to an array object increment its size"); - - obj = bt_object_array_get(array_obj, 4); - ok(!obj, "getting an array object's element at an index equal to its size fails"); - obj = bt_object_array_get(array_obj, 5); - ok(!obj, "getting an array object's element at a larger index fails"); - - obj = bt_object_array_get(NULL, 2); - ok(!obj, "bt_object_array_get() fails with an array object set to NULL"); - - obj = bt_object_array_get(array_obj, 0); - ok(obj && bt_object_is_integer(obj), - "bt_object_array_get() returns an object with the appropriate type (integer)"); - ret = bt_object_integer_get(obj, &int_value); - ok(!ret && int_value == 345, - "bt_object_array_get() returns an object with the appropriate value (integer)"); - BT_OBJECT_PUT(obj); - obj = bt_object_array_get(array_obj, 1); - ok(obj && bt_object_is_float(obj), - "bt_object_array_get() returns an object with the appropriate type (floating point number)"); - ret = bt_object_float_get(obj, &float_value); - ok(!ret && float_value == -17.45, - "bt_object_array_get() returns an object with the appropriate value (floating point number)"); - BT_OBJECT_PUT(obj); - obj = bt_object_array_get(array_obj, 2); - ok(obj && bt_object_is_bool(obj), - "bt_object_array_get() returns an object with the appropriate type (boolean)"); - ret = bt_object_bool_get(obj, &bool_value); - ok(!ret && bool_value, - "bt_object_array_get() returns an object with the appropriate value (boolean)"); - BT_OBJECT_PUT(obj); - obj = bt_object_array_get(array_obj, 3); - 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) == - 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) == 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) == - BT_OBJECT_STATUS_INVAL, - "bt_object_array_set() fails with an invalid index"); - obj = bt_object_integer_create_init(1001); - assert(obj); - ok(!bt_object_array_set(array_obj, 2, obj), - "bt_object_array_set() succeeds"); - BT_OBJECT_PUT(obj); - obj = bt_object_array_get(array_obj, 2); - ok(obj && bt_object_is_integer(obj), - "bt_object_array_set() inserts an object with the appropriate type"); - ret = bt_object_integer_get(obj, &int_value); - assert(!ret); - ok(int_value == 1001, - "bt_object_array_set() inserts an object with the appropriate value"); - BT_OBJECT_PUT(obj); - - ret = bt_object_array_append_bool(array_obj, false); - ok(!ret, "bt_object_array_append_bool() succeeds"); - 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"); - 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"); - 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"); - 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"); - 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"); - 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"); - ok(!bt_object_array_is_empty(array_obj), - "map object is not empty"); - - obj = bt_object_array_get(array_obj, 4); - ok(obj && bt_object_is_bool(obj), - "bt_object_array_append_bool() appends a boolean object"); - ret = bt_object_bool_get(obj, &bool_value); - ok(!ret && !bool_value, - "bt_object_array_append_bool() appends the appropriate value"); - BT_OBJECT_PUT(obj); - obj = bt_object_array_get(array_obj, 5); - ok(obj && bt_object_is_integer(obj), - "bt_object_array_append_integer() appends an integer object"); - ret = bt_object_integer_get(obj, &int_value); - ok(!ret && int_value == 98765, - "bt_object_array_append_integer() appends the appropriate value"); - BT_OBJECT_PUT(obj); - obj = bt_object_array_get(array_obj, 6); - ok(obj && bt_object_is_float(obj), - "bt_object_array_append_float() appends a floating point number object"); - ret = bt_object_float_get(obj, &float_value); - ok(!ret && float_value == 2.49578, - "bt_object_array_append_float() appends the appropriate value"); - BT_OBJECT_PUT(obj); - obj = bt_object_array_get(array_obj, 7); - ok(obj && bt_object_is_string(obj), - "bt_object_array_append_string() appends a string 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); - ok(obj && bt_object_is_array(obj), - "bt_object_array_append_array() appends an array object"); - ok(bt_object_array_is_empty(obj), - "bt_object_array_append_array() an empty array object"); - BT_OBJECT_PUT(obj); - obj = bt_object_array_get(array_obj, 9); - ok(obj && bt_object_is_map(obj), - "bt_object_array_append_map() appends a map object"); - ok(bt_object_map_is_empty(obj), - "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"); - - obj = bt_object_array_get(array_obj, 1); - assert(obj); - 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") -} - -static -bool test_map_foreach_cb_count(const char *key, struct bt_object *object, - void *data) -{ - int *count = data; - - if (*count == 3) { - return false; - } - - (*count)++; - - return true; -} - -struct map_foreach_checklist { - bool bool1; - bool int1; - bool float1; - bool null1; - bool bool2; - bool int2; - bool float2; - bool string2; - bool array2; - bool map2; -}; - -static -bool test_map_foreach_cb_check(const char *key, struct bt_object *object, - void *data) -{ - int ret; - struct map_foreach_checklist *checklist = data; - - if (!strcmp(key, "bool")) { - if (checklist->bool1) { - fail("test_map_foreach_cb_check(): duplicate key \"bool\""); - } else { - bool val = false; - - ret = bt_object_bool_get(object, &val); - ok(!ret, "test_map_foreach_cb_check(): success getting \"bool\" value"); - - 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")) { - if (checklist->int1) { - fail("test_map_foreach_cb_check(): duplicate key \"int\""); - } else { - int64_t val = 0; - - ret = bt_object_integer_get(object, &val); - ok(!ret, "test_map_foreach_cb_check(): success getting \"int\" value"); - - 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")) { - if (checklist->float1) { - fail("test_map_foreach_cb_check(): duplicate key \"float\""); - } else { - double val = 0; - - ret = bt_object_float_get(object, &val); - ok(!ret, "test_map_foreach_cb_check(): success getting \"float\" value"); - - 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")) { - if (checklist->null1) { - fail("test_map_foreach_cb_check(): duplicate key \"bool\""); - } else { - ok(bt_object_is_null(object), "test_map_foreach_cb_check(): success getting \"null\" object"); - checklist->null1 = true; - } - } else if (!strcmp(key, "bool2")) { - if (checklist->bool2) { - fail("test_map_foreach_cb_check(): duplicate key \"bool2\""); - } else { - bool val = false; - - ret = bt_object_bool_get(object, &val); - ok(!ret, "test_map_foreach_cb_check(): success getting \"bool2\" value"); - - 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")) { - if (checklist->int2) { - fail("test_map_foreach_cb_check(): duplicate key \"int2\""); - } else { - int64_t val = 0; - - ret = bt_object_integer_get(object, &val); - ok(!ret, "test_map_foreach_cb_check(): success getting \"int2\" value"); - - 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")) { - if (checklist->float2) { - fail("test_map_foreach_cb_check(): duplicate key \"float2\""); - } else { - double val = 0; - - ret = bt_object_float_get(object, &val); - ok(!ret, "test_map_foreach_cb_check(): success getting \"float2\" value"); - - 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; - - 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")) { - if (checklist->array2) { - fail("test_map_foreach_cb_check(): duplicate key \"array2\""); - } else { - ok(bt_object_is_array(object), "test_map_foreach_cb_check(): success getting \"array2\" object"); - ok(bt_object_array_is_empty(object), - "test_map_foreach_cb_check(): \"array2\" object is empty"); - checklist->array2 = true; - } - } else if (!strcmp(key, "map2")) { - if (checklist->map2) { - fail("test_map_foreach_cb_check(): duplicate key \"map2\""); - } else { - ok(bt_object_is_map(object), "test_map_foreach_cb_check(): success getting \"map2\" object"); - ok(bt_object_map_is_empty(object), - "test_map_foreach_cb_check(): \"map2\" object is empty"); - checklist->map2 = true; - } - } else { - fail("test_map_foreach_cb_check(): unknown map key \"%s\"", key); - } - - return true; -} - -static -void test_map(void) -{ - int ret; - int count = 0; - bool bool_value; - int64_t int_value; - double float_value; - struct bt_object *obj; - struct bt_object *map_obj; - struct map_foreach_checklist checklist; - - map_obj = bt_object_map_create(); - ok(map_obj && bt_object_is_map(map_obj), - "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) == 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) == - 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) == - BT_OBJECT_STATUS_INVAL, - "bt_object_array_insert() fails with a key set to 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); - ret = bt_object_map_insert(map_obj, "int", obj); - BT_OBJECT_PUT(obj); - obj = bt_object_float_create_init(5.444); - ret |= bt_object_map_insert(map_obj, "float", obj); - BT_OBJECT_PUT(obj); - obj = bt_object_bool_create(); - ret |= bt_object_map_insert(map_obj, "bool", obj); - BT_OBJECT_PUT(obj); - ret |= bt_object_map_insert(map_obj, "null", bt_object_null); - ok(!ret, "bt_object_map_insert() succeeds"); - ok(bt_object_map_size(map_obj) == 4, - "inserting an element into a map object increment its size"); - - obj = bt_object_bool_create_init(true); - ret = bt_object_map_insert(map_obj, "bool", obj); - BT_OBJECT_PUT(obj); - ok(!ret, "bt_object_map_insert() accepts an existing key"); - - obj = bt_object_map_get(map_obj, NULL); - ok(!obj, "bt_object_map_get() fails with a key set to NULL"); - obj = bt_object_map_get(NULL, "bool"); - ok(!obj, "bt_object_map_get() fails with a map object set to NULL"); - - obj = bt_object_map_get(map_obj, "life"); - ok(!obj, "bt_object_map_get() fails with an non existing key"); - obj = bt_object_map_get(map_obj, "float"); - ok(obj && bt_object_is_float(obj), - "bt_object_map_get() returns an object with the appropriate type (float)"); - ret = bt_object_float_get(obj, &float_value); - ok(!ret && float_value == 5.444, - "bt_object_map_get() returns an object with the appropriate value (float)"); - BT_OBJECT_PUT(obj); - obj = bt_object_map_get(map_obj, "int"); - ok(obj && bt_object_is_integer(obj), - "bt_object_map_get() returns an object with the appropriate type (integer)"); - ret = bt_object_integer_get(obj, &int_value); - ok(!ret && int_value == 19457, - "bt_object_map_get() returns an object with the appropriate value (integer)"); - BT_OBJECT_PUT(obj); - obj = bt_object_map_get(map_obj, "null"); - ok(obj && bt_object_is_null(obj), - "bt_object_map_get() returns an object with the appropriate type (null)"); - obj = bt_object_map_get(map_obj, "bool"); - ok(obj && bt_object_is_bool(obj), - "bt_object_map_get() returns an object with the appropriate type (boolean)"); - ret = bt_object_bool_get(obj, &bool_value); - ok(!ret && bool_value, - "bt_object_map_get() returns an object with the appropriate value (boolean)"); - BT_OBJECT_PUT(obj); - - ret = bt_object_map_insert_bool(map_obj, "bool2", true); - ok(!ret, "bt_object_map_insert_bool() succeeds"); - 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"); - 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"); - 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"); - 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"); - 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"); - 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"); - - ok(!bt_object_map_has_key(map_obj, "hello"), - "map object does not have key \"hello\""); - ok(bt_object_map_has_key(map_obj, "bool"), - "map object has key \"bool\""); - ok(bt_object_map_has_key(map_obj, "int"), - "map object has key \"int\""); - ok(bt_object_map_has_key(map_obj, "float"), - "map object has key \"float\""); - ok(bt_object_map_has_key(map_obj, "null"), - "map object has key \"null\""); - ok(bt_object_map_has_key(map_obj, "bool2"), - "map object has key \"bool2\""); - ok(bt_object_map_has_key(map_obj, "int2"), - "map object has key \"int2\""); - ok(bt_object_map_has_key(map_obj, "float2"), - "map object has key \"float2\""); - ok(bt_object_map_has_key(map_obj, "string2"), - "map object has key \"string2\""); - ok(bt_object_map_has_key(map_obj, "array2"), - "map object has key \"array2\""); - ok(bt_object_map_has_key(map_obj, "map2"), - "map object has key \"map2\""); - - 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"); - 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, - "bt_object_map_foreach() breaks the loop when the user function returns false"); - - memset(&checklist, 0, sizeof(checklist)); - ret = bt_object_map_foreach(map_obj, test_map_foreach_cb_check, - &checklist); - ok(ret == BT_OBJECT_STATUS_OK, - "bt_object_map_foreach() succeeds with test_map_foreach_cb_check()"); - ok(checklist.bool1 && checklist.int1 && checklist.float1 && - checklist.null1 && checklist.bool2 && checklist.int2 && - checklist.float2 && checklist.string2 && - 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") -} - -static -void test_types(void) -{ - test_null(); - test_bool(); - test_integer(); - test_float(); - test_string(); - test_array(); - test_map(); -} - -static -void test_compare_null(void) -{ - ok(!bt_object_compare(bt_object_null, NULL), - "cannot compare null object and NULL"); - ok(!bt_object_compare(NULL, bt_object_null), - "cannot compare NULL and null object"); - ok(bt_object_compare(bt_object_null, bt_object_null), - "null objects are equivalent"); -} - -static -void test_compare_bool(void) -{ - struct bt_object *bool1 = bt_object_bool_create_init(false); - struct bt_object *bool2 = bt_object_bool_create_init(true); - struct bt_object *bool3 = bt_object_bool_create_init(false); - - assert(bool1 && bool2 && bool3); - ok(!bt_object_compare(bt_object_null, bool1), - "cannot compare null object and bool object"); - ok(!bt_object_compare(bool1, bool2), - "integer objects are not equivalent (false and true)"); - ok(bt_object_compare(bool1, bool3), - "integer objects are equivalent (false and false)"); - - BT_OBJECT_PUT(bool1); - BT_OBJECT_PUT(bool2); - BT_OBJECT_PUT(bool3); -} - -static -void test_compare_integer(void) -{ - struct bt_object *int1 = bt_object_integer_create_init(10); - struct bt_object *int2 = bt_object_integer_create_init(-23); - struct bt_object *int3 = bt_object_integer_create_init(10); - - assert(int1 && int2 && int3); - ok(!bt_object_compare(bt_object_null, int1), - "cannot compare null object and integer object"); - ok(!bt_object_compare(int1, int2), - "integer objects are not equivalent (10 and -23)"); - ok(bt_object_compare(int1, int3), - "integer objects are equivalent (10 and 10)"); - - BT_OBJECT_PUT(int1); - BT_OBJECT_PUT(int2); - BT_OBJECT_PUT(int3); -} - -static -void test_compare_float(void) -{ - struct bt_object *float1 = bt_object_float_create_init(17.38); - struct bt_object *float2 = bt_object_float_create_init(-14.23); - struct bt_object *float3 = bt_object_float_create_init(17.38); - - assert(float1 && float2 && float3); - - ok(!bt_object_compare(bt_object_null, float1), - "cannot compare null object and floating point number object"); - ok(!bt_object_compare(float1, float2), - "floating point number objects are not equivalent (17.38 and -14.23)"); - ok(bt_object_compare(float1, float3), - "floating point number objects are equivalent (17.38 and 17.38)"); - - BT_OBJECT_PUT(float1); - BT_OBJECT_PUT(float2); - BT_OBJECT_PUT(float3); -} - -static -void test_compare_string(void) -{ - struct bt_object *string1 = bt_object_string_create_init("hello"); - struct bt_object *string2 = bt_object_string_create_init("bt_object"); - struct bt_object *string3 = bt_object_string_create_init("hello"); - - assert(string1 && string2 && string3); - - ok(!bt_object_compare(bt_object_null, string1), - "cannot compare null object and string object"); - ok(!bt_object_compare(string1, string2), - "string objects are not equivalent (\"hello\" and \"bt_object\")"); - ok(bt_object_compare(string1, string3), - "string objects are equivalent (\"hello\" and \"hello\")"); - - BT_OBJECT_PUT(string1); - BT_OBJECT_PUT(string2); - BT_OBJECT_PUT(string3); -} - -static -void test_compare_array(void) -{ - struct bt_object *array1 = bt_object_array_create(); - struct bt_object *array2 = bt_object_array_create(); - struct bt_object *array3 = bt_object_array_create(); - - assert(array1 && array2 && array3); - - ok(bt_object_compare(array1, array2), - "empty array objects are equivalent"); - - assert(!bt_object_array_append_integer(array1, 23)); - assert(!bt_object_array_append_float(array1, 14.2)); - assert(!bt_object_array_append_bool(array1, false)); - assert(!bt_object_array_append_float(array2, 14.2)); - assert(!bt_object_array_append_integer(array2, 23)); - assert(!bt_object_array_append_bool(array2, false)); - assert(!bt_object_array_append_integer(array3, 23)); - assert(!bt_object_array_append_float(array3, 14.2)); - assert(!bt_object_array_append_bool(array3, false)); - assert(bt_object_array_size(array1) == 3); - assert(bt_object_array_size(array2) == 3); - assert(bt_object_array_size(array3) == 3); - - ok(!bt_object_compare(bt_object_null, array1), - "cannot compare null object and array object"); - ok(!bt_object_compare(array1, array2), - "array objects are not equivalent ([23, 14.2, false] and [14.2, 23, false])"); - ok(bt_object_compare(array1, array3), - "array objects are equivalent ([23, 14.2, false] and [23, 14.2, false])"); - - BT_OBJECT_PUT(array1); - BT_OBJECT_PUT(array2); - BT_OBJECT_PUT(array3); -} - -static -void test_compare_map(void) -{ - struct bt_object *map1 = bt_object_map_create(); - struct bt_object *map2 = bt_object_map_create(); - struct bt_object *map3 = bt_object_map_create(); - - assert(map1 && map2 && map3); - - ok(bt_object_compare(map1, map2), - "empty map objects are equivalent"); - - assert(!bt_object_map_insert_integer(map1, "one", 23)); - assert(!bt_object_map_insert_float(map1, "two", 14.2)); - assert(!bt_object_map_insert_bool(map1, "three", false)); - assert(!bt_object_map_insert_float(map2, "one", 14.2)); - assert(!bt_object_map_insert_integer(map2, "two", 23)); - assert(!bt_object_map_insert_bool(map2, "three", false)); - assert(!bt_object_map_insert_bool(map3, "three", false)); - assert(!bt_object_map_insert_integer(map3, "one", 23)); - assert(!bt_object_map_insert_float(map3, "two", 14.2)); - assert(bt_object_map_size(map1) == 3); - assert(bt_object_map_size(map2) == 3); - assert(bt_object_map_size(map3) == 3); - - ok(!bt_object_compare(bt_object_null, map1), - "cannot compare null object and map object"); - ok(!bt_object_compare(map1, map2), - "map objects are not equivalent"); - ok(bt_object_compare(map1, map3), - "map objects are equivalent"); - - BT_OBJECT_PUT(map1); - BT_OBJECT_PUT(map2); - BT_OBJECT_PUT(map3); -} - -static -void test_compare(void) -{ - ok(!bt_object_compare(NULL, NULL), "cannot compare NULL and NULL"); - test_compare_null(); - test_compare_bool(); - test_compare_integer(); - test_compare_float(); - test_compare_string(); - test_compare_array(); - test_compare_map(); -} - -static -void test_copy(void) -{ - /* - * Here's the deal here. If we make sure that each object - * of our deep copy has a different address than its source, - * and that bt_object_compare() returns true for the top-level - * object, taking into account that we test the correctness of - * bt_object_compare() elsewhere, then the deep copy is a - * success. - */ - struct bt_object *null_copy_obj; - struct bt_object *bool_obj, *bool_copy_obj; - struct bt_object *integer_obj, *integer_copy_obj; - struct bt_object *float_obj, *float_copy_obj; - struct bt_object *string_obj, *string_copy_obj; - struct bt_object *array_obj, *array_copy_obj; - struct bt_object *map_obj, *map_copy_obj; - - bool_obj = bt_object_bool_create_init(true); - integer_obj = bt_object_integer_create_init(23); - float_obj = bt_object_float_create_init(-3.1416); - string_obj = bt_object_string_create_init("test"); - array_obj = bt_object_array_create(); - map_obj = bt_object_map_create(); - - assert(bool_obj && integer_obj && float_obj && string_obj && - array_obj && map_obj); - - assert(!bt_object_array_append(array_obj, bool_obj)); - assert(!bt_object_array_append(array_obj, integer_obj)); - assert(!bt_object_array_append(array_obj, float_obj)); - assert(!bt_object_array_append(array_obj, bt_object_null)); - assert(!bt_object_map_insert(map_obj, "array", array_obj)); - assert(!bt_object_map_insert(map_obj, "string", string_obj)); - - map_copy_obj = bt_object_copy(NULL); - ok(!map_copy_obj, - "bt_object_copy() fails with a source object set to NULL"); - - map_copy_obj = bt_object_copy(map_obj); - ok(map_copy_obj, - "bt_object_copy() succeeds"); - - ok(map_obj != map_copy_obj, - "bt_object_copy() returns a different pointer (map)"); - string_copy_obj = bt_object_map_get(map_copy_obj, "string"); - ok(string_copy_obj != string_obj, - "bt_object_copy() returns a different pointer (string)"); - array_copy_obj = bt_object_map_get(map_copy_obj, "array"); - ok(array_copy_obj != array_obj, - "bt_object_copy() returns a different pointer (array)"); - bool_copy_obj = bt_object_array_get(array_copy_obj, 0); - ok(bool_copy_obj != bool_obj, - "bt_object_copy() returns a different pointer (bool)"); - integer_copy_obj = bt_object_array_get(array_copy_obj, 1); - ok(integer_copy_obj != integer_obj, - "bt_object_copy() returns a different pointer (integer)"); - float_copy_obj = bt_object_array_get(array_copy_obj, 2); - ok(float_copy_obj != float_obj, - "bt_object_copy() returns a different pointer (float)"); - null_copy_obj = bt_object_array_get(array_copy_obj, 3); - ok(null_copy_obj == bt_object_null, - "bt_object_copy() returns the same pointer (null)"); - - ok(bt_object_compare(map_obj, map_copy_obj), - "source and destination objects have the same content"); - - BT_OBJECT_PUT(bool_copy_obj); - BT_OBJECT_PUT(integer_copy_obj); - BT_OBJECT_PUT(float_copy_obj); - BT_OBJECT_PUT(string_copy_obj); - BT_OBJECT_PUT(array_copy_obj); - BT_OBJECT_PUT(map_copy_obj); - BT_OBJECT_PUT(bool_obj); - BT_OBJECT_PUT(integer_obj); - BT_OBJECT_PUT(float_obj); - BT_OBJECT_PUT(string_obj); - BT_OBJECT_PUT(array_obj); - BT_OBJECT_PUT(map_obj); -} - -static -void test_macros(void) -{ - struct bt_object *obj = bt_object_bool_create(); - struct bt_object *src; - struct bt_object *dst; - - assert(obj); - BT_OBJECT_PUT(obj); - ok(!obj, "BT_OBJECT_PUT() resets the variable to NULL"); - - obj = bt_object_bool_create(); - assert(obj); - src = obj; - BT_OBJECT_MOVE(dst, src); - ok(!src, "BT_OBJECT_MOVE() resets the source variable to NULL"); - ok(dst == obj, "BT_OBJECT_MOVE() moves the ownership"); - - 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"); - obj = bt_object_integer_create(); - assert(obj); - 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(); - - return 0; -} diff --git a/tests/lib/test_bt_values.c b/tests/lib/test_bt_values.c new file mode 100644 index 00000000..4f563960 --- /dev/null +++ b/tests/lib/test_bt_values.c @@ -0,0 +1,1167 @@ +/* + * test_bt_values.c + * + * Babeltrace value value objects tests + * + * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation + * Copyright (c) 2015 Philippe Proulx + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include "tap/tap.h" + +static +void test_null(void) +{ + ok(bt_value_null, "bt_value_null is not NULL"); + ok(bt_value_is_null(bt_value_null), + "bt_value_null is a null value object"); + bt_value_get(bt_value_null); + pass("getting bt_value_null does not cause a crash"); + bt_value_put(bt_value_null); + pass("putting bt_value_null does not cause a crash"); + + bt_value_get(NULL); + pass("getting NULL does not cause a crash"); + bt_value_put(NULL); + pass("putting NULL does not cause a crash"); + + ok(bt_value_get_type(NULL) == BT_VALUE_TYPE_UNKNOWN, + "bt_value_get_type(NULL) returns BT_VALUE_TYPE_UNKNOWN"); +} + +static +void test_bool(void) +{ + int ret; + bool value; + struct bt_value *obj; + + obj = bt_value_bool_create(); + ok(obj && bt_value_is_bool(obj), + "bt_value_bool_create() returns a boolean value object"); + + value = true; + ret = bt_value_bool_get(obj, &value); + ok(!ret && !value, "default boolean value object value is false"); + + ret = bt_value_bool_set(NULL, true); + ok(ret == BT_VALUE_STATUS_INVAL, + "bt_value_bool_set() fails with an value object set to NULL"); + ret = bt_value_bool_get(NULL, &value); + ok(ret == BT_VALUE_STATUS_INVAL, + "bt_value_bool_get() fails with an value object set to NULL"); + ret = bt_value_bool_get(obj, NULL); + ok(ret == BT_VALUE_STATUS_INVAL, + "bt_value_bool_get() fails with a return value set to NULL"); + + assert(!bt_value_bool_set(obj, false)); + ret = bt_value_bool_set(obj, true); + ok(!ret, "bt_value_bool_set() succeeds"); + ret = bt_value_bool_get(obj, &value); + ok(!ret && value, "bt_value_bool_set() works"); + + BT_VALUE_PUT(obj); + pass("putting an existing boolean value object does not cause a crash") + + value = false; + obj = bt_value_bool_create_init(true); + ok(obj && bt_value_is_bool(obj), + "bt_value_bool_create_init() returns a boolean value object"); + ret = bt_value_bool_get(obj, &value); + ok(!ret && value, + "bt_value_bool_create_init() sets the appropriate initial value"); + + assert(!bt_value_freeze(obj)); + ok(bt_value_bool_set(obj, false) == BT_VALUE_STATUS_FROZEN, + "bt_value_bool_set() cannot be called on a frozen boolean value object"); + value = false; + ret = bt_value_bool_get(obj, &value); + ok(!ret && value, + "bt_value_bool_set() does not alter a frozen floating point number value object"); + + BT_VALUE_PUT(obj); +} + +static +void test_integer(void) +{ + int ret; + int64_t value; + struct bt_value *obj; + + obj = bt_value_integer_create(); + ok(obj && bt_value_is_integer(obj), + "bt_value_integer_create() returns an integer value object"); + + ret = bt_value_integer_set(NULL, -12345); + ok(ret == BT_VALUE_STATUS_INVAL, + "bt_value_integer_set() fails with an value object set to NULL"); + ret = bt_value_integer_get(NULL, &value); + ok(ret == BT_VALUE_STATUS_INVAL, + "bt_value_integer_get() fails with an value object set to NULL"); + ret = bt_value_integer_get(obj, NULL); + ok(ret == BT_VALUE_STATUS_INVAL, + "bt_value_integer_get() fails with a return value set to NULL"); + + value = 1961; + ret = bt_value_integer_get(obj, &value); + ok(!ret && value == 0, "default integer value object value is 0"); + + ret = bt_value_integer_set(obj, -98765); + ok(!ret, "bt_value_integer_set() succeeds"); + ret = bt_value_integer_get(obj, &value); + ok(!ret && value == -98765, "bt_value_integer_set() works"); + + BT_VALUE_PUT(obj); + pass("putting an existing integer value object does not cause a crash") + + obj = bt_value_integer_create_init(321456987); + ok(obj && bt_value_is_integer(obj), + "bt_value_integer_create_init() returns an integer value object"); + ret = bt_value_integer_get(obj, &value); + ok(!ret && value == 321456987, + "bt_value_integer_create_init() sets the appropriate initial value"); + + assert(!bt_value_freeze(obj)); + ok(bt_value_integer_set(obj, 18276) == BT_VALUE_STATUS_FROZEN, + "bt_value_integer_set() cannot be called on a frozen integer value object"); + value = 17; + ret = bt_value_integer_get(obj, &value); + ok(!ret && value == 321456987, + "bt_value_integer_set() does not alter a frozen integer value object"); + + BT_VALUE_PUT(obj); +} + +static +void test_float(void) +{ + int ret; + double value; + struct bt_value *obj; + + obj = bt_value_float_create(); + ok(obj && bt_value_is_float(obj), + "bt_value_float_create() returns a floating point number value object"); + + ret = bt_value_float_set(NULL, 1.2345); + ok(ret == BT_VALUE_STATUS_INVAL, + "bt_value_float_set() fails with an value object set to NULL"); + ret = bt_value_float_get(NULL, &value); + ok(ret == BT_VALUE_STATUS_INVAL, + "bt_value_float_get() fails with an value object set to NULL"); + ret = bt_value_float_get(obj, NULL); + ok(ret == BT_VALUE_STATUS_INVAL, + "bt_value_float_get() fails with a return value set to NULL"); + + value = 17.34; + ret = bt_value_float_get(obj, &value); + ok(!ret && value == 0., + "default floating point number value object value is 0"); + + ret = bt_value_float_set(obj, -3.1416); + ok(!ret, "bt_value_float_set() succeeds"); + ret = bt_value_float_get(obj, &value); + ok(!ret && value == -3.1416, "bt_value_float_set() works"); + + BT_VALUE_PUT(obj); + pass("putting an existing floating point number value object does not cause a crash") + + obj = bt_value_float_create_init(33.1649758); + ok(obj && bt_value_is_float(obj), + "bt_value_float_create_init() returns a floating point number value object"); + ret = bt_value_float_get(obj, &value); + ok(!ret && value == 33.1649758, + "bt_value_float_create_init() sets the appropriate initial value"); + + assert(!bt_value_freeze(obj)); + ok(bt_value_float_set(obj, 17.88) == BT_VALUE_STATUS_FROZEN, + "bt_value_float_set() fails with a frozen floating point number value object"); + value = 1.2; + ret = bt_value_float_get(obj, &value); + ok(!ret && value == 33.1649758, + "bt_value_float_set() does not alter a frozen floating point number value object"); + + BT_VALUE_PUT(obj); +} + +static +void test_string(void) +{ + int ret; + const char *value; + struct bt_value *obj; + + obj = bt_value_string_create(); + ok(obj && bt_value_is_string(obj), + "bt_value_string_create() returns a string value object"); + + ret = bt_value_string_set(NULL, "hoho"); + ok(ret == BT_VALUE_STATUS_INVAL, + "bt_value_string_set() fails with an value object set to NULL"); + ret = bt_value_string_set(obj, NULL); + ok(ret == BT_VALUE_STATUS_INVAL, + "bt_value_string_set() fails with a value set to NULL"); + ret = bt_value_string_get(NULL, &value); + ok(ret == BT_VALUE_STATUS_INVAL, + "bt_value_string_get() fails with an value object set to NULL"); + ret = bt_value_string_get(obj, NULL); + ok(ret == BT_VALUE_STATUS_INVAL, + "bt_value_string_get() fails with a return value set to NULL"); + + ret = bt_value_string_get(obj, &value); + ok(!ret && value && !strcmp(value, ""), + "default string value object value is \"\""); + + ret = bt_value_string_set(obj, "hello worldz"); + ok(!ret, "bt_value_string_set() succeeds"); + ret = bt_value_string_get(obj, &value); + ok(!ret && value && !strcmp(value, "hello worldz"), + "bt_value_string_get() works"); + + BT_VALUE_PUT(obj); + pass("putting an existing string value object does not cause a crash") + + obj = bt_value_string_create_init(NULL); + ok(!obj, "bt_value_string_create_init() fails with an initial value set to NULL"); + obj = bt_value_string_create_init("initial value"); + ok(obj && bt_value_is_string(obj), + "bt_value_string_create_init() returns a string value object"); + ret = bt_value_string_get(obj, &value); + ok(!ret && value && !strcmp(value, "initial value"), + "bt_value_string_create_init() sets the appropriate initial value"); + + assert(!bt_value_freeze(obj)); + ok(bt_value_string_set(obj, "new value") == BT_VALUE_STATUS_FROZEN, + "bt_value_string_set() fails with a frozen string value object"); + value = ""; + ret = bt_value_string_get(obj, &value); + ok(!ret && value && !strcmp(value, "initial value"), + "bt_value_string_set() does not alter a frozen string value object"); + + BT_VALUE_PUT(obj); +} + +static +void test_array(void) +{ + int ret; + bool bool_value; + int64_t int_value; + double float_value; + struct bt_value *obj; + const char *string_value; + struct bt_value *array_obj; + + array_obj = bt_value_array_create(); + ok(array_obj && bt_value_is_array(array_obj), + "bt_value_array_create() returns an array value object"); + ok(bt_value_array_is_empty(NULL) == false, + "bt_value_array_is_empty() returns false with an value object set to NULL"); + ok(bt_value_array_is_empty(array_obj), + "initial array value object size is 0"); + ok(bt_value_array_size(NULL) == BT_VALUE_STATUS_INVAL, + "bt_value_array_size() fails with an array value object set to NULL"); + + ok(bt_value_array_append(NULL, bt_value_null) + == BT_VALUE_STATUS_INVAL, + "bt_value_array_append() fails with an array value object set to NULL"); + ok(bt_value_array_append(array_obj, NULL) == BT_VALUE_STATUS_INVAL, + "bt_value_array_append() fails with a value set to NULL"); + + obj = bt_value_integer_create_init(345); + ret = bt_value_array_append(array_obj, obj); + BT_VALUE_PUT(obj); + obj = bt_value_float_create_init(-17.45); + ret |= bt_value_array_append(array_obj, obj); + BT_VALUE_PUT(obj); + obj = bt_value_bool_create_init(true); + ret |= bt_value_array_append(array_obj, obj); + BT_VALUE_PUT(obj); + ret |= bt_value_array_append(array_obj, bt_value_null); + ok(!ret, "bt_value_array_append() succeeds"); + ok(bt_value_array_size(array_obj) == 4, + "appending an element to an array value object increment its size"); + + obj = bt_value_array_get(array_obj, 4); + ok(!obj, "getting an array value object's element at an index equal to its size fails"); + obj = bt_value_array_get(array_obj, 5); + ok(!obj, "getting an array value object's element at a larger index fails"); + + obj = bt_value_array_get(NULL, 2); + ok(!obj, "bt_value_array_get() fails with an array value object set to NULL"); + + obj = bt_value_array_get(array_obj, 0); + ok(obj && bt_value_is_integer(obj), + "bt_value_array_get() returns an value object with the appropriate type (integer)"); + ret = bt_value_integer_get(obj, &int_value); + ok(!ret && int_value == 345, + "bt_value_array_get() returns an value object with the appropriate value (integer)"); + BT_VALUE_PUT(obj); + obj = bt_value_array_get(array_obj, 1); + ok(obj && bt_value_is_float(obj), + "bt_value_array_get() returns an value object with the appropriate type (floating point number)"); + ret = bt_value_float_get(obj, &float_value); + ok(!ret && float_value == -17.45, + "bt_value_array_get() returns an value object with the appropriate value (floating point number)"); + BT_VALUE_PUT(obj); + obj = bt_value_array_get(array_obj, 2); + ok(obj && bt_value_is_bool(obj), + "bt_value_array_get() returns an value object with the appropriate type (boolean)"); + ret = bt_value_bool_get(obj, &bool_value); + ok(!ret && bool_value, + "bt_value_array_get() returns an value object with the appropriate value (boolean)"); + BT_VALUE_PUT(obj); + obj = bt_value_array_get(array_obj, 3); + ok(obj == bt_value_null, + "bt_value_array_get() returns an value object with the appropriate type (null)"); + + ok(bt_value_array_set(NULL, 0, bt_value_null) == + BT_VALUE_STATUS_INVAL, + "bt_value_array_set() fails with an array value object set to NULL"); + ok(bt_value_array_set(array_obj, 0, NULL) == BT_VALUE_STATUS_INVAL, + "bt_value_array_set() fails with an element value object set to NULL"); + ok(bt_value_array_set(array_obj, 4, bt_value_null) == + BT_VALUE_STATUS_INVAL, + "bt_value_array_set() fails with an invalid index"); + obj = bt_value_integer_create_init(1001); + assert(obj); + ok(!bt_value_array_set(array_obj, 2, obj), + "bt_value_array_set() succeeds"); + BT_VALUE_PUT(obj); + obj = bt_value_array_get(array_obj, 2); + ok(obj && bt_value_is_integer(obj), + "bt_value_array_set() inserts an value object with the appropriate type"); + ret = bt_value_integer_get(obj, &int_value); + assert(!ret); + ok(int_value == 1001, + "bt_value_array_set() inserts an value object with the appropriate value"); + BT_VALUE_PUT(obj); + + ret = bt_value_array_append_bool(array_obj, false); + ok(!ret, "bt_value_array_append_bool() succeeds"); + ok(bt_value_array_append_bool(NULL, true) == BT_VALUE_STATUS_INVAL, + "bt_value_array_append_bool() fails with an array value object set to NULL"); + ret = bt_value_array_append_integer(array_obj, 98765); + ok(!ret, "bt_value_array_append_integer() succeeds"); + ok(bt_value_array_append_integer(NULL, 18765) == + BT_VALUE_STATUS_INVAL, + "bt_value_array_append_integer() fails with an array value object set to NULL"); + ret = bt_value_array_append_float(array_obj, 2.49578); + ok(!ret, "bt_value_array_append_float() succeeds"); + ok(bt_value_array_append_float(NULL, 1.49578) == + BT_VALUE_STATUS_INVAL, + "bt_value_array_append_float() fails with an array value object set to NULL"); + ret = bt_value_array_append_string(array_obj, "bt_value"); + ok(!ret, "bt_value_array_append_string() succeeds"); + ok(bt_value_array_append_string(NULL, "bt_obj") == + BT_VALUE_STATUS_INVAL, + "bt_value_array_append_string() fails with an array value object set to NULL"); + ret = bt_value_array_append_array(array_obj); + ok(!ret, "bt_value_array_append_array() succeeds"); + ok(bt_value_array_append_array(NULL) == BT_VALUE_STATUS_INVAL, + "bt_value_array_append_array() fails with an array value object set to NULL"); + ret = bt_value_array_append_map(array_obj); + ok(!ret, "bt_value_array_append_map() succeeds"); + ok(bt_value_array_append_map(NULL) == BT_VALUE_STATUS_INVAL, + "bt_value_array_append_map() fails with an array value object set to NULL"); + + ok(bt_value_array_size(array_obj) == 10, + "the bt_value_array_append_*() functions increment the array value object's size"); + ok(!bt_value_array_is_empty(array_obj), + "map value object is not empty"); + + obj = bt_value_array_get(array_obj, 4); + ok(obj && bt_value_is_bool(obj), + "bt_value_array_append_bool() appends a boolean value object"); + ret = bt_value_bool_get(obj, &bool_value); + ok(!ret && !bool_value, + "bt_value_array_append_bool() appends the appropriate value"); + BT_VALUE_PUT(obj); + obj = bt_value_array_get(array_obj, 5); + ok(obj && bt_value_is_integer(obj), + "bt_value_array_append_integer() appends an integer value object"); + ret = bt_value_integer_get(obj, &int_value); + ok(!ret && int_value == 98765, + "bt_value_array_append_integer() appends the appropriate value"); + BT_VALUE_PUT(obj); + obj = bt_value_array_get(array_obj, 6); + ok(obj && bt_value_is_float(obj), + "bt_value_array_append_float() appends a floating point number value object"); + ret = bt_value_float_get(obj, &float_value); + ok(!ret && float_value == 2.49578, + "bt_value_array_append_float() appends the appropriate value"); + BT_VALUE_PUT(obj); + obj = bt_value_array_get(array_obj, 7); + ok(obj && bt_value_is_string(obj), + "bt_value_array_append_string() appends a string value object"); + ret = bt_value_string_get(obj, &string_value); + ok(!ret && string_value && !strcmp(string_value, "bt_value"), + "bt_value_array_append_string() appends the appropriate value"); + BT_VALUE_PUT(obj); + obj = bt_value_array_get(array_obj, 8); + ok(obj && bt_value_is_array(obj), + "bt_value_array_append_array() appends an array value object"); + ok(bt_value_array_is_empty(obj), + "bt_value_array_append_array() an empty array value object"); + BT_VALUE_PUT(obj); + obj = bt_value_array_get(array_obj, 9); + ok(obj && bt_value_is_map(obj), + "bt_value_array_append_map() appends a map value object"); + ok(bt_value_map_is_empty(obj), + "bt_value_array_append_map() an empty map value object"); + BT_VALUE_PUT(obj); + + assert(!bt_value_freeze(array_obj)); + ok(bt_value_array_append(array_obj, bt_value_null) == + BT_VALUE_STATUS_FROZEN, + "bt_value_array_append() fails with a frozen array value object"); + ok(bt_value_array_append_bool(array_obj, false) == + BT_VALUE_STATUS_FROZEN, + "bt_value_array_append_bool() fails with a frozen array value object"); + ok(bt_value_array_append_integer(array_obj, 23) == + BT_VALUE_STATUS_FROZEN, + "bt_value_array_append_integer() fails with a frozen array value object"); + ok(bt_value_array_append_float(array_obj, 2.34) == + BT_VALUE_STATUS_FROZEN, + "bt_value_array_append_float() fails with a frozen array value object"); + ok(bt_value_array_append_string(array_obj, "yayayayaya") == + BT_VALUE_STATUS_FROZEN, + "bt_value_array_append_string() fails with a frozen array value object"); + ok(bt_value_array_append_array(array_obj) == + BT_VALUE_STATUS_FROZEN, + "bt_value_array_append_array() fails with a frozen array value object"); + ok(bt_value_array_append_map(array_obj) == + BT_VALUE_STATUS_FROZEN, + "bt_value_array_append_map() fails with a frozen array value object"); + ok(bt_value_array_set(array_obj, 2, bt_value_null) == + BT_VALUE_STATUS_FROZEN, + "bt_value_array_set() fails with a frozen array value object"); + ok(bt_value_array_size(array_obj) == 10, + "appending to a frozen array value object does not change its size"); + + obj = bt_value_array_get(array_obj, 1); + assert(obj); + ok(bt_value_float_set(obj, 14.52) == BT_VALUE_STATUS_FROZEN, + "freezing an array value object also freezes its elements"); + BT_VALUE_PUT(obj); + + BT_VALUE_PUT(array_obj); + pass("putting an existing array value object does not cause a crash") +} + +static +bool test_map_foreach_cb_count(const char *key, struct bt_value *object, + void *data) +{ + int *count = data; + + if (*count == 3) { + return false; + } + + (*count)++; + + return true; +} + +struct map_foreach_checklist { + bool bool1; + bool int1; + bool float1; + bool null1; + bool bool2; + bool int2; + bool float2; + bool string2; + bool array2; + bool map2; +}; + +static +bool test_map_foreach_cb_check(const char *key, struct bt_value *object, + void *data) +{ + int ret; + struct map_foreach_checklist *checklist = data; + + if (!strcmp(key, "bool")) { + if (checklist->bool1) { + fail("test_map_foreach_cb_check(): duplicate key \"bool\""); + } else { + bool val = false; + + ret = bt_value_bool_get(object, &val); + ok(!ret, "test_map_foreach_cb_check(): success getting \"bool\" value"); + + if (val) { + pass("test_map_foreach_cb_check(): \"bool\" value object has the right value"); + checklist->bool1 = true; + } else { + fail("test_map_foreach_cb_check(): \"bool\" value object has the wrong value"); + } + } + } else if (!strcmp(key, "int")) { + if (checklist->int1) { + fail("test_map_foreach_cb_check(): duplicate key \"int\""); + } else { + int64_t val = 0; + + ret = bt_value_integer_get(object, &val); + ok(!ret, "test_map_foreach_cb_check(): success getting \"int\" value"); + + if (val == 19457) { + pass("test_map_foreach_cb_check(): \"int\" value object has the right value"); + checklist->int1 = true; + } else { + fail("test_map_foreach_cb_check(): \"int\" value object has the wrong value"); + } + } + } else if (!strcmp(key, "float")) { + if (checklist->float1) { + fail("test_map_foreach_cb_check(): duplicate key \"float\""); + } else { + double val = 0; + + ret = bt_value_float_get(object, &val); + ok(!ret, "test_map_foreach_cb_check(): success getting \"float\" value"); + + if (val == 5.444) { + pass("test_map_foreach_cb_check(): \"float\" value object has the right value"); + checklist->float1 = true; + } else { + fail("test_map_foreach_cb_check(): \"float\" value object has the wrong value"); + } + } + } else if (!strcmp(key, "null")) { + if (checklist->null1) { + fail("test_map_foreach_cb_check(): duplicate key \"bool\""); + } else { + ok(bt_value_is_null(object), "test_map_foreach_cb_check(): success getting \"null\" value object"); + checklist->null1 = true; + } + } else if (!strcmp(key, "bool2")) { + if (checklist->bool2) { + fail("test_map_foreach_cb_check(): duplicate key \"bool2\""); + } else { + bool val = false; + + ret = bt_value_bool_get(object, &val); + ok(!ret, "test_map_foreach_cb_check(): success getting \"bool2\" value"); + + if (val) { + pass("test_map_foreach_cb_check(): \"bool2\" value object has the right value"); + checklist->bool2 = true; + } else { + fail("test_map_foreach_cb_check(): \"bool2\" value object has the wrong value"); + } + } + } else if (!strcmp(key, "int2")) { + if (checklist->int2) { + fail("test_map_foreach_cb_check(): duplicate key \"int2\""); + } else { + int64_t val = 0; + + ret = bt_value_integer_get(object, &val); + ok(!ret, "test_map_foreach_cb_check(): success getting \"int2\" value"); + + if (val == 98765) { + pass("test_map_foreach_cb_check(): \"int2\" value object has the right value"); + checklist->int2 = true; + } else { + fail("test_map_foreach_cb_check(): \"int2\" value object has the wrong value"); + } + } + } else if (!strcmp(key, "float2")) { + if (checklist->float2) { + fail("test_map_foreach_cb_check(): duplicate key \"float2\""); + } else { + double val = 0; + + ret = bt_value_float_get(object, &val); + ok(!ret, "test_map_foreach_cb_check(): success getting \"float2\" value"); + + if (val == -49.0001) { + pass("test_map_foreach_cb_check(): \"float2\" value object has the right value"); + checklist->float2 = true; + } else { + fail("test_map_foreach_cb_check(): \"float2\" value 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; + + ret = bt_value_string_get(object, &val); + ok(!ret, "test_map_foreach_cb_check(): success getting \"string2\" value"); + + if (val && !strcmp(val, "bt_value")) { + pass("test_map_foreach_cb_check(): \"string2\" value object has the right value"); + checklist->string2 = true; + } else { + fail("test_map_foreach_cb_check(): \"string2\" value object has the wrong value"); + } + } + } else if (!strcmp(key, "array2")) { + if (checklist->array2) { + fail("test_map_foreach_cb_check(): duplicate key \"array2\""); + } else { + ok(bt_value_is_array(object), "test_map_foreach_cb_check(): success getting \"array2\" value object"); + ok(bt_value_array_is_empty(object), + "test_map_foreach_cb_check(): \"array2\" value object is empty"); + checklist->array2 = true; + } + } else if (!strcmp(key, "map2")) { + if (checklist->map2) { + fail("test_map_foreach_cb_check(): duplicate key \"map2\""); + } else { + ok(bt_value_is_map(object), "test_map_foreach_cb_check(): success getting \"map2\" value object"); + ok(bt_value_map_is_empty(object), + "test_map_foreach_cb_check(): \"map2\" value object is empty"); + checklist->map2 = true; + } + } else { + fail("test_map_foreach_cb_check(): unknown map key \"%s\"", key); + } + + return true; +} + +static +void test_map(void) +{ + int ret; + int count = 0; + bool bool_value; + int64_t int_value; + double float_value; + struct bt_value *obj; + struct bt_value *map_obj; + struct map_foreach_checklist checklist; + + map_obj = bt_value_map_create(); + ok(map_obj && bt_value_is_map(map_obj), + "bt_value_map_create() returns a map value object"); + ok(bt_value_map_size(map_obj) == 0, + "initial map value object size is 0"); + ok(bt_value_map_size(NULL) == BT_VALUE_STATUS_INVAL, + "bt_value_map_size() fails with a map value object set to NULL"); + + ok(bt_value_map_insert(NULL, "hello", bt_value_null) == + BT_VALUE_STATUS_INVAL, + "bt_value_array_insert() fails with a map value object set to NULL"); + ok(bt_value_map_insert(map_obj, NULL, bt_value_null) == + BT_VALUE_STATUS_INVAL, + "bt_value_array_insert() fails with a key set to NULL"); + ok(bt_value_map_insert(map_obj, "yeah", NULL) == + BT_VALUE_STATUS_INVAL, + "bt_value_array_insert() fails with an element value object set to NULL"); + + obj = bt_value_integer_create_init(19457); + ret = bt_value_map_insert(map_obj, "int", obj); + BT_VALUE_PUT(obj); + obj = bt_value_float_create_init(5.444); + ret |= bt_value_map_insert(map_obj, "float", obj); + BT_VALUE_PUT(obj); + obj = bt_value_bool_create(); + ret |= bt_value_map_insert(map_obj, "bool", obj); + BT_VALUE_PUT(obj); + ret |= bt_value_map_insert(map_obj, "null", bt_value_null); + ok(!ret, "bt_value_map_insert() succeeds"); + ok(bt_value_map_size(map_obj) == 4, + "inserting an element into a map value object increment its size"); + + obj = bt_value_bool_create_init(true); + ret = bt_value_map_insert(map_obj, "bool", obj); + BT_VALUE_PUT(obj); + ok(!ret, "bt_value_map_insert() accepts an existing key"); + + obj = bt_value_map_get(map_obj, NULL); + ok(!obj, "bt_value_map_get() fails with a key set to NULL"); + obj = bt_value_map_get(NULL, "bool"); + ok(!obj, "bt_value_map_get() fails with a map value object set to NULL"); + + obj = bt_value_map_get(map_obj, "life"); + ok(!obj, "bt_value_map_get() fails with an non existing key"); + obj = bt_value_map_get(map_obj, "float"); + ok(obj && bt_value_is_float(obj), + "bt_value_map_get() returns an value object with the appropriate type (float)"); + ret = bt_value_float_get(obj, &float_value); + ok(!ret && float_value == 5.444, + "bt_value_map_get() returns an value object with the appropriate value (float)"); + BT_VALUE_PUT(obj); + obj = bt_value_map_get(map_obj, "int"); + ok(obj && bt_value_is_integer(obj), + "bt_value_map_get() returns an value object with the appropriate type (integer)"); + ret = bt_value_integer_get(obj, &int_value); + ok(!ret && int_value == 19457, + "bt_value_map_get() returns an value object with the appropriate value (integer)"); + BT_VALUE_PUT(obj); + obj = bt_value_map_get(map_obj, "null"); + ok(obj && bt_value_is_null(obj), + "bt_value_map_get() returns an value object with the appropriate type (null)"); + obj = bt_value_map_get(map_obj, "bool"); + ok(obj && bt_value_is_bool(obj), + "bt_value_map_get() returns an value object with the appropriate type (boolean)"); + ret = bt_value_bool_get(obj, &bool_value); + ok(!ret && bool_value, + "bt_value_map_get() returns an value object with the appropriate value (boolean)"); + BT_VALUE_PUT(obj); + + ret = bt_value_map_insert_bool(map_obj, "bool2", true); + ok(!ret, "bt_value_map_insert_bool() succeeds"); + ok(bt_value_map_insert_bool(NULL, "bool2", false) == + BT_VALUE_STATUS_INVAL, + "bt_value_map_insert_bool() fails with a map value object set to NULL"); + ret = bt_value_map_insert_integer(map_obj, "int2", 98765); + ok(!ret, "bt_value_map_insert_integer() succeeds"); + ok(bt_value_map_insert_integer(NULL, "int2", 1001) == + BT_VALUE_STATUS_INVAL, + "bt_value_map_insert_integer() fails with a map value object set to NULL"); + ret = bt_value_map_insert_float(map_obj, "float2", -49.0001); + ok(!ret, "bt_value_map_insert_float() succeeds"); + ok(bt_value_map_insert_float(NULL, "float2", 495) == + BT_VALUE_STATUS_INVAL, + "bt_value_map_insert_float() fails with a map value object set to NULL"); + ret = bt_value_map_insert_string(map_obj, "string2", "bt_value"); + ok(!ret, "bt_value_map_insert_string() succeeds"); + ok(bt_value_map_insert_string(NULL, "string2", "bt_obj") == + BT_VALUE_STATUS_INVAL, + "bt_value_map_insert_string() fails with a map value object set to NULL"); + ret = bt_value_map_insert_array(map_obj, "array2"); + ok(!ret, "bt_value_map_insert_array() succeeds"); + ok(bt_value_map_insert_array(NULL, "array2") == BT_VALUE_STATUS_INVAL, + "bt_value_map_insert_array() fails with a map value object set to NULL"); + ret = bt_value_map_insert_map(map_obj, "map2"); + ok(!ret, "bt_value_map_insert_map() succeeds"); + ok(bt_value_map_insert_map(NULL, "map2") == BT_VALUE_STATUS_INVAL, + "bt_value_map_insert_map() fails with a map value object set to NULL"); + + ok(bt_value_map_size(map_obj) == 10, + "the bt_value_map_insert*() functions increment the map value object's size"); + + ok(!bt_value_map_has_key(map_obj, "hello"), + "map value object does not have key \"hello\""); + ok(bt_value_map_has_key(map_obj, "bool"), + "map value object has key \"bool\""); + ok(bt_value_map_has_key(map_obj, "int"), + "map value object has key \"int\""); + ok(bt_value_map_has_key(map_obj, "float"), + "map value object has key \"float\""); + ok(bt_value_map_has_key(map_obj, "null"), + "map value object has key \"null\""); + ok(bt_value_map_has_key(map_obj, "bool2"), + "map value object has key \"bool2\""); + ok(bt_value_map_has_key(map_obj, "int2"), + "map value object has key \"int2\""); + ok(bt_value_map_has_key(map_obj, "float2"), + "map value object has key \"float2\""); + ok(bt_value_map_has_key(map_obj, "string2"), + "map value object has key \"string2\""); + ok(bt_value_map_has_key(map_obj, "array2"), + "map value object has key \"array2\""); + ok(bt_value_map_has_key(map_obj, "map2"), + "map value object has key \"map2\""); + + ok(bt_value_map_foreach(NULL, test_map_foreach_cb_count, &count) == + BT_VALUE_STATUS_INVAL, + "bt_value_map_foreach() fails with a map value object set to NULL"); + ok(bt_value_map_foreach(map_obj, NULL, &count) == + BT_VALUE_STATUS_INVAL, + "bt_value_map_foreach() fails with a user function set to NULL"); + ret = bt_value_map_foreach(map_obj, test_map_foreach_cb_count, &count); + ok(ret == BT_VALUE_STATUS_CANCELLED && count == 3, + "bt_value_map_foreach() breaks the loop when the user function returns false"); + + memset(&checklist, 0, sizeof(checklist)); + ret = bt_value_map_foreach(map_obj, test_map_foreach_cb_check, + &checklist); + ok(ret == BT_VALUE_STATUS_OK, + "bt_value_map_foreach() succeeds with test_map_foreach_cb_check()"); + ok(checklist.bool1 && checklist.int1 && checklist.float1 && + checklist.null1 && checklist.bool2 && checklist.int2 && + checklist.float2 && checklist.string2 && + checklist.array2 && checklist.map2, + "bt_value_map_foreach() iterates over all the map value object's elements"); + + assert(!bt_value_freeze(map_obj)); + ok(bt_value_map_insert(map_obj, "allo", bt_value_null) == + BT_VALUE_STATUS_FROZEN, + "bt_value_map_insert() fails with a frozen map value object"); + ok(bt_value_map_insert_bool(map_obj, "duh", false) == + BT_VALUE_STATUS_FROZEN, + "bt_value_map_insert_bool() fails with a frozen array value object"); + ok(bt_value_map_insert_integer(map_obj, "duh", 23) == + BT_VALUE_STATUS_FROZEN, + "bt_value_map_insert_integer() fails with a frozen array value object"); + ok(bt_value_map_insert_float(map_obj, "duh", 2.34) == + BT_VALUE_STATUS_FROZEN, + "bt_value_map_insert_float() fails with a frozen array value object"); + ok(bt_value_map_insert_string(map_obj, "duh", "yayayayaya") == + BT_VALUE_STATUS_FROZEN, + "bt_value_map_insert_string() fails with a frozen array value object"); + ok(bt_value_map_insert_array(map_obj, "duh") == + BT_VALUE_STATUS_FROZEN, + "bt_value_map_insert_array() fails with a frozen array value object"); + ok(bt_value_map_insert_map(map_obj, "duh") == + BT_VALUE_STATUS_FROZEN, + "bt_value_map_insert_map() fails with a frozen array value object"); + ok(bt_value_map_size(map_obj) == 10, + "appending to a frozen map value object does not change its size"); + + BT_VALUE_PUT(map_obj); + pass("putting an existing map value object does not cause a crash") +} + +static +void test_types(void) +{ + test_null(); + test_bool(); + test_integer(); + test_float(); + test_string(); + test_array(); + test_map(); +} + +static +void test_compare_null(void) +{ + ok(!bt_value_compare(bt_value_null, NULL), + "cannot compare null value object and NULL"); + ok(!bt_value_compare(NULL, bt_value_null), + "cannot compare NULL and null value object"); + ok(bt_value_compare(bt_value_null, bt_value_null), + "null value objects are equivalent"); +} + +static +void test_compare_bool(void) +{ + struct bt_value *bool1 = bt_value_bool_create_init(false); + struct bt_value *bool2 = bt_value_bool_create_init(true); + struct bt_value *bool3 = bt_value_bool_create_init(false); + + assert(bool1 && bool2 && bool3); + ok(!bt_value_compare(bt_value_null, bool1), + "cannot compare null value object and bool value object"); + ok(!bt_value_compare(bool1, bool2), + "integer value objects are not equivalent (false and true)"); + ok(bt_value_compare(bool1, bool3), + "integer value objects are equivalent (false and false)"); + + BT_VALUE_PUT(bool1); + BT_VALUE_PUT(bool2); + BT_VALUE_PUT(bool3); +} + +static +void test_compare_integer(void) +{ + struct bt_value *int1 = bt_value_integer_create_init(10); + struct bt_value *int2 = bt_value_integer_create_init(-23); + struct bt_value *int3 = bt_value_integer_create_init(10); + + assert(int1 && int2 && int3); + ok(!bt_value_compare(bt_value_null, int1), + "cannot compare null value object and integer value object"); + ok(!bt_value_compare(int1, int2), + "integer value objects are not equivalent (10 and -23)"); + ok(bt_value_compare(int1, int3), + "integer value objects are equivalent (10 and 10)"); + + BT_VALUE_PUT(int1); + BT_VALUE_PUT(int2); + BT_VALUE_PUT(int3); +} + +static +void test_compare_float(void) +{ + struct bt_value *float1 = bt_value_float_create_init(17.38); + struct bt_value *float2 = bt_value_float_create_init(-14.23); + struct bt_value *float3 = bt_value_float_create_init(17.38); + + assert(float1 && float2 && float3); + + ok(!bt_value_compare(bt_value_null, float1), + "cannot compare null value object and floating point number value object"); + ok(!bt_value_compare(float1, float2), + "floating point number value objects are not equivalent (17.38 and -14.23)"); + ok(bt_value_compare(float1, float3), + "floating point number value objects are equivalent (17.38 and 17.38)"); + + BT_VALUE_PUT(float1); + BT_VALUE_PUT(float2); + BT_VALUE_PUT(float3); +} + +static +void test_compare_string(void) +{ + struct bt_value *string1 = bt_value_string_create_init("hello"); + struct bt_value *string2 = bt_value_string_create_init("bt_value"); + struct bt_value *string3 = bt_value_string_create_init("hello"); + + assert(string1 && string2 && string3); + + ok(!bt_value_compare(bt_value_null, string1), + "cannot compare null value object and string value object"); + ok(!bt_value_compare(string1, string2), + "string value objects are not equivalent (\"hello\" and \"bt_value\")"); + ok(bt_value_compare(string1, string3), + "string value objects are equivalent (\"hello\" and \"hello\")"); + + BT_VALUE_PUT(string1); + BT_VALUE_PUT(string2); + BT_VALUE_PUT(string3); +} + +static +void test_compare_array(void) +{ + struct bt_value *array1 = bt_value_array_create(); + struct bt_value *array2 = bt_value_array_create(); + struct bt_value *array3 = bt_value_array_create(); + + assert(array1 && array2 && array3); + + ok(bt_value_compare(array1, array2), + "empty array value objects are equivalent"); + + assert(!bt_value_array_append_integer(array1, 23)); + assert(!bt_value_array_append_float(array1, 14.2)); + assert(!bt_value_array_append_bool(array1, false)); + assert(!bt_value_array_append_float(array2, 14.2)); + assert(!bt_value_array_append_integer(array2, 23)); + assert(!bt_value_array_append_bool(array2, false)); + assert(!bt_value_array_append_integer(array3, 23)); + assert(!bt_value_array_append_float(array3, 14.2)); + assert(!bt_value_array_append_bool(array3, false)); + assert(bt_value_array_size(array1) == 3); + assert(bt_value_array_size(array2) == 3); + assert(bt_value_array_size(array3) == 3); + + ok(!bt_value_compare(bt_value_null, array1), + "cannot compare null value object and array value object"); + ok(!bt_value_compare(array1, array2), + "array value objects are not equivalent ([23, 14.2, false] and [14.2, 23, false])"); + ok(bt_value_compare(array1, array3), + "array value objects are equivalent ([23, 14.2, false] and [23, 14.2, false])"); + + BT_VALUE_PUT(array1); + BT_VALUE_PUT(array2); + BT_VALUE_PUT(array3); +} + +static +void test_compare_map(void) +{ + struct bt_value *map1 = bt_value_map_create(); + struct bt_value *map2 = bt_value_map_create(); + struct bt_value *map3 = bt_value_map_create(); + + assert(map1 && map2 && map3); + + ok(bt_value_compare(map1, map2), + "empty map value objects are equivalent"); + + assert(!bt_value_map_insert_integer(map1, "one", 23)); + assert(!bt_value_map_insert_float(map1, "two", 14.2)); + assert(!bt_value_map_insert_bool(map1, "three", false)); + assert(!bt_value_map_insert_float(map2, "one", 14.2)); + assert(!bt_value_map_insert_integer(map2, "two", 23)); + assert(!bt_value_map_insert_bool(map2, "three", false)); + assert(!bt_value_map_insert_bool(map3, "three", false)); + assert(!bt_value_map_insert_integer(map3, "one", 23)); + assert(!bt_value_map_insert_float(map3, "two", 14.2)); + assert(bt_value_map_size(map1) == 3); + assert(bt_value_map_size(map2) == 3); + assert(bt_value_map_size(map3) == 3); + + ok(!bt_value_compare(bt_value_null, map1), + "cannot compare null value object and map value object"); + ok(!bt_value_compare(map1, map2), + "map value objects are not equivalent"); + ok(bt_value_compare(map1, map3), + "map value objects are equivalent"); + + BT_VALUE_PUT(map1); + BT_VALUE_PUT(map2); + BT_VALUE_PUT(map3); +} + +static +void test_compare(void) +{ + ok(!bt_value_compare(NULL, NULL), "cannot compare NULL and NULL"); + test_compare_null(); + test_compare_bool(); + test_compare_integer(); + test_compare_float(); + test_compare_string(); + test_compare_array(); + test_compare_map(); +} + +static +void test_copy(void) +{ + /* + * Here's the deal here. If we make sure that each value object + * of our deep copy has a different address than its source, + * and that bt_value_compare() returns true for the top-level + * value object, taking into account that we test the correctness of + * bt_value_compare() elsewhere, then the deep copy is a + * success. + */ + struct bt_value *null_copy_obj; + struct bt_value *bool_obj, *bool_copy_obj; + struct bt_value *integer_obj, *integer_copy_obj; + struct bt_value *float_obj, *float_copy_obj; + struct bt_value *string_obj, *string_copy_obj; + struct bt_value *array_obj, *array_copy_obj; + struct bt_value *map_obj, *map_copy_obj; + + bool_obj = bt_value_bool_create_init(true); + integer_obj = bt_value_integer_create_init(23); + float_obj = bt_value_float_create_init(-3.1416); + string_obj = bt_value_string_create_init("test"); + array_obj = bt_value_array_create(); + map_obj = bt_value_map_create(); + + assert(bool_obj && integer_obj && float_obj && string_obj && + array_obj && map_obj); + + assert(!bt_value_array_append(array_obj, bool_obj)); + assert(!bt_value_array_append(array_obj, integer_obj)); + assert(!bt_value_array_append(array_obj, float_obj)); + assert(!bt_value_array_append(array_obj, bt_value_null)); + assert(!bt_value_map_insert(map_obj, "array", array_obj)); + assert(!bt_value_map_insert(map_obj, "string", string_obj)); + + map_copy_obj = bt_value_copy(NULL); + ok(!map_copy_obj, + "bt_value_copy() fails with a source value object set to NULL"); + + map_copy_obj = bt_value_copy(map_obj); + ok(map_copy_obj, + "bt_value_copy() succeeds"); + + ok(map_obj != map_copy_obj, + "bt_value_copy() returns a different pointer (map)"); + string_copy_obj = bt_value_map_get(map_copy_obj, "string"); + ok(string_copy_obj != string_obj, + "bt_value_copy() returns a different pointer (string)"); + array_copy_obj = bt_value_map_get(map_copy_obj, "array"); + ok(array_copy_obj != array_obj, + "bt_value_copy() returns a different pointer (array)"); + bool_copy_obj = bt_value_array_get(array_copy_obj, 0); + ok(bool_copy_obj != bool_obj, + "bt_value_copy() returns a different pointer (bool)"); + integer_copy_obj = bt_value_array_get(array_copy_obj, 1); + ok(integer_copy_obj != integer_obj, + "bt_value_copy() returns a different pointer (integer)"); + float_copy_obj = bt_value_array_get(array_copy_obj, 2); + ok(float_copy_obj != float_obj, + "bt_value_copy() returns a different pointer (float)"); + null_copy_obj = bt_value_array_get(array_copy_obj, 3); + ok(null_copy_obj == bt_value_null, + "bt_value_copy() returns the same pointer (null)"); + + ok(bt_value_compare(map_obj, map_copy_obj), + "source and destination value objects have the same content"); + + BT_VALUE_PUT(bool_copy_obj); + BT_VALUE_PUT(integer_copy_obj); + BT_VALUE_PUT(float_copy_obj); + BT_VALUE_PUT(string_copy_obj); + BT_VALUE_PUT(array_copy_obj); + BT_VALUE_PUT(map_copy_obj); + BT_VALUE_PUT(bool_obj); + BT_VALUE_PUT(integer_obj); + BT_VALUE_PUT(float_obj); + BT_VALUE_PUT(string_obj); + BT_VALUE_PUT(array_obj); + BT_VALUE_PUT(map_obj); +} + +static +void test_macros(void) +{ + struct bt_value *obj = bt_value_bool_create(); + struct bt_value *src; + struct bt_value *dst; + + assert(obj); + BT_VALUE_PUT(obj); + ok(!obj, "BT_VALUE_PUT() resets the variable to NULL"); + + obj = bt_value_bool_create(); + assert(obj); + src = obj; + BT_VALUE_MOVE(dst, src); + ok(!src, "BT_VALUE_MOVE() resets the source variable to NULL"); + ok(dst == obj, "BT_VALUE_MOVE() moves the ownership"); + + BT_VALUE_PUT(dst); +} + +static +void test_freeze(void) +{ + struct bt_value *obj; + + ok(bt_value_freeze(NULL) == BT_VALUE_STATUS_INVAL, + "bt_value_freeze() fails with an value object set to NULL"); + ok(!bt_value_freeze(bt_value_null), + "bt_value_freeze() succeeds with a null value object"); + + ok(!bt_value_is_frozen(NULL), "NULL is not frozen"); + ok(bt_value_is_frozen(bt_value_null), + "the null singleton is frozen"); + obj = bt_value_integer_create(); + assert(obj); + ok(!bt_value_is_frozen(obj), + "bt_value_is_frozen() returns false with a fresh value object"); + assert(!bt_value_freeze(obj)); + ok(!bt_value_freeze(obj), + "bt_value_freeze() passes with a frozen value object"); + ok(bt_value_is_frozen(obj), + "bt_value_is_frozen() returns true with a frozen value object"); + + BT_VALUE_PUT(obj); +} + +int main(void) +{ + plan_no_plan(); + + test_macros(); + test_freeze(); + test_types(); + test_compare(); + test_copy(); + + return 0; +} diff --git a/tests/lib/test_ctf_writer.c b/tests/lib/test_ctf_writer.c index 130baef2..db1eeab5 100644 --- a/tests/lib/test_ctf_writer.c +++ b/tests/lib/test_ctf_writer.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include @@ -789,7 +789,7 @@ void append_complex_event(struct bt_ctf_stream_class *stream_class, struct bt_ctf_stream_class *ret_stream_class; struct bt_ctf_event_class *ret_event_class; struct bt_ctf_field *packet_context, *packet_context_field; - struct bt_object *obj; + struct bt_value *obj; ok(bt_ctf_field_type_set_alignment(int_16_type, 0), "bt_ctf_field_type_set_alignment handles 0-alignment correctly"); @@ -953,17 +953,17 @@ void append_complex_event(struct bt_ctf_stream_class *stream_class, "bt_ctf_event_class_get_id returns the correct value"); /* Test event class attributes */ - assert(obj = bt_object_integer_create_init(15)); + assert(obj = bt_value_integer_create_init(15)); ok(bt_ctf_event_class_set_attribute(NULL, "id", obj), "bt_ctf_event_class_set_attribute handles a NULL event class correctly"); ok(bt_ctf_event_class_set_attribute(event_class, NULL, obj), "bt_ctf_event_class_set_attribute handles a NULL name correctly"); ok(bt_ctf_event_class_set_attribute(event_class, "id", NULL), "bt_ctf_event_class_set_attribute handles a NULL value correctly"); - assert(!bt_object_integer_set(obj, -3)); + assert(!bt_value_integer_set(obj, -3)); ok(bt_ctf_event_class_set_attribute(event_class, "id", obj), "bt_ctf_event_class_set_attribute fails with a negative \"id\" attribute"); - assert(!bt_object_integer_set(obj, 11)); + assert(!bt_value_integer_set(obj, 11)); ret = bt_ctf_event_class_set_attribute(event_class, "id", obj); ok(!ret && bt_ctf_event_class_get_id(event_class) == 11, "bt_ctf_event_class_set_attribute succeeds in replacing the existing \"id\" attribute"); @@ -971,13 +971,13 @@ void append_complex_event(struct bt_ctf_stream_class *stream_class, ret &= bt_ctf_event_class_set_attribute(event_class, "model.emf.uri", obj); ok(ret, "bt_ctf_event_class_set_attribute cannot set \"name\" or \"model.emf.uri\" to an integer value"); - BT_OBJECT_PUT(obj); + BT_VALUE_PUT(obj); - obj = bt_object_integer_create_init(5); + obj = bt_value_integer_create_init(5); assert(obj); ok(!bt_ctf_event_class_set_attribute(event_class, "loglevel", obj), "bt_ctf_event_class_set_attribute succeeds in setting the \"loglevel\" attribute"); - BT_OBJECT_PUT(obj); + BT_VALUE_PUT(obj); ok(!bt_ctf_event_class_get_attribute_value_by_name(NULL, "loglevel"), "bt_ctf_event_class_get_attribute_value_by_name handles a NULL event class correctly"); ok(!bt_ctf_event_class_get_attribute_value_by_name(event_class, NULL), @@ -987,12 +987,12 @@ void append_complex_event(struct bt_ctf_stream_class *stream_class, obj = bt_ctf_event_class_get_attribute_value_by_name(event_class, "loglevel"); int64_value = 0; - ret = bt_object_integer_get(obj, &int64_value); + ret = bt_value_integer_get(obj, &int64_value); ok(obj && !ret && int64_value == 5, "bt_ctf_event_class_get_attribute_value_by_name returns the correct value"); - BT_OBJECT_PUT(obj); + BT_VALUE_PUT(obj); - assert(obj = bt_object_string_create_init("nu name")); + assert(obj = bt_value_string_create_init("nu name")); assert(!bt_ctf_event_class_set_attribute(event_class, "name", obj)); ret_string = bt_ctf_event_class_get_name(event_class); ok(!strcmp(ret_string, "nu name"), @@ -1001,11 +1001,11 @@ void append_complex_event(struct bt_ctf_stream_class *stream_class, ret &= bt_ctf_event_class_set_attribute(event_class, "loglevel", obj); ok(ret, "bt_ctf_event_class_set_attribute cannot set \"id\" or \"loglevel\" to a string value"); - BT_OBJECT_PUT(obj); - obj = bt_object_string_create_init("http://kernel.org/"); + BT_VALUE_PUT(obj); + obj = bt_value_string_create_init("http://kernel.org/"); assert(obj); assert(!bt_ctf_event_class_set_attribute(event_class, "model.emf.uri", obj)); - BT_OBJECT_PUT(obj); + BT_VALUE_PUT(obj); ok(bt_ctf_event_class_get_attribute_count(NULL), "bt_ctf_event_class_get_attribute_count handles a NULL event class"); @@ -1030,29 +1030,29 @@ void append_complex_event(struct bt_ctf_stream_class *stream_class, if (!strcmp(ret_string, "id")) { attrs_count.id++; - ok(bt_object_is_integer(obj), + ok(bt_value_is_integer(obj), "bt_ctf_event_class_get_attribute_value returns the correct type (\"%s\")", ret_string); } else if (!strcmp(ret_string, "name")) { attrs_count.name++; - ok(bt_object_is_string(obj), + ok(bt_value_is_string(obj), "bt_ctf_event_class_get_attribute_value returns the correct type (\"%s\")", ret_string); } else if (!strcmp(ret_string, "loglevel")) { attrs_count.loglevel++; - ok(bt_object_is_integer(obj), + ok(bt_value_is_integer(obj), "bt_ctf_event_class_get_attribute_value returns the correct type (\"%s\")", ret_string); } else if (!strcmp(ret_string, "model.emf.uri")) { attrs_count.modelemfuri++; - ok(bt_object_is_string(obj), + ok(bt_value_is_string(obj), "bt_ctf_event_class_get_attribute_value returns the correct type (\"%s\")", ret_string); } else { attrs_count.unknown++; } - BT_OBJECT_PUT(obj); + BT_VALUE_PUT(obj); } ok(attrs_count.unknown == 0, "event class has no unknown attributes"); @@ -2678,7 +2678,7 @@ int main(int argc, char **argv) struct bt_ctf_trace *trace; int ret; int64_t ret_int64_t; - struct bt_object *obj; + struct bt_value *obj; if (argc < 3) { printf("Usage: tests-ctf-writer path_to_ctf_parser_test path_to_babeltrace\n"); @@ -2726,7 +2726,7 @@ int main(int argc, char **argv) "bt_ctf_writer_add_environment_field error with NULL field value"); /* Test bt_ctf_trace_set_environment_field with an integer object */ - obj = bt_object_integer_create_init(23); + obj = bt_value_integer_create_init(23); assert(obj); ok(bt_ctf_trace_set_environment_field(NULL, "test_env_int_obj", obj), "bt_ctf_trace_set_environment_field handles a NULL trace correctly"); @@ -2736,14 +2736,14 @@ int main(int argc, char **argv) "bt_ctf_trace_set_environment_field handles a NULL value correctly"); ok(!bt_ctf_trace_set_environment_field(trace, "test_env_int_obj", obj), "bt_ctf_trace_set_environment_field succeeds in adding an integer object"); - BT_OBJECT_PUT(obj); + BT_VALUE_PUT(obj); /* Test bt_ctf_trace_set_environment_field with a string object */ - obj = bt_object_string_create_init("the value"); + obj = bt_value_string_create_init("the value"); assert(obj); ok(!bt_ctf_trace_set_environment_field(trace, "test_env_str_obj", obj), "bt_ctf_trace_set_environment_field succeeds in adding a string object"); - BT_OBJECT_PUT(obj); + BT_VALUE_PUT(obj); /* Test bt_ctf_trace_set_environment_field_integer */ ok(bt_ctf_trace_set_environment_field_integer(NULL, "test_env_int", @@ -2805,15 +2805,15 @@ int main(int argc, char **argv) ok(bt_ctf_trace_get_environment_field_value(trace, 5) == NULL, "bt_ctf_trace_get_environment_field_value handles an invalid index correctly (too large)"); obj = bt_ctf_trace_get_environment_field_value(trace, 1); - ret = bt_object_integer_get(obj, &ret_int64_t); + ret = bt_value_integer_get(obj, &ret_int64_t); ok(!ret && ret_int64_t == 23, "bt_ctf_trace_get_environment_field_value succeeds in getting an integer value"); - BT_OBJECT_PUT(obj); + BT_VALUE_PUT(obj); obj = bt_ctf_trace_get_environment_field_value(trace, 2); - ret = bt_object_string_get(obj, &ret_string); + ret = bt_value_string_get(obj, &ret_string); ok(!ret && ret_string && !strcmp(ret_string, "the value"), "bt_ctf_trace_get_environment_field_value succeeds in getting a string value"); - BT_OBJECT_PUT(obj); + BT_VALUE_PUT(obj); /* Test bt_ctf_trace_get_environment_field_value_by_name */ ok(!bt_ctf_trace_get_environment_field_value_by_name(NULL, @@ -2825,10 +2825,10 @@ int main(int argc, char **argv) "bt_ctf_trace_get_environment_field_value_by_name returns NULL or an unknown field name"); obj = bt_ctf_trace_get_environment_field_value_by_name(trace, "test_env_str"); - ret = bt_object_string_get(obj, &ret_string); + ret = bt_value_string_get(obj, &ret_string); ok(!ret && ret_string && !strcmp(ret_string, "oh yeah"), "bt_ctf_trace_get_environment_field_value_by_name succeeds in getting an existing field"); - BT_OBJECT_PUT(obj); + BT_VALUE_PUT(obj); /* Test environment field replacement */ ok(!bt_ctf_trace_set_environment_field_integer(trace, "test_env_int", @@ -2837,10 +2837,10 @@ int main(int argc, char **argv) ok(bt_ctf_trace_get_environment_field_count(trace) == 5, "bt_ctf_trace_set_environment_field_integer with an existing key does not increase the environment size"); obj = bt_ctf_trace_get_environment_field_value(trace, 3); - ret = bt_object_integer_get(obj, &ret_int64_t); + ret = bt_value_integer_get(obj, &ret_int64_t); ok(!ret && ret_int64_t == 654321, "bt_ctf_trace_get_environment_field_value successfully replaces an existing field"); - BT_OBJECT_PUT(obj); + BT_VALUE_PUT(obj); if (uname(&name)) { perror("uname"); diff --git a/tests/tests b/tests/tests index 006f51b7..7d6ba4d4 100644 --- a/tests/tests +++ b/tests/tests @@ -3,4 +3,4 @@ lib/test_bitfield lib/test_seek_empty_packet lib/test_seek_big_trace lib/test_ctf_writer_complete -lib/test_bt_objects +lib/test_bt_values