X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=blobdiff_plain;f=src%2Fplugins%2Ftext%2Fdetails%2Fwrite.c;h=b98efb78c4d55e0afb42816ff719feecfccd7553;hp=b102485b48b519b40f3701271a29cec0bc0a6d27;hb=27c61ce8f6ee66d910507f8a40ae5497287c943e;hpb=335a2da576e59d32c17de2ece1e7e339c50e9c25 diff --git a/src/plugins/text/details/write.c b/src/plugins/text/details/write.c index b102485b..b98efb78 100644 --- a/src/plugins/text/details/write.c +++ b/src/plugins/text/details/write.c @@ -21,11 +21,13 @@ */ #include +#include #include #include #include "common/assert.h" #include "common/common.h" +#include "common/uuid.h" #include "details.h" #include "write.h" #include "obj-lifetime-mgmt.h" @@ -40,7 +42,7 @@ const char *plural(uint64_t value) static inline void incr_indent_by(struct details_write_ctx *ctx, unsigned int value) { - BT_ASSERT(ctx); + BT_ASSERT_DBG(ctx); ctx->indent_level += value; } @@ -53,8 +55,8 @@ void incr_indent(struct details_write_ctx *ctx) static inline void decr_indent_by(struct details_write_ctx *ctx, unsigned int value) { - BT_ASSERT(ctx); - BT_ASSERT(ctx->indent_level >= value); + BT_ASSERT_DBG(ctx); + BT_ASSERT_DBG(ctx->indent_level >= value); ctx->indent_level -= value; } @@ -100,7 +102,7 @@ void format_uint(char *buf, uint64_t value, unsigned int base) break; default: - abort(); + bt_common_abort(); } sprintf(buf_start, spec, value); @@ -153,7 +155,7 @@ void format_int(char *buf, int64_t value, unsigned int base) break; default: - abort(); + bt_common_abort(); } sprintf(buf_start, spec, abs_value); @@ -166,14 +168,14 @@ void format_int(char *buf, int64_t value, unsigned int base) static inline void write_nl(struct details_write_ctx *ctx) { - BT_ASSERT(ctx); + BT_ASSERT_DBG(ctx); g_string_append_c(ctx->str, '\n'); } static inline void write_sp(struct details_write_ctx *ctx) { - BT_ASSERT(ctx); + BT_ASSERT_DBG(ctx); g_string_append_c(ctx->str, ' '); } @@ -182,7 +184,7 @@ void write_indent(struct details_write_ctx *ctx) { uint64_t i; - BT_ASSERT(ctx); + BT_ASSERT_DBG(ctx); for (i = 0; i < ctx->indent_level; i++) { write_sp(ctx); @@ -198,21 +200,23 @@ void write_compound_member_name(struct details_write_ctx *ctx, const char *name) } static inline -void write_array_index(struct details_write_ctx *ctx, uint64_t index) +void write_array_index(struct details_write_ctx *ctx, uint64_t index, + const char *color) { char buf[32]; write_indent(ctx); format_uint(buf, index, 10); g_string_append_printf(ctx->str, "%s[%s]%s:", - color_fg_cyan(ctx), buf, color_reset(ctx)); + color, buf, color_reset(ctx)); } static inline void write_obj_type_name(struct details_write_ctx *ctx, const char *name) { g_string_append_printf(ctx->str, "%s%s%s%s", - color_fg_yellow(ctx), color_bold(ctx), name, color_reset(ctx)); + color_bold(ctx), color_fg_bright_yellow(ctx), name, + color_reset(ctx)); } static inline @@ -222,6 +226,14 @@ void write_prop_name(struct details_write_ctx *ctx, const char *prop_name) color_fg_magenta(ctx), prop_name, color_reset(ctx)); } +static inline +void write_prop_name_line(struct details_write_ctx *ctx, const char *prop_name) +{ + write_indent(ctx); + g_string_append_printf(ctx->str, "%s%s%s:", + color_fg_magenta(ctx), prop_name, color_reset(ctx)); +} + static inline void write_str_prop_value(struct details_write_ctx *ctx, const char *value) { @@ -229,6 +241,14 @@ void write_str_prop_value(struct details_write_ctx *ctx, const char *value) color_bold(ctx), value, color_reset(ctx)); } +static inline +void write_none_prop_value(struct details_write_ctx *ctx, const char *value) +{ + g_string_append_printf(ctx->str, "%s%s%s%s", + color_bold(ctx), color_fg_bright_magenta(ctx), + value, color_reset(ctx)); +} + static inline void write_uint_str_prop_value(struct details_write_ctx *ctx, const char *value) { @@ -264,7 +284,7 @@ static inline void write_str_prop_line(struct details_write_ctx *ctx, const char *prop_name, const char *prop_value) { - BT_ASSERT(prop_value); + BT_ASSERT_DBG(prop_value); write_indent(ctx); write_prop_name(ctx, prop_name); g_string_append(ctx->str, ": "); @@ -301,55 +321,194 @@ void write_int_str_prop_value(struct details_write_ctx *ctx, const char *value) } static inline -void write_bool_prop_line(struct details_write_ctx *ctx, const char *prop_name, - bt_bool prop_value) +void write_bool_prop_value(struct details_write_ctx *ctx, bt_bool prop_value) { const char *str; - write_indent(ctx); - write_prop_name(ctx, prop_name); - g_string_append_printf(ctx->str, ": %s", color_bold(ctx)); + g_string_append(ctx->str, color_bold(ctx)); if (prop_value) { - g_string_append(ctx->str, color_fg_green(ctx)); + g_string_append(ctx->str, color_fg_bright_green(ctx)); str = "Yes"; } else { - g_string_append(ctx->str, color_fg_red(ctx)); + g_string_append(ctx->str, color_fg_bright_red(ctx)); str = "No"; } - g_string_append_printf(ctx->str, "%s%s\n", str, color_reset(ctx)); + g_string_append_printf(ctx->str, "%s%s", str, color_reset(ctx)); +} + +static inline +void write_bool_prop_line(struct details_write_ctx *ctx, const char *prop_name, + bt_bool prop_value) +{ + write_indent(ctx); + write_prop_name(ctx, prop_name); + g_string_append(ctx->str, ": "); + write_bool_prop_value(ctx, prop_value); + write_nl(ctx); } static inline void write_uuid_prop_line(struct details_write_ctx *ctx, const char *prop_name, bt_uuid uuid) { - BT_ASSERT(uuid); + BT_ASSERT_DBG(uuid); write_indent(ctx); write_prop_name(ctx, prop_name); g_string_append_printf(ctx->str, - ": %s%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%s\n", + ": %s" BT_UUID_FMT "%s\n", color_bold(ctx), - (unsigned int) uuid[0], - (unsigned int) uuid[1], - (unsigned int) uuid[2], - (unsigned int) uuid[3], - (unsigned int) uuid[4], - (unsigned int) uuid[5], - (unsigned int) uuid[6], - (unsigned int) uuid[7], - (unsigned int) uuid[8], - (unsigned int) uuid[9], - (unsigned int) uuid[10], - (unsigned int) uuid[11], - (unsigned int) uuid[12], - (unsigned int) uuid[13], - (unsigned int) uuid[14], - (unsigned int) uuid[15], + BT_UUID_FMT_VALUES(uuid), color_reset(ctx)); } +static +gint compare_strings(const char **a, const char **b) +{ + return strcmp(*a, *b); +} + +static +bt_value_map_foreach_entry_const_func_status map_value_foreach_add_key_to_array( + const char *key, const bt_value *object, void *data) +{ + GPtrArray *keys = data; + + BT_ASSERT_DBG(keys); + g_ptr_array_add(keys, (void *) key); + return BT_VALUE_MAP_FOREACH_ENTRY_CONST_FUNC_STATUS_OK; +} + +static +void write_value(struct details_write_ctx *ctx, const bt_value *value, + const char *name) +{ + uint64_t i; + bt_value_type value_type = bt_value_get_type(value); + GPtrArray *keys = g_ptr_array_new(); + char buf[64]; + + BT_ASSERT_DBG(keys); + + /* Write field's name */ + if (name) { + write_prop_name_line(ctx, name); + } + + /* Write field's value */ + switch (value_type) { + case BT_VALUE_TYPE_NULL: + write_sp(ctx); + write_none_prop_value(ctx, "Null"); + break; + case BT_VALUE_TYPE_BOOL: + write_sp(ctx); + write_bool_prop_value(ctx, bt_value_bool_get(value)); + break; + case BT_VALUE_TYPE_UNSIGNED_INTEGER: + format_uint(buf, bt_value_integer_unsigned_get(value), 10); + write_sp(ctx); + write_uint_str_prop_value(ctx, buf); + break; + case BT_VALUE_TYPE_SIGNED_INTEGER: + format_int(buf, bt_value_integer_signed_get(value), 10); + write_sp(ctx); + write_int_str_prop_value(ctx, buf); + break; + case BT_VALUE_TYPE_REAL: + write_sp(ctx); + write_float_prop_value(ctx, bt_value_real_get(value)); + break; + case BT_VALUE_TYPE_STRING: + write_sp(ctx); + write_str_prop_value(ctx, bt_value_string_get(value)); + break; + case BT_VALUE_TYPE_ARRAY: + { + uint64_t length = bt_value_array_get_length(value); + + if (length == 0) { + write_sp(ctx); + write_none_prop_value(ctx, "Empty"); + } else { + g_string_append(ctx->str, " Length "); + write_uint_prop_value(ctx, length); + g_string_append_c(ctx->str, ':'); + } + + incr_indent(ctx); + + for (i = 0; i < length; i++) { + const bt_value *elem_value = + bt_value_array_borrow_element_by_index_const( + value, i); + + write_nl(ctx); + write_array_index(ctx, i, color_fg_magenta(ctx)); + write_value(ctx, elem_value, NULL); + } + + decr_indent(ctx); + break; + } + case BT_VALUE_TYPE_MAP: + { + bt_value_map_foreach_entry_const_status foreach_status = + bt_value_map_foreach_entry_const(value, + map_value_foreach_add_key_to_array, keys); + + BT_ASSERT_DBG(foreach_status == + BT_VALUE_MAP_FOREACH_ENTRY_CONST_STATUS_OK); + g_ptr_array_sort(keys, (GCompareFunc) compare_strings); + + if (keys->len > 0) { + incr_indent(ctx); + + for (i = 0; i < keys->len; i++) { + const char *key = keys->pdata[i]; + const bt_value *entry_value = + bt_value_map_borrow_entry_value_const( + value, key); + + write_nl(ctx); + write_value(ctx, entry_value, key); + } + + decr_indent(ctx); + } else { + write_sp(ctx); + write_none_prop_value(ctx, "Empty"); + } + + break; + } + default: + bt_common_abort(); + } + + g_ptr_array_free(keys, TRUE); +} + +static +void write_user_attributes(struct details_write_ctx *ctx, + const bt_value *user_attrs, bool write_newline, bool *written) +{ + BT_ASSERT_DBG(user_attrs); + + if (!bt_value_map_is_empty(user_attrs)) { + write_value(ctx, user_attrs, "User attributes"); + + if (write_newline) { + write_nl(ctx); + } + + if (written) { + *written = true; + } + } +} + static void write_int_field_class_props(struct details_write_ctx *ctx, const bt_field_class *fc, bool close) @@ -373,7 +532,7 @@ void write_int_field_class_props(struct details_write_ctx *ctx, write_uint_prop_value(ctx, 16); break; default: - abort(); + bt_common_abort(); } if (close) { @@ -381,7 +540,7 @@ void write_int_field_class_props(struct details_write_ctx *ctx, } } -struct enum_field_class_mapping_range { +struct int_range { union { uint64_t u; int64_t i; @@ -397,7 +556,7 @@ struct enum_field_class_mapping { /* Weak */ const char *label; - /* Array of `struct enum_field_class_mapping_range` */ + /* Array of `struct int_range` */ GArray *ranges; }; @@ -409,9 +568,7 @@ gint compare_enum_field_class_mappings(struct enum_field_class_mapping **a, } static -gint compare_enum_field_class_mapping_ranges_signed( - struct enum_field_class_mapping_range *a, - struct enum_field_class_mapping_range *b) +gint compare_int_ranges_signed(struct int_range *a, struct int_range *b) { if (a->lower.i < b->lower.i) { @@ -430,9 +587,7 @@ gint compare_enum_field_class_mapping_ranges_signed( } static -gint compare_enum_field_class_mapping_ranges_unsigned( - struct enum_field_class_mapping_range *a, - struct enum_field_class_mapping_range *b) +gint compare_int_ranges_unsigned(struct int_range *a, struct int_range *b) { if (a->lower.u < b->lower.u) { return -1; @@ -449,6 +604,58 @@ gint compare_enum_field_class_mapping_ranges_unsigned( } } +static +GArray *range_set_to_int_ranges(const void *spec_range_set, bool is_signed) +{ + uint64_t i; + const bt_integer_range_set *range_set; + GArray *ranges = g_array_new(FALSE, TRUE, sizeof(struct int_range)); + + if (!ranges) { + goto end; + } + + if (is_signed) { + range_set = bt_integer_range_set_signed_as_range_set_const( + spec_range_set); + } else { + range_set = bt_integer_range_set_unsigned_as_range_set_const( + spec_range_set); + } + + for (i = 0; i < bt_integer_range_set_get_range_count(range_set); i++) { + struct int_range range; + + if (is_signed) { + const bt_integer_range_signed *orig_range = + bt_integer_range_set_signed_borrow_range_by_index_const( + spec_range_set, i); + + range.lower.i = bt_integer_range_signed_get_lower(orig_range); + range.upper.i = bt_integer_range_signed_get_upper(orig_range); + } else { + const bt_integer_range_unsigned *orig_range = + bt_integer_range_set_unsigned_borrow_range_by_index_const( + spec_range_set, i); + + range.lower.u = bt_integer_range_unsigned_get_lower(orig_range); + range.upper.u = bt_integer_range_unsigned_get_upper(orig_range); + } + + g_array_append_val(ranges, range); + } + + if (is_signed) { + g_array_sort(ranges, (GCompareFunc) compare_int_ranges_signed); + } else { + g_array_sort(ranges, + (GCompareFunc) compare_int_ranges_unsigned); + } + +end: + return ranges; +} + static void destroy_enum_field_class_mapping(struct enum_field_class_mapping *mapping) { @@ -461,8 +668,14 @@ void destroy_enum_field_class_mapping(struct enum_field_class_mapping *mapping) } static -void write_enum_field_class_mapping_range(struct details_write_ctx *ctx, - struct enum_field_class_mapping_range *range, bool is_signed) +struct int_range *int_range_at(GArray *ranges, uint64_t index) +{ + return &g_array_index(ranges, struct int_range, index); +} + +static +void write_int_range(struct details_write_ctx *ctx, + struct int_range *range, bool is_signed) { g_string_append(ctx->str, "["); @@ -472,12 +685,14 @@ void write_enum_field_class_mapping_range(struct details_write_ctx *ctx, write_int_prop_value(ctx, range->lower.u); } - g_string_append(ctx->str, ", "); + if (range->lower.u != range->upper.u) { + g_string_append(ctx->str, ", "); - if (is_signed) { - write_int_prop_value(ctx, range->upper.i); - } else { - write_int_prop_value(ctx, range->upper.u); + if (is_signed) { + write_int_prop_value(ctx, range->upper.i); + } else { + write_int_prop_value(ctx, range->upper.u); + } } g_string_append(ctx->str, "]"); @@ -495,7 +710,7 @@ void write_enum_field_class_mappings(struct details_write_ctx *ctx, mappings = g_ptr_array_new_with_free_func( (GDestroyNotify) destroy_enum_field_class_mapping); - BT_ASSERT(mappings); + BT_ASSERT_DBG(mappings); /* * Copy field class's mappings to our own arrays and structures @@ -503,95 +718,50 @@ void write_enum_field_class_mappings(struct details_write_ctx *ctx, */ for (i = 0; i < bt_field_class_enumeration_get_mapping_count(fc); i++) { const void *fc_mapping; + const void *fc_range_set; struct enum_field_class_mapping *mapping = g_new0( struct enum_field_class_mapping, 1); - BT_ASSERT(mapping); - mapping->ranges = g_array_new(FALSE, TRUE, - sizeof(struct enum_field_class_mapping_range)); - BT_ASSERT(mapping->ranges); + BT_ASSERT_DBG(mapping); if (is_signed) { - fc_mapping = bt_field_class_signed_enumeration_borrow_mapping_by_index_const( + fc_mapping = bt_field_class_enumeration_signed_borrow_mapping_by_index_const( fc, i); + fc_range_set = bt_field_class_enumeration_signed_mapping_borrow_ranges_const( + fc_mapping); } else { - fc_mapping = bt_field_class_unsigned_enumeration_borrow_mapping_by_index_const( + fc_mapping = bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const( fc, i); + fc_range_set = bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const( + fc_mapping); } mapping->label = bt_field_class_enumeration_mapping_get_label( - bt_field_class_signed_enumeration_mapping_as_mapping_const( + bt_field_class_enumeration_signed_mapping_as_mapping_const( fc_mapping)); - - for (range_i = 0; - range_i < bt_field_class_enumeration_mapping_get_range_count( - bt_field_class_signed_enumeration_mapping_as_mapping_const(fc_mapping)); - range_i++) { - struct enum_field_class_mapping_range range; - - if (is_signed) { - bt_field_class_signed_enumeration_mapping_get_range_by_index( - fc_mapping, range_i, - &range.lower.i, &range.upper.i); - } else { - bt_field_class_unsigned_enumeration_mapping_get_range_by_index( - fc_mapping, range_i, - &range.lower.u, &range.upper.u); - } - - g_array_append_val(mapping->ranges, range); - } - + mapping->ranges = range_set_to_int_ranges(fc_range_set, + is_signed); + BT_ASSERT_DBG(mapping->ranges); g_ptr_array_add(mappings, mapping); } - /* Sort mappings, and for each mapping, sort ranges */ + /* Sort mappings (ranges are already sorted within mappings) */ g_ptr_array_sort(mappings, (GCompareFunc) compare_enum_field_class_mappings); - for (i = 0; i < mappings->len; i++) { - struct enum_field_class_mapping *mapping = mappings->pdata[i]; - - if (is_signed) { - g_array_sort(mapping->ranges, - (GCompareFunc) - compare_enum_field_class_mapping_ranges_signed); - } else { - g_array_sort(mapping->ranges, - (GCompareFunc) - compare_enum_field_class_mapping_ranges_unsigned); - } - } - /* Write mappings */ for (i = 0; i < mappings->len; i++) { struct enum_field_class_mapping *mapping = mappings->pdata[i]; write_nl(ctx); - write_compound_member_name(ctx, mapping->label); - - if (mapping->ranges->len == 1) { - /* Single one: write on same line */ - write_sp(ctx); - write_enum_field_class_mapping_range(ctx, - &g_array_index(mapping->ranges, - struct enum_field_class_mapping_range, - 0), is_signed); - continue; - } - - incr_indent(ctx); + write_prop_name_line(ctx, mapping->label); for (range_i = 0; range_i < mapping->ranges->len; range_i++) { - write_nl(ctx); - write_indent(ctx); - write_enum_field_class_mapping_range(ctx, - &g_array_index(mapping->ranges, - struct enum_field_class_mapping_range, - range_i), is_signed); + write_sp(ctx); + write_int_range(ctx, + int_range_at(mapping->ranges, range_i), + is_signed); } - - decr_indent(ctx); } g_ptr_array_free(mappings, TRUE); @@ -606,20 +776,20 @@ void write_field_path(struct details_write_ctx *ctx, g_string_append_c(ctx->str, '['); switch (bt_field_path_get_root_scope(field_path)) { - case BT_SCOPE_PACKET_CONTEXT: + case BT_FIELD_PATH_SCOPE_PACKET_CONTEXT: write_str_prop_value(ctx, "Packet context"); break; - case BT_SCOPE_EVENT_COMMON_CONTEXT: + case BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT: write_str_prop_value(ctx, "Event common context"); break; - case BT_SCOPE_EVENT_SPECIFIC_CONTEXT: + case BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT: write_str_prop_value(ctx, "Event specific context"); break; - case BT_SCOPE_EVENT_PAYLOAD: + case BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD: write_str_prop_value(ctx, "Event payload"); break; default: - abort(); + bt_common_abort(); } g_string_append(ctx->str, ": "); @@ -641,7 +811,7 @@ void write_field_path(struct details_write_ctx *ctx, write_str_prop_value(ctx, ""); break; default: - abort(); + bt_common_abort(); } } @@ -649,21 +819,108 @@ void write_field_path(struct details_write_ctx *ctx, } static -void write_field_class(struct details_write_ctx *ctx, const bt_field_class *fc, - const char *name) +void write_field_class(struct details_write_ctx *ctx, const bt_field_class *fc); + +static +void write_variant_field_class_option(struct details_write_ctx *ctx, + const bt_field_class *fc, uint64_t index) { - uint64_t i; - const char *type; bt_field_class_type fc_type = bt_field_class_get_type(fc); + const bt_field_class_variant_option *option = + bt_field_class_variant_borrow_option_by_index_const( + fc, index); + const void *orig_ranges = NULL; + GArray *int_ranges = NULL; + bool is_signed; + const bt_value *user_attrs = + bt_field_class_variant_option_borrow_user_attributes_const( + option); + const bt_field_class *option_fc = + bt_field_class_variant_option_borrow_field_class_const(option); - /* Write field class's name */ - if (name) { - write_compound_member_name(ctx, name); + write_nl(ctx); + write_compound_member_name(ctx, + bt_field_class_variant_option_get_name(option)); + + if (fc_type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD) { + const bt_field_class_variant_with_selector_field_integer_unsigned_option *spec_opt = + bt_field_class_variant_with_selector_field_integer_unsigned_borrow_option_by_index_const( + fc, index); + + orig_ranges = + bt_field_class_variant_with_selector_field_integer_unsigned_option_borrow_ranges_const( + spec_opt); + is_signed = false; + } else if (fc_type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD) { + const bt_field_class_variant_with_selector_field_integer_signed_option *spec_opt = + bt_field_class_variant_with_selector_field_integer_signed_borrow_option_by_index_const( + fc, index); + + orig_ranges = + bt_field_class_variant_with_selector_field_integer_signed_option_borrow_ranges_const( + spec_opt); + is_signed = true; + } + + if (orig_ranges) { + uint64_t i; + + int_ranges = range_set_to_int_ranges(orig_ranges, is_signed); + BT_ASSERT_DBG(int_ranges); + + for (i = 0; i < int_ranges->len; i++) { + struct int_range *range = int_range_at(int_ranges, i); + + write_sp(ctx); + write_int_range(ctx, range, is_signed); + } + + g_string_append(ctx->str, ": "); + } else { write_sp(ctx); } + if (bt_value_map_is_empty(user_attrs)) { + write_field_class(ctx, option_fc); + } else { + write_nl(ctx); + incr_indent(ctx); + + /* Field class */ + write_prop_name_line(ctx, "Field class"); + write_sp(ctx); + write_field_class(ctx, option_fc); + write_nl(ctx); + + /* User attributes */ + write_user_attributes(ctx, user_attrs, + false, NULL); + + decr_indent(ctx); + } + + if (int_ranges) { + g_array_free(int_ranges, TRUE); + } +} + +static +void write_field_class(struct details_write_ctx *ctx, const bt_field_class *fc) +{ + uint64_t i; + const char *type; + bt_field_class_type fc_type = bt_field_class_get_type(fc); + const bt_value *user_attrs; + bool wrote_user_attrs = false; + /* Write field class's type */ switch (fc_type) { + case BT_FIELD_CLASS_TYPE_BOOL: + type = "Boolean"; + break; + case BT_FIELD_CLASS_TYPE_BIT_ARRAY: + type = "Bit array"; + break; case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER: type = "Unsigned integer"; break; @@ -676,8 +933,11 @@ void write_field_class(struct details_write_ctx *ctx, const bt_field_class *fc, case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION: type = "Signed enumeration"; break; - case BT_FIELD_CLASS_TYPE_REAL: - type = "Real"; + case BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL: + type = "Single-precision real"; + break; + case BT_FIELD_CLASS_TYPE_DOUBLE_PRECISION_REAL: + type = "Double-precision real"; break; case BT_FIELD_CLASS_TYPE_STRING: type = "String"; @@ -688,29 +948,42 @@ void write_field_class(struct details_write_ctx *ctx, const bt_field_class *fc, case BT_FIELD_CLASS_TYPE_STATIC_ARRAY: type = "Static array"; break; - case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY: - type = "Dynamic array"; + case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITHOUT_LENGTH_FIELD: + type = "Dynamic array (no length field)"; + break; + case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITH_LENGTH_FIELD: + type = "Dynamic array (with length field)"; + break; + case BT_FIELD_CLASS_TYPE_OPTION_WITHOUT_SELECTOR_FIELD: + type = "Option (no selector)"; + break; + case BT_FIELD_CLASS_TYPE_OPTION_WITH_BOOL_SELECTOR_FIELD: + type = "Option (boolean selector)"; break; - case BT_FIELD_CLASS_TYPE_VARIANT: - type = "Variant"; + case BT_FIELD_CLASS_TYPE_OPTION_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD: + type = "Option (unsigned integer selector)"; + break; + case BT_FIELD_CLASS_TYPE_OPTION_WITH_SIGNED_INTEGER_SELECTOR_FIELD: + type = "Option (signed integer selector)"; + break; + case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR_FIELD: + type = "Variant (no selector)"; + break; + case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD: + type = "Variant (unsigned integer selector)"; + break; + case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD: + type = "Variant (signed integer selector)"; break; default: - abort(); + bt_common_abort(); } g_string_append_printf(ctx->str, "%s%s%s", color_fg_blue(ctx), type, color_reset(ctx)); - /* Write field class's properties */ - switch (fc_type) { - case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER: - case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER: - write_sp(ctx); - write_int_field_class_props(ctx, fc, true); - break; - case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION: - case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION: - { + /* Write field class's single-line properties */ + if (bt_field_class_type_is(fc_type, BT_FIELD_CLASS_TYPE_ENUMERATION)) { uint64_t mapping_count = bt_field_class_enumeration_get_mapping_count(fc); @@ -720,136 +993,248 @@ void write_field_class(struct details_write_ctx *ctx, const bt_field_class *fc, write_uint_prop_value(ctx, mapping_count); g_string_append_printf(ctx->str, " mapping%s)", plural(mapping_count)); + } else if (bt_field_class_type_is(fc_type, + BT_FIELD_CLASS_TYPE_INTEGER)) { + write_sp(ctx); + write_int_field_class_props(ctx, fc, true); + } else if (fc_type == BT_FIELD_CLASS_TYPE_STRUCTURE) { + uint64_t member_count = + bt_field_class_structure_get_member_count(fc); + + g_string_append(ctx->str, " ("); + write_uint_prop_value(ctx, member_count); + g_string_append_printf(ctx->str, " member%s)", + plural(member_count)); + } else if (fc_type == BT_FIELD_CLASS_TYPE_STATIC_ARRAY) { + g_string_append(ctx->str, " (Length "); + write_uint_prop_value(ctx, + bt_field_class_array_static_get_length(fc)); + g_string_append_c(ctx->str, ')'); + } else if (fc_type == BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITH_LENGTH_FIELD) { + const bt_field_path *length_field_path = + bt_field_class_array_dynamic_with_length_field_borrow_length_field_path_const( + fc); + + g_string_append(ctx->str, " (Length field path "); + write_field_path(ctx, length_field_path); + g_string_append_c(ctx->str, ')'); + } else if (bt_field_class_type_is(fc_type, + BT_FIELD_CLASS_TYPE_OPTION_WITH_SELECTOR_FIELD)) { + const bt_field_path *selector_field_path = + bt_field_class_option_with_selector_field_borrow_selector_field_path_const( + fc); + + g_string_append(ctx->str, " (Selector field path "); + write_field_path(ctx, selector_field_path); + g_string_append_c(ctx->str, ')'); + } else if (bt_field_class_type_is(fc_type, + BT_FIELD_CLASS_TYPE_VARIANT)) { + uint64_t option_count = + bt_field_class_variant_get_option_count(fc); + const bt_field_path *sel_field_path = NULL; + + if (bt_field_class_type_is(fc_type, + BT_FIELD_CLASS_TYPE_VARIANT_WITH_SELECTOR_FIELD)) { + sel_field_path = + bt_field_class_variant_with_selector_field_borrow_selector_field_path_const( + fc); + BT_ASSERT_DBG(sel_field_path); + } + + g_string_append(ctx->str, " ("); + write_uint_prop_value(ctx, option_count); + g_string_append_printf(ctx->str, " option%s", + plural(option_count)); + + if (sel_field_path) { + g_string_append(ctx->str, ", Selector field path "); + write_field_path(ctx, sel_field_path); + } + + g_string_append_c(ctx->str, ')'); + } + + incr_indent(ctx); + user_attrs = bt_field_class_borrow_user_attributes_const(fc); + if (!bt_value_map_is_empty(user_attrs)) { + g_string_append(ctx->str, ":\n"); + write_user_attributes(ctx, user_attrs, false, NULL); + wrote_user_attrs = true; + } + + /* Write field class's complex properties */ + if (bt_field_class_type_is(fc_type, BT_FIELD_CLASS_TYPE_ENUMERATION)) { + uint64_t mapping_count = + bt_field_class_enumeration_get_mapping_count(fc); if (mapping_count > 0) { - g_string_append_c(ctx->str, ':'); - incr_indent(ctx); + if (wrote_user_attrs) { + write_nl(ctx); + write_indent(ctx); + write_prop_name(ctx, "Mappings"); + g_string_append_c(ctx->str, ':'); + incr_indent(ctx); + } else { + /* Each mapping starts with its own newline */ + g_string_append_c(ctx->str, ':'); + } + write_enum_field_class_mappings(ctx, fc); - decr_indent(ctx); - } - break; - } - case BT_FIELD_CLASS_TYPE_REAL: - if (bt_field_class_real_is_single_precision(fc)) { - g_string_append(ctx->str, " (Single precision)"); - } else { - g_string_append(ctx->str, " (Double precision)"); + if (wrote_user_attrs) { + decr_indent(ctx); + } } - - break; - case BT_FIELD_CLASS_TYPE_STRUCTURE: - { + } else if (fc_type == BT_FIELD_CLASS_TYPE_STRUCTURE) { uint64_t member_count = bt_field_class_structure_get_member_count(fc); - g_string_append(ctx->str, " ("); - write_uint_prop_value(ctx, member_count); - g_string_append_printf(ctx->str, " member%s)", - plural(member_count)); - if (member_count > 0) { - g_string_append_c(ctx->str, ':'); - incr_indent(ctx); + if (wrote_user_attrs) { + write_nl(ctx); + write_indent(ctx); + write_prop_name(ctx, "Members"); + g_string_append_c(ctx->str, ':'); + incr_indent(ctx); + } else { + /* Each member starts with its own newline */ + g_string_append_c(ctx->str, ':'); + } for (i = 0; i < member_count; i++) { const bt_field_class_structure_member *member = bt_field_class_structure_borrow_member_by_index_const( fc, i); + const bt_value *member_user_attrs; + const bt_field_class *member_fc = + bt_field_class_structure_member_borrow_field_class_const(member); write_nl(ctx); - write_field_class(ctx, - bt_field_class_structure_member_borrow_field_class_const(member), + write_compound_member_name(ctx, bt_field_class_structure_member_get_name(member)); + member_user_attrs = bt_field_class_structure_member_borrow_user_attributes_const( + member); + + if (bt_value_map_is_empty(member_user_attrs)) { + write_sp(ctx); + write_field_class(ctx, member_fc); + } else { + write_nl(ctx); + incr_indent(ctx); + + /* Field class */ + write_prop_name_line(ctx, "Field class"); + write_sp(ctx); + write_field_class(ctx, member_fc); + write_nl(ctx); + + /* User attributes */ + write_user_attributes(ctx, member_user_attrs, + false, NULL); + + decr_indent(ctx); + } } - decr_indent(ctx); + if (wrote_user_attrs) { + decr_indent(ctx); + } + } + } else if (bt_field_class_type_is(fc_type, BT_FIELD_CLASS_TYPE_ARRAY)) { + if (wrote_user_attrs) { + write_nl(ctx); + } else { + g_string_append(ctx->str, ":\n"); } - break; - } - case BT_FIELD_CLASS_TYPE_STATIC_ARRAY: - case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY: - if (fc_type == BT_FIELD_CLASS_TYPE_STATIC_ARRAY) { - g_string_append(ctx->str, " (Length "); - write_uint_prop_value(ctx, - bt_field_class_static_array_get_length(fc)); - g_string_append_c(ctx->str, ')'); + write_prop_name_line(ctx, "Element"); + write_sp(ctx); + write_field_class(ctx, + bt_field_class_array_borrow_element_field_class_const(fc)); + } else if (bt_field_class_type_is(fc_type, + BT_FIELD_CLASS_TYPE_OPTION)) { + const void *ranges = NULL; + bool selector_is_signed = false; + + if (wrote_user_attrs) { + write_nl(ctx); } else { - const bt_field_path *length_field_path = - bt_field_class_dynamic_array_borrow_length_field_path_const( - fc); + g_string_append(ctx->str, ":\n"); + } - if (length_field_path) { - g_string_append(ctx->str, " (Length field path "); - write_field_path(ctx, length_field_path); - g_string_append_c(ctx->str, ')'); - } + if (fc_type == BT_FIELD_CLASS_TYPE_OPTION_WITH_BOOL_SELECTOR_FIELD) { + write_bool_prop_line(ctx, "Selector is reversed", + bt_field_class_option_with_selector_field_bool_selector_is_reversed(fc)); + } else if (fc_type == BT_FIELD_CLASS_TYPE_OPTION_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD) { + ranges = bt_field_class_option_with_selector_field_integer_unsigned_borrow_selector_ranges_const(fc); + } else if (fc_type == BT_FIELD_CLASS_TYPE_OPTION_WITH_SIGNED_INTEGER_SELECTOR_FIELD) { + ranges = bt_field_class_option_with_selector_field_integer_signed_borrow_selector_ranges_const(fc); + selector_is_signed = true; } - g_string_append_c(ctx->str, ':'); - write_nl(ctx); - incr_indent(ctx); - write_field_class(ctx, - bt_field_class_array_borrow_element_field_class_const(fc), - "Element"); - decr_indent(ctx); - break; - case BT_FIELD_CLASS_TYPE_VARIANT: - { - uint64_t option_count = - bt_field_class_variant_get_option_count(fc); - const bt_field_path *sel_field_path = - bt_field_class_variant_borrow_selector_field_path_const( - fc); + if (ranges) { + GArray *sorted_ranges = range_set_to_int_ranges( + ranges, selector_is_signed); - g_string_append(ctx->str, " ("); - write_uint_prop_value(ctx, option_count); - g_string_append_printf(ctx->str, " option%s, ", - plural(option_count)); + BT_ASSERT_DBG(sorted_ranges); + BT_ASSERT_DBG(sorted_ranges->len > 0); + write_prop_name_line(ctx, "Selector ranges"); - if (sel_field_path) { - g_string_append(ctx->str, "Selector field path "); - write_field_path(ctx, sel_field_path); + for (i = 0; i < sorted_ranges->len; i++) { + write_sp(ctx); + write_int_range(ctx, + int_range_at(sorted_ranges, i), + selector_is_signed); + } + + write_nl(ctx); + g_array_free(sorted_ranges, TRUE); } - g_string_append_c(ctx->str, ')'); + write_prop_name_line(ctx, "Content"); + write_sp(ctx); + write_field_class(ctx, + bt_field_class_option_borrow_field_class_const(fc)); + } else if (bt_field_class_type_is(fc_type, + BT_FIELD_CLASS_TYPE_VARIANT)) { + uint64_t option_count = + bt_field_class_variant_get_option_count(fc); if (option_count > 0) { - g_string_append_c(ctx->str, ':'); - incr_indent(ctx); + if (wrote_user_attrs) { + write_nl(ctx); + write_indent(ctx); + write_prop_name(ctx, "Options"); + g_string_append_c(ctx->str, ':'); + incr_indent(ctx); + } else { + /* Each option starts with its own newline */ + g_string_append_c(ctx->str, ':'); + } for (i = 0; i < option_count; i++) { - const bt_field_class_variant_option *option = - bt_field_class_variant_borrow_option_by_index_const( - fc, i); - - write_nl(ctx); - write_field_class(ctx, - bt_field_class_variant_option_borrow_field_class_const(option), - bt_field_class_variant_option_get_name(option)); + write_variant_field_class_option(ctx, fc, i); } - decr_indent(ctx); + if (wrote_user_attrs) { + decr_indent(ctx); + } } - - break; - } - default: - break; } + + decr_indent(ctx); } static void write_root_field_class(struct details_write_ctx *ctx, const char *name, const bt_field_class *fc) { - BT_ASSERT(name); - BT_ASSERT(fc); + BT_ASSERT_DBG(name); + BT_ASSERT_DBG(fc); write_indent(ctx); write_prop_name(ctx, name); g_string_append(ctx->str, ": "); - write_field_class(ctx, fc, NULL); + write_field_class(ctx, fc); write_nl(ctx); } @@ -877,6 +1262,10 @@ void write_event_class(struct details_write_ctx *ctx, const bt_event_class *ec) /* Write properties */ incr_indent(ctx); + /* Write user attributes */ + write_user_attributes(ctx, + bt_event_class_borrow_user_attributes_const(ec), true, NULL); + /* Write log level */ if (bt_event_class_get_log_level(ec, &log_level) == BT_PROPERTY_AVAILABILITY_AVAILABLE) { @@ -929,7 +1318,7 @@ void write_event_class(struct details_write_ctx *ctx, const bt_event_class *ec) ll_str = "Debug"; break; default: - abort(); + bt_common_abort(); } write_str_prop_line(ctx, "Log level", ll_str); @@ -969,6 +1358,8 @@ void write_clock_class_prop_lines(struct details_write_ctx *ctx, write_str_prop_line(ctx, "Name", str); } + write_user_attributes(ctx, + bt_clock_class_borrow_user_attributes_const(cc), true, NULL); str = bt_clock_class_get_description(cc); if (str) { write_str_prop_line(ctx, "Description", str); @@ -1037,25 +1428,42 @@ void write_stream_class(struct details_write_ctx *ctx, /* Write properties */ incr_indent(ctx); + /* Write user attributes */ + write_user_attributes(ctx, + bt_stream_class_borrow_user_attributes_const(sc), true, NULL); + /* Write configuration */ write_bool_prop_line(ctx, - "Packets have beginning default clock snapshot", - bt_stream_class_packets_have_beginning_default_clock_snapshot(sc)); - write_bool_prop_line(ctx, - "Packets have end default clock snapshot", - bt_stream_class_packets_have_end_default_clock_snapshot(sc)); + "Supports packets", bt_stream_class_supports_packets(sc)); + + if (bt_stream_class_supports_packets(sc)) { + write_bool_prop_line(ctx, + "Packets have beginning default clock snapshot", + bt_stream_class_packets_have_beginning_default_clock_snapshot(sc)); + write_bool_prop_line(ctx, + "Packets have end default clock snapshot", + bt_stream_class_packets_have_end_default_clock_snapshot(sc)); + } + write_bool_prop_line(ctx, "Supports discarded events", bt_stream_class_supports_discarded_events(sc)); - write_bool_prop_line(ctx, - "Discarded events have default clock snapshots", - bt_stream_class_discarded_events_have_default_clock_snapshots(sc)); + + if (bt_stream_class_supports_discarded_events(sc)) { + write_bool_prop_line(ctx, + "Discarded events have default clock snapshots", + bt_stream_class_discarded_events_have_default_clock_snapshots(sc)); + } + write_bool_prop_line(ctx, "Supports discarded packets", bt_stream_class_supports_discarded_packets(sc)); - write_bool_prop_line(ctx, - "Discarded packets have default clock snapshots", - bt_stream_class_discarded_packets_have_default_clock_snapshots(sc)); + + if (bt_stream_class_supports_discarded_packets(sc)) { + write_bool_prop_line(ctx, + "Discarded packets have default clock snapshots", + bt_stream_class_discarded_packets_have_default_clock_snapshots(sc)); + } /* Write default clock class */ if (bt_stream_class_borrow_default_clock_class_const(sc)) { @@ -1111,12 +1519,6 @@ gint compare_stream_classes(const bt_stream_class **a, const bt_stream_class **b } } -static -gint compare_strings(const char **a, const char **b) -{ - return strcmp(*a, *b); -} - static void write_trace_class(struct details_write_ctx *ctx, const bt_trace_class *tc) { @@ -1127,6 +1529,7 @@ void write_trace_class(struct details_write_ctx *ctx, const bt_trace_class *tc) write_indent(ctx); write_obj_type_name(ctx, "Trace class"); + for (i = 0; i < bt_trace_class_get_stream_class_count(tc); i++) { g_ptr_array_add(stream_classes, (gpointer) bt_trace_class_borrow_stream_class_by_index_const( @@ -1144,6 +1547,12 @@ void write_trace_class(struct details_write_ctx *ctx, const bt_trace_class *tc) incr_indent(ctx); + /* Write user attributes */ + write_user_attributes(ctx, + bt_trace_class_borrow_user_attributes_const(tc), true, + &printed_prop); + + /* Write stream classes */ for (i = 0; i < stream_classes->len; i++) { write_stream_class(ctx, stream_classes->pdata[i]); } @@ -1162,7 +1571,7 @@ int try_write_meta(struct details_write_ctx *ctx, const bt_trace_class *tc, { int ret = 0; - BT_ASSERT(tc); + BT_ASSERT_DBG(tc); if (details_need_to_write_trace_class(ctx, tc)) { uint64_t sc_i; @@ -1183,7 +1592,6 @@ int try_write_meta(struct details_write_ctx *ctx, const bt_trace_class *tc, * rewrite `sc`. */ write_trace_class(ctx, tc); - write_nl(ctx); /* * Mark this trace class as written, as well as all @@ -1218,7 +1626,7 @@ int try_write_meta(struct details_write_ctx *ctx, const bt_trace_class *tc, if (sc && details_need_to_write_meta_object(ctx, tc, sc)) { uint64_t ec_i; - BT_ASSERT(tc); + BT_ASSERT_DBG(tc); if (ctx->details_comp->cfg.compact && ctx->details_comp->printed_something) { @@ -1235,7 +1643,6 @@ int try_write_meta(struct details_write_ctx *ctx, const bt_trace_class *tc, * classes, so we don't need to rewrite `ec`. */ write_stream_class(ctx, sc); - write_nl(ctx); /* * Mark this stream class as written, as well as all its @@ -1255,7 +1662,7 @@ int try_write_meta(struct details_write_ctx *ctx, const bt_trace_class *tc, } if (ec && details_need_to_write_meta_object(ctx, tc, ec)) { - BT_ASSERT(sc); + BT_ASSERT_DBG(sc); if (ctx->details_comp->cfg.compact && ctx->details_comp->printed_something) { @@ -1268,7 +1675,6 @@ int try_write_meta(struct details_write_ctx *ctx, const bt_trace_class *tc, } write_event_class(ctx, ec); - write_nl(ctx); details_did_write_meta_object(ctx, tc, ec); goto end; } @@ -1285,7 +1691,8 @@ void write_time_str(struct details_write_ctx *ctx, const char *str) } g_string_append_printf(ctx->str, "[%s%s%s%s]", - color_bold(ctx), color_fg_blue(ctx), str, color_reset(ctx)); + color_bold(ctx), color_fg_bright_blue(ctx), str, + color_reset(ctx)); if (ctx->details_comp->cfg.compact) { write_sp(ctx); @@ -1310,7 +1717,7 @@ void write_time(struct details_write_ctx *ctx, const bt_clock_snapshot *cs) format_uint(buf, bt_clock_snapshot_get_value(cs), 10); g_string_append_printf(ctx->str, "[%s%s%s%s%s", - color_bold(ctx), color_fg_blue(ctx), buf, + color_bold(ctx), color_fg_bright_blue(ctx), buf, color_reset(ctx), ctx->details_comp->cfg.compact ? "" : " cycles"); cs_status = bt_clock_snapshot_get_ns_from_origin(cs, &ns_from_origin); @@ -1318,7 +1725,7 @@ void write_time(struct details_write_ctx *ctx, const bt_clock_snapshot *cs) format_int(buf, ns_from_origin, 10); g_string_append_printf(ctx->str, "%s %s%s%s%s%s", ctx->details_comp->cfg.compact ? "" : ",", - color_bold(ctx), color_fg_blue(ctx), buf, + color_bold(ctx), color_fg_bright_blue(ctx), buf, color_reset(ctx), ctx->details_comp->cfg.compact ? "" : " ns from origin"); } @@ -1351,22 +1758,25 @@ int write_message_follow_tag(struct details_write_ctx *ctx, if (ctx->details_comp->cfg.compact) { g_string_append_printf(ctx->str, - "%s{%s%" PRIu64 " %" PRIu64 " %" PRIu64 "%s%s}%s ", + "%s{%s%s%" PRIu64 " %" PRIu64 " %" PRIu64 "%s%s}%s ", color_fg_cyan(ctx), color_bold(ctx), + color_fg_bright_cyan(ctx), unique_trace_id, bt_stream_class_get_id(sc), bt_stream_get_id(stream), color_reset(ctx), color_fg_cyan(ctx), color_reset(ctx)); } else { g_string_append_printf(ctx->str, - "%s{Trace %s%" PRIu64 "%s%s, Stream class ID %s%" PRIu64 "%s%s, Stream ID %s%" PRIu64 "%s%s}%s\n", + "%s{Trace %s%s%" PRIu64 "%s%s, Stream class ID %s%s%" PRIu64 "%s%s, Stream ID %s%s%" PRIu64 "%s%s}%s\n", + color_fg_cyan(ctx), + color_bold(ctx), color_fg_bright_cyan(ctx), + unique_trace_id, color_reset(ctx), color_fg_cyan(ctx), - color_bold(ctx), unique_trace_id, - color_reset(ctx), color_fg_cyan(ctx), - color_bold(ctx), bt_stream_class_get_id(sc), - color_reset(ctx), color_fg_cyan(ctx), - color_bold(ctx), bt_stream_get_id(stream), - color_reset(ctx), color_fg_cyan(ctx), - color_reset(ctx)); + color_bold(ctx), color_fg_bright_cyan(ctx), + bt_stream_class_get_id(sc), color_reset(ctx), + color_fg_cyan(ctx), + color_bold(ctx), color_fg_bright_cyan(ctx), + bt_stream_get_id(stream), color_reset(ctx), + color_fg_cyan(ctx), color_reset(ctx)); } end: @@ -1388,12 +1798,16 @@ void write_field(struct details_write_ctx *ctx, const bt_field *field, } /* Write field's value */ - switch (fc_type) { - case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER: - case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION: - case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER: - case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION: - { + if (fc_type == BT_FIELD_CLASS_TYPE_BOOL) { + write_sp(ctx); + write_bool_prop_value(ctx, bt_field_bool_get_value(field)); + } else if (fc_type == BT_FIELD_CLASS_TYPE_BIT_ARRAY) { + format_uint(buf, bt_field_bit_array_get_value_as_integer(field), + 16); + write_sp(ctx); + write_uint_str_prop_value(ctx, buf); + } else if (bt_field_class_type_is(fc_type, + BT_FIELD_CLASS_TYPE_INTEGER)) { unsigned int fmt_base; bt_field_class_integer_preferred_display_base base; @@ -1414,36 +1828,33 @@ void write_field(struct details_write_ctx *ctx, const bt_field *field, fmt_base = 16; break; default: - abort(); + bt_common_abort(); } - if (fc_type == BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER || - fc_type == BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION) { + if (bt_field_class_type_is(fc_type, + BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER)) { format_uint(buf, - bt_field_unsigned_integer_get_value(field), + bt_field_integer_unsigned_get_value(field), fmt_base); write_sp(ctx); write_uint_str_prop_value(ctx, buf); } else { format_int(buf, - bt_field_signed_integer_get_value(field), + bt_field_integer_signed_get_value(field), fmt_base); write_sp(ctx); write_int_str_prop_value(ctx, buf); } - - break; - } - case BT_FIELD_CLASS_TYPE_REAL: + } else if (fc_type == BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL) { write_sp(ctx); - write_float_prop_value(ctx, bt_field_real_get_value(field)); - break; - case BT_FIELD_CLASS_TYPE_STRING: + write_float_prop_value(ctx, bt_field_real_single_precision_get_value(field)); + } else if (fc_type == BT_FIELD_CLASS_TYPE_DOUBLE_PRECISION_REAL) { + write_sp(ctx); + write_float_prop_value(ctx, bt_field_real_double_precision_get_value(field)); + } else if (fc_type == BT_FIELD_CLASS_TYPE_STRING) { write_sp(ctx); write_str_prop_value(ctx, bt_field_string_get_value(field)); - break; - case BT_FIELD_CLASS_TYPE_STRUCTURE: - { + } else if (fc_type == BT_FIELD_CLASS_TYPE_STRUCTURE) { uint64_t member_count; fc = bt_field_borrow_class_const(field); @@ -1467,18 +1878,15 @@ void write_field(struct details_write_ctx *ctx, const bt_field *field, decr_indent(ctx); } else { - g_string_append(ctx->str, " Empty"); + write_sp(ctx); + write_none_prop_value(ctx, "Empty"); } - - break; - } - case BT_FIELD_CLASS_TYPE_STATIC_ARRAY: - case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY: - { + } else if (bt_field_class_type_is(fc_type, BT_FIELD_CLASS_TYPE_ARRAY)) { uint64_t length = bt_field_array_get_length(field); if (length == 0) { - g_string_append(ctx->str, " Empty"); + write_sp(ctx); + write_none_prop_value(ctx, "Empty"); } else { g_string_append(ctx->str, " Length "); write_uint_prop_value(ctx, length); @@ -1493,20 +1901,29 @@ void write_field(struct details_write_ctx *ctx, const bt_field *field, field, i); write_nl(ctx); - write_array_index(ctx, i); + write_array_index(ctx, i, color_fg_cyan(ctx)); write_field(ctx, elem_field, NULL); } decr_indent(ctx); - break; - } - case BT_FIELD_CLASS_TYPE_VARIANT: + } else if (bt_field_class_type_is(fc_type, + BT_FIELD_CLASS_TYPE_OPTION)) { + const bt_field *content_field = + bt_field_option_borrow_field_const(field); + + if (!content_field) { + write_sp(ctx); + write_none_prop_value(ctx, "None"); + } else { + write_field(ctx, content_field, NULL); + } + } else if (bt_field_class_type_is(fc_type, + BT_FIELD_CLASS_TYPE_VARIANT)) { write_field(ctx, bt_field_variant_borrow_selected_option_field_const( field), NULL); - break; - default: - abort(); + } else { + bt_common_abort(); } } @@ -1514,8 +1931,8 @@ static void write_root_field(struct details_write_ctx *ctx, const char *name, const bt_field *field) { - BT_ASSERT(name); - BT_ASSERT(field); + BT_ASSERT_DBG(name); + BT_ASSERT_DBG(field); write_indent(ctx); write_prop_name(ctx, name); g_string_append(ctx->str, ":"); @@ -1541,6 +1958,18 @@ int write_event_message(struct details_write_ctx *ctx, goto end; } + if (!ctx->details_comp->cfg.with_data) { + goto end; + } + + if (ctx->str->len > 0) { + /* + * Output buffer contains metadata: separate blocks with + * newline. + */ + write_nl(ctx); + } + /* Write time */ if (bt_stream_class_borrow_default_clock_class_const(sc)) { write_time(ctx, @@ -1597,7 +2026,6 @@ int write_event_message(struct details_write_ctx *ctx, decr_indent(ctx); end: - return ret; } @@ -1630,7 +2058,6 @@ gint compare_streams(const bt_stream **a, const bt_stream **b) static void write_trace(struct details_write_ctx *ctx, const bt_trace *trace) { - const char *name; GPtrArray *streams = g_ptr_array_new(); uint64_t i; bool printed_prop = false; @@ -1642,7 +2069,7 @@ void write_trace(struct details_write_ctx *ctx, const bt_trace *trace) /* Write name */ if (ctx->details_comp->cfg.with_trace_name) { - name = bt_trace_get_name(trace); + const char *name = bt_trace_get_name(trace); if (name) { g_string_append(ctx->str, " `"); write_str_prop_value(ctx, name); @@ -1701,20 +2128,20 @@ void write_trace(struct details_write_ctx *ctx, const bt_trace *trace) bt_trace_borrow_environment_entry_value_by_name_const( trace, name); - BT_ASSERT(value); + BT_ASSERT_DBG(value); write_compound_member_name(ctx, name); write_sp(ctx); if (bt_value_get_type(value) == BT_VALUE_TYPE_SIGNED_INTEGER) { write_int_prop_value(ctx, - bt_value_signed_integer_get(value)); + bt_value_integer_signed_get(value)); } else if (bt_value_get_type(value) == BT_VALUE_TYPE_STRING) { write_str_prop_value(ctx, bt_value_string_get(value)); } else { - abort(); + bt_common_abort(); } write_nl(ctx); @@ -1769,6 +2196,7 @@ int write_stream_beginning_message(struct details_write_ctx *ctx, bt_message_stream_beginning_borrow_stream_const(msg); const bt_trace *trace = bt_stream_borrow_trace_const(stream); const bt_stream_class *sc = bt_stream_borrow_class_const(stream); + const bt_clock_class *cc = bt_stream_class_borrow_default_clock_class_const(sc); const bt_trace_class *tc = bt_stream_class_borrow_trace_class_const(sc); const char *name; @@ -1777,6 +2205,31 @@ int write_stream_beginning_message(struct details_write_ctx *ctx, goto end; } + if (!ctx->details_comp->cfg.with_data) { + goto end; + } + + if (ctx->str->len > 0) { + /* + * Output buffer contains metadata: separate blocks with + * newline. + */ + write_nl(ctx); + } + + /* Write time */ + if (cc) { + const bt_clock_snapshot *cs; + bt_message_stream_clock_snapshot_state cs_state = + bt_message_stream_beginning_borrow_default_clock_snapshot_const(msg, &cs); + + if (cs_state == BT_MESSAGE_STREAM_CLOCK_SNAPSHOT_STATE_KNOWN) { + write_time(ctx, cs); + } else { + write_time_str(ctx, "Unknown"); + } + } + /* Write follow tag for message */ ret = write_message_follow_tag(ctx, stream); if (ret) { @@ -1822,87 +2275,26 @@ int write_stream_end_message(struct details_write_ctx *ctx, int ret = 0; const bt_stream *stream = bt_message_stream_end_borrow_stream_const(msg); + const bt_stream_class *sc = + bt_stream_borrow_class_const(stream); + const bt_clock_class *cc = + bt_stream_class_borrow_default_clock_class_const(sc); - /* Write follow tag for message */ - ret = write_message_follow_tag(ctx, stream); - if (ret) { + if (!ctx->details_comp->cfg.with_data) { goto end; } - /* Write stream properties */ - write_obj_type_name(ctx, "Stream end\n"); - -end: - return ret; -} - -static -int write_stream_activity_beginning_message(struct details_write_ctx *ctx, - const bt_message *msg) -{ - int ret = 0; - const bt_stream *stream = - bt_message_stream_activity_beginning_borrow_stream_const(msg); - bt_message_stream_activity_clock_snapshot_state cs_state; - const bt_clock_snapshot *cs = NULL; - /* Write time */ - cs_state = bt_message_stream_activity_beginning_borrow_default_clock_snapshot_const( - msg, &cs); - switch (cs_state) { - case BT_MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_KNOWN: - BT_ASSERT(cs); - write_time(ctx, cs); - break; - case BT_MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_UNKNOWN: - write_time_str(ctx, "Unknown"); - break; - case BT_MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_INFINITE: - write_time_str(ctx, "-Infinity"); - break; - default: - abort(); - } - - /* Write follow tag for message */ - ret = write_message_follow_tag(ctx, stream); - if (ret) { - goto end; - } - - write_obj_type_name(ctx, "Stream activity beginning"); - write_nl(ctx); - -end: - return ret; -} - -static -int write_stream_activity_end_message(struct details_write_ctx *ctx, - const bt_message *msg) -{ - int ret = 0; - const bt_stream *stream = - bt_message_stream_activity_end_borrow_stream_const(msg); - bt_message_stream_activity_clock_snapshot_state cs_state; - const bt_clock_snapshot *cs = NULL; + if (cc) { + const bt_clock_snapshot *cs; + bt_message_stream_clock_snapshot_state cs_state = + bt_message_stream_end_borrow_default_clock_snapshot_const(msg, &cs); - /* Write time */ - cs_state = bt_message_stream_activity_end_borrow_default_clock_snapshot_const( - msg, &cs); - switch (cs_state) { - case BT_MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_KNOWN: - BT_ASSERT(cs); - write_time(ctx, cs); - break; - case BT_MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_UNKNOWN: - write_time_str(ctx, "Unknown"); - break; - case BT_MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_INFINITE: - write_time_str(ctx, "+Infinity"); - break; - default: - abort(); + if (cs_state == BT_MESSAGE_STREAM_CLOCK_SNAPSHOT_STATE_KNOWN) { + write_time(ctx, cs); + } else { + write_time_str(ctx, "Unknown"); + } } /* Write follow tag for message */ @@ -1911,8 +2303,8 @@ int write_stream_activity_end_message(struct details_write_ctx *ctx, goto end; } - write_obj_type_name(ctx, "Stream activity end"); - write_nl(ctx); + /* Write stream properties */ + write_obj_type_name(ctx, "Stream end\n"); end: return ret; @@ -1929,6 +2321,10 @@ int write_packet_beginning_message(struct details_write_ctx *ctx, const bt_stream_class *sc = bt_stream_borrow_class_const(stream); const bt_field *field; + if (!ctx->details_comp->cfg.with_data) { + goto end; + } + /* Write time */ if (bt_stream_class_packets_have_beginning_default_clock_snapshot(sc)) { write_time(ctx, @@ -1950,15 +2346,16 @@ int write_packet_beginning_message(struct details_write_ctx *ctx, } /* Write field */ - g_string_append(ctx->str, ":\n"); - incr_indent(ctx); field = bt_packet_borrow_context_field_const(packet); if (field) { + g_string_append(ctx->str, ":\n"); + incr_indent(ctx); write_root_field(ctx, "Context", field); + decr_indent(ctx); + } else { + write_nl(ctx); } - decr_indent(ctx); - end: return ret; } @@ -1974,7 +2371,7 @@ int write_discarded_items_message(struct details_write_ctx *ctx, /* Write times */ if (beginning_cs) { write_time(ctx, beginning_cs); - BT_ASSERT(end_cs); + BT_ASSERT_DBG(end_cs); write_time(ctx, end_cs); } @@ -2005,6 +2402,7 @@ static int write_discarded_events_message(struct details_write_ctx *ctx, const bt_message *msg) { + int ret = 0; const bt_stream *stream = bt_message_discarded_events_borrow_stream_const( msg); const bt_stream_class *sc = bt_stream_borrow_class_const(stream); @@ -2012,6 +2410,10 @@ int write_discarded_events_message(struct details_write_ctx *ctx, const bt_clock_snapshot *end_cs = NULL; uint64_t count; + if (!ctx->details_comp->cfg.with_data) { + goto end; + } + if (bt_stream_class_discarded_events_have_default_clock_snapshots(sc)) { beginning_cs = bt_message_discarded_events_borrow_beginning_default_clock_snapshot_const( @@ -2026,14 +2428,18 @@ int write_discarded_events_message(struct details_write_ctx *ctx, count = UINT64_C(-1); } - return write_discarded_items_message(ctx, "events", stream, + ret = write_discarded_items_message(ctx, "events", stream, beginning_cs, end_cs, count); + +end: + return ret; } static int write_discarded_packets_message(struct details_write_ctx *ctx, const bt_message *msg) { + int ret = 0; const bt_stream *stream = bt_message_discarded_packets_borrow_stream_const( msg); const bt_stream_class *sc = bt_stream_borrow_class_const(stream); @@ -2041,6 +2447,10 @@ int write_discarded_packets_message(struct details_write_ctx *ctx, const bt_clock_snapshot *end_cs = NULL; uint64_t count; + if (!ctx->details_comp->cfg.with_data) { + goto end; + } + if (bt_stream_class_discarded_packets_have_default_clock_snapshots(sc)) { beginning_cs = bt_message_discarded_packets_borrow_beginning_default_clock_snapshot_const( @@ -2055,8 +2465,11 @@ int write_discarded_packets_message(struct details_write_ctx *ctx, count = UINT64_C(-1); } - return write_discarded_items_message(ctx, "packets", stream, + ret = write_discarded_items_message(ctx, "packets", stream, beginning_cs, end_cs, count); + +end: + return ret; } static @@ -2069,6 +2482,10 @@ int write_packet_end_message(struct details_write_ctx *ctx, const bt_stream *stream = bt_packet_borrow_stream_const(packet); const bt_stream_class *sc = bt_stream_borrow_class_const(stream); + if (!ctx->details_comp->cfg.with_data) { + goto end; + } + /* Write time */ if (bt_stream_class_packets_have_end_default_clock_snapshot(sc)) { write_time(ctx, @@ -2137,10 +2554,6 @@ int details_write_message(struct details_comp *details_comp, /* Reset output buffer */ g_string_assign(details_comp->str, ""); - if (details_comp->printed_something && !details_comp->cfg.compact) { - write_nl(&ctx); - } - switch (bt_message_get_type(msg)) { case BT_MESSAGE_TYPE_EVENT: ret = write_event_message(&ctx, msg); @@ -2160,12 +2573,6 @@ int details_write_message(struct details_comp *details_comp, case BT_MESSAGE_TYPE_PACKET_END: ret = write_packet_end_message(&ctx, msg); break; - case BT_MESSAGE_TYPE_STREAM_ACTIVITY_BEGINNING: - ret = write_stream_activity_beginning_message(&ctx, msg); - break; - case BT_MESSAGE_TYPE_STREAM_ACTIVITY_END: - ret = write_stream_activity_end_message(&ctx, msg); - break; case BT_MESSAGE_TYPE_DISCARDED_EVENTS: ret = write_discarded_events_message(&ctx, msg); break; @@ -2173,7 +2580,19 @@ int details_write_message(struct details_comp *details_comp, ret = write_discarded_packets_message(&ctx, msg); break; default: - abort(); + bt_common_abort(); + } + + /* + * If this component printed at least one character so far, and + * we're not in compact mode, and there's something in the + * output buffer for this message, then prepend a newline to the + * output buffer to visually separate message blocks. + */ + if (details_comp->printed_something && !details_comp->cfg.compact && + details_comp->str->len > 0) { + /* TODO: Optimize this */ + g_string_prepend_c(details_comp->str, '\n'); } return ret;