From 616d1f0f81b6c340f77250b6b3f5f24fb7c278ef Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 14 Nov 2024 15:25:05 +0100 Subject: [PATCH] Initial wchar support Signed-off-by: Erik Boasson --- examples/dynsub/print_sample.c | 1 + examples/dynsub/type_cache.c | 2 +- examples/dynsub/variouspub.c | 6 +- examples/dynsub/variouspub_types.idl | 1 + src/core/cdr/src/dds_cdrstream.c | 177 ++++++++++++++---- src/core/cdr/src/dds_cdrstream_keys.part.h | 4 + src/core/cdr/src/dds_cdrstream_write.part.h | 39 +++- .../dds/ddsc/dds_data_type_properties.h | 1 + src/core/ddsc/include/dds/ddsc/dds_opcodes.h | 15 +- src/core/ddsc/src/dds_dynamic_type.c | 2 +- src/core/ddsc/tests/dynamic_type.c | 2 +- src/core/ddsi/src/ddsi_typebuilder.c | 23 ++- src/idl/src/descriptor_type_meta.c | 1 + src/idl/src/print.c | 2 + .../idlc/src/libidlc/libidlc__descriptor.c | 7 + 15 files changed, 226 insertions(+), 57 deletions(-) diff --git a/examples/dynsub/print_sample.c b/examples/dynsub/print_sample.c index e9bfcb0f10..f2a32334dc 100644 --- a/examples/dynsub/print_sample.c +++ b/examples/dynsub/print_sample.c @@ -58,6 +58,7 @@ static bool print_sample1_simple (const unsigned char *sample, const uint8_t dis } case CASEI(BOOLEAN, uint8_t, printf ("%s", *p ? "true" : "false")); case CASEI(CHAR8, int8_t, printf ("\"%c\"", (char) *p)); + case CASEI(CHAR16, wchar_t, printf ("\"%lc\"", (wchar_t) *p)); case CASEI(INT16, int16_t, printf ("%"PRId16, *p)); case CASEI(INT32, int32_t, printf ("%"PRId32, *p)); case CASEI(INT64, int64_t, printf ("%"PRId64, *p)); diff --git a/examples/dynsub/type_cache.c b/examples/dynsub/type_cache.c index 2aec098cfd..ccf20adff6 100644 --- a/examples/dynsub/type_cache.c +++ b/examples/dynsub/type_cache.c @@ -163,7 +163,7 @@ static bool build_typecache_simple (const uint8_t disc, size_t *align, size_t *s case CASE(INT8, int8_t); case CASE(UINT8, uint8_t); case CASE(CHAR8, int8_t); - case CASE(CHAR16, uint16_t); + case CASE(CHAR16, wchar_t); case CASE(STRING8, unsigned char *); case CASE(STRING16, wchar_t *); #undef CASE diff --git a/examples/dynsub/variouspub.c b/examples/dynsub/variouspub.c index c0faeffe2b..c51111fcc8 100644 --- a/examples/dynsub/variouspub.c +++ b/examples/dynsub/variouspub.c @@ -93,9 +93,9 @@ static void *samples_M1_O[] = { }; static void *samples_d[] = { - &(D){ L"😀 Een Kruyck gaat soo langh te water tot datse barst.", 0 }, - &(D){ L"🙃 Men treckt een Boogh soo lang tot datse stucken knarst.", 0 }, - &(D){ L"😊 De Steel-kunst doet zyn Meester de dood vaak verwerven.", 0 }, + &(D){ L"😀 Een Kruyck gaat soo langh te water tot datse barst.", L'∆', 0 }, + &(D){ L"🙃 Men treckt een Boogh soo lang tot datse stucken knarst.", L'∇', 0 }, + &(D){ L"😊 De Steel-kunst doet zyn Meester de dood vaak verwerven.", L'⊥', 0 }, NULL }; diff --git a/examples/dynsub/variouspub_types.idl b/examples/dynsub/variouspub_types.idl index 12c3a2e033..085cdb52ff 100644 --- a/examples/dynsub/variouspub_types.idl +++ b/examples/dynsub/variouspub_types.idl @@ -30,5 +30,6 @@ module M1 { struct D { wstring ws; + wchar wc; unsigned long count; }; diff --git a/src/core/cdr/src/dds_cdrstream.c b/src/core/cdr/src/dds_cdrstream.c index 49272dde6c..6674cbe9c1 100644 --- a/src/core/cdr/src/dds_cdrstream.c +++ b/src/core/cdr/src/dds_cdrstream.c @@ -69,6 +69,7 @@ #define dds_ostreamBO_fini NAME2_BYTE_ORDER(dds_ostream, _fini) #define dds_stream_write_stringBO NAME_BYTE_ORDER(dds_stream_write_string) #define dds_stream_write_wstringBO NAME_BYTE_ORDER(dds_stream_write_wstring) +#define dds_stream_write_wcharBO NAME_BYTE_ORDER(dds_stream_write_wchar) #define dds_stream_write_seqBO NAME_BYTE_ORDER(dds_stream_write_seq) #define dds_stream_write_arrBO NAME_BYTE_ORDER(dds_stream_write_arr) #define dds_stream_write_bool_valueBO NAME_BYTE_ORDER(dds_stream_write_bool_value) @@ -454,7 +455,7 @@ static void dds_os_put_bytes_aligned (dds_ostream_t * __restrict os, const struc static inline bool is_primitive_type (enum dds_stream_typecode type) { - return type <= DDS_OP_VAL_8BY || type == DDS_OP_VAL_BLN; + return type <= DDS_OP_VAL_8BY || type == DDS_OP_VAL_BLN || type == DDS_OP_VAL_WCHAR; } #ifndef NDEBUG @@ -473,7 +474,14 @@ static uint32_t get_primitive_size (enum dds_stream_typecode type) { DDSRT_STATIC_ASSERT (DDS_OP_VAL_1BY == 1 && DDS_OP_VAL_2BY == 2 && DDS_OP_VAL_4BY == 3 && DDS_OP_VAL_8BY == 4); assert (is_primitive_type (type)); - return type == DDS_OP_VAL_BLN ? 1 : (uint32_t)1 << ((uint32_t) type - 1); + if (type <= DDS_OP_VAL_8BY) + return (uint32_t)1 << ((uint32_t) type - 1); + else if (type == DDS_OP_VAL_BLN) + return 1; + else if (type == DDS_OP_VAL_WCHAR) + return 2; + else + abort (); } static uint32_t get_collection_elem_size (uint32_t insn, const uint32_t * __restrict ops) @@ -490,6 +498,8 @@ static uint32_t get_collection_elem_size (uint32_t insn, const uint32_t * __rest return sizeof (char *); case DDS_OP_VAL_WSTR: return sizeof (wchar_t *); + case DDS_OP_VAL_WCHAR: + return sizeof (wchar_t); case DDS_OP_VAL_BST: case DDS_OP_VAL_BWSTR: case DDS_OP_VAL_SEQ: case DDS_OP_VAL_BSQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: if (DDS_OP_TYPE (insn) == DDS_OP_VAL_ARR) @@ -522,6 +532,9 @@ static uint32_t get_adr_type_size (uint32_t insn, const uint32_t * __restrict op case DDS_OP_VAL_WSTR: sz = sizeof (wchar_t *); break; + case DDS_OP_VAL_WCHAR: + sz = sizeof (wchar_t); + break; case DDS_OP_VAL_BST: case DDS_OP_VAL_BWSTR: sz = ops[2]; break; @@ -567,6 +580,9 @@ static uint32_t get_jeq4_type_size (const enum dds_stream_typecode valtype, cons case DDS_OP_VAL_WSTR: sz = sizeof (wchar_t *); break; + case DDS_OP_VAL_WCHAR: + sz = sizeof (wchar_t); + break; case DDS_OP_VAL_BMK: case DDS_OP_VAL_BST: case DDS_OP_VAL_BWSTR: case DDS_OP_VAL_ARR: { @@ -703,6 +719,7 @@ static uint32_t dds_stream_check_optimize1 (const struct dds_cdrstream_desc * __ case DDS_OP_VAL_BST: case DDS_OP_VAL_WSTR: case DDS_OP_VAL_BWSTR: + case DDS_OP_VAL_WCHAR: case DDS_OP_VAL_STU: case DDS_OP_VAL_UNI: return 0; @@ -747,6 +764,10 @@ static const uint32_t *dds_stream_get_ops_info_seq (const uint32_t * __restrict ops += 3 + bound_op; info->data_types |= DDS_DATA_TYPE_CONTAINS_BWSTRING; break; + case DDS_OP_VAL_WCHAR: + ops += 2 + bound_op; + info->data_types |= DDS_DATA_TYPE_CONTAINS_WCHAR; + break; case DDS_OP_VAL_ENU: ops += 3 + bound_op; info->data_types |= DDS_DATA_TYPE_CONTAINS_ENUM; @@ -790,6 +811,10 @@ static const uint32_t *dds_stream_get_ops_info_arr (const uint32_t * __restrict ops += 3; info->data_types |= DDS_DATA_TYPE_CONTAINS_WSTRING; break; + case DDS_OP_VAL_WCHAR: + ops += 3; + info->data_types |= DDS_DATA_TYPE_CONTAINS_WCHAR; + break; case DDS_OP_VAL_ENU: ops += 4; info->data_types |= DDS_DATA_TYPE_CONTAINS_ENUM; @@ -848,6 +873,9 @@ static const uint32_t *dds_stream_get_ops_info_uni (const uint32_t * __restrict case DDS_OP_VAL_WSTR: info->data_types |= DDS_DATA_TYPE_CONTAINS_WSTRING; break; + case DDS_OP_VAL_WCHAR: + info->data_types |= DDS_DATA_TYPE_CONTAINS_WCHAR; + break; case DDS_OP_VAL_ENU: info->data_types |= DDS_DATA_TYPE_CONTAINS_ENUM; break; @@ -940,6 +968,10 @@ static void dds_stream_get_ops_info1 (const uint32_t * __restrict ops, uint32_t ops += 2; info->data_types |= DDS_DATA_TYPE_CONTAINS_WSTRING; break; + case DDS_OP_VAL_WCHAR: + ops += 2; + info->data_types |= DDS_DATA_TYPE_CONTAINS_WCHAR; + break; case DDS_OP_VAL_BST: ops += 3; info->data_types |= DDS_DATA_TYPE_CONTAINS_BSTRING; @@ -1258,7 +1290,7 @@ static const uint32_t *skip_sequence_insns (uint32_t insn, const uint32_t * __re switch (DDS_OP_SUBTYPE (insn)) { case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: - case DDS_OP_VAL_STR: case DDS_OP_VAL_WSTR: + case DDS_OP_VAL_STR: case DDS_OP_VAL_WSTR: case DDS_OP_VAL_WCHAR: return ops + 2 + bound_op; case DDS_OP_VAL_BST: case DDS_OP_VAL_BWSTR: case DDS_OP_VAL_ENU: return ops + 3 + bound_op; @@ -1282,7 +1314,7 @@ static const uint32_t *skip_array_insns (uint32_t insn, const uint32_t * __restr switch (DDS_OP_SUBTYPE (insn)) { case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: - case DDS_OP_VAL_STR: case DDS_OP_VAL_WSTR: + case DDS_OP_VAL_STR: case DDS_OP_VAL_WSTR: case DDS_OP_VAL_WCHAR: return ops + 3; case DDS_OP_VAL_ENU: return ops + 4; @@ -1306,7 +1338,7 @@ static const uint32_t *skip_array_default (uint32_t insn, char * __restrict data const uint32_t num = ops[2]; switch (subtype) { - case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: { + case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: case DDS_OP_VAL_WCHAR: { const uint32_t elem_size = get_primitive_size (subtype); memset (data, 0, num * elem_size); return ops + 3; @@ -1415,6 +1447,7 @@ static const uint32_t * skip_union_default (uint32_t insn, char * __restrict dis case DDS_OP_VAL_8BY: *((uint64_t *) valaddr) = 0; break; case DDS_OP_VAL_STR: *(char **) valaddr = dds_stream_reuse_string_empty (*((char **) valaddr), allocator, sample_state); break; case DDS_OP_VAL_WSTR: *(wchar_t **) valaddr = dds_stream_reuse_wstring_empty (*((wchar_t **) valaddr), allocator, sample_state); break; + case DDS_OP_VAL_WCHAR: *((wchar_t *) valaddr) = L'\0'; break; case DDS_OP_VAL_BST: case DDS_OP_VAL_BWSTR: case DDS_OP_VAL_SEQ: case DDS_OP_VAL_BSQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: case DDS_OP_VAL_BMK: (void) dds_stream_skip_default (valaddr, allocator, jeq_op + DDS_OP_ADR_JSR (jeq_op[0]), sample_state); break; @@ -1437,7 +1470,7 @@ static uint32_t get_length_code_seq (const enum dds_stream_typecode subtype) /* A sequence with primitive subtype does not include a DHEADER, only the seq length, so we have to include a NEXTINT */ - case DDS_OP_VAL_2BY: + case DDS_OP_VAL_2BY: case DDS_OP_VAL_WCHAR: return LENGTH_CODE_NEXTINT; /* Sequence length (item count) is used to calculate byte length */ @@ -1466,7 +1499,7 @@ static uint32_t get_length_code_arr (const enum dds_stream_typecode subtype) { /* An array with primitive subtype does not include a DHEADER, so we have to include a NEXTINT */ - case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: + case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: case DDS_OP_VAL_WCHAR: return LENGTH_CODE_NEXTINT; /* Arrays with non-primitive subtype contain a DHEADER */ @@ -1493,7 +1526,7 @@ static uint32_t get_length_code (const uint32_t * __restrict ops) switch (DDS_OP_TYPE (insn)) { case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: return LENGTH_CODE_1B; - case DDS_OP_VAL_2BY: return LENGTH_CODE_2B; + case DDS_OP_VAL_2BY: case DDS_OP_VAL_WCHAR: return LENGTH_CODE_2B; case DDS_OP_VAL_4BY: return LENGTH_CODE_4B; case DDS_OP_VAL_8BY: return LENGTH_CODE_8B; case DDS_OP_VAL_ENU: case DDS_OP_VAL_BMK: @@ -1767,7 +1800,7 @@ static const uint32_t *dds_stream_getsize_seq (struct getsize_state * __restrict getsize_reserve_many (st, 1, num); ops += 2 + bound_op; break; - case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: + case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: case DDS_OP_VAL_WCHAR: getsize_reserve_many (st, get_primitive_size (subtype), num); ops += 2 + bound_op; break; @@ -1845,7 +1878,7 @@ static const uint32_t *dds_stream_getsize_arr (struct getsize_state * __restrict getsize_reserve_many (st, 1, num); ops += 3; break; - case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: + case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: case DDS_OP_VAL_WCHAR: getsize_reserve_many (st, get_primitive_size (subtype), num); ops += 3; break; @@ -1963,8 +1996,9 @@ static const uint32_t *dds_stream_getsize_uni (struct getsize_state * __restrict switch (valtype) { - case DDS_OP_VAL_BLN: getsize_reserve (st, 1); break; + case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: getsize_reserve (st, 1); break; + case DDS_OP_VAL_WCHAR: case DDS_OP_VAL_2BY: getsize_reserve (st, 2); break; case DDS_OP_VAL_4BY: getsize_reserve (st, 4); break; case DDS_OP_VAL_8BY: getsize_reserve (st, 8); break; @@ -2010,8 +2044,9 @@ static const uint32_t *dds_stream_getsize_adr (uint32_t insn, struct getsize_sta switch (DDS_OP_TYPE (insn)) { - case DDS_OP_VAL_BLN: getsize_reserve (st, 1); ops += 2; break; + case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: getsize_reserve (st, 1); ops += 2; break; + case DDS_OP_VAL_WCHAR: case DDS_OP_VAL_2BY: getsize_reserve (st, 2); ops += 2; break; case DDS_OP_VAL_4BY: getsize_reserve (st, 4); ops += 2; break; case DDS_OP_VAL_8BY: getsize_reserve (st, 8); ops += 2; break; @@ -2180,6 +2215,7 @@ static void dds_stream_getsize_key_impl (struct getsize_state * __restrict st, c { case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: getsize_reserve (st, 1); break; + case DDS_OP_VAL_WCHAR: case DDS_OP_VAL_2BY: getsize_reserve (st, 2); break; case DDS_OP_VAL_4BY: getsize_reserve (st, 4); break; case DDS_OP_VAL_8BY: getsize_reserve (st, 8); break; @@ -2395,6 +2431,15 @@ static const uint32_t *dds_stream_read_seq (dds_istream_t * __restrict is, char dds_stream_skip_forward (is, num - seq->_length, elem_size); return ops + 2 + bound_op; } + case DDS_OP_VAL_WCHAR: { + adjust_sequence_buffer (seq, allocator, num, sizeof (wchar_t), &sample_state); + seq->_length = (num <= seq->_maximum) ? num : seq->_maximum; + for (uint32_t i = 0; i < seq->_length; i++) + ((wchar_t *) seq->_buffer)[i] = (wchar_t) dds_is_get2 (is); + if (seq->_length < num) + dds_stream_skip_forward (is, num - seq->_length, 2); + return ops + 2 + bound_op; + } case DDS_OP_VAL_ENU: { const uint32_t elem_size = DDS_OP_TYPE_SZ (insn); adjust_sequence_buffer (seq, allocator, num, 4, &sample_state); @@ -2505,6 +2550,11 @@ static const uint32_t *dds_stream_read_arr (dds_istream_t * __restrict is, char dds_is_get_bytes (is, addr, num, elem_size); return ops + 3; } + case DDS_OP_VAL_WCHAR: { + for (uint32_t i = 0; i < num; i++) + ((wchar_t *) addr)[i] = (wchar_t) dds_is_get2 (is); + return ops + 3; + } case DDS_OP_VAL_ENU: { switch (DDS_OP_TYPE_SZ (insn)) { @@ -2592,6 +2642,7 @@ static const uint32_t *dds_stream_read_uni (dds_istream_t * __restrict is, char case DDS_OP_VAL_2BY: *((uint16_t *) valaddr) = dds_is_get2 (is); break; case DDS_OP_VAL_4BY: *((uint32_t *) valaddr) = dds_is_get4 (is); break; case DDS_OP_VAL_8BY: *((uint64_t *) valaddr) = dds_is_get8 (is); break; + case DDS_OP_VAL_WCHAR: *((wchar_t *) valaddr) = (wchar_t) dds_is_get2 (is); break; case DDS_OP_VAL_ENU: switch (DDS_OP_TYPE_SZ (jeq_op[0])) { @@ -2664,6 +2715,7 @@ static inline const uint32_t *dds_stream_read_adr (uint32_t insn, dds_istream_t case DDS_OP_VAL_2BY: *((uint16_t *) addr) = dds_is_get2 (is); ops += 2; break; case DDS_OP_VAL_4BY: *((uint32_t *) addr) = dds_is_get4 (is); ops += 2; break; case DDS_OP_VAL_8BY: *((uint64_t *) addr) = dds_is_get8 (is); ops += 2; break; + case DDS_OP_VAL_WCHAR: *((wchar_t *) addr) = (wchar_t) dds_is_get2 (is); ops += 2; break; case DDS_OP_VAL_STR: *((char **) addr) = dds_stream_reuse_string (is, *((char **) addr), allocator, sample_state); ops += 2; break; case DDS_OP_VAL_WSTR: *((wchar_t **) addr) = dds_stream_reuse_wstring (is, *((wchar_t **) addr), allocator, sample_state); ops += 2; break; case DDS_OP_VAL_BST: (void) dds_stream_reuse_string_bound (is, (char *) addr, ops[2]); ops += 3; break; @@ -2717,7 +2769,7 @@ static const uint32_t *dds_stream_skip_adr (uint32_t insn, const uint32_t * __re switch (DDS_OP_TYPE (insn)) { case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: - case DDS_OP_VAL_STR: case DDS_OP_VAL_WSTR: + case DDS_OP_VAL_STR: case DDS_OP_VAL_WSTR: case DDS_OP_VAL_WCHAR: return ops + 2; case DDS_OP_VAL_BST: case DDS_OP_VAL_BWSTR: @@ -2764,6 +2816,7 @@ static const uint32_t *dds_stream_skip_adr_default (uint32_t insn, char * __rest case DDS_OP_VAL_2BY: *(uint16_t *) addr = 0; return ops + 2; case DDS_OP_VAL_4BY: *(uint32_t *) addr = 0; return ops + 2; case DDS_OP_VAL_8BY: *(uint64_t *) addr = 0; return ops + 2; + case DDS_OP_VAL_WCHAR: *(wchar_t *) addr = L'\0'; return ops + 2; case DDS_OP_VAL_STR: *(char **) addr = dds_stream_reuse_string_empty (*(char **) addr, allocator, sample_state); return ops + 2; case DDS_OP_VAL_WSTR: *(wchar_t **) addr = dds_stream_reuse_wstring_empty (*(wchar_t **) addr, allocator, sample_state); return ops + 2; case DDS_OP_VAL_BST: ((char *) addr)[0] = '\0'; return ops + 3; @@ -3323,6 +3376,21 @@ static bool normalize_string (char * __restrict data, uint32_t * __restrict off, return true; } +static inline bool normalize_wchar (char * __restrict data, uint32_t * __restrict off, uint32_t size, bool bswap) ddsrt_attribute_warn_unused_result ddsrt_nonnull_all; +static inline bool normalize_wchar (char * __restrict data, uint32_t * __restrict off, uint32_t size, bool bswap) +{ + if ((*off = check_align_prim (*off, size, 1, 1)) == UINT32_MAX) + return false; + if (bswap) + *((uint16_t *) (data + *off)) = ddsrt_bswap2u (*((uint16_t *) (data + *off))); + const uint16_t val = *((uint16_t *) (data + *off)); + // surrogates are disallowed + if (val >= 0xd800 && val < 0xe000) + return false; + (*off) += 2; + return true; +} + static bool normalize_wstring (char * __restrict data, uint32_t * __restrict off, uint32_t size, bool bswap, size_t maxsz) ddsrt_attribute_warn_unused_result ddsrt_nonnull_all; static bool normalize_wstring (char * __restrict data, uint32_t * __restrict off, uint32_t size, bool bswap, size_t maxsz) { @@ -3590,6 +3658,13 @@ static const uint32_t *normalize_seq (char * __restrict data, uint32_t * __restr ops += (subtype == DDS_OP_VAL_WSTR ? 2 : 3) + bound_op; break; } + case DDS_OP_VAL_WCHAR: { + for (uint32_t i = 0; i < num; i++) + if (!normalize_wchar (data, off, size1, bswap)) + return NULL; + ops += 2 + bound_op; + break; + } case DDS_OP_VAL_SEQ: case DDS_OP_VAL_BSQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: { const uint32_t jmp = DDS_OP_ADR_JMP (ops[3 + bound_op]); uint32_t const * const jsr_ops = ops + DDS_OP_ADR_JSR (ops[3 + bound_op]); @@ -3656,6 +3731,13 @@ static const uint32_t *normalize_arr (char * __restrict data, uint32_t * __restr ops += (subtype == DDS_OP_VAL_WSTR) ? 3 : 5; break; } + case DDS_OP_VAL_WCHAR: { + for (uint32_t i = 0; i < num; i++) + if (!normalize_wchar (data, off, size1, bswap)) + return NULL; + ops += 3; + break; + } case DDS_OP_VAL_SEQ: case DDS_OP_VAL_BSQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: { const uint32_t jmp = DDS_OP_ADR_JMP (ops[3]); uint32_t const * const jsr_ops = ops + DDS_OP_ADR_JSR (ops[3]); @@ -3735,6 +3817,7 @@ static const uint32_t *normalize_uni (char * __restrict data, uint32_t * __restr case DDS_OP_VAL_2BY: if (!normalize_uint16 (data, off, size, bswap)) return NULL; break; case DDS_OP_VAL_4BY: if (!normalize_uint32 (data, off, size, bswap)) return NULL; break; case DDS_OP_VAL_8BY: if (!normalize_uint64 (data, off, size, bswap, xcdr_version)) return NULL; break; + case DDS_OP_VAL_WCHAR: if (!normalize_wchar (data, off, size, bswap)) return NULL; break; case DDS_OP_VAL_STR: if (!normalize_string (data, off, size, bswap, SIZE_MAX)) return NULL; break; case DDS_OP_VAL_WSTR: if (!normalize_wstring (data, off, size, bswap, SIZE_MAX)) return NULL; break; case DDS_OP_VAL_ENU: if (!normalize_enum (data, off, size, bswap, jeq_op[0], jeq_op[3])) return NULL; break; @@ -3780,6 +3863,7 @@ static const uint32_t *stream_normalize_adr (uint32_t insn, char * __restrict da case DDS_OP_VAL_WSTR: if (!normalize_wstring (data, off, size, bswap, SIZE_MAX)) return NULL; ops += 2; break; case DDS_OP_VAL_BST: if (!normalize_string (data, off, size, bswap, ops[2])) return NULL; ops += 3; break; case DDS_OP_VAL_BWSTR: if (!normalize_wstring (data, off, size, bswap, ops[2])) return NULL; ops += 3; break; + case DDS_OP_VAL_WCHAR: if (!normalize_wchar (data, off, size, bswap)) return NULL; ops += 2; break; case DDS_OP_VAL_SEQ: case DDS_OP_VAL_BSQ: ops = normalize_seq (data, off, size, bswap, xcdr_version, ops, insn, cdr_kind); if (!ops) return NULL; break; case DDS_OP_VAL_ARR: ops = normalize_arr (data, off, size, bswap, xcdr_version, ops, insn, cdr_kind); if (!ops) return NULL; break; case DDS_OP_VAL_UNI: ops = normalize_uni (data, off, size, bswap, xcdr_version, ops, insn, cdr_kind); if (!ops) return NULL; break; @@ -4049,6 +4133,7 @@ static bool stream_normalize_key_impl (void * __restrict data, uint32_t size, ui case DDS_OP_VAL_WSTR: if (!normalize_wstring (data, offs, size, bswap, SIZE_MAX)) return false; break; case DDS_OP_VAL_BST: if (!normalize_string (data, offs, size, bswap, ops[2])) return false; break; case DDS_OP_VAL_BWSTR: if (!normalize_wstring (data, offs, size, bswap, ops[2])) return false; break; + case DDS_OP_VAL_WCHAR: if (!normalize_wchar (data, offs, size, bswap)) return false; break; case DDS_OP_VAL_ARR: if (!normalize_arr (data, offs, size, bswap, xcdr_version, ops, insn, true)) return false; break; case DDS_OP_VAL_EXT: { assert (key_offset_count > 0); @@ -4139,7 +4224,7 @@ static const uint32_t *dds_stream_free_sample_seq (char * __restrict addr, const { switch (subtype) { - case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: + case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: case DDS_OP_VAL_WCHAR: ops += 2 + bound_op; break; case DDS_OP_VAL_BST: case DDS_OP_VAL_BWSTR: case DDS_OP_VAL_ENU: @@ -4201,7 +4286,7 @@ static const uint32_t *dds_stream_free_sample_arr (char * __restrict addr, const uint32_t num = *ops++; switch (subtype) { - case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: break; + case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: case DDS_OP_VAL_WCHAR: break; case DDS_OP_VAL_ENU: ops++; break; case DDS_OP_VAL_BMK: case DDS_OP_VAL_BST: case DDS_OP_VAL_BWSTR: ops += 2; break; case DDS_OP_VAL_STR: { @@ -4264,7 +4349,7 @@ static const uint32_t *dds_stream_free_sample_uni (char * __restrict discaddr, c switch (subtype) { - case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: case DDS_OP_VAL_BST: case DDS_OP_VAL_BWSTR: case DDS_OP_VAL_ENU: break; + case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: case DDS_OP_VAL_BST: case DDS_OP_VAL_BWSTR: case DDS_OP_VAL_ENU: case DDS_OP_VAL_WCHAR: break; case DDS_OP_VAL_STR: allocator->free (*((char **) valaddr)); *((char **) valaddr) = NULL; @@ -4325,7 +4410,7 @@ static const uint32_t *stream_free_sample_adr_nonexternal (uint32_t insn, void * switch (DDS_OP_TYPE (insn)) { - case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: ops += 2; break; + case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: case DDS_OP_VAL_WCHAR: ops += 2; break; case DDS_OP_VAL_STR: { allocator->free (*((char **) addr)); *(char **) addr = NULL; @@ -4427,6 +4512,7 @@ static void dds_stream_extract_key_from_key_prim_op (dds_istream_t * __restrict { case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: dds_os_put1 (os, allocator, dds_is_get1 (is)); break; + case DDS_OP_VAL_WCHAR: case DDS_OP_VAL_2BY: dds_os_put2 (os, allocator, dds_is_get2 (is)); break; case DDS_OP_VAL_4BY: dds_os_put4 (os, allocator, dds_is_get4 (is)); break; case DDS_OP_VAL_8BY: dds_os_put8 (os, allocator, dds_is_get8 (is)); break; @@ -4540,6 +4626,7 @@ static void dds_stream_extract_keyBE_from_key_prim_op (dds_istream_t * __restric { case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: dds_os_put1BE (os, allocator, dds_is_get1 (is)); break; + case DDS_OP_VAL_WCHAR: case DDS_OP_VAL_2BY: dds_os_put2BE (os, allocator, dds_is_get2 (is)); break; case DDS_OP_VAL_4BY: dds_os_put4BE (os, allocator, dds_is_get4 (is)); break; case DDS_OP_VAL_8BY: dds_os_put8BE (os, allocator, dds_is_get8 (is)); break; @@ -4778,6 +4865,7 @@ static void dds_stream_read_key_impl (dds_istream_t * __restrict is, char * __re case DDS_OP_VAL_2BY: *((uint16_t *) dst) = dds_is_get2 (is); break; case DDS_OP_VAL_4BY: *((uint32_t *) dst) = dds_is_get4 (is); break; case DDS_OP_VAL_8BY: *((uint64_t *) dst) = dds_is_get8 (is); break; + case DDS_OP_VAL_WCHAR: *((wchar_t *) dst) = (wchar_t) dds_is_get2 (is); break; case DDS_OP_VAL_ENU: switch (DDS_OP_TYPE_SZ (insn)) { @@ -4974,6 +5062,23 @@ static bool prtf_str (char * __restrict *buf, size_t * __restrict bufsize, dds_i return ret; } +static bool prtf_utf32 (char * __restrict *buf, size_t * __restrict bufsize, uint32_t utf32) +{ + unsigned char utf8[5], lead; + int len; + if (utf32 <= 0x7f) { lead = 0; len = 1; } + else if (utf32 <= 0x7ff) { lead = 0xc0; len = 2; } + else if (utf32 <= 0xffff) { lead = 0xe0; len = 3; } + else { lead = 0xf0; len = 4; } + utf8[len] = 0; + for (int j = len - 1; j > 0; j--) { + utf8[j] = (unsigned char) ((utf32 & 0x3f) | 0x80); + utf32 >>= 6; + } + utf8[0] = (unsigned char) ((utf32 & 0xff) | lead); + return prtf (buf, bufsize, "%s", utf8); +} + static bool prtf_wstr (char * __restrict *buf, size_t * __restrict bufsize, dds_istream_t * __restrict is) { size_t sz = dds_is_get4 (is); @@ -4990,22 +5095,7 @@ static bool prtf_wstr (char * __restrict *buf, size_t * __restrict bufsize, dds_ else utf32 = 0x10000 + (((uint32_t) (w1 - 0xd800) << 10) | (uint32_t) (src[i] - 0xdc00)); if (utf32) - { - unsigned char utf8[5], lead; - int len; - if (utf32 <= 0x7f) { lead = 0; len = 1; } - else if (utf32 <= 0x7ff) { lead = 0xc0; len = 2; } - else if (utf32 <= 0xffff) { lead = 0xe0; len = 3; } - else { lead = 0xf0; len = 4; } - utf8[len] = 0; - for (int j = len - 1; j > 0; j--) { - utf8[j] = (unsigned char) ((utf32 & 0x3f) | 0x80); - utf32 >>= 6; - } - utf8[0] = (unsigned char) ((utf32 & 0xff) | lead); - utf32 = 0; - ret = prtf (buf, bufsize, "%s", utf8); - } + ret = prtf_utf32 (buf, bufsize, utf32); } ret = prtf (buf, bufsize, "\""); is->m_index += 2u * (uint32_t) sz; @@ -5086,6 +5176,10 @@ static bool prtf_simple (char * __restrict *buf, size_t * __restrict bufsize, dd else return prtf (buf, bufsize, "%"PRIu64, x.u); } + case DDS_OP_VAL_WCHAR: { + const uint16_t x = dds_is_get2 (is); + return prtf (buf, bufsize, "L'") && prtf_utf32 (buf, bufsize, x) && prtf (buf, bufsize, "'"); + } case DDS_OP_VAL_ENU: case DDS_OP_VAL_BMK: return prtf_enum_bitmask (buf, bufsize, is, flags); case DDS_OP_VAL_STR: case DDS_OP_VAL_BST: return prtf_str (buf, bufsize, is); @@ -5134,7 +5228,7 @@ static bool prtf_simple_array (char * __restrict *buf, size_t * __restrict bufsi } break; case DDS_OP_VAL_BLN: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: - case DDS_OP_VAL_STR: case DDS_OP_VAL_BST: + case DDS_OP_VAL_STR: case DDS_OP_VAL_BST: case DDS_OP_VAL_WCHAR: for (size_t i = 0; cont && i < num; i++) { if (i != 0) @@ -5166,7 +5260,7 @@ static const uint32_t *prtf_seq (char * __restrict *buf, size_t *bufsize, dds_is } switch (subtype) { - case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: + case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: case DDS_OP_VAL_WCHAR: (void) prtf_simple_array (buf, bufsize, is, num, subtype, DDS_OP_FLAGS (insn)); return ops + 2 + bound_op; case DDS_OP_VAL_STR: case DDS_OP_VAL_BST: @@ -5210,7 +5304,8 @@ static const uint32_t *prtf_arr (char * __restrict *buf, size_t *bufsize, dds_is switch (subtype) { case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: - case DDS_OP_VAL_STR: case DDS_OP_VAL_BST: case DDS_OP_VAL_WSTR: case DDS_OP_VAL_BWSTR: case DDS_OP_VAL_ENU: case DDS_OP_VAL_BMK: { + case DDS_OP_VAL_STR: case DDS_OP_VAL_BST: case DDS_OP_VAL_WSTR: case DDS_OP_VAL_BWSTR: case DDS_OP_VAL_WCHAR: + case DDS_OP_VAL_ENU: case DDS_OP_VAL_BMK: { (void) prtf_simple_array (buf, bufsize, is, num, subtype, DDS_OP_FLAGS (insn)); const uint32_t *ret_ops = ops + 3; if (subtype == DDS_OP_VAL_BST || subtype == DDS_OP_VAL_BWSTR || subtype == DDS_OP_VAL_BMK) @@ -5251,7 +5346,7 @@ static const uint32_t *prtf_uni (char * __restrict *buf, size_t *bufsize, dds_is switch (valtype) { case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: case DDS_OP_VAL_ENU: - case DDS_OP_VAL_STR: case DDS_OP_VAL_BST: case DDS_OP_VAL_WSTR: case DDS_OP_VAL_BWSTR: + case DDS_OP_VAL_STR: case DDS_OP_VAL_BST: case DDS_OP_VAL_WSTR: case DDS_OP_VAL_BWSTR: case DDS_OP_VAL_WCHAR: (void) prtf_simple (buf, bufsize, is, valtype, DDS_OP_FLAGS (jeq_op[0])); break; case DDS_OP_VAL_SEQ: case DDS_OP_VAL_BSQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: case DDS_OP_VAL_BMK: @@ -5281,7 +5376,7 @@ static const uint32_t * dds_stream_print_adr (char * __restrict *buf, size_t * _ switch (DDS_OP_TYPE (insn)) { case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: - case DDS_OP_VAL_STR: case DDS_OP_VAL_WSTR: + case DDS_OP_VAL_STR: case DDS_OP_VAL_WSTR: case DDS_OP_VAL_WCHAR: if (!prtf_simple (buf, bufsize, is, DDS_OP_TYPE (insn), DDS_OP_FLAGS (insn))) return NULL; ops += 2; @@ -5610,7 +5705,7 @@ static const uint32_t *dds_stream_key_size_arr (const uint32_t * __restrict ops, switch (subtype) { - case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: { + case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: case DDS_OP_VAL_WCHAR: { const uint32_t elem_size = get_primitive_size (subtype); add_to_key_size (k, elem_size, bound, elem_size); return ops + 3; @@ -5670,7 +5765,7 @@ static const uint32_t *dds_stream_key_size_adr (const uint32_t * __restrict ops, switch (DDS_OP_TYPE (insn)) { - case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: { + case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: case DDS_OP_VAL_WCHAR: { const uint32_t sz = get_primitive_size (DDS_OP_TYPE (insn)); add_to_key_size (k, sz, 1, sz); ops += 2; @@ -5835,7 +5930,7 @@ static void dds_stream_key_size_prim_op (const uint32_t * __restrict ops, uint16 assert ((insn & DDS_OP_FLAG_KEY) && ((DDS_OP (insn)) == DDS_OP_ADR)); switch (DDS_OP_TYPE (insn)) { - case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: + case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: case DDS_OP_VAL_WCHAR: case DDS_OP_VAL_STR: case DDS_OP_VAL_BST: case DDS_OP_VAL_WSTR: case DDS_OP_VAL_BWSTR: case DDS_OP_VAL_SEQ: case DDS_OP_VAL_BSQ: diff --git a/src/core/cdr/src/dds_cdrstream_keys.part.h b/src/core/cdr/src/dds_cdrstream_keys.part.h index 0917407781..f4c04325ea 100644 --- a/src/core/cdr/src/dds_cdrstream_keys.part.h +++ b/src/core/cdr/src/dds_cdrstream_keys.part.h @@ -42,6 +42,10 @@ static bool dds_stream_write_keyBO_impl (DDS_OSTREAM_T * __restrict os, const st case DDS_OP_VAL_WSTR: dds_stream_write_wstringBO (os, allocator, (const wchar_t *) addr); break; case DDS_OP_VAL_BST: dds_stream_write_stringBO (os, allocator, addr); break; case DDS_OP_VAL_BWSTR: dds_stream_write_wstringBO (os, allocator, (const wchar_t *) addr); break; + case DDS_OP_VAL_WCHAR: + if (!dds_stream_write_wcharBO (os, allocator, *(wchar_t *) addr)) + return false; + break; case DDS_OP_VAL_ARR: { const uint32_t num = ops[2]; switch (DDS_OP_SUBTYPE (insn)) diff --git a/src/core/cdr/src/dds_cdrstream_write.part.h b/src/core/cdr/src/dds_cdrstream_write.part.h index 49a489b022..a33c1bad41 100644 --- a/src/core/cdr/src/dds_cdrstream_write.part.h +++ b/src/core/cdr/src/dds_cdrstream_write.part.h @@ -116,6 +116,18 @@ static void dds_stream_write_wstringBO (DDS_OSTREAM_T * __restrict os, const str } } +ddsrt_attribute_warn_unused_result +static bool dds_stream_write_wcharBO (DDS_OSTREAM_T * __restrict os, const struct dds_cdrstream_allocator * __restrict allocator, const wchar_t val) +{ + // surrogates are forbidden + if ((uint32_t) val >= 0xd800 && (uint32_t) val < 0xe000) + return false; + else if ((uint32_t) val > 0xffff) // out-of-range + return false; + dds_os_put2BO (os, allocator, (uint16_t) val); + return true; +} + static bool dds_stream_write_bool_arrBO (DDS_OSTREAM_T * __restrict os, const struct dds_cdrstream_allocator * __restrict allocator, const uint8_t * __restrict addr, uint32_t num) { for (uint32_t i = 0; i < num; i++) @@ -302,7 +314,15 @@ static const uint32_t *dds_stream_write_seqBO (DDS_OSTREAM_T * __restrict os, co ops += 3 + bound_op; break; } - case DDS_OP_VAL_SEQ: case DDS_OP_VAL_BSQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: { + case DDS_OP_VAL_WCHAR: { + const wchar_t *ptr = (const wchar_t *) seq->_buffer; + for (uint32_t i = 0; i < num; i++) + if (!dds_stream_write_wcharBO (os, allocator, ptr[i])) + return NULL; + ops += 2 + bound_op; + break; + } + case DDS_OP_VAL_SEQ: case DDS_OP_VAL_BSQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: { const uint32_t elem_size = ops[2 + bound_op]; const uint32_t jmp = DDS_OP_ADR_JMP (ops[3 + bound_op]); uint32_t const * const jsr_ops = ops + DDS_OP_ADR_JSR (ops[3 + bound_op]); @@ -394,6 +414,14 @@ static const uint32_t *dds_stream_write_arrBO (DDS_OSTREAM_T * __restrict os, co ops += 5; break; } + case DDS_OP_VAL_WCHAR: { + const wchar_t *ptr = (const wchar_t *) addr; + for (uint32_t i = 0; i < num; i++) + if (!dds_stream_write_wcharBO (os, allocator, ptr[i])) + return NULL; + ops += 3; + break; + } case DDS_OP_VAL_SEQ: case DDS_OP_VAL_BSQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: { const uint32_t * jsr_ops = ops + DDS_OP_ADR_JSR (ops[3]); const uint32_t jmp = DDS_OP_ADR_JMP (ops[3]); @@ -492,6 +520,10 @@ static const uint32_t *dds_stream_write_uniBO (DDS_OSTREAM_T * __restrict os, co case DDS_OP_VAL_WSTR: dds_stream_write_wstringBO (os, allocator, *(const wchar_t **) valaddr); break; case DDS_OP_VAL_BST: dds_stream_write_stringBO (os, allocator, (const char *) valaddr); break; case DDS_OP_VAL_BWSTR: dds_stream_write_wstringBO (os, allocator, (const wchar_t *) valaddr); break; + case DDS_OP_VAL_WCHAR: + if (!dds_stream_write_wcharBO (os, allocator, *((const wchar_t *) valaddr))) + return NULL; + break; case DDS_OP_VAL_SEQ: case DDS_OP_VAL_BSQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: case DDS_OP_VAL_BMK: if (!dds_stream_write_implBO (os, allocator, valaddr, jeq_op + DDS_OP_ADR_JSR (jeq_op[0]), false, cdr_kind)) return NULL; @@ -552,6 +584,11 @@ static const uint32_t *dds_stream_write_adrBO (uint32_t insn, DDS_OSTREAM_T * __ case DDS_OP_VAL_WSTR: dds_stream_write_wstringBO (os, allocator, (const wchar_t *) addr); ops += 2; break; case DDS_OP_VAL_BST: dds_stream_write_stringBO (os, allocator, (const char *) addr); ops += 3; break; case DDS_OP_VAL_BWSTR: dds_stream_write_wstringBO (os, allocator, (const wchar_t *) addr); ops += 3; break; + case DDS_OP_VAL_WCHAR: + if (!dds_stream_write_wcharBO (os, allocator, *((const wchar_t *) addr))) + return NULL; + ops += 2; + break; case DDS_OP_VAL_SEQ: case DDS_OP_VAL_BSQ: ops = dds_stream_write_seqBO (os, allocator, addr, ops, insn, cdr_kind); break; case DDS_OP_VAL_ARR: ops = dds_stream_write_arrBO (os, allocator, addr, ops, insn, cdr_kind); break; case DDS_OP_VAL_UNI: ops = dds_stream_write_uniBO (os, allocator, addr, data, ops, insn, cdr_kind); break; diff --git a/src/core/ddsc/include/dds/ddsc/dds_data_type_properties.h b/src/core/ddsc/include/dds/ddsc/dds_data_type_properties.h index 1b0abd4255..4f18247278 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_data_type_properties.h +++ b/src/core/ddsc/include/dds/ddsc/dds_data_type_properties.h @@ -34,6 +34,7 @@ extern "C" { #define DDS_DATA_TYPE_CONTAINS_EXTERNAL (0x1ull << 11) #define DDS_DATA_TYPE_CONTAINS_KEY (0x1ull << 12) #define DDS_DATA_TYPE_CONTAINS_BWSTRING (0x1ull << 13) +#define DDS_DATA_TYPE_CONTAINS_WCHAR (0x1ull << 14) #define DDS_DATA_TYPE_IS_MEMCPY_SAFE (0x1ull << 63) diff --git a/src/core/ddsc/include/dds/ddsc/dds_opcodes.h b/src/core/ddsc/include/dds/ddsc/dds_opcodes.h index 1b74b597b8..5d01b77c77 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_opcodes.h +++ b/src/core/ddsc/include/dds/ddsc/dds_opcodes.h @@ -377,8 +377,9 @@ enum dds_stream_typecode { DDS_OP_VAL_EXT = 0x0d, /**< field with external definition */ DDS_OP_VAL_BLN = 0x0e, /**< boolean */ DDS_OP_VAL_BMK = 0x0f, /**< bitmask */ - DDS_OP_VAL_WSTR = 0x10, /**< wstring */ - DDS_OP_VAL_BWSTR = 0x11 /**< bounded wstring */ + DDS_OP_VAL_WSTR = 0x10, /**< wstring (UTF-16) */ + DDS_OP_VAL_BWSTR = 0x11, /**< bounded wstring (UTF-16) */ + DDS_OP_VAL_WCHAR = 0x12 /**< wchar: UTF-16, no surrogates allowed */ }; /** @@ -402,8 +403,9 @@ enum dds_stream_typecode_primary { DDS_OP_TYPE_EXT = DDS_OP_VAL_EXT << 16, /**< field with external definition */ DDS_OP_TYPE_BLN = DDS_OP_VAL_BLN << 16, /**< boolean */ DDS_OP_TYPE_BMK = DDS_OP_VAL_BMK << 16, /**< bitmask */ - DDS_OP_TYPE_WSTR = DDS_OP_VAL_WSTR << 16, /**< wstring */ - DDS_OP_TYPE_BWSTR = DDS_OP_VAL_BWSTR << 16 /**< bounded wstring */ + DDS_OP_TYPE_WSTR = DDS_OP_VAL_WSTR << 16, /**< wstring (UTF-16) */ + DDS_OP_TYPE_BWSTR = DDS_OP_VAL_BWSTR << 16, /**< bounded wstring (UTF-16) */ + DDS_OP_TYPE_WCHAR = DDS_OP_VAL_WCHAR << 16 /**< wchar: UTF-16, no surrogates allowed */ }; /** @@ -441,8 +443,9 @@ enum dds_stream_typecode_subtype { DDS_OP_SUBTYPE_ENU = DDS_OP_VAL_ENU << 8, /**< enumerated value (long) */ DDS_OP_SUBTYPE_BLN = DDS_OP_VAL_BLN << 8, /**< boolean */ DDS_OP_SUBTYPE_BMK = DDS_OP_VAL_BMK << 8, /**< bitmask */ - DDS_OP_SUBTYPE_WSTR = DDS_OP_VAL_WSTR << 8, /**< wstring */ - DDS_OP_SUBTYPE_BWSTR = DDS_OP_VAL_BWSTR << 8 /**< bounded wstring */ + DDS_OP_SUBTYPE_WSTR = DDS_OP_VAL_WSTR << 8, /**< wstring */ + DDS_OP_SUBTYPE_BWSTR = DDS_OP_VAL_BWSTR << 8, /**< bounded wstring */ + DDS_OP_SUBTYPE_WCHAR = DDS_OP_VAL_WCHAR << 8 /**< wchar: UTF-16, no surrogates allowed */ }; /** diff --git a/src/core/ddsc/src/dds_dynamic_type.c b/src/core/ddsc/src/dds_dynamic_type.c index db6345733b..d334d5675c 100644 --- a/src/core/ddsc/src/dds_dynamic_type.c +++ b/src/core/ddsc/src/dds_dynamic_type.c @@ -196,6 +196,7 @@ dds_dynamic_type_t dds_dynamic_type_create (dds_entity_t entity, dds_dynamic_typ case DDS_DYNAMIC_INT8: case DDS_DYNAMIC_UINT8: case DDS_DYNAMIC_CHAR8: + case DDS_DYNAMIC_CHAR16: type.ret = ddsi_dynamic_type_create_primitive (gv, get_dtype_complete_addr (&type), descriptor.kind); break; case DDS_DYNAMIC_STRING8: @@ -257,7 +258,6 @@ dds_dynamic_type_t dds_dynamic_type_create (dds_entity_t entity, dds_dynamic_typ break; } - case DDS_DYNAMIC_CHAR16: case DDS_DYNAMIC_MAP: case DDS_DYNAMIC_BITSET: type.ret = DDS_RETCODE_UNSUPPORTED; diff --git a/src/core/ddsc/tests/dynamic_type.c b/src/core/ddsc/tests/dynamic_type.c index b10a58b3ca..428c454a8f 100644 --- a/src/core/ddsc/tests/dynamic_type.c +++ b/src/core/ddsc/tests/dynamic_type.c @@ -120,7 +120,7 @@ CU_Test (ddsc_dynamic_type, type_create, .init = dynamic_type_init, .fini = dyna { { .kind = DDS_DYNAMIC_INT8, .name = "t" }, DDS_RETCODE_OK }, { { .kind = DDS_DYNAMIC_UINT8, .name = "t" }, DDS_RETCODE_OK }, { { .kind = DDS_DYNAMIC_CHAR8, .name = "t" }, DDS_RETCODE_OK }, - { { .kind = DDS_DYNAMIC_CHAR16, .name = "t" }, DDS_RETCODE_UNSUPPORTED }, + { { .kind = DDS_DYNAMIC_CHAR16, .name = "t" }, DDS_RETCODE_OK }, { { .kind = DDS_DYNAMIC_STRING8, .name = "t" }, DDS_RETCODE_OK }, { { .kind = DDS_DYNAMIC_STRING16, .name = "t" }, DDS_RETCODE_OK }, { { .kind = DDS_DYNAMIC_ENUMERATION, .name = "t" }, DDS_RETCODE_OK }, diff --git a/src/core/ddsi/src/ddsi_typebuilder.c b/src/core/ddsi/src/ddsi_typebuilder.c index 6d6b980585..a6227e2af6 100644 --- a/src/core/ddsi/src/ddsi_typebuilder.c +++ b/src/core/ddsi/src/ddsi_typebuilder.c @@ -392,6 +392,13 @@ static dds_return_t typebuilder_add_type (struct typebuilder_data *tbd, uint32_t *align = ALGN (uint16_t, is_ext); *size = SZ (uint16_t, is_ext); break; + case DDS_XTypes_TK_CHAR16: + tb_type->type_code = DDS_OP_VAL_WCHAR; + tb_type->args.prim_args.is_signed = false; + tb_type->cdr_align = 2; + *align = ALGN (uint16_t, is_ext); + *size = SZ (uint16_t, is_ext); + break; case DDS_XTypes_TK_INT32: case DDS_XTypes_TK_UINT32: case DDS_XTypes_TK_FLOAT32: @@ -578,7 +585,6 @@ static dds_return_t typebuilder_add_type (struct typebuilder_data *tbd, uint32_t break; } case DDS_XTypes_TK_FLOAT128: - case DDS_XTypes_TK_CHAR16: case DDS_XTypes_TK_ANNOTATION: case DDS_XTypes_TK_MAP: case DDS_XTypes_TK_BITSET: @@ -932,6 +938,11 @@ static dds_return_t get_ops_type (struct typebuilder_type *tb_type, uint32_t fla PUSH_ARG (member_offset); PUSH_ARG (tb_type->args.string_args.max_size); break; + case DDS_OP_VAL_WCHAR: + flags |= get_type_flags (tb_type); + PUSH_OP (DDS_OP_ADR | DDS_OP_TYPE_WCHAR | flags); + PUSH_ARG (member_offset); + break; case DDS_OP_VAL_BSQ: case DDS_OP_VAL_SEQ: { bool bounded = tb_type->type_code == DDS_OP_VAL_BSQ; @@ -946,7 +957,7 @@ static dds_return_t get_ops_type (struct typebuilder_type *tb_type, uint32_t fla switch (element_type->type_code) { case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: - case DDS_OP_VAL_BLN: case DDS_OP_VAL_STR: case DDS_OP_VAL_WSTR: + case DDS_OP_VAL_BLN: case DDS_OP_VAL_STR: case DDS_OP_VAL_WSTR: case DDS_OP_VAL_WCHAR: break; case DDS_OP_VAL_ENU: PUSH_ARG (element_type->args.enum_args.max); @@ -1003,7 +1014,7 @@ static dds_return_t get_ops_type (struct typebuilder_type *tb_type, uint32_t fla switch (element_type->type_code) { case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: - case DDS_OP_VAL_BLN: case DDS_OP_VAL_STR: case DDS_OP_VAL_WSTR: + case DDS_OP_VAL_BLN: case DDS_OP_VAL_STR: case DDS_OP_VAL_WSTR: case DDS_OP_VAL_WCHAR: break; case DDS_OP_VAL_ENU: PUSH_ARG (element_type->args.enum_args.max); @@ -1147,6 +1158,12 @@ static dds_return_t get_ops_union_case (struct typebuilder_type *tb_type, uint32 PUSH_ARG (offset); PUSH_ARG (0); break; + case DDS_OP_VAL_WCHAR: + PUSH_OP (DDS_OP_JEQ4 | DDS_OP_TYPE_WCHAR | flags); + PUSH_ARG (disc_value); + PUSH_ARG (offset); + PUSH_ARG (0); + break; case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: { flags |= get_type_flags (tb_type); diff --git a/src/idl/src/descriptor_type_meta.c b/src/idl/src/descriptor_type_meta.c index 65a15e80f4..18b47e7325 100644 --- a/src/idl/src/descriptor_type_meta.c +++ b/src/idl/src/descriptor_type_meta.c @@ -264,6 +264,7 @@ get_plain_typeid (const idl_pstate_t *pstate, struct descriptor_type_meta *dtm, { case IDL_BOOL: ti->_d = DDS_XTypes_TK_BOOLEAN; break; case IDL_CHAR: ti->_d = DDS_XTypes_TK_CHAR8; break; + case IDL_WCHAR: ti->_d = DDS_XTypes_TK_CHAR16; break; case IDL_OCTET: ti->_d = DDS_XTypes_TK_BYTE; break; case IDL_INT8: ti->_d = DDS_XTypes_TK_INT8; break; case IDL_INT16: case IDL_SHORT: ti->_d = DDS_XTypes_TK_INT16; break; diff --git a/src/idl/src/print.c b/src/idl/src/print.c index f66f7897cc..dacf9fe68c 100644 --- a/src/idl/src/print.c +++ b/src/idl/src/print.c @@ -129,6 +129,7 @@ static int print_base_type( switch (idl_type(node)) { case IDL_BOOL: type = "bool"; break; case IDL_CHAR: type = "char"; break; + case IDL_WCHAR: type = "wchar_t"; break; case IDL_INT8: type = "int8_t"; break; case IDL_OCTET: case IDL_UINT8: type = "uint8_t"; break; @@ -224,6 +225,7 @@ static int print_templ_type( switch (idl_type(type_spec)) { case IDL_BOOL: type = "bool"; break; case IDL_CHAR: type = "char"; break; + case IDL_WCHAR: type = "wchar_t"; break; case IDL_INT8: type = "int8"; break; case IDL_OCTET: type = "octet"; break; case IDL_UINT8: type = "uint8"; break; diff --git a/src/tools/idlc/src/libidlc/libidlc__descriptor.c b/src/tools/idlc/src/libidlc/libidlc__descriptor.c index 939a0cf73a..98fa45eb23 100644 --- a/src/tools/idlc/src/libidlc/libidlc__descriptor.c +++ b/src/tools/idlc/src/libidlc/libidlc__descriptor.c @@ -516,6 +516,9 @@ static idl_retcode_t add_typecode(const idl_pstate_t *pstate, const idl_type_spe case IDL_CHAR: *add_to |= ((uint32_t)DDS_OP_VAL_1BY << shift) | (uint32_t)DDS_OP_FLAG_SGN; break; + case IDL_WCHAR: + *add_to |= ((uint32_t)DDS_OP_VAL_WCHAR << shift); + break; case IDL_BOOL: *add_to |= ((uint32_t)DDS_OP_VAL_BLN << shift); break; @@ -1666,6 +1669,7 @@ static int print_opcode(FILE *fp, const struct instruction *inst) case DDS_OP_VAL_EXT: vec[len++] = " | DDS_OP_TYPE_EXT"; break; case DDS_OP_VAL_WSTR: vec[len++] = " | DDS_OP_TYPE_WSTR"; break; case DDS_OP_VAL_BWSTR: vec[len++] = " | DDS_OP_TYPE_BWSTR"; break; + case DDS_OP_VAL_WCHAR: vec[len++] = " | DDS_OP_TYPE_WCHAR"; break; } } @@ -1702,6 +1706,7 @@ static int print_opcode(FILE *fp, const struct instruction *inst) case DDS_OP_VAL_BMK: vec[len++] = " | DDS_OP_SUBTYPE_BMK"; break; case DDS_OP_VAL_WSTR: vec[len++] = " | DDS_OP_SUBTYPE_WSTR"; break; case DDS_OP_VAL_BWSTR: vec[len++] = " | DDS_OP_SUBTYPE_BWSTR"; break; + case DDS_OP_VAL_WCHAR: vec[len++] = " | DDS_OP_SUBTYPE_WCHAR"; break; case DDS_OP_VAL_EXT: abort(); break; } @@ -1992,6 +1997,7 @@ static idl_retcode_t get_ctype_keys_adr( switch (subtype) { case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: key->size = key->align = 1; break; + case DDS_OP_VAL_WCHAR: case DDS_OP_VAL_2BY: key->size = key->align = 2; break; case DDS_OP_VAL_4BY: key->size = key->align = 4; break; case DDS_OP_VAL_8BY: key->size = key->align = 8; break; @@ -2024,6 +2030,7 @@ static idl_retcode_t get_ctype_keys_adr( switch (type) { case DDS_OP_VAL_BLN: case DDS_OP_VAL_1BY: key->size = key->align = 1; break; + case DDS_OP_VAL_WCHAR: case DDS_OP_VAL_2BY: key->size = key->align = 2; break; case DDS_OP_VAL_4BY: key->size = key->align = 4; break; case DDS_OP_VAL_8BY: key->size = key->align = 8; break;