+static
+int auto_map_field_to_trace_clock_class(struct ctx *ctx,
+ struct bt_ctf_field_type *ft)
+{
+ struct bt_ctf_clock_class *clock_class_to_map_to = NULL;
+ struct bt_ctf_clock_class *mapped_clock_class = NULL;
+ int ret = 0;
+ int64_t clock_class_count;
+
+ if (!ft || !bt_ctf_field_type_is_integer(ft)) {
+ goto end;
+ }
+
+ mapped_clock_class =
+ bt_ctf_field_type_integer_get_mapped_clock_class(ft);
+ if (mapped_clock_class) {
+ goto end;
+ }
+
+ clock_class_count = bt_ctf_trace_get_clock_class_count(ctx->trace);
+ assert(clock_class_count >= 0);
+
+ switch (clock_class_count) {
+ case 0:
+ /*
+ * No clock class exists in the trace at this
+ * point. Create an implicit one at 1 GHz,
+ * named `default`, and use this clock class.
+ */
+ clock_class_to_map_to = bt_ctf_clock_class_create("default",
+ 1000000000);
+ if (!clock_class_to_map_to) {
+ BT_LOGE_STR("Cannot create a clock class.");
+ ret = -1;
+ goto end;
+ }
+
+ ret = bt_ctf_trace_add_clock_class(ctx->trace,
+ clock_class_to_map_to);
+ if (ret) {
+ BT_LOGE_STR("Cannot add clock class to trace.");
+ goto end;
+ }
+ break;
+ case 1:
+ /*
+ * Only one clock class exists in the trace at
+ * this point: use this one.
+ */
+ clock_class_to_map_to =
+ bt_ctf_trace_get_clock_class_by_index(ctx->trace, 0);
+ assert(clock_class_to_map_to);
+ break;
+ default:
+ /*
+ * Timestamp field not mapped to a clock class
+ * and there's more than one clock class in the
+ * trace: this is an error.
+ */
+ BT_LOGE_STR("Timestamp field found with no mapped clock class, "
+ "but there's more than one clock class in the trace at this point.");
+ ret = -1;
+ goto end;
+ }
+
+ assert(clock_class_to_map_to);
+ ret = bt_ctf_field_type_integer_set_mapped_clock_class(ft,
+ clock_class_to_map_to);
+ if (ret) {
+ BT_LOGE("Cannot map field type's field to trace's clock class: "
+ "clock-class-name=\"%s\", ret=%d",
+ bt_ctf_clock_class_get_name(clock_class_to_map_to),
+ ret);
+ goto end;
+ }
+
+end:
+ bt_put(clock_class_to_map_to);
+ bt_put(mapped_clock_class);
+ return ret;
+}
+
+static
+int auto_map_fields_to_trace_clock_class(struct ctx *ctx,
+ struct bt_ctf_field_type *root_ft, const char *field_name)
+{
+ int ret = 0;
+ int64_t i, count;
+
+ if (!root_ft) {
+ goto end;
+ }
+
+ if (!bt_ctf_field_type_is_structure(root_ft) &&
+ !bt_ctf_field_type_is_variant(root_ft)) {
+ goto end;
+ }
+
+ if (bt_ctf_field_type_is_structure(root_ft)) {
+ count = bt_ctf_field_type_structure_get_field_count(root_ft);
+ } else {
+ count = bt_ctf_field_type_variant_get_field_count(root_ft);
+ }
+
+ assert(count >= 0);
+
+ for (i = 0; i < count; i++) {
+ _BT_CTF_FIELD_TYPE_INIT(ft);
+ const char *name;
+
+ if (bt_ctf_field_type_is_structure(root_ft)) {
+ ret = bt_ctf_field_type_structure_get_field_by_index(
+ root_ft, &name, &ft, i);
+ } else if (bt_ctf_field_type_is_variant(root_ft)) {
+ ret = bt_ctf_field_type_variant_get_field_by_index(
+ root_ft, &name, &ft, i);
+ }
+
+ assert(ret == 0);
+
+ if (strcmp(name, field_name) == 0) {
+ ret = auto_map_field_to_trace_clock_class(ctx, ft);
+ if (ret) {
+ BT_LOGE("Cannot automatically map field to trace's clock class: "
+ "field-name=\"%s\"", field_name);
+ bt_put(ft);
+ goto end;
+ }
+ }
+
+ ret = auto_map_fields_to_trace_clock_class(ctx, ft, field_name);
+ bt_put(ft);
+ if (ret) {
+ BT_LOGE("Cannot automatically map structure or variant field type's fields to trace's clock class: "
+ "field-name=\"%s\", root-field-name=\"%s\"",
+ field_name, name);
+ goto end;
+ }
+ }
+
+end:
+ return ret;
+}
+