+ return ret;
+}
+
+static
+enum bt_component_status print_integer(struct text_component *text,
+ struct bt_ctf_field *field)
+{
+ enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
+ struct bt_ctf_field_type *field_type = NULL;
+ enum bt_ctf_integer_base base;
+ enum bt_ctf_string_encoding encoding;
+ int signedness;
+ union {
+ uint64_t u;
+ int64_t s;
+ } v;
+ bool rst_color = false;
+
+ field_type = bt_ctf_field_get_type(field);
+ if (!field_type) {
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
+ }
+ signedness = bt_ctf_field_type_integer_get_signed(field_type);
+ if (signedness < 0) {
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
+ }
+ if (!signedness) {
+ if (bt_ctf_field_unsigned_integer_get_value(field, &v.u) < 0) {
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
+ }
+ } else {
+ if (bt_ctf_field_signed_integer_get_value(field, &v.s) < 0) {
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
+ }
+ }
+
+ encoding = bt_ctf_field_type_integer_get_encoding(field_type);
+ switch (encoding) {
+ case BT_CTF_STRING_ENCODING_UTF8:
+ case BT_CTF_STRING_ENCODING_ASCII:
+ g_string_append_c(text->string, (int) v.u);
+ goto end;
+ case BT_CTF_STRING_ENCODING_NONE:
+ case BT_CTF_STRING_ENCODING_UNKNOWN:
+ break;
+ default:
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
+ }
+
+ if (text->use_colors) {
+ fputs(COLOR_NUMBER_VALUE, text->out);
+ rst_color = true;
+ }
+
+ base = bt_ctf_field_type_integer_get_base(field_type);
+ switch (base) {
+ case BT_CTF_INTEGER_BASE_BINARY:
+ {
+ int bitnr, len;
+
+ len = bt_ctf_field_type_integer_get_size(field_type);
+ if (len < 0) {
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
+ }
+ fprintf(text->out, "0b");
+ v.u = _bt_piecewise_lshift(v.u, 64 - len);
+ for (bitnr = 0; bitnr < len; bitnr++) {
+ fprintf(text->out, "%u", (v.u & (1ULL << 63)) ? 1 : 0);
+ v.u = _bt_piecewise_lshift(v.u, 1);
+ }
+ break;
+ }
+ case BT_CTF_INTEGER_BASE_OCTAL:
+ {
+ if (signedness) {
+ int len;
+
+ len = bt_ctf_field_type_integer_get_size(field_type);
+ if (len < 0) {
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
+ }
+ if (len < 64) {
+ size_t rounded_len;
+
+ assert(len != 0);
+ /* Round length to the nearest 3-bit */
+ rounded_len = (((len - 1) / 3) + 1) * 3;
+ v.u &= ((uint64_t) 1 << rounded_len) - 1;
+ }
+ }
+
+ fprintf(text->out, "0%" PRIo64, v.u);
+ break;
+ }
+ case BT_CTF_INTEGER_BASE_DECIMAL:
+ if (!signedness) {
+ fprintf(text->out, "%" PRIu64, v.u);
+ } else {
+ fprintf(text->out, "%" PRId64, v.s);
+ }
+ break;
+ case BT_CTF_INTEGER_BASE_HEXADECIMAL:
+ {
+ int len;
+
+ len = bt_ctf_field_type_integer_get_size(field_type);
+ if (len < 0) {
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
+ }
+ if (len < 64) {
+ /* Round length to the nearest nibble */
+ uint8_t rounded_len = ((len + 3) & ~0x3);
+
+ v.u &= ((uint64_t) 1 << rounded_len) - 1;
+ }
+
+ fprintf(text->out, "0x%" PRIX64, v.u);
+ break;
+ }
+ default:
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
+ }
+end:
+ if (rst_color) {
+ fputs(COLOR_RST, text->out);
+ }
+ bt_put(field_type);
+ return ret;
+}
+
+static
+enum bt_component_status print_enum(struct text_component *text,
+ struct bt_ctf_field *field)
+{
+ enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
+ struct bt_ctf_field *container_field = NULL;
+ 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;
+ }
+ 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 {
+ 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, ", ");
+ if (text->use_colors) {
+ fputs(COLOR_ENUM_MAPPING_NAME, text->out);
+ }
+ // TODO: escape string
+ fprintf(text->out, "\"%s\"", mapping_name);
+ if (text->use_colors) {
+ fputs(COLOR_RST, text->out);
+ }
+ if (bt_ctf_field_type_enumeration_mapping_iterator_next(iter) < 0) {
+ break;
+ }
+ }
+ if (!nr_mappings) {
+ if (text->use_colors) {
+ fputs(COLOR_UNKNOWN, text->out);
+ }
+ fprintf(text->out, "<unknown>");
+ if (text->use_colors) {
+ fputs(COLOR_RST, text->out);
+ }
+ }
+ fprintf(text->out, " : container = ");
+ ret = print_integer(text, container_field);
+ if (ret != BT_COMPONENT_STATUS_OK) {
+ goto end;
+ }
+ fprintf(text->out, " )");
+end:
+ bt_put(iter);
+ bt_put(container_field_type);
+ bt_put(container_field);
+ bt_put(enumeration_field_type);
+ return ret;
+}
+
+static
+int filter_field_name(struct text_component *text, const char *field_name,
+ GQuark *filter_fields, int filter_array_len)
+{
+ int i;
+ GQuark field_quark = g_quark_try_string(field_name);
+
+ if (!field_quark || text->options.verbose) {
+ return 1;
+ }
+
+ for (i = 0; i < filter_array_len; i++) {
+ if (field_quark == filter_fields[i]) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static
+enum bt_component_status print_struct_field(struct text_component *text,
+ struct bt_ctf_field *_struct,
+ struct bt_ctf_field_type *struct_type,
+ int i, bool print_names, int *nr_printed_fields,
+ GQuark *filter_fields, int filter_array_len)
+{
+ enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
+ const char *field_name;
+ struct bt_ctf_field *field = NULL;
+ struct bt_ctf_field_type *field_type = NULL;;
+
+ field = bt_ctf_field_structure_get_field_by_index(_struct, i);
+ if (!field) {
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
+ }
+ if (bt_ctf_field_type_structure_get_field(struct_type,
+ &field_name, &field_type, i) < 0) {
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
+ }
+
+ if (filter_fields && !filter_field_name(text, field_name,
+ filter_fields, filter_array_len)) {
+ ret = BT_COMPONENT_STATUS_OK;
+ goto end;
+ }
+
+ if (*nr_printed_fields > 0) {
+ fprintf(text->out, ", ");
+ } else {
+ fprintf(text->out, " ");
+ }
+ if (print_names) {
+ print_field_name_equal(text, rem_(field_name));
+ }
+ ret = print_field(text, field, print_names, NULL, 0);
+ *nr_printed_fields += 1;
+end:
+ bt_put(field_type);
+ bt_put(field);
+ return ret;
+}
+
+static
+enum bt_component_status print_struct(struct text_component *text,
+ struct bt_ctf_field *_struct, bool print_names,
+ GQuark *filter_fields, int filter_array_len)
+{
+ enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
+ struct bt_ctf_field_type *struct_type = NULL;
+ int nr_fields, i, nr_printed_fields;
+
+ struct_type = bt_ctf_field_get_type(_struct);
+ if (!struct_type) {
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
+ }
+ nr_fields = bt_ctf_field_type_structure_get_field_count(struct_type);
+ if (nr_fields < 0) {
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
+ }
+ fprintf(text->out, "{");
+ text->depth++;
+ nr_printed_fields = 0;
+ for (i = 0; i < nr_fields; i++) {
+ ret = print_struct_field(text, _struct, struct_type, i,
+ print_names, &nr_printed_fields, filter_fields,
+ filter_array_len);
+ if (ret != BT_COMPONENT_STATUS_OK) {
+ goto end;
+ }
+ }
+ text->depth--;
+ fprintf(text->out, " }");
+end:
+ bt_put(struct_type);
+ return ret;
+}
+
+static
+enum bt_component_status print_array_field(struct text_component *text,
+ struct bt_ctf_field *array, uint64_t i,
+ bool is_string, bool print_names)
+{
+ enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
+ struct bt_ctf_field *field = NULL;
+
+ if (!is_string) {
+ if (i != 0) {
+ fprintf(text->out, ", ");
+ } else {
+ fprintf(text->out, " ");
+ }
+ if (print_names) {
+ fprintf(text->out, "[%" PRIu64 "] = ", i);
+ }
+ }
+ field = bt_ctf_field_array_get_field(array, i);
+ if (!field) {
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
+ }
+ ret = print_field(text, field, print_names, NULL, 0);
+end:
+ bt_put(field);
+ return ret;
+}
+
+static
+enum bt_component_status print_array(struct text_component *text,
+ struct bt_ctf_field *array, bool print_names)
+{
+ enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
+ struct bt_ctf_field_type *array_type = NULL, *field_type = NULL;
+ enum bt_ctf_type_id type_id;
+ int64_t len;
+ uint64_t i;
+ bool is_string = false;
+
+ array_type = bt_ctf_field_get_type(array);
+ if (!array_type) {
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
+ }
+ field_type = bt_ctf_field_type_array_get_element_type(array_type);
+ if (!field_type) {
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
+ }
+ len = bt_ctf_field_type_array_get_length(array_type);
+ if (len < 0) {
+ ret = BT_COMPONENT_STATUS_ERROR;
+ goto end;
+ }
+ type_id = bt_ctf_field_type_get_type_id(field_type);
+ if (type_id == BT_CTF_TYPE_ID_INTEGER) {
+ enum bt_ctf_string_encoding encoding;
+
+ encoding = bt_ctf_field_type_integer_get_encoding(field_type);
+ if (encoding == BT_CTF_STRING_ENCODING_UTF8
+ || encoding == BT_CTF_STRING_ENCODING_ASCII) {
+ int integer_len, integer_alignment;
+
+ integer_len = bt_ctf_field_type_integer_get_size(field_type);
+ if (integer_len < 0) {
+ return BT_COMPONENT_STATUS_ERROR;
+ }
+ integer_alignment = bt_ctf_field_type_get_alignment(field_type);
+ if (integer_alignment < 0) {
+ return BT_COMPONENT_STATUS_ERROR;
+ }
+ if (integer_len == CHAR_BIT
+ && integer_alignment == CHAR_BIT) {
+ is_string = true;
+ }
+ }
+ }
+
+ if (is_string) {
+ g_string_assign(text->string, "");
+ } else {
+ fprintf(text->out, "[");
+ }
+
+ text->depth++;
+ for (i = 0; i < len; i++) {
+ ret = print_array_field(text, array, i, is_string, print_names);
+ if (ret != BT_COMPONENT_STATUS_OK) {
+ goto end;
+ }
+ }
+ text->depth--;
+
+ if (is_string) {
+ if (text->use_colors) {
+ fputs(COLOR_STRING_VALUE, text->out);
+ }
+ // TODO: escape string
+ fprintf(text->out, "\"%s\"", text->string->str);
+ if (text->use_colors) {
+ fputs(COLOR_RST, text->out);
+ }
+ } else {
+ fprintf(text->out, " ]");
+ }