From 96e8f959f3f895366c26f945c418a006e6ea397c Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Fri, 16 Dec 2016 18:30:24 +0100 Subject: [PATCH] Fix: allow duplicate keys and overlapping ranges in enumerations MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This changes the field and field types IR API. It adds a validation to the variant that checks if there are overlapping ranges in its enumeration tag. Signed-off-by: Mathieu Desnoyers Signed-off-by: Jérémie Galarneau --- formats/ctf/ir/field-types.c | 641 +++++++++++------- formats/ctf/ir/fields.c | 28 +- .../babeltrace/ctf-ir/field-types-internal.h | 29 +- include/babeltrace/ctf-ir/field-types.h | 127 ++-- include/babeltrace/ctf-ir/fields.h | 17 + plugins/text/print.c | 74 +- tests/lib/test_ctf_writer.c | 133 ++-- 7 files changed, 627 insertions(+), 422 deletions(-) diff --git a/formats/ctf/ir/field-types.c b/formats/ctf/ir/field-types.c index ad34a86f..f6dcf991 100644 --- a/formats/ctf/ir/field-types.c +++ b/formats/ctf/ir/field-types.c @@ -557,6 +557,13 @@ end: return ret; } +static +bool bt_ctf_field_type_enumeration_has_overlapping_ranges( + struct bt_ctf_field_type_enumeration *enumeration_type) +{ + return enumeration_type->has_overlapping_ranges; +} + static int bt_ctf_field_type_variant_validate(struct bt_ctf_field_type *type) { @@ -574,6 +581,12 @@ int bt_ctf_field_type_variant_validate(struct bt_ctf_field_type *type) goto end; } + if (bt_ctf_field_type_enumeration_has_overlapping_ranges( + variant->tag)) { + ret = -1; + goto end; + } + tag_mappings_count = bt_ctf_field_type_enumeration_get_mapping_count( (struct bt_ctf_field_type *) variant->tag); @@ -585,12 +598,11 @@ int bt_ctf_field_type_variant_validate(struct bt_ctf_field_type *type) for (i = 0; i < tag_mappings_count; ++i) { const char *label; - int64_t range_start, range_end; struct bt_ctf_field_type *ft; - ret = bt_ctf_field_type_enumeration_get_mapping( + ret = bt_ctf_field_type_enumeration_get_mapping_name( (struct bt_ctf_field_type *) variant->tag, - i, &label, &range_start, &range_end); + i, &label); if (ret) { goto end; } @@ -856,6 +868,311 @@ end: return ret; } +static +struct enumeration_mapping *get_enumeration_mapping( + struct bt_ctf_field_type *type, int index) +{ + struct enumeration_mapping *mapping = NULL; + struct bt_ctf_field_type_enumeration *enumeration; + + enumeration = container_of(type, struct bt_ctf_field_type_enumeration, + parent); + if (index >= enumeration->entries->len) { + goto end; + } + + mapping = g_ptr_array_index(enumeration->entries, index); +end: + return mapping; +} + +static void bt_ctf_field_type_enum_iter_destroy(struct bt_object *obj) +{ + struct bt_ctf_field_type_enumeration_mapping_iterator *iter = + container_of(obj, + struct bt_ctf_field_type_enumeration_mapping_iterator, + base); + + bt_put(&iter->enumeration_type->parent); + g_free(iter); +} + +int bt_ctf_field_type_enumeration_mapping_iterator_next( + struct bt_ctf_field_type_enumeration_mapping_iterator *iter) +{ + struct bt_ctf_field_type_enumeration *enumeration; + struct bt_ctf_field_type *type; + int i, ret = 0, len; + + enumeration = iter->enumeration_type; + type = &enumeration->parent; + len = enumeration->entries->len; + for (i = iter->index + 1; i < len; i++) { + struct enumeration_mapping *mapping = + get_enumeration_mapping(type, i); + + switch (iter->kind) { + case ITERATOR_BY_NAME: + if (mapping->string == iter->u.name_quark) { + iter->index = i; + goto end; + } + break; + case ITERATOR_BY_SIGNED_VALUE: + { + int64_t value = iter->u.signed_value; + + if (value >= mapping->range_start._signed && + value <= mapping->range_end._signed) { + iter->index = i; + goto end; + } + break; + } + case ITERATOR_BY_UNSIGNED_VALUE: + { + uint64_t value = iter->u.unsigned_value; + + if (value >= mapping->range_start._unsigned && + value <= mapping->range_end._unsigned) { + iter->index = i; + goto end; + } + break; + } + default: + abort(); + } + } + + ret = -1; +end: + return ret; +} + +static struct bt_ctf_field_type_enumeration_mapping_iterator * + bt_ctf_field_type_enumeration_find_mappings_kind( + struct bt_ctf_field_type *type, + enum bt_ctf_field_type_enumeration_mapping_iterator_kind kind) +{ + struct bt_ctf_field_type_enumeration_mapping_iterator *iter; + struct bt_ctf_field_type_enumeration *enumeration_type; + + if (!type || (type->declaration->id != BT_CTF_TYPE_ID_ENUM)) { + return NULL; + } + enumeration_type = container_of(type, + struct bt_ctf_field_type_enumeration, parent); + iter = g_new0(struct bt_ctf_field_type_enumeration_mapping_iterator, 1); + if (!iter) { + return NULL; + } + bt_object_init(&iter->base, bt_ctf_field_type_enum_iter_destroy); + bt_get(type); + iter->enumeration_type = enumeration_type; + iter->index = -1; + iter->kind = kind; + return iter; +} + +struct bt_ctf_field_type_enumeration_mapping_iterator * + bt_ctf_field_type_enumeration_find_mappings_by_name( + struct bt_ctf_field_type *type, + const char *name) +{ + struct bt_ctf_field_type_enumeration_mapping_iterator *iter = NULL; + + iter = bt_ctf_field_type_enumeration_find_mappings_kind( + type, ITERATOR_BY_NAME); + if (!iter) { + goto error; + } + iter->u.name_quark = g_quark_try_string(name); + if (!iter->u.name_quark) { + goto error; + } + /* Advance iterator to first entry, or leave index at -1. */ + if (bt_ctf_field_type_enumeration_mapping_iterator_next(iter)) { + /* No entry found. */ + goto error; + } + return iter; + +error: + bt_put(iter); + return NULL; +} + +struct bt_ctf_field_type_enumeration_mapping_iterator * + bt_ctf_field_type_enumeration_find_mappings_by_signed_value( + struct bt_ctf_field_type *type, + int64_t value) +{ + struct bt_ctf_field_type_enumeration_mapping_iterator *iter = NULL; + + iter = bt_ctf_field_type_enumeration_find_mappings_kind( + type, ITERATOR_BY_SIGNED_VALUE); + if (!iter) { + goto error; + } + if (bt_ctf_field_type_integer_get_signed( + iter->enumeration_type->container) != 1) { + goto error; + } + iter->u.signed_value = value; + /* Advance iterator to first entry, or leave index at -1. */ + if (bt_ctf_field_type_enumeration_mapping_iterator_next(iter)) { + /* No entry found. */ + goto error; + } + return iter; + +error: + bt_put(iter); + return NULL; +} + +struct bt_ctf_field_type_enumeration_mapping_iterator * + bt_ctf_field_type_enumeration_find_mappings_by_unsigned_value( + struct bt_ctf_field_type *type, + uint64_t value) +{ + struct bt_ctf_field_type_enumeration_mapping_iterator *iter = NULL; + + iter = bt_ctf_field_type_enumeration_find_mappings_kind( + type, ITERATOR_BY_UNSIGNED_VALUE); + if (!iter) { + goto error; + } + if (bt_ctf_field_type_integer_get_signed( + iter->enumeration_type->container) != 0) { + goto error; + } + iter->u.unsigned_value = value; + /* Advance iterator to first entry, or leave index at -1. */ + if (bt_ctf_field_type_enumeration_mapping_iterator_next(iter)) { + /* No entry found. */ + goto error; + } + return iter; + +error: + bt_put(iter); + return NULL; +} + +int bt_ctf_field_type_enumeration_get_mapping_name( + struct bt_ctf_field_type *enum_field_type, + int index, + const char **mapping_name) +{ + struct enumeration_mapping *mapping; + + if (!enum_field_type || index < 0) { + return -1; + } + mapping = get_enumeration_mapping(enum_field_type, index); + if (!mapping) { + return -1; + } + if (mapping_name) { + *mapping_name = g_quark_to_string(mapping->string); + } + return 0; +} + +int bt_ctf_field_type_enumeration_mapping_iterator_get_name( + struct bt_ctf_field_type_enumeration_mapping_iterator *iter, + const char **mapping_name) +{ + if (!iter) { + return -1; + } + return bt_ctf_field_type_enumeration_get_mapping_name( + &iter->enumeration_type->parent, iter->index, + mapping_name); +} + +int bt_ctf_field_type_enumeration_get_mapping_signed( + struct bt_ctf_field_type *enum_field_type, + int index, + const char **mapping_name, int64_t *range_begin, + int64_t *range_end) +{ + struct enumeration_mapping *mapping; + + if (!enum_field_type || index < 0) { + return -1; + } + mapping = get_enumeration_mapping(enum_field_type, index); + if (!mapping) { + return -1; + } + if (mapping_name) { + *mapping_name = g_quark_to_string(mapping->string); + } + if (range_begin) { + *range_begin = mapping->range_start._signed; + } + if (range_end) { + *range_end = mapping->range_end._signed; + } + return 0; +} + +int bt_ctf_field_type_enumeration_mapping_iterator_get_signed( + struct bt_ctf_field_type_enumeration_mapping_iterator *iter, + const char **mapping_name, int64_t *range_begin, + int64_t *range_end) +{ + if (!iter) { + return -1; + } + return bt_ctf_field_type_enumeration_get_mapping_signed( + &iter->enumeration_type->parent, iter->index, + mapping_name, range_begin, range_end); +} + +int bt_ctf_field_type_enumeration_get_mapping_unsigned( + struct bt_ctf_field_type *enum_field_type, + int index, + const char **mapping_name, uint64_t *range_begin, + uint64_t *range_end) +{ + struct enumeration_mapping *mapping; + + if (!enum_field_type || index < 0) { + return -1; + } + mapping = get_enumeration_mapping(enum_field_type, index); + if (!mapping) { + return -1; + } + if (mapping_name) { + *mapping_name = g_quark_to_string(mapping->string); + } + if (range_begin) { + *range_begin = mapping->range_start._unsigned; + } + if (range_end) { + *range_end = mapping->range_end._unsigned; + } + return 0; +} + +int bt_ctf_field_type_enumeration_mapping_iterator_get_unsigned( + struct bt_ctf_field_type_enumeration_mapping_iterator *iter, + const char **mapping_name, uint64_t *range_begin, + uint64_t *range_end) +{ + if (!iter) { + return -1; + } + return bt_ctf_field_type_enumeration_get_mapping_unsigned( + &iter->enumeration_type->parent, iter->index, + mapping_name, range_begin, range_end); +} + struct bt_ctf_field_type *bt_ctf_field_type_enumeration_create( struct bt_ctf_field_type *integer_container_type) { @@ -917,7 +1234,6 @@ int bt_ctf_field_type_enumeration_add_mapping( GQuark mapping_name; struct enumeration_mapping *mapping; struct bt_ctf_field_type_enumeration *enumeration; - struct range_overlap_query query; char *escaped_string; if (!type || (type->declaration->id != BT_CTF_TYPE_ID_ENUM) || @@ -938,31 +1254,19 @@ int bt_ctf_field_type_enumeration_add_mapping( goto end; } - mapping_name = g_quark_from_string(escaped_string); - query = (struct range_overlap_query) { - .range_start._signed = range_start, - .range_end._signed = range_end, - .mapping_name = mapping_name, - .overlaps = 0 }; - enumeration = container_of(type, struct bt_ctf_field_type_enumeration, - parent); - - /* Check that the range does not overlap with one already present */ - g_ptr_array_foreach(enumeration->entries, check_ranges_overlap, &query); - if (query.overlaps) { - ret = -1; - goto error_free; - } - mapping = g_new(struct enumeration_mapping, 1); if (!mapping) { ret = -1; goto error_free; } - + mapping_name = g_quark_from_string(escaped_string); *mapping = (struct enumeration_mapping) { .range_start._signed = range_start, - .range_end._signed = range_end, .string = mapping_name}; + .range_end._signed = range_end, + .string = mapping_name, + }; + enumeration = container_of(type, struct bt_ctf_field_type_enumeration, + parent); g_ptr_array_add(enumeration->entries, mapping); g_ptr_array_sort(enumeration->entries, (GCompareFunc)compare_enumeration_mappings_signed); @@ -980,7 +1284,6 @@ int bt_ctf_field_type_enumeration_add_mapping_unsigned( GQuark mapping_name; struct enumeration_mapping *mapping; struct bt_ctf_field_type_enumeration *enumeration; - struct range_overlap_query query; char *escaped_string; if (!type || (type->declaration->id != BT_CTF_TYPE_ID_ENUM) || @@ -1001,32 +1304,19 @@ int bt_ctf_field_type_enumeration_add_mapping_unsigned( goto end; } - mapping_name = g_quark_from_string(escaped_string); - query = (struct range_overlap_query) { - .range_start._unsigned = range_start, - .range_end._unsigned = range_end, - .mapping_name = mapping_name, - .overlaps = 0 }; - enumeration = container_of(type, struct bt_ctf_field_type_enumeration, - parent); - - /* Check that the range does not overlap with one already present */ - g_ptr_array_foreach(enumeration->entries, check_ranges_overlap_unsigned, - &query); - if (query.overlaps) { - ret = -1; - goto error_free; - } - mapping = g_new(struct enumeration_mapping, 1); if (!mapping) { ret = -1; goto error_free; } - + mapping_name = g_quark_from_string(escaped_string); *mapping = (struct enumeration_mapping) { .range_start._unsigned = range_start, - .range_end._unsigned = range_end, .string = mapping_name}; + .range_end._unsigned = range_end, + .string = mapping_name, + }; + enumeration = container_of(type, struct bt_ctf_field_type_enumeration, + parent); g_ptr_array_add(enumeration->entries, mapping); g_ptr_array_sort(enumeration->entries, (GCompareFunc)compare_enumeration_mappings_unsigned); @@ -1036,51 +1326,6 @@ end: return ret; } -const char *bt_ctf_field_type_enumeration_get_mapping_name_unsigned( - struct bt_ctf_field_type_enumeration *enumeration_type, - uint64_t value) -{ - const char *name = NULL; - struct range_overlap_query query = - (struct range_overlap_query) { - .range_start._unsigned = value, - .range_end._unsigned = value, - .overlaps = 0 }; - - g_ptr_array_foreach(enumeration_type->entries, - check_ranges_overlap_unsigned, - &query); - if (!query.overlaps) { - goto end; - } - - name = g_quark_to_string(query.mapping_name); -end: - return name; -} - -const char *bt_ctf_field_type_enumeration_get_mapping_name_signed( - struct bt_ctf_field_type_enumeration *enumeration_type, - int64_t value) -{ - const char *name = NULL; - struct range_overlap_query query = - (struct range_overlap_query) { - .range_start._signed = value, - .range_end._signed = value, - .overlaps = 0 }; - - g_ptr_array_foreach(enumeration_type->entries, check_ranges_overlap, - &query); - if (!query.overlaps) { - goto end; - } - - name = g_quark_to_string(query.mapping_name); -end: - return name; -} - int bt_ctf_field_type_enumeration_get_mapping_count( struct bt_ctf_field_type *type) { @@ -1099,170 +1344,6 @@ end: return ret; } -static inline -struct enumeration_mapping *get_enumeration_mapping( - struct bt_ctf_field_type *type, int index) -{ - struct enumeration_mapping *mapping = NULL; - struct bt_ctf_field_type_enumeration *enumeration; - - enumeration = container_of(type, struct bt_ctf_field_type_enumeration, - parent); - if (index >= enumeration->entries->len) { - goto end; - } - - mapping = g_ptr_array_index(enumeration->entries, index); -end: - return mapping; -} - -int bt_ctf_field_type_enumeration_get_mapping( - struct bt_ctf_field_type *type, int index, - const char **string, int64_t *range_start, int64_t *range_end) -{ - struct enumeration_mapping *mapping; - int ret = 0; - - if (!type || index < 0 || !string || !range_start || !range_end || - (type->declaration->id != BT_CTF_TYPE_ID_ENUM)) { - ret = -1; - goto end; - } - - mapping = get_enumeration_mapping(type, index); - if (!mapping) { - ret = -1; - goto end; - } - - *string = g_quark_to_string(mapping->string); - *range_start = mapping->range_start._signed; - *range_end = mapping->range_end._signed; -end: - return ret; -} - -int bt_ctf_field_type_enumeration_get_mapping_unsigned( - struct bt_ctf_field_type *type, int index, - const char **string, uint64_t *range_start, uint64_t *range_end) -{ - struct enumeration_mapping *mapping; - int ret = 0; - - if (!type || index < 0 || !string || !range_start || !range_end || - (type->declaration->id != BT_CTF_TYPE_ID_ENUM)) { - ret = -1; - goto end; - } - - mapping = get_enumeration_mapping(type, index); - if (!mapping) { - ret = -1; - goto end; - } - - *string = g_quark_to_string(mapping->string); - *range_start = mapping->range_start._unsigned; - *range_end = mapping->range_end._unsigned; -end: - return ret; -} - -int bt_ctf_field_type_enumeration_get_mapping_index_by_name( - struct bt_ctf_field_type *type, const char *name) -{ - GQuark name_quark; - struct bt_ctf_field_type_enumeration *enumeration; - int i, ret = 0; - - if (!type || !name || - (type->declaration->id != BT_CTF_TYPE_ID_ENUM)) { - ret = -1; - goto end; - } - - name_quark = g_quark_try_string(name); - if (!name_quark) { - ret = -1; - goto end; - } - - enumeration = container_of(type, - struct bt_ctf_field_type_enumeration, parent); - for (i = 0; i < enumeration->entries->len; i++) { - struct enumeration_mapping *mapping = - get_enumeration_mapping(type, i); - - if (mapping->string == name_quark) { - ret = i; - goto end; - } - } - - ret = -1; -end: - return ret; -} - -int bt_ctf_field_type_enumeration_get_mapping_index_by_value( - struct bt_ctf_field_type *type, int64_t value) -{ - struct bt_ctf_field_type_enumeration *enumeration; - int i, ret = 0; - - if (!type || (type->declaration->id != BT_CTF_TYPE_ID_ENUM)) { - ret = -1; - goto end; - } - - enumeration = container_of(type, - struct bt_ctf_field_type_enumeration, parent); - for (i = 0; i < enumeration->entries->len; i++) { - struct enumeration_mapping *mapping = - get_enumeration_mapping(type, i); - - if (value >= mapping->range_start._signed && - value <= mapping->range_end._signed) { - ret = i; - goto end; - } - } - - ret = -1; -end: - return ret; -} - -int bt_ctf_field_type_enumeration_get_mapping_index_by_unsigned_value( - struct bt_ctf_field_type *type, uint64_t value) -{ - struct bt_ctf_field_type_enumeration *enumeration; - int i, ret = 0; - - if (!type || (type->declaration->id != BT_CTF_TYPE_ID_ENUM)) { - ret = -1; - goto end; - } - - enumeration = container_of(type, - struct bt_ctf_field_type_enumeration, parent); - for (i = 0; i < enumeration->entries->len; i++) { - struct enumeration_mapping *mapping = - get_enumeration_mapping(type, i); - - if (value >= mapping->range_start._unsigned && - value <= mapping->range_end._unsigned) { - ret = i; - goto end; - } - } - - ret = -1; -end: - return ret; -} - struct bt_ctf_field_type *bt_ctf_field_type_floating_point_create(void) { struct bt_ctf_field_type_floating_point *floating_point = @@ -1707,7 +1788,7 @@ struct bt_ctf_field_type *bt_ctf_field_type_variant_get_field_type_from_tag( goto end; } - enum_value = bt_ctf_field_enumeration_get_mapping_name(tag); + enum_value = bt_ctf_field_enumeration_get_single_mapping_name(tag); if (!enum_value) { goto end; } @@ -2297,7 +2378,9 @@ struct bt_ctf_field_type *bt_ctf_field_type_variant_get_field_type_signed( struct range_overlap_query query = { .range_start._signed = tag_value, .range_end._signed = tag_value, - .mapping_name = 0, .overlaps = 0}; + .mapping_name = 0, + .overlaps = 0, + }; g_ptr_array_foreach(variant->tag->entries, check_ranges_overlap, &query); @@ -2329,7 +2412,9 @@ struct bt_ctf_field_type *bt_ctf_field_type_variant_get_field_type_unsigned( struct range_overlap_query query = { .range_start._unsigned = tag_value, .range_end._unsigned = tag_value, - .mapping_name = 0, .overlaps = 0}; + .mapping_name = 0, + .overlaps = 0, + }; g_ptr_array_foreach(variant->tag->entries, check_ranges_overlap_unsigned, @@ -2731,12 +2816,58 @@ void bt_ctf_field_type_integer_freeze(struct bt_ctf_field_type *type) generic_field_type_freeze(type); } +/* + * Note: This algorithm is O(n^2) vs number of enumeration mappings. + * Only used when freezing an enumeration. + */ +static +void enumeration_range_overlap_check(struct bt_ctf_field_type *type, + struct bt_ctf_field_type_enumeration *enumeration_type) +{ + int i, j, len = enumeration_type->entries->len; + struct bt_ctf_field_type *container_type; + int is_signed; + + container_type = bt_ctf_field_type_enumeration_get_container_type(type); + assert(container_type); + is_signed = bt_ctf_field_type_integer_get_signed(container_type); + assert(is_signed >= 0); + + for (i = 0; i < len; i++) { + for (j = i + 1; j < len; j++) { + struct enumeration_mapping *mapping[2]; + + mapping[0] = get_enumeration_mapping(type, i); + mapping[1] = get_enumeration_mapping(type, j); + if (is_signed) { + if (mapping[0]->range_start._signed + <= mapping[1]->range_end._signed + && mapping[0]->range_end._signed + >= mapping[1]->range_start._signed) { + enumeration_type->has_overlapping_ranges = true; + return; + } + } else { + if (mapping[0]->range_start._unsigned + <= mapping[1]->range_end._unsigned + && mapping[0]->range_end._unsigned + >= mapping[1]->range_start._unsigned) { + enumeration_type->has_overlapping_ranges = true; + return; + } + } + } + } + assert(!enumeration_type->has_overlapping_ranges); +} + static void bt_ctf_field_type_enumeration_freeze(struct bt_ctf_field_type *type) { struct bt_ctf_field_type_enumeration *enumeration_type = container_of( type, struct bt_ctf_field_type_enumeration, parent); + enumeration_range_overlap_check(type, enumeration_type); generic_field_type_freeze(type); bt_ctf_field_type_freeze(enumeration_type->container); } @@ -3370,7 +3501,7 @@ struct bt_ctf_field_type *bt_ctf_field_type_enumeration_copy( for (i = 0; i < enumeration->entries->len; i++) { struct enumeration_mapping *mapping = g_ptr_array_index( enumeration->entries, i); - struct enumeration_mapping* copy_mapping = g_new0( + struct enumeration_mapping *copy_mapping = g_new0( struct enumeration_mapping, 1); if (!copy_mapping) { diff --git a/formats/ctf/ir/fields.c b/formats/ctf/ir/fields.c index 1a2a2c7f..35db0185 100644 --- a/formats/ctf/ir/fields.c +++ b/formats/ctf/ir/fields.c @@ -866,7 +866,7 @@ end: return container; } -const char *bt_ctf_field_enumeration_get_mapping_name( +const char *bt_ctf_field_enumeration_get_single_mapping_name( struct bt_ctf_field *field) { int ret; @@ -874,7 +874,7 @@ const char *bt_ctf_field_enumeration_get_mapping_name( struct bt_ctf_field *container = NULL; struct bt_ctf_field_type *container_type = NULL; struct bt_ctf_field_type_integer *integer_type = NULL; - struct bt_ctf_field_type_enumeration *enumeration_type = NULL; + struct bt_ctf_field_type_enumeration_mapping_iterator *iter = NULL; container = bt_ctf_field_enumeration_get_container(field); if (!container) { @@ -888,29 +888,37 @@ const char *bt_ctf_field_enumeration_get_mapping_name( integer_type = container_of(container_type, struct bt_ctf_field_type_integer, parent); - enumeration_type = container_of(field->type, - struct bt_ctf_field_type_enumeration, parent); if (!integer_type->declaration.signedness) { uint64_t value; + ret = bt_ctf_field_unsigned_integer_get_value(container, &value); if (ret) { goto error_put_container_type; } - - name = bt_ctf_field_type_enumeration_get_mapping_name_unsigned( - enumeration_type, value); + iter = bt_ctf_field_type_enumeration_find_mappings_by_unsigned_value( + field->type, value); + if (!iter) { + goto error_put_container_type; + } + (void) bt_ctf_field_type_enumeration_mapping_iterator_get_unsigned( + iter, &name, NULL, NULL); } else { int64_t value; + ret = bt_ctf_field_signed_integer_get_value(container, &value); if (ret) { goto error_put_container_type; } - - name = bt_ctf_field_type_enumeration_get_mapping_name_signed( - enumeration_type, value); + iter = bt_ctf_field_type_enumeration_find_mappings_by_signed_value( + field->type, value); + if (!iter) { + goto error_put_container_type; + } + (void) bt_ctf_field_type_enumeration_mapping_iterator_get_signed( + iter, &name, NULL, NULL); } error_put_container_type: diff --git a/include/babeltrace/ctf-ir/field-types-internal.h b/include/babeltrace/ctf-ir/field-types-internal.h index 3df8e745..bd2f4857 100644 --- a/include/babeltrace/ctf-ir/field-types-internal.h +++ b/include/babeltrace/ctf-ir/field-types-internal.h @@ -93,6 +93,25 @@ struct bt_ctf_field_type_enumeration { struct bt_ctf_field_type *container; GPtrArray *entries; /* Array of ptrs to struct enumeration_mapping */ struct declaration_enum declaration; + bool has_overlapping_ranges; +}; + +enum bt_ctf_field_type_enumeration_mapping_iterator_kind { + ITERATOR_BY_NAME, + ITERATOR_BY_SIGNED_VALUE, + ITERATOR_BY_UNSIGNED_VALUE, +}; + +struct bt_ctf_field_type_enumeration_mapping_iterator { + struct bt_object base; + struct bt_ctf_field_type_enumeration *enumeration_type; + enum bt_ctf_field_type_enumeration_mapping_iterator_kind kind; + int index; + union { + GQuark name_quark; + int64_t signed_value; + uint64_t unsigned_value; + } u; }; struct bt_ctf_field_type_floating_point { @@ -177,16 +196,6 @@ int bt_ctf_field_type_serialize(struct bt_ctf_field_type *type, BT_HIDDEN int bt_ctf_field_type_validate(struct bt_ctf_field_type *type); -BT_HIDDEN -const char *bt_ctf_field_type_enumeration_get_mapping_name_unsigned( - struct bt_ctf_field_type_enumeration *enumeration_type, - uint64_t value); - -BT_HIDDEN -const char *bt_ctf_field_type_enumeration_get_mapping_name_signed( - struct bt_ctf_field_type_enumeration *enumeration_type, - int64_t value); - /* Override field type's byte order only if it is set to "native" */ BT_HIDDEN void bt_ctf_field_type_set_native_byte_order( diff --git a/include/babeltrace/ctf-ir/field-types.h b/include/babeltrace/ctf-ir/field-types.h index 682d1a1e..7ae3ae55 100644 --- a/include/babeltrace/ctf-ir/field-types.h +++ b/include/babeltrace/ctf-ir/field-types.h @@ -1176,6 +1176,36 @@ extern int bt_ctf_field_type_floating_point_set_mantissa_digits( /** @} */ +struct bt_ctf_field_type_enumeration_mapping_iterator * + bt_ctf_field_type_enumeration_find_mappings_by_name( + struct bt_ctf_field_type *type, + const char *name); + +struct bt_ctf_field_type_enumeration_mapping_iterator * + bt_ctf_field_type_enumeration_find_mappings_by_signed_value( + struct bt_ctf_field_type *type, + int64_t value); + +struct bt_ctf_field_type_enumeration_mapping_iterator * + bt_ctf_field_type_enumeration_find_mappings_by_unsigned_value( + struct bt_ctf_field_type *type, + uint64_t value); + +int bt_ctf_field_type_enumeration_mapping_iterator_get_name( + struct bt_ctf_field_type_enumeration_mapping_iterator *iter, + const char **mapping_name); + +int bt_ctf_field_type_enumeration_mapping_iterator_get_signed( + struct bt_ctf_field_type_enumeration_mapping_iterator *iter, + const char **mapping_name, int64_t *lower, int64_t *upper); + +int bt_ctf_field_type_enumeration_mapping_iterator_get_unsigned( + struct bt_ctf_field_type_enumeration_mapping_iterator *iter, + const char **mapping_name, uint64_t *lower, uint64_t *upper); + +int bt_ctf_field_type_enumeration_mapping_iterator_next( + struct bt_ctf_field_type_enumeration_mapping_iterator *iter); + /** @defgroup ctfirenumfieldtype CTF IR enumeration field type @ingroup ctfirfieldtypes @@ -1205,8 +1235,8 @@ bt_ctf_field_type_enumeration_add_mapping() or bt_ctf_field_type_enumeration_add_mapping_unsigned(), depending on the signedness of the wrapped @intft. -Many mappings can share the same name, but the ranges of a given -enumeration field type must not overlap. For example, +Many mappings can share the same name, and the ranges of a given +enumeration field type are allowed to overlap. For example, this is a valid set of mappings: @verbatim @@ -1216,7 +1246,7 @@ CHERRY -> [ 25, 34] APPLE -> [ 55, 55] @endverbatim -The following set of mappings is \em not valid, however: +The following set of mappings is also valid: @verbatim APPLE -> [ 3, 19] @@ -1286,6 +1316,10 @@ struct bt_ctf_field_type *bt_ctf_field_type_enumeration_get_container_type( extern int bt_ctf_field_type_enumeration_get_mapping_count( struct bt_ctf_field_type *enum_field_type); +extern int bt_ctf_field_type_enumeration_get_mapping_name( + struct bt_ctf_field_type *enum_field_type, int index, + const char **name); + /** @brief Returns the signed mapping of the @enumft \p enum_field_type at index \p index. @@ -1320,11 +1354,11 @@ On success, \p enum_field_type remains the sole owner of \p *name. bt_ctf_field_type_enumeration_get_mapping_count()). @postrefcountsame{enum_field_type} -@sa bt_ctf_field_type_enumeration_get_mapping_unsigned(): Returns the - unsigned mapping contained by a given enumeration field type +@sa bt_ctf_field_type_enumeration_get_mapping_signed(): Returns the + signed mapping contained by a given enumeration field type at a given index. */ -extern int bt_ctf_field_type_enumeration_get_mapping( +extern int bt_ctf_field_type_enumeration_get_mapping_signed( struct bt_ctf_field_type *enum_field_type, int index, const char **name, int64_t *range_begin, int64_t *range_end); @@ -1362,8 +1396,8 @@ On success, \p enum_field_type remains the sole owner of \p *name. bt_ctf_field_type_enumeration_get_mapping_count()). @postrefcountsame{enum_field_type} -@sa bt_ctf_field_type_enumeration_get_mapping(): Returns the - signed mapping contained by a given enumeration field type +@sa bt_ctf_field_type_enumeration_get_mapping_unsigned(): Returns the + unsigned mapping contained by a given enumeration field type at a given index. */ extern int bt_ctf_field_type_enumeration_get_mapping_unsigned( @@ -1371,75 +1405,6 @@ extern int bt_ctf_field_type_enumeration_get_mapping_unsigned( const char **name, uint64_t *range_begin, uint64_t *range_end); -/** @cond DOCUMENT */ -/* - * TODO: Document once we know what to do with this function (return - * the first match?). - */ -extern int bt_ctf_field_type_enumeration_get_mapping_index_by_name( - struct bt_ctf_field_type *enum_field_type, const char *name); -/** @endcond */ - -/** -@brief Returns the index of the signed mapping of the @enumft - \p field_type which contains the value \p value. - -The @intft wrapped by \p enum_field_type, as returned by -bt_ctf_field_type_enumeration_get_container_type(), must be -\b signed to use this function. - -@param[in] enum_field_type Enumeration field type of which to get - the index of the mapping which contains - \p value. -@param[in] value Value of the mapping to find. -@returns Index of the mapping of - \p enum_field_type which contains - \p value, or a negative value if the - function cannot find such a mapping or - on error. - -@prenotnull{enum_field_type} -@preisenumft{enum_field_type} -@pre The wrapped @intft of \p enum_field_type is signed. -@postrefcountsame{enum_field_type} - -@sa bt_ctf_field_type_enumeration_get_mapping_index_by_unsigned_value(): - Finds the index of an unsigned mapping of a given enumeration - field type by value. -*/ -extern int bt_ctf_field_type_enumeration_get_mapping_index_by_value( - struct bt_ctf_field_type *enum_field_type, int64_t value); - -/** -@brief Returns the index of the unsigned mapping of the @enumft - \p field_type which contains the value \p value. - -The @intft wrapped by \p enum_field_type, as returned by -bt_ctf_field_type_enumeration_get_container_type(), must be -\b unsigned to use this function. - -@param[in] enum_field_type Enumeration field type of which to get - the index of the mapping which contains - \p value. -@param[in] value Value of the mapping to find. -@returns Index of the mapping of - \p enum_field_type which contains - \p value, or a negative value if the - function cannot find such a mapping or - on error. - -@prenotnull{enum_field_type} -@preisenumft{enum_field_type} -@pre The wrapped @intft of \p enum_field_type is unsigned. -@postrefcountsame{enum_field_type} - -@sa bt_ctf_field_type_enumeration_get_mapping_index_by_unsigned_value(): - Finds the index of a signed mapping of a given enumeration - field type by value. -*/ -extern int bt_ctf_field_type_enumeration_get_mapping_index_by_unsigned_value( - struct bt_ctf_field_type *enum_field_type, uint64_t value); - /** @brief Adds a mapping to the @enumft \p enum_field_type which maps the name \p name to the signed range \p range_begin (included) to @@ -1452,9 +1417,7 @@ The @intft wrapped by \p enum_field_type, as returned by bt_ctf_field_type_enumeration_get_container_type(), must be \b signed to use this function. -A mapping in \p enum_field_type can exist with the name \p name, but -there must be no overlap amongst all the ranges of -\p enum_field_type. +A mapping in \p enum_field_type can exist with the name \p name. @param[in] enum_field_type Enumeration field type to which to add a mapping. @@ -1492,9 +1455,7 @@ The @intft wrapped by \p enum_field_type, as returned by bt_ctf_field_type_enumeration_get_container_type(), must be \b unsigned to use this function. -A mapping in \p enum_field_type can exist with the name \p name, but -there must be no overlap amongst all the ranges of -\p enum_field_type. +A mapping in \p enum_field_type can exist with the name \p name. @param[in] enum_field_type Enumeration field type to which to add a mapping. diff --git a/include/babeltrace/ctf-ir/fields.h b/include/babeltrace/ctf-ir/fields.h index 536a88f5..e9f59fb3 100644 --- a/include/babeltrace/ctf-ir/fields.h +++ b/include/babeltrace/ctf-ir/fields.h @@ -126,6 +126,7 @@ struct bt_ctf_field; struct bt_ctf_event_class; struct bt_ctf_event; struct bt_ctf_field_type; +struct bt_ctf_field_type_enum_iter; /** @name Creation and parent field type access functions @@ -208,6 +209,19 @@ extern struct bt_ctf_field_type *bt_ctf_field_get_type( */ extern enum bt_ctf_type_id bt_ctf_field_get_type_id(struct bt_ctf_field *field); +/* + * bt_ctf_field_signed_integer_get_value: get a signed integer field's value + * + * Get a signed integer field's value. + * + * @param integer Signed integer field instance. + * @param value Pointer to a signed integer where the value will be stored. + * + * Returns 0 on success, a negative value on error. + */ +extern int bt_ctf_field_signed_integer_get_value(struct bt_ctf_field *integer, + int64_t *value); + /** @brief Returns whether or not the @field \p field is a @intfield. @@ -1111,6 +1125,9 @@ extern struct bt_ctf_field *bt_ctf_field_variant_get_tag( /** @} */ +const char *bt_ctf_field_enumeration_get_single_mapping_name( + struct bt_ctf_field *field); + #ifdef __cplusplus } #endif diff --git a/plugins/text/print.c b/plugins/text/print.c index c1ae888b..5ba97958 100644 --- a/plugins/text/print.c +++ b/plugins/text/print.c @@ -627,18 +627,75 @@ enum bt_component_status print_enum(struct text_component *text, { enum bt_component_status ret = BT_COMPONENT_STATUS_OK; struct bt_ctf_field *container_field = NULL; - const char *mapping_name; - + struct bt_ctf_field_type *enumeration_field_type = NULL; + struct bt_ctf_field_type *container_field_type = NULL; + struct bt_ctf_field_type_enumeration_mapping_iterator *iter = NULL; + int nr_mappings = 0; + int is_signed; + + enumeration_field_type = bt_ctf_field_get_type(field); + if (!enumeration_field_type) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } container_field = bt_ctf_field_enumeration_get_container(field); if (!container_field) { ret = BT_COMPONENT_STATUS_ERROR; goto end; } - mapping_name = bt_ctf_field_enumeration_get_mapping_name(field); - if (mapping_name) { - fprintf(text->out, "( \"%s\"", mapping_name); + container_field_type = bt_ctf_field_get_type(container_field); + if (!container_field_type) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + is_signed = bt_ctf_field_type_integer_get_signed(container_field_type); + if (is_signed < 0) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + if (is_signed) { + int64_t value; + + if (bt_ctf_field_signed_integer_get_value(container_field, + &value)) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + iter = bt_ctf_field_type_enumeration_find_mappings_by_signed_value( + enumeration_field_type, value); } else { - fprintf(text->out, "( "); + uint64_t value; + + if (bt_ctf_field_unsigned_integer_get_value(container_field, + &value)) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + iter = bt_ctf_field_type_enumeration_find_mappings_by_unsigned_value( + enumeration_field_type, value); + } + if (!iter) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + fprintf(text->out, "( "); + for (;;) { + const char *mapping_name; + + if (bt_ctf_field_type_enumeration_mapping_iterator_get_signed( + iter, &mapping_name, NULL, NULL) < 0) { + ret = BT_COMPONENT_STATUS_ERROR; + goto end; + } + if (nr_mappings++) + fprintf(text->out, ", "); + fprintf(text->out, "\"%s\"", mapping_name); + if (bt_ctf_field_type_enumeration_mapping_iterator_next(iter) < 0) { + break; + } + } + if (!nr_mappings) { + fprintf(text->out, ""); } fprintf(text->out, " : container = "); ret = print_integer(text, container_field); @@ -647,7 +704,10 @@ enum bt_component_status print_enum(struct text_component *text, } fprintf(text->out, " )"); end: + bt_put(iter); + bt_put(container_field_type); bt_put(container_field); + bt_put(enumeration_field_type); return ret; } @@ -958,7 +1018,7 @@ enum bt_component_status print_variant(struct text_component *text, ret = BT_COMPONENT_STATUS_ERROR; goto end; } - tag_choice = bt_ctf_field_enumeration_get_mapping_name(tag_field); + tag_choice = bt_ctf_field_enumeration_get_single_mapping_name(tag_field); if (!tag_choice) { bt_put(tag_field); ret = BT_COMPONENT_STATUS_ERROR; diff --git a/tests/lib/test_ctf_writer.c b/tests/lib/test_ctf_writer.c index a16d895b..2dd55963 100644 --- a/tests/lib/test_ctf_writer.c +++ b/tests/lib/test_ctf_writer.c @@ -60,7 +60,7 @@ #define DEFAULT_CLOCK_TIME 0 #define DEFAULT_CLOCK_VALUE 0 -#define NR_TESTS 596 +#define NR_TESTS 600 static int64_t current_time = 42; @@ -330,6 +330,7 @@ void append_simple_event(struct bt_ctf_stream_class *stream_class, struct bt_ctf_field_type *ep_integer_field_type = NULL; struct bt_ctf_field_type *ep_enum_field_type = NULL; struct bt_ctf_field_type *ep_enum_field_unsigned_type = NULL; + struct bt_ctf_field_type_enumeration_mapping_iterator *iter = NULL; int ret; ok(uint_12_type, "Create an unsigned integer type"); @@ -381,44 +382,50 @@ void append_simple_event(struct bt_ctf_stream_class *stream_class, bt_ctf_field_type_enumeration_add_mapping(enum_type, mapping_name_test, 42, 42); ok(bt_ctf_field_type_enumeration_add_mapping(enum_type, mapping_name_test, - 43, 51), "bt_ctf_field_type_enumeration_add_mapping rejects duplicate mapping names"); + 43, 51) == 0, "bt_ctf_field_type_enumeration_add_mapping accepts duplicate mapping names"); ok(bt_ctf_field_type_enumeration_add_mapping(enum_type, "something", - -500, -400), "bt_ctf_field_type_enumeration_add_mapping rejects overlapping enum entries"); + -500, -400) == 0, "bt_ctf_field_type_enumeration_add_mapping accepts overlapping enum entries"); ok(bt_ctf_field_type_enumeration_add_mapping(enum_type, mapping_name_test, -54, -55), "bt_ctf_field_type_enumeration_add_mapping rejects mapping where end < start"); bt_ctf_field_type_enumeration_add_mapping(enum_type, "another entry", -42000, -13000); - ok(bt_ctf_field_type_enumeration_get_mapping_index_by_value(NULL, -42) < 0, - "bt_ctf_field_type_enumeration_get_mapping_index_by_value handles a NULL field type correctly"); - ok(bt_ctf_field_type_enumeration_get_mapping_index_by_value(enum_type, 1000000) < 0, - "bt_ctf_field_type_enumeration_get_mapping_index_by_value handles invalid values correctly"); - ok(bt_ctf_field_type_enumeration_get_mapping_index_by_value(enum_type, -55) == 1, - "bt_ctf_field_type_enumeration_get_mapping_index_by_value returns the correct index"); + iter = bt_ctf_field_type_enumeration_find_mappings_by_signed_value(NULL, -42); + ok(iter == NULL, "bt_ctf_field_type_enumeration_find_mappings_by_signed_value handles a NULL field type correctly"); + + iter = bt_ctf_field_type_enumeration_find_mappings_by_signed_value(enum_type, -4200000); + ok(iter == NULL, "bt_ctf_field_type_enumeration_find_mappings_by_signed_value rejects non-mapped values"); + + iter = bt_ctf_field_type_enumeration_find_mappings_by_signed_value(enum_type, 3); + ok(iter != NULL, "bt_ctf_field_type_enumeration_find_mappings_by_signed_value succeeds with mapped value"); + ok(bt_ctf_field_type_enumeration_mapping_iterator_get_signed(iter, NULL, NULL, NULL) == 0, + "bt_ctf_field_type_enumeration_mapping_iterator_get_signed handles mapped values correctly"); + BT_PUT(iter); ok(bt_ctf_event_class_add_field(simple_event_class, enum_type, "enum_field") == 0, "Add signed enumeration field to event"); - ok(bt_ctf_field_type_enumeration_get_mapping(NULL, 0, &ret_char, - &ret_range_start_int64_t, &ret_range_end_int64_t) < 0, - "bt_ctf_field_type_enumeration_get_mapping handles a NULL enumeration correctly"); - ok(bt_ctf_field_type_enumeration_get_mapping(enum_type, 0, NULL, + ok(bt_ctf_field_type_enumeration_get_mapping_signed(NULL, 0, &ret_char, &ret_range_start_int64_t, &ret_range_end_int64_t) < 0, - "bt_ctf_field_type_enumeration_get_mapping handles a NULL string correctly"); - ok(bt_ctf_field_type_enumeration_get_mapping(enum_type, 0, &ret_char, - NULL, &ret_range_end_int64_t) < 0, - "bt_ctf_field_type_enumeration_get_mapping handles a NULL start correctly"); - ok(bt_ctf_field_type_enumeration_get_mapping(enum_type, 0, &ret_char, - &ret_range_start_int64_t, NULL) < 0, - "bt_ctf_field_type_enumeration_get_mapping handles a NULL end correctly"); - ok(bt_ctf_field_type_enumeration_get_mapping(enum_type, 5, &ret_char, + "bt_ctf_field_type_enumeration_get_mapping_signed handles a NULL enumeration correctly"); + ok(bt_ctf_field_type_enumeration_get_mapping_signed(enum_type, 0, NULL, &ret_range_start_int64_t, &ret_range_end_int64_t) == 0, - "bt_ctf_field_type_enumeration_get_mapping returns a value"); + "bt_ctf_field_type_enumeration_get_mapping_signed handles a NULL string correctly"); + ok(bt_ctf_field_type_enumeration_get_mapping_signed(enum_type, 0, &ret_char, + NULL, &ret_range_end_int64_t) == 0, + "bt_ctf_field_type_enumeration_get_mapping_signed handles a NULL start correctly"); + ok(bt_ctf_field_type_enumeration_get_mapping_signed(enum_type, 0, &ret_char, + &ret_range_start_int64_t, NULL) == 0, + "bt_ctf_field_type_enumeration_get_mapping_signed handles a NULL end correctly"); + /* Assumes entries are sorted by range_start values. */ + ok(bt_ctf_field_type_enumeration_get_mapping_signed(enum_type, 6, &ret_char, + &ret_range_start_int64_t, &ret_range_end_int64_t) == 0, + "bt_ctf_field_type_enumeration_get_mapping_signed returns a value"); ok(!strcmp(ret_char, mapping_name_test), - "bt_ctf_field_type_enumeration_get_mapping returns a correct mapping name"); + "bt_ctf_field_type_enumeration_get_mapping_signed returns a correct mapping name"); ok(ret_range_start_int64_t == 42, - "bt_ctf_field_type_enumeration_get_mapping returns a correct mapping start"); + "bt_ctf_field_type_enumeration_get_mapping_signed returns a correct mapping start"); ok(ret_range_end_int64_t == 42, - "bt_ctf_field_type_enumeration_get_mapping returns a correct mapping end"); + "bt_ctf_field_type_enumeration_get_mapping_signed returns a correct mapping end"); ok(bt_ctf_field_type_enumeration_add_mapping_unsigned(enum_type_unsigned, "escaping; \"test\"", 0, 0) == 0, @@ -432,9 +439,9 @@ void append_simple_event(struct bt_ctf_stream_class *stream_class, bt_ctf_field_type_enumeration_add_mapping_unsigned(enum_type_unsigned, mapping_name_test, 42, 42); ok(bt_ctf_field_type_enumeration_add_mapping_unsigned(enum_type_unsigned, mapping_name_test, - 43, 51), "bt_ctf_field_type_enumeration_add_mapping_unsigned rejects duplicate mapping names"); + 43, 51) == 0, "bt_ctf_field_type_enumeration_add_mapping_unsigned accepts duplicate mapping names"); ok(bt_ctf_field_type_enumeration_add_mapping_unsigned(enum_type_unsigned, "something", - 7, 8), "bt_ctf_field_type_enumeration_add_mapping_unsigned rejects overlapping enum entries"); + 7, 8) == 0, "bt_ctf_field_type_enumeration_add_mapping_unsigned accepts overlapping enum entries"); ok(bt_ctf_field_type_enumeration_add_mapping_unsigned(enum_type_unsigned, mapping_name_test, 55, 54), "bt_ctf_field_type_enumeration_add_mapping_unsigned rejects mapping where end < start"); ok(bt_ctf_event_class_add_field(simple_event_class, enum_type_unsigned, @@ -442,22 +449,22 @@ void append_simple_event(struct bt_ctf_stream_class *stream_class, ok(bt_ctf_field_type_enumeration_get_mapping_count(NULL) < 0, "bt_ctf_field_type_enumeration_get_mapping_count handles NULL correctly"); - ok(bt_ctf_field_type_enumeration_get_mapping_count(enum_type_unsigned) == 4, + ok(bt_ctf_field_type_enumeration_get_mapping_count(enum_type_unsigned) == 6, "bt_ctf_field_type_enumeration_get_mapping_count returns the correct value"); ok(bt_ctf_field_type_enumeration_get_mapping_unsigned(NULL, 0, &ret_char, &ret_range_start_uint64_t, &ret_range_end_uint64_t) < 0, "bt_ctf_field_type_enumeration_get_mapping_unsigned handles a NULL enumeration correctly"); ok(bt_ctf_field_type_enumeration_get_mapping_unsigned(enum_type_unsigned, 0, NULL, - &ret_range_start_uint64_t, &ret_range_end_uint64_t) < 0, + &ret_range_start_uint64_t, &ret_range_end_uint64_t) == 0, "bt_ctf_field_type_enumeration_get_mapping_unsigned handles a NULL string correctly"); ok(bt_ctf_field_type_enumeration_get_mapping_unsigned(enum_type_unsigned, 0, &ret_char, - NULL, &ret_range_end_uint64_t) < 0, + NULL, &ret_range_end_uint64_t) == 0, "bt_ctf_field_type_enumeration_get_mapping_unsigned handles a NULL start correctly"); ok(bt_ctf_field_type_enumeration_get_mapping_unsigned(enum_type_unsigned, 0, &ret_char, - &ret_range_start_uint64_t, NULL) < 0, + &ret_range_start_uint64_t, NULL) == 0, "bt_ctf_field_type_enumeration_get_mapping_unsigned handles a NULL end correctly"); - ok(bt_ctf_field_type_enumeration_get_mapping_unsigned(enum_type_unsigned, 3, &ret_char, + ok(bt_ctf_field_type_enumeration_get_mapping_unsigned(enum_type_unsigned, 4, &ret_char, &ret_range_start_uint64_t, &ret_range_end_uint64_t) == 0, "bt_ctf_field_type_enumeration_get_mapping_unsigned returns a value"); ok(!strcmp(ret_char, mapping_name_test), @@ -578,18 +585,19 @@ void append_simple_event(struct bt_ctf_stream_class *stream_class, enum_field = bt_ctf_field_create(ep_enum_field_type); assert(enum_field); - ret_char = bt_ctf_field_enumeration_get_mapping_name(NULL); - ok(!ret_char, "bt_ctf_field_enumeration_get_mapping_name handles NULL correctly"); - ret_char = bt_ctf_field_enumeration_get_mapping_name(enum_field); - ok(!ret_char, "bt_ctf_field_enumeration_get_mapping_name returns NULL if the enumeration's container field is unset"); + + ret_char = bt_ctf_field_enumeration_get_single_mapping_name(NULL); + ok(!ret_char, "bt_ctf_field_enumeration_get_single_mapping_name handles NULL correctly"); + ret_char = bt_ctf_field_enumeration_get_single_mapping_name(enum_field); + ok(!ret_char, "bt_ctf_field_enumeration_get_single_mapping_name returns NULL if the enumeration's container field is unset"); enum_container_field = bt_ctf_field_enumeration_get_container( enum_field); ok(bt_ctf_field_signed_integer_set_value( enum_container_field, -42) == 0, "Set signed enumeration container value"); - ret_char = bt_ctf_field_enumeration_get_mapping_name(enum_field); + ret_char = bt_ctf_field_enumeration_get_single_mapping_name(enum_field); ok(!strcmp(ret_char, mapping_name_negative_test), - "bt_ctf_field_enumeration_get_mapping_name returns the correct mapping name with an signed container"); + "bt_ctf_field_enumeration_get_single_mapping_name returns the correct mapping name with an signed container"); ret = bt_ctf_event_set_payload(simple_event, "enum_field", enum_field); assert(!ret); @@ -603,9 +611,9 @@ void append_simple_event(struct bt_ctf_stream_class *stream_class, ret = bt_ctf_event_set_payload(simple_event, "enum_field_unsigned", enum_field_unsigned); assert(!ret); - ret_char = bt_ctf_field_enumeration_get_mapping_name(enum_field_unsigned); + ret_char = bt_ctf_field_enumeration_get_single_mapping_name(enum_field_unsigned); ok(ret_char && !strcmp(ret_char, mapping_name_test), - "bt_ctf_field_enumeration_get_mapping_name returns the correct mapping name with an unsigned container"); + "bt_ctf_field_enumeration_get_single_mapping_name returns the correct mapping name with an unsigned container"); ok(bt_ctf_clock_set_time(clock, current_time) == 0, "Set clock time"); @@ -750,6 +758,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_ctf_field_type_enumeration_mapping_iterator *iter = NULL; struct bt_value *obj; ok(bt_ctf_field_type_set_alignment(int_16_type, 0), @@ -801,22 +810,32 @@ void append_complex_event(struct bt_ctf_stream_class *stream_class, bt_ctf_field_type_enumeration_add_mapping(enum_variant_type, "UINT35_TYPE", 2, 7); - ok(bt_ctf_field_type_enumeration_get_mapping_index_by_name(NULL, - "INT16_TYPE") < 0, - "bt_ctf_field_type_enumeration_get_mapping_index_by_name handles a NULL field type correctly"); - ok(bt_ctf_field_type_enumeration_get_mapping_index_by_name( - enum_variant_type, NULL) < 0, - "bt_ctf_field_type_enumeration_get_mapping_index_by_name handles a NULL name correctly"); - ok(bt_ctf_field_type_enumeration_get_mapping_index_by_name( - enum_variant_type, "INT16_TYPE") == 1, - "bt_ctf_field_type_enumeration_get_mapping_index_by_name returns the correct index"); - - ok(bt_ctf_field_type_enumeration_get_mapping_index_by_unsigned_value(NULL, 1) < 0, - "bt_ctf_field_type_enumeration_get_mapping_index_by_unsigned_value handles a NULL field type correctly"); - ok(bt_ctf_field_type_enumeration_get_mapping_index_by_unsigned_value(enum_variant_type, -42) < 0, - "bt_ctf_field_type_enumeration_get_mapping_index_by_unsigned_value handles invalid values correctly"); - ok(bt_ctf_field_type_enumeration_get_mapping_index_by_unsigned_value(enum_variant_type, 5) == 2, - "bt_ctf_field_type_enumeration_get_mapping_index_by_unsigned_value returns the correct index"); + iter = bt_ctf_field_type_enumeration_find_mappings_by_name(NULL, "INT16_TYPE"); + ok(iter == NULL, "bt_ctf_field_type_enumeration_find_mappings_by_name handles a NULL field type correctly"); + + iter = bt_ctf_field_type_enumeration_find_mappings_by_name(enum_variant_type, "INT16_TYPE"); + ok(iter != NULL, "bt_ctf_field_type_enumeration_find_mappings_by_name handles an existing mapping correctly"); + ok(bt_ctf_field_type_enumeration_mapping_iterator_get_unsigned(iter, NULL, NULL, NULL) == 0, + "bt_ctf_field_type_enumeration_mapping_iterator_get_unsigned handles mapped values correctly"); + BT_PUT(iter); + + iter = bt_ctf_field_type_enumeration_find_mappings_by_name(enum_variant_type, NULL); + ok(iter == NULL, "bt_ctf_field_type_enumeration_find_mappings_by_name handles a NULL name correctly"); + + iter = bt_ctf_field_type_enumeration_find_mappings_by_unsigned_value(NULL, 1); + ok(iter == NULL, "bt_ctf_field_type_enumeration_find_mappings_by_unsigned_value handles a NULL field type correctly"); + + iter = bt_ctf_field_type_enumeration_find_mappings_by_unsigned_value(enum_variant_type, -42); + ok(iter == NULL, "bt_ctf_field_type_enumeration_find_mappings_by_unsigned_value handles invalid values correctly"); + ok(bt_ctf_field_type_enumeration_mapping_iterator_get_unsigned(iter, NULL, NULL, NULL) != 0, + "bt_ctf_field_type_enumeration_mapping_iterator_get_unsigned handles invalid values correctly"); + BT_PUT(iter); + + iter = bt_ctf_field_type_enumeration_find_mappings_by_unsigned_value(enum_variant_type, 5); + ok(iter != NULL, "bt_ctf_field_type_enumeration_find_mappings_by_unsigned_value handles valid values correctly"); + ok(bt_ctf_field_type_enumeration_mapping_iterator_get_unsigned(iter, NULL, NULL, NULL) == 0, + "bt_ctf_field_type_enumeration_mapping_iterator_get_unsigned handles valid values correctly"); + BT_PUT(iter); ok(bt_ctf_field_type_variant_add_field(variant_type, uint_3_type, "An unknown entry"), "Reject a variant field based on an unknown tag value"); @@ -1689,7 +1708,7 @@ void field_copy_tests() "bt_ctf_field_copy creates a valid enum's integer field copy"); /* validate e copy */ - str_val = bt_ctf_field_enumeration_get_mapping_name(e_copy); + str_val = bt_ctf_field_enumeration_get_single_mapping_name(e_copy); ok(str_val && !strcmp(str_val, "LABEL2"), "bt_ctf_field_copy creates a valid enum field copy"); -- 2.34.1