Implement support for UTF16, UTF32 strings
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 10 Nov 2022 17:36:43 +0000 (12:36 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 10 Nov 2022 17:36:43 +0000 (12:36 -0500)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
include/side/trace.h
src/test.c
src/tracer.c

index e2eb4192dc07c382c978193a21fc2bffb25e57fb..bfbf880ed0b27a1c505d44359cfc16bf010e265a 100644 (file)
@@ -101,7 +101,9 @@ enum side_type_label {
        SIDE_TYPE_FLOAT_BINARY32,
        SIDE_TYPE_FLOAT_BINARY64,
        SIDE_TYPE_FLOAT_BINARY128,
-       SIDE_TYPE_STRING,
+       SIDE_TYPE_STRING_UTF8,
+       SIDE_TYPE_STRING_UTF16,
+       SIDE_TYPE_STRING_UTF32,
 
        /* Stack-copy compound types */
        SIDE_TYPE_STRUCT,
@@ -163,7 +165,9 @@ enum side_attr_type {
        SIDE_ATTR_TYPE_FLOAT_BINARY32,
        SIDE_ATTR_TYPE_FLOAT_BINARY64,
        SIDE_ATTR_TYPE_FLOAT_BINARY128,
-       SIDE_ATTR_TYPE_STRING,
+       SIDE_ATTR_TYPE_STRING_UTF8,
+       SIDE_ATTR_TYPE_STRING_UTF16,
+       SIDE_ATTR_TYPE_STRING_UTF32,
 };
 
 enum side_loglevel {
@@ -258,7 +262,7 @@ struct side_attr_value {
        uint32_t type;  /* enum side_attr_type */
        union {
                uint8_t bool_value;
-               uint64_t string_value;  /* const char * */
+               uint64_t string_value;  /* const { uint8_t, uint16_t, uint32_t } * */
                union side_integer_value integer_value;
                union side_float_value float_value;
        } SIDE_PACKED u;
@@ -292,6 +296,8 @@ struct side_type_byte {
 struct side_type_string {
        const struct side_attr *attr;
        uint32_t nr_attr;
+       uint8_t unit_size;              /* 1, 2, or 4 bytes */
+       uint8_t byte_order;             /* enum side_type_label_byte_order */
 } SIDE_PACKED;
 
 struct side_type_integer {
@@ -497,7 +503,7 @@ struct side_arg_static {
        /* Stack-copy basic types */
        union side_bool_value bool_value;
        uint8_t byte_value;
-       uint64_t string_value;  /* const char * */
+       uint64_t string_value;  /* const {uint8_t, uint16_t, uint32_t} * */
        union side_integer_value integer_value;
        union side_float_value float_value;
 
@@ -656,7 +662,9 @@ struct side_event_description {
 #define side_attr_float_binary32(_val) { .type = SIDE_ATTR_TYPE_FLOAT_BINARY32, .u = { .float_value = { .side_float_binary32 = (_val) } } }
 #define side_attr_float_binary64(_val) { .type = SIDE_ATTR_TYPE_FLOAT_BINARY64, .u = { .float_value = { .side_float_binary64 = (_val) } } }
 #define side_attr_float_binary128(_val)        { .type = SIDE_ATTR_TYPE_FLOAT_BINARY128, .u = { .float_value = { .side_float_binary128 = (_val) } } }
-#define side_attr_string(_val)         { .type = SIDE_ATTR_TYPE_STRING, .u = { .string_value = (uintptr_t) (_val) } }
+#define side_attr_string(_val)         { .type = SIDE_ATTR_TYPE_STRING_UTF8, .u = { .string_value = (uintptr_t) (_val) } }
+#define side_attr_string16(_val)       { .type = SIDE_ATTR_TYPE_STRING_UTF16, .u = { .string_value = (uintptr_t) (_val) } }
+#define side_attr_string32(_val)       { .type = SIDE_ATTR_TYPE_STRING_UTF32, .u = { .string_value = (uintptr_t) (_val) } }
 
 /* Stack-copy enumeration type definitions */
 
@@ -748,13 +756,15 @@ struct side_event_description {
                }, \
        }
 
-#define side_type_string(_attr) \
+#define _side_type_string(_type, _byte_order, _unit_size, _attr) \
        { \
-               .type = SIDE_TYPE_STRING, \
+               .type = _type, \
                .u = { \
                        .side_string = { \
                                .attr = _attr, \
                                .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
+                               .unit_size = _unit_size, \
+                               .byte_order = _byte_order, \
                        }, \
                }, \
        }
@@ -812,6 +822,9 @@ struct side_event_description {
 #define side_type_float_binary32(_attr)                        _side_type_float(SIDE_TYPE_FLOAT_BINARY32, SIDE_TYPE_FLOAT_WORD_ORDER_HOST, sizeof(_Float32), SIDE_PARAM(_attr))
 #define side_type_float_binary64(_attr)                        _side_type_float(SIDE_TYPE_FLOAT_BINARY64, SIDE_TYPE_FLOAT_WORD_ORDER_HOST, sizeof(_Float64), SIDE_PARAM(_attr))
 #define side_type_float_binary128(_attr)               _side_type_float(SIDE_TYPE_FLOAT_BINARY128, SIDE_TYPE_FLOAT_WORD_ORDER_HOST, sizeof(_Float128), SIDE_PARAM(_attr))
+#define side_type_string(_attr)                                _side_type_string(SIDE_TYPE_STRING_UTF8, SIDE_TYPE_BYTE_ORDER_HOST, sizeof(uint8_t), SIDE_PARAM(_attr))
+#define side_type_string16(_attr)                      _side_type_string(SIDE_TYPE_STRING_UTF16, SIDE_TYPE_BYTE_ORDER_HOST, sizeof(uint16_t), SIDE_PARAM(_attr))
+#define side_type_string32(_attr)                      _side_type_string(SIDE_TYPE_STRING_UTF32, SIDE_TYPE_BYTE_ORDER_HOST, sizeof(uint32_t), SIDE_PARAM(_attr))
 
 #define side_field_null(_name, _attr)                  _side_field(_name, side_type_null(SIDE_PARAM(_attr)))
 #define side_field_bool(_name, _attr)                  _side_field(_name, side_type_bool(SIDE_PARAM(_attr)))
@@ -830,6 +843,8 @@ struct side_event_description {
 #define side_field_float_binary64(_name, _attr)                _side_field(_name, side_type_float_binary64(SIDE_PARAM(_attr)))
 #define side_field_float_binary128(_name, _attr)       _side_field(_name, side_type_float_binary128(SIDE_PARAM(_attr)))
 #define side_field_string(_name, _attr)                        _side_field(_name, side_type_string(SIDE_PARAM(_attr)))
+#define side_field_string16(_name, _attr)              _side_field(_name, side_type_string16(SIDE_PARAM(_attr)))
+#define side_field_string32(_name, _attr)              _side_field(_name, side_type_string32(SIDE_PARAM(_attr)))
 #define side_field_dynamic(_name)                      _side_field(_name, side_type_dynamic())
 
 /* Little endian */
@@ -844,6 +859,8 @@ struct side_event_description {
 #define side_type_float_binary32_le(_attr)             _side_type_float(SIDE_TYPE_FLOAT_BINARY32, SIDE_TYPE_BYTE_ORDER_LE, sizeof(_Float32), SIDE_PARAM(_attr))
 #define side_type_float_binary64_le(_attr)             _side_type_float(SIDE_TYPE_FLOAT_BINARY64, SIDE_TYPE_BYTE_ORDER_LE, sizeof(_Float64), SIDE_PARAM(_attr))
 #define side_type_float_binary128_le(_attr)            _side_type_float(SIDE_TYPE_FLOAT_BINARY128, SIDE_TYPE_BYTE_ORDER_LE, sizeof(_Float128), SIDE_PARAM(_attr))
+#define side_type_string16_le(_attr)                   _side_type_string(SIDE_TYPE_STRING_UTF16, SIDE_TYPE_BYTE_ORDER_LE, sizeof(uint16_t), SIDE_PARAM(_attr))
+#define side_type_string32_le(_attr)                   _side_type_string(SIDE_TYPE_STRING_UTF32, SIDE_TYPE_BYTE_ORDER_LE, sizeof(uint32_t), SIDE_PARAM(_attr))
 
 #define side_field_u16_le(_name, _attr)                        _side_field(_name, side_type_u16_le(SIDE_PARAM(_attr)))
 #define side_field_u32_le(_name, _attr)                        _side_field(_name, side_type_u32_le(SIDE_PARAM(_attr)))
@@ -856,6 +873,8 @@ struct side_event_description {
 #define side_field_float_binary32_le(_name, _attr)     _side_field(_name, side_type_float_binary32_le(SIDE_PARAM(_attr)))
 #define side_field_float_binary64_le(_name, _attr)     _side_field(_name, side_type_float_binary64_le(SIDE_PARAM(_attr)))
 #define side_field_float_binary128_le(_name, _attr)    _side_field(_name, side_type_float_binary128_le(SIDE_PARAM(_attr)))
+#define side_field_string16_le(_name, _attr)           _side_field(_name, side_type_string16_le(SIDE_PARAM(_attr)))
+#define side_field_string32_le(_name, _attr)           _side_field(_name, side_type_string32_le(SIDE_PARAM(_attr)))
 
 /* Big endian */
 #define side_type_u16_be(_attr)                                _side_type_integer(SIDE_TYPE_U16, false, SIDE_TYPE_BYTE_ORDER_BE, sizeof(uint16_t), 0, SIDE_PARAM(_attr))
@@ -869,6 +888,8 @@ struct side_event_description {
 #define side_type_float_binary32_be(_attr)             _side_type_float(SIDE_TYPE_FLOAT_BINARY32, SIDE_TYPE_BYTE_ORDER_BE, sizeof(_Float32), SIDE_PARAM(_attr))
 #define side_type_float_binary64_be(_attr)             _side_type_float(SIDE_TYPE_FLOAT_BINARY64, SIDE_TYPE_BYTE_ORDER_BE, sizeof(_Float64), SIDE_PARAM(_attr))
 #define side_type_float_binary128_be(_attr)            _side_type_float(SIDE_TYPE_FLOAT_BINARY128, SIDE_TYPE_BYTE_ORDER_BE, sizeof(_Float128), SIDE_PARAM(_attr))
+#define side_type_string16_be(_attr)                   _side_type_string(SIDE_TYPE_STRING_UTF16, SIDE_TYPE_BYTE_ORDER_BE, sizeof(uint16_t), SIDE_PARAM(_attr))
+#define side_type_string32_be(_attr)                   _side_type_string(SIDE_TYPE_STRING_UTF32, SIDE_TYPE_BYTE_ORDER_BE, sizeof(uint32_t), SIDE_PARAM(_attr))
 
 #define side_field_u16_be(_name, _attr)                        _side_field(_name, side_type_u16_be(SIDE_PARAM(_attr)))
 #define side_field_u32_be(_name, _attr)                        _side_field(_name, side_type_u32_be(SIDE_PARAM(_attr)))
@@ -881,6 +902,8 @@ struct side_event_description {
 #define side_field_float_binary32_be(_name, _attr)     _side_field(_name, side_type_float_binary32_be(SIDE_PARAM(_attr)))
 #define side_field_float_binary64_be(_name, _attr)     _side_field(_name, side_type_float_binary64_be(SIDE_PARAM(_attr)))
 #define side_field_float_binary128_be(_name, _attr)    _side_field(_name, side_type_float_binary128_be(SIDE_PARAM(_attr)))
+#define side_field_string16_be(_name, _attr)           _side_field(_name, side_type_string16_be(SIDE_PARAM(_attr)))
+#define side_field_string32_be(_name, _attr)           _side_field(_name, side_type_string32_be(SIDE_PARAM(_attr)))
 
 #define side_type_enum(_mappings, _elem_type) \
        { \
@@ -1150,7 +1173,7 @@ struct side_event_description {
 #define side_field_gather_float_be(_name, _offset, _float_size, _access_mode, _attr) \
        _side_field(_name, side_type_gather_float_be(_offset, _float_size, _access_mode, _attr))
 
-#define side_type_gather_string(_offset, _access_mode, _attr) \
+#define _side_type_gather_string(_offset, _byte_order, _unit_size, _access_mode, _attr) \
        { \
                .type = SIDE_TYPE_GATHER_STRING, \
                .u = { \
@@ -1162,15 +1185,47 @@ struct side_event_description {
                                                .type = { \
                                                        .attr = _attr, \
                                                        .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
+                                                       .unit_size = _unit_size, \
+                                                       .byte_order = _byte_order, \
                                                }, \
                                        }, \
                                }, \
                        }, \
                }, \
        }
+#define side_type_gather_string(_offset, _access_mode, _attr) \
+       _side_type_gather_string(_offset, SIDE_TYPE_BYTE_ORDER_HOST, sizeof(uint8_t), _access_mode, SIDE_PARAM(_attr))
 #define side_field_gather_string(_name, _offset, _access_mode, _attr) \
        _side_field(_name, side_type_gather_string(_offset, _access_mode, SIDE_PARAM(_attr)))
 
+#define side_type_gather_string16(_offset, _access_mode, _attr) \
+       _side_type_gather_string(_offset, SIDE_TYPE_BYTE_ORDER_HOST, sizeof(uint16_t), _access_mode, SIDE_PARAM(_attr))
+#define side_type_gather_string16_le(_offset, _access_mode, _attr) \
+       _side_type_gather_string(_offset, SIDE_TYPE_BYTE_ORDER_LE, sizeof(uint16_t), _access_mode, SIDE_PARAM(_attr))
+#define side_type_gather_string16_be(_offset, _access_mode, _attr) \
+       _side_type_gather_string(_offset, SIDE_TYPE_BYTE_ORDER_BE, sizeof(uint16_t), _access_mode, SIDE_PARAM(_attr))
+
+#define side_field_gather_string16(_name, _offset, _access_mode, _attr) \
+       _side_field(_name, side_type_gather_string16(_offset, _access_mode, SIDE_PARAM(_attr)))
+#define side_field_gather_string16_le(_name, _offset, _access_mode, _attr) \
+       _side_field(_name, side_type_gather_string16_le(_offset, _access_mode, SIDE_PARAM(_attr)))
+#define side_field_gather_string16_be(_name, _offset, _access_mode, _attr) \
+       _side_field(_name, side_type_gather_string16_be(_offset, _access_mode, SIDE_PARAM(_attr)))
+
+#define side_type_gather_string32(_offset, _access_mode, _attr) \
+       _side_type_gather_string(_offset, SIDE_TYPE_BYTE_ORDER_HOST, sizeof(uint32_t), _access_mode, SIDE_PARAM(_attr))
+#define side_type_gather_string32_le(_offset, _access_mode, _attr) \
+       _side_type_gather_string(_offset, SIDE_TYPE_BYTE_ORDER_LE, sizeof(uint32_t), _access_mode, SIDE_PARAM(_attr))
+#define side_type_gather_string32_be(_offset, _access_mode, _attr) \
+       _side_type_gather_string(_offset, SIDE_TYPE_BYTE_ORDER_BE, sizeof(uint32_t), _access_mode, SIDE_PARAM(_attr))
+
+#define side_field_gather_string32(_name, _offset, _access_mode, _attr) \
+       _side_field(_name, side_type_gather_string32(_offset, _access_mode, SIDE_PARAM(_attr)))
+#define side_field_gather_string32_le(_name, _offset, _access_mode, _attr) \
+       _side_field(_name, side_type_gather_string32_le(_offset, _access_mode, SIDE_PARAM(_attr)))
+#define side_field_gather_string32_be(_name, _offset, _access_mode, _attr) \
+       _side_field(_name, side_type_gather_string32_be(_offset, _access_mode, SIDE_PARAM(_attr)))
+
 #define side_type_gather_enum(_mappings, _elem_type) \
        { \
                .type = SIDE_TYPE_GATHER_ENUM, \
@@ -1263,7 +1318,9 @@ struct side_event_description {
 #define side_arg_null(_val)            { .type = SIDE_TYPE_NULL }
 #define side_arg_bool(_val)            { .type = SIDE_TYPE_BOOL, .u = { .side_static = { .bool_value = { .side_bool8 = !!(_val) } } } }
 #define side_arg_byte(_val)            { .type = SIDE_TYPE_BYTE, .u = { .side_static = { .byte_value = (_val) } } }
-#define side_arg_string(_val)          { .type = SIDE_TYPE_STRING, .u = { .side_static = { .string_value = (uintptr_t) (_val) } } }
+#define side_arg_string(_val)          { .type = SIDE_TYPE_STRING_UTF8, .u = { .side_static = { .string_value = (uintptr_t) (_val) } } }
+#define side_arg_string16(_val)                { .type = SIDE_TYPE_STRING_UTF16, .u = { .side_static = { .string_value = (uintptr_t) (_val) } } }
+#define side_arg_string32(_val)                { .type = SIDE_TYPE_STRING_UTF32, .u = { .side_static = { .string_value = (uintptr_t) (_val) } } }
 
 #define side_arg_u8(_val)              { .type = SIDE_TYPE_U8, .u = { .side_static = {  .integer_value = { .side_u8 = (_val) } } } }
 #define side_arg_u16(_val)             { .type = SIDE_TYPE_U16, .u = { .side_static = { .integer_value = { .side_u16 = (_val) } } } }
@@ -1347,7 +1404,7 @@ struct side_event_description {
                        }, \
                }, \
        }
-#define side_arg_dynamic_string(_val, _attr) \
+#define _side_arg_dynamic_string(_val, _byte_order, _unit_size, _attr) \
        { \
                .type = SIDE_TYPE_DYNAMIC_STRING, \
                .u = { \
@@ -1356,12 +1413,28 @@ struct side_event_description {
                                        .type = { \
                                                .attr = _attr, \
                                                .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
+                                               .unit_size = _unit_size, \
+                                               .byte_order = _byte_order, \
                                        }, \
                                        .value = (uintptr_t) (_val), \
                                }, \
                        }, \
                }, \
        }
+#define side_arg_dynamic_string(_val, _attr) \
+       _side_arg_dynamic_string(_val, SIDE_TYPE_BYTE_ORDER_HOST, sizeof(uint8_t), SIDE_PARAM(_attr))
+#define side_arg_dynamic_string16(_val, _attr) \
+       _side_arg_dynamic_string(_val, SIDE_TYPE_BYTE_ORDER_HOST, sizeof(uint16_t), SIDE_PARAM(_attr))
+#define side_arg_dynamic_string16_le(_val, _attr) \
+       _side_arg_dynamic_string(_val, SIDE_TYPE_BYTE_ORDER_LE, sizeof(uint16_t), SIDE_PARAM(_attr))
+#define side_arg_dynamic_string16_be(_val, _attr) \
+       _side_arg_dynamic_string(_val, SIDE_TYPE_BYTE_ORDER_BE, sizeof(uint16_t), SIDE_PARAM(_attr))
+#define side_arg_dynamic_string32(_val, _attr) \
+       _side_arg_dynamic_string(_val, SIDE_TYPE_BYTE_ORDER_HOST, sizeof(uint32_t), SIDE_PARAM(_attr))
+#define side_arg_dynamic_string32_le(_val, _attr) \
+       _side_arg_dynamic_string(_val, SIDE_TYPE_BYTE_ORDER_LE, sizeof(uint32_t), SIDE_PARAM(_attr))
+#define side_arg_dynamic_string32_be(_val, _attr) \
+       _side_arg_dynamic_string(_val, SIDE_TYPE_BYTE_ORDER_BE, sizeof(uint32_t), SIDE_PARAM(_attr))
 
 #define _side_arg_dynamic_integer(_field, _val, _type, _signedness, _byte_order, _integer_size, _len_bits, _attr) \
        { \
index 77b5961aabbc51f6bec6f65af9138491055b0a90..dc7016275118b4fb4749c21f02d39bb54e756fa4 100644 (file)
@@ -2156,6 +2156,60 @@ void test_gather_string(void)
        }
 }
 
+side_static_event(my_provider_event_str_utf, "myprovider", "myevent_str_utf", SIDE_LOGLEVEL_DEBUG,
+       side_field_list(
+               side_field_string("utf8", side_attr_list()),
+               side_field_string32("utf32", side_attr_list()),
+               side_field_string16("utf16", side_attr_list()),
+               side_field_string32_le("utf32_le", side_attr_list()),
+               side_field_string16_le("utf16_le", side_attr_list()),
+               side_field_string32_be("utf32_be", side_attr_list()),
+               side_field_string16_be("utf16_be", side_attr_list()),
+               side_field_dynamic("dynamic_utf32"),
+               side_field_gather_string32("gather_utf32", 0, SIDE_TYPE_GATHER_ACCESS_DIRECT, side_attr_list()),
+       ),
+       side_attr_list()
+);
+
+static
+void test_string_utf(void)
+{
+       /*
+        * Character '®' is:
+        * UTF-8: \c2 \ae
+        * UTF-16: U+00ae
+        * UTF-32: U+000000ae
+        */
+       uint8_t str8[] = { 0xc2, 0xae, 'a', 'b', 'c', 0 };
+       uint32_t str32[] = { 0x000000ae, 'a', 'b', 'c', 0 };
+       uint16_t str16[] = { 0x00ae, 'a', 'b', 'c', 0 };
+#if SIDE_BYTE_ORDER == SIDE_LITTLE_ENDIAN
+       uint32_t str32_le[] = { 0x000000ae, 'a', 'b', 'c', 0 };
+       uint16_t str16_le[] = { 0x00ae, 'a', 'b', 'c', 0 };
+       uint32_t str32_be[] = { side_bswap_32(0x000000ae), side_bswap_32('a'), side_bswap_32('b'), side_bswap_32('c'), 0 };
+       uint16_t str16_be[] = { side_bswap_16(0x00ae), side_bswap_16('a'), side_bswap_16('b'), side_bswap_16('c'), 0 };
+#else
+       uint32_t str32_le[] = { side_bswap_32(0x000000ae), side_bswap_32('a'), side_bswap_32('b'), side_bswap_32('c'), 0 };
+       uint16_t str16_le[] = { side_bswap_16(0x00ae), side_bswap_16('a'), side_bswap_16('b'), side_bswap_16('c'), 0 };
+       uint32_t str32_be[] = { 0x000000ae, 'a', 'b', 'c', 0 };
+       uint16_t str16_be[] = { 0x00ae, 'a', 'b', 'c', 0 };
+#endif
+
+       side_event(my_provider_event_str_utf,
+               side_arg_list(
+                       side_arg_string(str8),
+                       side_arg_string32(str32),
+                       side_arg_string16(str16),
+                       side_arg_string32(str32_le),
+                       side_arg_string16(str16_le),
+                       side_arg_string32(str32_be),
+                       side_arg_string16(str16_be),
+                       side_arg_dynamic_string32(str32, side_attr_list()),
+                       side_arg_gather_string(str32),
+               )
+       );
+}
+
 int main()
 {
        test_fields();
@@ -2206,5 +2260,6 @@ int main()
        test_gather_pointer();
        test_gather_enum();
        test_gather_string();
+       test_string_utf();
        return 0;
 }
index 9a4d39a98d460424c31949ae6d210621c748d1a1..f8482cdd6af9fed66703b3849578b74c35cf4453 100644 (file)
@@ -9,6 +9,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <string.h>
+#include <iconv.h>
 
 #include <side/trace.h>
 
@@ -59,6 +60,113 @@ uint32_t tracer_print_gather_vla(const struct side_type_gather *type_gather, con
 static
 void tracer_print_type(const struct side_type *type_desc, const struct side_arg *item);
 
+static
+void tracer_print_string(const void *p, uint8_t unit_size, enum side_type_label_byte_order byte_order,
+               size_t *strlen_with_null)
+{
+       size_t ret, inbytesleft = 0, outbytesleft, bufsize;
+       const char *str = p, *fromcode;
+       char *inbuf = (char *) p, *outbuf, *buf;
+       iconv_t cd;
+
+       switch (unit_size) {
+       case 1:
+               printf("\"%s\"", str);
+               if (strlen_with_null)
+                       *strlen_with_null = strlen(str) + 1;
+               return;
+       case 2:
+       {
+               const uint16_t *p16 = p;
+
+               switch (byte_order) {
+               case SIDE_TYPE_BYTE_ORDER_LE:
+               {
+                       fromcode = "UTF-16LE";
+                       break;
+               }
+               case SIDE_TYPE_BYTE_ORDER_BE:
+               {
+                       fromcode = "UTF-16BE";
+                       break;
+               }
+               default:
+                       fprintf(stderr, "Unknown byte order\n");
+                       abort();
+               }
+               for (; *p16; p16++)
+                       inbytesleft += 2;
+               /*
+                * Worse case is U+FFFF UTF-16 (2 bytes) converting to
+                * { ef, bf, bf } UTF-8 (3 bytes).
+                */
+               bufsize = inbytesleft / 2 * 3 + 1;
+               break;
+       }
+       case 4:
+       {
+               const uint32_t *p32 = p;
+
+               switch (byte_order) {
+               case SIDE_TYPE_BYTE_ORDER_LE:
+               {
+                       fromcode = "UTF-32LE";
+                       break;
+               }
+               case SIDE_TYPE_BYTE_ORDER_BE:
+               {
+                       fromcode = "UTF-32BE";
+                       break;
+               }
+               default:
+                       fprintf(stderr, "Unknown byte order\n");
+                       abort();
+               }
+               for (; *p32; p32++)
+                       inbytesleft += 4;
+               /*
+                * Each 4-byte UTF-32 character converts to at most a
+                * 4-byte UTF-8 character.
+                */
+               bufsize = inbytesleft + 1;
+               break;
+       }
+       default:
+               fprintf(stderr, "Unknown string unit size %" PRIu8 "\n", unit_size);
+               abort();
+       }
+
+       cd = iconv_open("UTF8", fromcode);
+       if (cd == (iconv_t) -1) {
+               perror("iconv_open");
+               abort();
+       }
+       buf = malloc(bufsize);
+       if (!buf) {
+               abort();
+       }
+       outbuf = (char *) buf;
+       outbytesleft = bufsize;
+       ret = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
+       if (ret == (size_t) -1) {
+               perror("iconv");
+               abort();
+       }
+       if (inbytesleft) {
+               fprintf(stderr, "Buffer too small to convert string input\n");
+               abort();
+       }
+       (*outbuf++) = '\0';
+       if (strlen_with_null)
+               *strlen_with_null = outbuf - buf;
+       printf("\"%s\"", buf);
+       free(buf);
+       if (iconv_close(cd) == -1) {
+               perror("iconv_close");
+               abort();
+       }
+}
+
 static
 int64_t get_attr_integer_value(const struct side_attr *attr)
 {
@@ -190,8 +298,17 @@ void tracer_print_attr_type(const char *separator, const struct side_attr *attr)
                fprintf(stderr, "ERROR: Unsupported binary128 float type\n");
                abort();
 #endif
-       case SIDE_ATTR_TYPE_STRING:
-               printf("\"%s\"", (const char *)(uintptr_t) attr->value.u.string_value);
+       case SIDE_ATTR_TYPE_STRING_UTF8:
+               tracer_print_string((const void *)(uintptr_t) attr->value.u.string_value,
+                               1, SIDE_TYPE_BYTE_ORDER_HOST, NULL);
+               break;
+       case SIDE_ATTR_TYPE_STRING_UTF16:
+               tracer_print_string((const void *)(uintptr_t) attr->value.u.string_value,
+                               2, SIDE_TYPE_BYTE_ORDER_HOST, NULL);
+               break;
+       case SIDE_ATTR_TYPE_STRING_UTF32:
+               tracer_print_string((const void *)(uintptr_t) attr->value.u.string_value,
+                               4, SIDE_TYPE_BYTE_ORDER_HOST, NULL);
                break;
        default:
                fprintf(stderr, "ERROR: <UNKNOWN ATTRIBUTE TYPE>");
@@ -804,9 +921,12 @@ void tracer_print_type(const struct side_type *type_desc, const struct side_arg
                tracer_print_type_float(":", &type_desc->u.side_float, &item->u.side_static.float_value);
                break;
 
-       case SIDE_TYPE_STRING:
+       case SIDE_TYPE_STRING_UTF8:
+       case SIDE_TYPE_STRING_UTF16:
+       case SIDE_TYPE_STRING_UTF32:
                tracer_print_type_header(":", type_desc->u.side_string.attr, type_desc->u.side_string.nr_attr);
-               printf("\"%s\"", (const char *)(uintptr_t) item->u.side_static.string_value);
+               tracer_print_string((const void *)(uintptr_t) item->u.side_static.string_value,
+                               type_desc->u.side_string.unit_size, type_desc->u.side_string.byte_order, NULL);
                break;
 
                /* Stack-copy compound types */
@@ -1105,11 +1225,11 @@ uint32_t tracer_print_gather_string_type(const struct side_type_gather *type_gat
        tracer_print_type_header(":", type_gather->u.side_string.type.attr,
                        type_gather->u.side_string.type.nr_attr);
        if (ptr) {
-               printf("\"%s\"", ptr);
-               string_len = strlen(ptr) + 1;
+               tracer_print_string(ptr, type_gather->u.side_string.type.unit_size,
+                               type_gather->u.side_string.type.byte_order, &string_len);
        } else {
                printf("<NULL>");
-               string_len = 1;
+               string_len = type_gather->u.side_string.type.unit_size;
        }
        return tracer_gather_size(access_mode, string_len);
 }
@@ -1498,7 +1618,9 @@ void tracer_print_dynamic(const struct side_arg *item)
                break;
        case SIDE_TYPE_DYNAMIC_STRING:
                tracer_print_type_header("::", item->u.side_dynamic.side_string.type.attr, item->u.side_dynamic.side_string.type.nr_attr);
-               printf("\"%s\"", (const char *)(uintptr_t) item->u.side_dynamic.side_string.value);
+               tracer_print_string((const char *)(uintptr_t) item->u.side_dynamic.side_string.value,
+                               item->u.side_dynamic.side_string.type.unit_size,
+                               item->u.side_dynamic.side_string.type.byte_order, NULL);
                break;
 
                /* Dynamic compound types */
This page took 0.030982 seconds and 4 git commands to generate.