Fix: allow duplicate keys and overlapping ranges in enumerations
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Fri, 16 Dec 2016 17:30:24 +0000 (18:30 +0100)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Sat, 27 May 2017 18:09:09 +0000 (14:09 -0400)
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 <mathieu.desnoyers@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
formats/ctf/ir/field-types.c
formats/ctf/ir/fields.c
include/babeltrace/ctf-ir/field-types-internal.h
include/babeltrace/ctf-ir/field-types.h
include/babeltrace/ctf-ir/fields.h
plugins/text/print.c
tests/lib/test_ctf_writer.c

index ad34a86f44539967e7529b89cf14f96579eac832..f6dcf991cea78ae6f6d3fd869f1bc27e41c0b735 100644 (file)
@@ -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_mappingcopy_mapping = g_new0(
+               struct enumeration_mapping *copy_mapping = g_new0(
                        struct enumeration_mapping, 1);
 
                if (!copy_mapping) {
index 1a2a2c7f5d95b8a8cae94b9d7dc312bf205abc74..35db018557bc62684f495c839919d6fdc3985ff5 100644 (file)
@@ -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:
index 3df8e7458c9aae5695f59cd9af686aebf892c18e..bd2f485758d265b873ba38fa9f96fdd2e93a247b 100644 (file)
@@ -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(
index 682d1a1e03c99fdb72acdd59e5e7e62d4dfc7819..7ae3ae55bbd3506392bd70dd90da09901bb67971 100644 (file)
@@ -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 <strong>must not overlap</strong>. 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.
index 536a88f57da3e08a5dd4e6523cb7f7093621bd36..e9f59fb303bf20cad66f32cdb1d1cc7f644246b0 100644 (file)
@@ -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
index c1ae888bcf370fef83cb4f5dcf9732664099bea1..5ba979588d9381231bb6b0d2c20827faa3991547 100644 (file)
@@ -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, "( <unknown>");
+               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, "<unknown>");
        }
        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;
index a16d895b25942363fa2d03da0cb4bc053c991f77..2dd5596302210f9c3223e81c5dadb13cd1adf134 100644 (file)
@@ -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");
 
This page took 0.044273 seconds and 4 git commands to generate.