+BT_HIDDEN
+struct bt_field_path *bt_field_type_common_variant_borrow_tag_field_path(
+ struct bt_field_type_common *ft)
+{
+ struct bt_field_type_common_variant *var_ft = BT_FROM_COMMON(ft);
+
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_VARIANT,
+ "Field type");
+ return var_ft->tag_field_path;
+}
+
+struct bt_field_path *bt_field_type_variant_borrow_tag_field_path(
+ struct bt_field_type *ft)
+{
+ return bt_field_type_common_variant_borrow_tag_field_path((void *) ft);
+}
+
+BT_HIDDEN
+struct bt_field_path *bt_field_type_common_sequence_borrow_length_field_path(
+ struct bt_field_type_common *ft)
+{
+ struct bt_field_type_common_sequence *seq_ft = BT_FROM_COMMON(ft);
+
+ BT_ASSERT_PRE_NON_NULL(ft, "Field type");
+ BT_ASSERT_PRE_FT_COMMON_HAS_ID(ft, BT_FIELD_TYPE_ID_SEQUENCE,
+ "Field type");
+ return seq_ft->length_field_path;
+}
+
+struct bt_field_path *bt_field_type_sequence_borrow_length_field_path(
+ struct bt_field_type *ft)
+{
+ return bt_field_type_common_sequence_borrow_length_field_path(
+ (void *) ft);
+}
+
+BT_HIDDEN
+int bt_field_type_common_validate_single_clock_class(
+ struct bt_field_type_common *ft,
+ struct bt_clock_class **expected_clock_class)
+{
+ int ret = 0;
+
+ if (!ft) {
+ goto end;
+ }
+
+ BT_ASSERT(expected_clock_class);
+
+ switch (ft->id) {
+ case BT_FIELD_TYPE_ID_INTEGER:
+ {
+ struct bt_clock_class *mapped_clock_class =
+ bt_field_type_common_integer_borrow_mapped_clock_class(ft);
+
+ if (!mapped_clock_class) {
+ goto end;
+ }
+
+ if (!*expected_clock_class) {
+ /* Move reference to output parameter */
+ *expected_clock_class = bt_get(mapped_clock_class);
+ mapped_clock_class = NULL;
+ BT_LOGV("Setting expected clock class: "
+ "expected-clock-class-addr=%p",
+ *expected_clock_class);
+ } else {
+ if (mapped_clock_class != *expected_clock_class) {
+ BT_LOGW("Integer field type is not mapped to "
+ "the expected clock class: "
+ "mapped-clock-class-addr=%p, "
+ "mapped-clock-class-name=\"%s\", "
+ "expected-clock-class-addr=%p, "
+ "expected-clock-class-name=\"%s\"",
+ mapped_clock_class,
+ bt_clock_class_get_name(mapped_clock_class),
+ *expected_clock_class,
+ bt_clock_class_get_name(*expected_clock_class));
+ bt_put(mapped_clock_class);
+ ret = -1;
+ goto end;
+ }
+ }
+
+ break;
+ }
+ case BT_FIELD_TYPE_ID_ENUM:
+ case BT_FIELD_TYPE_ID_ARRAY:
+ case BT_FIELD_TYPE_ID_SEQUENCE:
+ {
+ struct bt_field_type_common *sub_ft = NULL;
+
+ switch (ft->id) {
+ case BT_FIELD_TYPE_ID_ENUM:
+ sub_ft = bt_field_type_common_enumeration_borrow_container_field_type(
+ ft);
+ break;
+ case BT_FIELD_TYPE_ID_ARRAY:
+ sub_ft = bt_field_type_common_array_borrow_element_field_type(
+ ft);
+ break;
+ case BT_FIELD_TYPE_ID_SEQUENCE:
+ sub_ft = bt_field_type_common_sequence_borrow_element_field_type(
+ ft);
+ break;
+ default:
+ BT_LOGF("Unexpected field type ID: id=%d", ft->id);
+ abort();
+ }
+
+ BT_ASSERT(sub_ft);
+ ret = bt_field_type_common_validate_single_clock_class(sub_ft,
+ expected_clock_class);
+ break;
+ }
+ case BT_FIELD_TYPE_ID_STRUCT:
+ {
+ uint64_t i;
+ int64_t count = bt_field_type_common_structure_get_field_count(
+ ft);
+
+ for (i = 0; i < count; i++) {
+ const char *name;
+ struct bt_field_type_common *member_type;
+
+ ret = bt_field_type_common_structure_borrow_field_by_index(
+ ft, &name, &member_type, i);
+ BT_ASSERT(ret == 0);
+ ret = bt_field_type_common_validate_single_clock_class(
+ member_type, expected_clock_class);
+ if (ret) {
+ BT_LOGW("Structure field type's field's type "
+ "is not recursively mapped to the "
+ "expected clock class: "
+ "field-ft-addr=%p, field-name=\"%s\"",
+ member_type, name);
+ goto end;
+ }
+ }
+ break;
+ }
+ case BT_FIELD_TYPE_ID_VARIANT:
+ {
+ uint64_t i;
+ int64_t count = bt_field_type_common_variant_get_field_count(
+ ft);
+
+ for (i = 0; i < count; i++) {
+ const char *name;
+ struct bt_field_type_common *member_type;
+
+ ret = bt_field_type_common_variant_borrow_field_by_index(
+ ft, &name, &member_type, i);
+ BT_ASSERT(ret == 0);
+ ret = bt_field_type_common_validate_single_clock_class(
+ member_type, expected_clock_class);
+ if (ret) {
+ BT_LOGW("Variant field type's field's type "
+ "is not recursively mapped to the "
+ "expected clock class: "
+ "field-ft-addr=%p, field-name=\"%s\"",
+ member_type, name);
+ goto end;
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+end:
+ return ret;
+}
+
+static
+struct bt_field_type *bt_field_type_integer_copy(
+ struct bt_field_type *ft)
+{
+ struct bt_field_type_common_integer *int_ft = (void *) ft;
+ struct bt_field_type_common_integer *copy_ft;
+
+ BT_LOGD("Copying integer field type's: addr=%p", ft);
+ copy_ft = (void *) bt_field_type_integer_create(int_ft->size);
+ if (!copy_ft) {
+ BT_LOGE_STR("Cannot create integer field type.");
+ goto end;
+ }
+
+ copy_ft->mapped_clock_class = bt_get(int_ft->mapped_clock_class);
+ copy_ft->user_byte_order = int_ft->user_byte_order;
+ copy_ft->is_signed = int_ft->is_signed;
+ copy_ft->size = int_ft->size;
+ copy_ft->base = int_ft->base;
+ copy_ft->encoding = int_ft->encoding;
+ BT_LOGD("Copied integer field type: original-ft-addr=%p, copy-ft-addr=%p",
+ ft, copy_ft);
+
+end:
+ return (void *) copy_ft;
+}
+
+static
+struct bt_field_type *bt_field_type_enumeration_copy_recursive(
+ struct bt_field_type *ft)
+{
+ size_t i;
+ struct bt_field_type_common_enumeration *enum_ft = (void *) ft;
+ struct bt_field_type_common_enumeration *copy_ft = NULL;
+ struct bt_field_type_common_enumeration *container_copy_ft;
+
+ BT_LOGD("Copying enumeration field type's: addr=%p", ft);
+
+ /* Copy the source enumeration's container */
+ BT_LOGD_STR("Copying enumeration field type's container field type.");
+ container_copy_ft = BT_FROM_COMMON(bt_field_type_common_copy(
+ BT_TO_COMMON(enum_ft->container_ft)));
+ if (!container_copy_ft) {
+ BT_LOGE_STR("Cannot copy enumeration field type's container field type.");
+ goto end;
+ }
+
+ copy_ft = (void *) bt_field_type_enumeration_create(
+ (void *) container_copy_ft);
+ if (!copy_ft) {
+ BT_LOGE_STR("Cannot create enumeration field type.");
+ goto end;
+ }
+
+ /* Copy all enumaration entries */
+ for (i = 0; i < enum_ft->entries->len; i++) {
+ struct enumeration_mapping *mapping = g_ptr_array_index(
+ enum_ft->entries, i);
+ struct enumeration_mapping *copy_mapping = g_new0(
+ struct enumeration_mapping, 1);
+
+ if (!copy_mapping) {
+ BT_LOGE_STR("Failed to allocate one enumeration mapping.");
+ goto error;
+ }
+
+ *copy_mapping = *mapping;
+ g_ptr_array_add(copy_ft->entries, copy_mapping);
+ }
+
+ BT_LOGD("Copied enumeration field type: original-ft-addr=%p, copy-ft-addr=%p",
+ ft, copy_ft);
+
+end:
+ bt_put(container_copy_ft);
+ return (void *) copy_ft;
+
+error:
+ bt_put(container_copy_ft);
+ BT_PUT(copy_ft);
+ return (void *) copy_ft;
+}
+
+static
+struct bt_field_type *bt_field_type_floating_point_copy(
+ struct bt_field_type *ft)
+{
+ struct bt_field_type_common_floating_point *flt_ft = BT_FROM_COMMON(ft);
+ struct bt_field_type_common_floating_point *copy_ft;
+
+ BT_LOGD("Copying floating point number field type's: addr=%p", ft);
+ copy_ft = (void *) bt_field_type_floating_point_create();
+ if (!copy_ft) {
+ BT_LOGE_STR("Cannot create floating point number field type.");
+ goto end;
+ }
+
+ copy_ft->user_byte_order = flt_ft->user_byte_order;
+ copy_ft->exp_dig = flt_ft->exp_dig;
+ copy_ft->mant_dig = flt_ft->mant_dig;
+ BT_LOGD("Copied floating point number field type: original-ft-addr=%p, copy-ft-addr=%p",
+ ft, copy_ft);
+
+end:
+ return (void *) copy_ft;
+}
+
+static
+struct bt_field_type *bt_field_type_structure_copy_recursive(
+ struct bt_field_type *ft)
+{
+ int64_t i;
+ GHashTableIter iter;
+ gpointer key, value;
+ struct bt_field_type_common_structure *struct_ft = (void *) ft;
+ struct bt_field_type_common_structure *copy_ft;
+
+ BT_LOGD("Copying structure field type's: addr=%p", ft);
+ copy_ft = (void *) bt_field_type_structure_create();
+ if (!copy_ft) {
+ BT_LOGE_STR("Cannot create structure field type.");
+ goto end;
+ }
+
+ /* Copy field_name_to_index */
+ g_hash_table_iter_init(&iter, struct_ft->field_name_to_index);
+ while (g_hash_table_iter_next(&iter, &key, &value)) {
+ g_hash_table_insert(copy_ft->field_name_to_index,
+ key, value);
+ }
+
+ g_array_set_size(copy_ft->fields, struct_ft->fields->len);
+
+ for (i = 0; i < struct_ft->fields->len; i++) {
+ struct bt_field_type_common_structure_field *entry, *copy_entry;
+ struct bt_field_type_common *field_ft_copy;
+
+ entry = BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
+ struct_ft, i);
+ copy_entry = BT_FIELD_TYPE_COMMON_STRUCTURE_FIELD_AT_INDEX(
+ copy_ft, i);
+ BT_LOGD("Copying structure field type's field: "
+ "index=%" PRId64 ", "
+ "field-ft-addr=%p, field-name=\"%s\"",
+ i, entry, g_quark_to_string(entry->name));
+
+ field_ft_copy = (void *) bt_field_type_copy(
+ (void *) entry->type);
+ if (!field_ft_copy) {
+ BT_LOGE("Cannot copy structure field type's field: "
+ "index=%" PRId64 ", "
+ "field-ft-addr=%p, field-name=\"%s\"",
+ i, entry, g_quark_to_string(entry->name));
+ goto error;
+ }
+
+ copy_entry->name = entry->name;
+ copy_entry->type = field_ft_copy;
+ }
+
+ BT_LOGD("Copied structure field type: original-ft-addr=%p, copy-ft-addr=%p",
+ ft, copy_ft);
+
+end:
+ return (void *) copy_ft;
+
+error:
+ BT_PUT(copy_ft);
+ return NULL;
+}
+
+static
+struct bt_field_type *bt_field_type_variant_copy_recursive(
+ struct bt_field_type *ft)
+{
+ int64_t i;
+ GHashTableIter iter;
+ gpointer key, value;
+ struct bt_field_type_common *tag_ft_copy = NULL;
+ struct bt_field_type_common_variant *var_ft = (void *) ft;
+ struct bt_field_type_common_variant *copy_ft = NULL;
+
+ BT_LOGD("Copying variant field type's: addr=%p", ft);
+ if (var_ft->tag_ft) {
+ BT_LOGD_STR("Copying variant field type's tag field type.");
+ tag_ft_copy = bt_field_type_common_copy(
+ BT_TO_COMMON(var_ft->tag_ft));
+ if (!tag_ft_copy) {
+ BT_LOGE_STR("Cannot copy variant field type's tag field type.");
+ goto end;
+ }
+ }
+
+ copy_ft = (void *) bt_field_type_variant_create(
+ (void *) tag_ft_copy,
+ var_ft->tag_name->len ? var_ft->tag_name->str : NULL);
+ if (!copy_ft) {
+ BT_LOGE_STR("Cannot create variant field type.");
+ goto end;
+ }
+
+ /* Copy field_name_to_index */
+ g_hash_table_iter_init(&iter, var_ft->choice_name_to_index);
+ while (g_hash_table_iter_next(&iter, &key, &value)) {
+ g_hash_table_insert(copy_ft->choice_name_to_index,
+ key, value);
+ }
+
+ g_array_set_size(copy_ft->choices, var_ft->choices->len);
+
+ for (i = 0; i < var_ft->choices->len; i++) {
+ struct bt_field_type_common_variant_choice *entry, *copy_entry;
+ struct bt_field_type_common *field_ft_copy;
+ uint64_t range_i;
+
+ entry = BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(var_ft, i);
+ copy_entry = BT_FIELD_TYPE_COMMON_VARIANT_CHOICE_AT_INDEX(
+ copy_ft, i);
+ BT_LOGD("Copying variant field type's field: "
+ "index=%" PRId64 ", "
+ "field-ft-addr=%p, field-name=\"%s\"",
+ i, entry, g_quark_to_string(entry->name));
+
+ field_ft_copy = (void *) bt_field_type_copy(
+ (void *) entry->type);
+ if (!field_ft_copy) {
+ BT_LOGE("Cannot copy variant field type's field: "
+ "index=%" PRId64 ", "
+ "field-ft-addr=%p, field-name=\"%s\"",
+ i, entry, g_quark_to_string(entry->name));
+ g_free(copy_entry);
+ goto error;
+ }
+
+ copy_entry->name = entry->name;
+ copy_entry->type = field_ft_copy;
+
+ /* Copy ranges */
+ copy_entry->ranges = g_array_new(FALSE, TRUE,
+ sizeof(struct bt_field_type_common_variant_choice_range));
+ BT_ASSERT(copy_entry->ranges);
+ g_array_set_size(copy_entry->ranges, entry->ranges->len);
+
+ for (range_i = 0; range_i < entry->ranges->len; range_i++) {
+ copy_entry->ranges[range_i] = entry->ranges[range_i];
+ }
+ }
+
+ if (var_ft->tag_field_path) {
+ BT_LOGD_STR("Copying variant field type's tag field path.");
+ copy_ft->tag_field_path = bt_field_path_copy(
+ var_ft->tag_field_path);
+ if (!copy_ft->tag_field_path) {
+ BT_LOGE_STR("Cannot copy variant field type's tag field path.");
+ goto error;
+ }
+ }
+
+ copy_ft->choices_up_to_date = var_ft->choices_up_to_date;
+ BT_LOGD("Copied variant field type: original-ft-addr=%p, copy-ft-addr=%p",
+ ft, copy_ft);
+
+end:
+ bt_put(tag_ft_copy);
+ return (void *) copy_ft;
+
+error:
+ bt_put(tag_ft_copy);
+ BT_PUT(copy_ft);
+ return NULL;
+}
+
+static
+struct bt_field_type *bt_field_type_array_copy_recursive(
+ struct bt_field_type *ft)
+{
+ struct bt_field_type_common *container_ft_copy = NULL;
+ struct bt_field_type_common_array *array_ft = (void *) ft;
+ struct bt_field_type_common_array *copy_ft = NULL;
+
+ BT_LOGD("Copying array field type's: addr=%p", ft);
+ BT_LOGD_STR("Copying array field type's element field type.");
+ container_ft_copy = bt_field_type_common_copy(array_ft->element_ft);
+ if (!container_ft_copy) {
+ BT_LOGE_STR("Cannot copy array field type's element field type.");
+ goto end;
+ }
+
+ copy_ft = (void *) bt_field_type_array_create(
+ (void *) container_ft_copy, array_ft->length);
+ if (!copy_ft) {
+ BT_LOGE_STR("Cannot create array field type.");
+ goto end;
+ }
+
+ BT_LOGD("Copied array field type: original-ft-addr=%p, copy-ft-addr=%p",
+ ft, copy_ft);
+
+end:
+ bt_put(container_ft_copy);
+ return (void *) copy_ft;
+}
+
+static
+struct bt_field_type *bt_field_type_sequence_copy_recursive(
+ struct bt_field_type *ft)