1616#ifndef MINGW_COMPILER
1717 #include < codecvt>
1818#endif // ifndef MINGW_COMPILER
19+ #include < cstdint>
1920#include < iomanip>
2021#include < iostream>
22+ #include < limits>
2123#include < string>
2224
2325#include < nlohmann/json.hpp>
@@ -266,6 +268,7 @@ ReturnCode_t json_serialize_member(
266268 }
267269 case TK_MAP :
268270 {
271+ // TODO: encapsulate all complex kinds serialization?
269272 traits<DynamicDataImpl>::ref_type st_data =
270273 traits<DynamicData>::narrow<DynamicDataImpl>(data->loan_value (member_id));
271274 if (nullptr == st_data)
@@ -364,6 +367,7 @@ ReturnCode_t json_serialize_member(
364367 traits<DynamicTypeImpl>::ref_type bitmask_type = st_data->enclosing_type ();
365368 const TypeDescriptorImpl& bitmask_desc = bitmask_type->get_descriptor ();
366369
370+ // Get the bitmask bound to determine the value precision
367371 auto bound = bitmask_desc.bound ().at (0 );
368372
369373 if (format == DynamicDataJsonFormat::OMG )
@@ -716,6 +720,14 @@ ReturnCode_t json_serialize_basic_member(
716720 ReturnCode_t ret = data->get_float128_value (value, member_id);
717721 if (RETCODE_OK == ret)
718722 {
723+ // Fail if value exceeds double limits, as JSON does not support long double
724+ if (value < std::numeric_limits<double >::lowest () ||
725+ value > std::numeric_limits<double >::max ())
726+ {
727+ EPROSIMA_LOG_ERROR (XTYPES_UTILS ,
728+ " Error encountered while serializing TK_FLOAT128 member to JSON: value out of range." );
729+ return RETCODE_BAD_PARAMETER ;
730+ }
719731 json_insert (member_name, value, output);
720732 }
721733 else
@@ -746,20 +758,39 @@ ReturnCode_t json_serialize_basic_member(
746758 if (RETCODE_OK == ret)
747759 {
748760 // Insert UTF-8 converted value
749- #if defined(MINGW_COMPILER)
750761 std::wstring aux_wstring_value ({value});
751- std::string utf8_value;
752- int size_needed = std::wcstombs (nullptr , aux_wstring_value.data (), 0 );
753- if (size_needed > 0 )
762+ std::string utf8_value (" \0 " , 1 );
763+ #if defined(MINGW_COMPILER)
764+ // WARNING: it is the user responsibility to set the appropiate UTF-8 locale before calling this method
765+ int size_needed = std::wcstombs (nullptr , aux_wstring_value.c_str (), 0 );
766+ if (size_needed < 0 )
767+ {
768+ EPROSIMA_LOG_ERROR (XTYPES_UTILS ,
769+ " Error encountered while serializing TK_CHAR16 member to JSON: encountered invalid character." );
770+ return RETCODE_BAD_PARAMETER ;
771+ }
772+ else if (size_needed > 0 )
754773 {
755774 utf8_value.resize (size_needed);
756- std::wcstombs (&utf8_value[0 ], aux_wstring_value.data (), size_needed);
775+ if (std::wcstombs (&utf8_value[0 ], aux_wstring_value.c_str (), size_needed) == static_cast <std::size_t >(-1 ))
776+ {
777+ EPROSIMA_LOG_ERROR (XTYPES_UTILS ,
778+ " Error encountered while serializing TK_CHAR16 member to JSON: encountered invalid character." );
779+ return RETCODE_BAD_PARAMETER ;
780+ }
757781 }
758782#else
759- std::wstring aux_wstring_value ({value});
760783 std::wstring_convert<std::codecvt_utf8<wchar_t >> converter;
761- std::string utf8_value = converter.to_bytes (aux_wstring_value); // TODO: handle exception
762-
784+ try
785+ {
786+ utf8_value = converter.to_bytes (aux_wstring_value);
787+ }
788+ catch (const std::exception& e)
789+ {
790+ EPROSIMA_LOG_ERROR (XTYPES_UTILS ,
791+ " Error encountered while serializing TK_CHAR16 member to JSON: " << e.what ());
792+ return RETCODE_BAD_PARAMETER ;
793+ }
763794#endif // defined(MINGW_COMPILER)
764795 json_insert (member_name, utf8_value, output);
765796 }
@@ -790,17 +821,38 @@ ReturnCode_t json_serialize_basic_member(
790821 if (RETCODE_OK == ret)
791822 {
792823 // Insert UTF-8 converted value
793- #ifdef MINGW_COMPILER
794824 std::string utf8_value;
795- int size_needed = std::wcstombs (nullptr , value.data (), 0 );
796- if (size_needed > 0 )
825+ #ifdef MINGW_COMPILER
826+ // WARNING: it is the user responsibility to set the appropiate UTF-8 locale before calling this method
827+ int size_needed = std::wcstombs (nullptr , value.c_str (), 0 );
828+ if (size_needed < 0 )
829+ {
830+ EPROSIMA_LOG_ERROR (XTYPES_UTILS ,
831+ " Error encountered while serializing TK_STRING16 member to JSON: encountered invalid character." );
832+ return RETCODE_BAD_PARAMETER ;
833+ }
834+ else if (size_needed > 0 )
797835 {
798836 utf8_value.resize (size_needed);
799- std::wcstombs (&utf8_value[0 ], value.data (), size_needed);
837+ if (std::wcstombs (&utf8_value[0 ], value.c_str (), size_needed) == static_cast <std::size_t >(-1 ))
838+ {
839+ EPROSIMA_LOG_ERROR (XTYPES_UTILS ,
840+ " Error encountered while serializing TK_STRING16 member to JSON: encountered invalid character." );
841+ return RETCODE_BAD_PARAMETER ;
842+ }
800843 }
801844#else
802845 std::wstring_convert<std::codecvt_utf8<wchar_t >> converter;
803- std::string utf8_value = converter.to_bytes (value); // TODO: handle exception
846+ try
847+ {
848+ utf8_value = converter.to_bytes (value);
849+ }
850+ catch (const std::exception& e)
851+ {
852+ EPROSIMA_LOG_ERROR (XTYPES_UTILS ,
853+ " Error encountered while serializing TK_STRING16 member to JSON: " << e.what ());
854+ return RETCODE_BAD_PARAMETER ;
855+ }
804856#endif // defined(MINGW_COMPILER)
805857 json_insert (member_name, utf8_value, output);
806858 }
@@ -812,24 +864,17 @@ ReturnCode_t json_serialize_basic_member(
812864 }
813865 case TK_ENUM :
814866 {
815- int32_t value;
816- ReturnCode_t ret = data->get_int32_value (value, member_id);
817- if (RETCODE_OK != ret)
818- {
819- EPROSIMA_LOG_ERROR (XTYPES_UTILS , " Error encountered while serializing TK_ENUM member to JSON." );
820- return ret;
821- }
822-
823- // Get enumeration type to obtain the names of the different values
867+ // Get enumeration type to obtain the names of the different values, and also the underlying primitive type
824868 // NOTE: a different approach is required for collections and other "holder" types (e.g. structures),
825869 // as unlike with DynamicData::loan_value or DynamicData::get_X_value, DynamicData::get_descriptor method
826870 // is not meant to work with sequences nor arrays according to XTypes standard.
827- traits<DynamicType >::ref_type enum_type;
871+ traits<DynamicTypeImpl >::ref_type enum_type;
828872 TypeKind holder_kind = data->enclosing_type ()->get_kind ();
873+ ReturnCode_t ret = RETCODE_OK ;
829874 if (TK_ARRAY == holder_kind || TK_SEQUENCE == holder_kind)
830875 {
831876 const TypeDescriptorImpl& collection_descriptor = data->enclosing_type ()->get_descriptor ();
832- enum_type = collection_descriptor.element_type ();
877+ enum_type = traits<DynamicType>::narrow<DynamicTypeImpl>( collection_descriptor.element_type ())-> resolve_alias_enclosed_type ();
833878 }
834879 else
835880 {
@@ -840,14 +885,67 @@ ReturnCode_t json_serialize_basic_member(
840885 " Error encountered while serializing TK_ENUM member to JSON: get_descriptor failed." );
841886 return ret;
842887 }
843- enum_type = enum_desc->type ();
888+ enum_type = traits<DynamicType>::narrow<DynamicTypeImpl>(enum_desc->type ())->resolve_alias_enclosed_type ();
889+ }
890+
891+ // Get value depending on the enclosing type
892+ assert (enum_type->get_kind () == TK_ENUM );
893+ TypeKind enclosing_kind = traits<DynamicType>::narrow<DynamicTypeImpl>(enum_type->get_all_members_by_index ().at (0 )->get_descriptor ().type ())->get_kind (); // Unfortunately DynamicDataImpl::get_enclosing_typekind is private
894+ nlohmann::json j_value;
895+ if (TK_INT8 == enclosing_kind)
896+ {
897+ int8_t value;
898+ ret = data->get_int8_value (value, member_id);
899+ j_value = value;
900+ }
901+ else if (TK_UINT8 == enclosing_kind)
902+ {
903+ uint8_t value;
904+ ret = data->get_uint8_value (value, member_id);
905+ j_value = value;
906+ }
907+ else if (TK_INT16 == enclosing_kind)
908+ {
909+ int16_t value;
910+ ret = data->get_int16_value (value, member_id);
911+ j_value = value;
912+ }
913+ else if (TK_UINT16 == enclosing_kind)
914+ {
915+ uint16_t value;
916+ ret = data->get_uint16_value (value, member_id);
917+ j_value = value;
918+ }
919+ else if (TK_INT32 == enclosing_kind)
920+ {
921+ int32_t value;
922+ ret = data->get_int32_value (value, member_id);
923+ j_value = value;
924+ }
925+ else if (TK_UINT32 == enclosing_kind)
926+ {
927+ uint32_t value;
928+ ret = data->get_uint32_value (value, member_id);
929+ j_value = value;
930+ }
931+ else
932+ {
933+ EPROSIMA_LOG_ERROR (XTYPES_UTILS ,
934+ " Error encountered while serializing TK_ENUM member to JSON: unexpected enclosing kind " <<
935+ enclosing_kind << " found." );
936+ return RETCODE_BAD_PARAMETER ;
937+ }
938+
939+ if (RETCODE_OK != ret)
940+ {
941+ EPROSIMA_LOG_ERROR (XTYPES_UTILS , " Error encountered while serializing TK_ENUM member to JSON." );
942+ return ret;
844943 }
845944
846945 DynamicTypeMembersByName all_members;
847946 if (RETCODE_OK !=
848947 (ret =
849- traits<DynamicType>::narrow<DynamicTypeImpl>(enum_type)->resolve_alias_enclosed_type ()->
850- get_all_members_by_name (all_members)))
948+ enum_type->get_all_members_by_name (all_members)))
851949 {
852950 EPROSIMA_LOG_ERROR (XTYPES_UTILS ,
853951 " Error encountered while serializing TK_ENUM member to JSON: get_all_members_by_name failed." );
@@ -860,7 +958,7 @@ ReturnCode_t json_serialize_basic_member(
860958 {
861959 MemberDescriptorImpl& enum_member_desc = traits<DynamicTypeMember>::narrow<DynamicTypeMemberImpl>(
862960 it.second )->get_descriptor ();
863- if (enum_member_desc.default_value () == std::to_string (value ))
961+ if (enum_member_desc.default_value () == j_value. dump ( ))
864962 {
865963 name = it.first ;
866964 assert (name == it.second ->get_name ());
@@ -876,7 +974,7 @@ ReturnCode_t json_serialize_basic_member(
876974 }
877975 else if (format == DynamicDataJsonFormat::EPROSIMA )
878976 {
879- nlohmann::json enum_dict = {{" name" , name}, {" value" , value }};
977+ nlohmann::json enum_dict = {{" name" , name}, {" value" , j_value }};
880978 json_insert (member_name, enum_dict, output);
881979 }
882980 }
@@ -902,20 +1000,18 @@ ReturnCode_t json_serialize_collection(
9021000 DynamicDataJsonFormat format) noexcept
9031001{
9041002 ReturnCode_t ret = RETCODE_OK ;
1003+ const TypeDescriptorImpl& descriptor = data->enclosing_type ()->get_descriptor ();
1004+ auto element_kind = traits<DynamicType>::narrow<DynamicTypeImpl>(descriptor.element_type ())->resolve_alias_enclosed_type ()->get_kind ();
9051005 if (data->enclosing_type ()->get_kind () == TK_SEQUENCE )
9061006 {
907- const TypeDescriptorImpl& descriptor = data->enclosing_type ()->get_descriptor ();
908-
1007+ assert (descriptor.bound ().size () == 1 );
9091008 auto count = data->get_item_count ();
9101009 nlohmann::json j_array = nlohmann::json::array ();
9111010 for (uint32_t index = 0 ; index < count; ++index)
9121011 {
9131012 if (RETCODE_OK !=
9141013 (ret =
915- json_serialize_member (data, static_cast <MemberId>(index),
916- traits<DynamicType>::narrow<DynamicTypeImpl>(descriptor.element_type ())->resolve_alias_enclosed_type ()
917- ->get_kind (), j_array,
918- format)))
1014+ json_serialize_member (data, static_cast <MemberId>(index), element_kind, j_array, format)))
9191015 {
9201016 EPROSIMA_LOG_ERROR (XTYPES_UTILS , " Error encountered while serializing sequence collection to JSON." );
9211017 break ;
@@ -928,13 +1024,10 @@ ReturnCode_t json_serialize_collection(
9281024 }
9291025 else
9301026 {
931- const TypeDescriptorImpl& descriptor = data->enclosing_type ()->get_descriptor ();
932-
9331027 const BoundSeq& bounds = descriptor.bound ();
9341028 nlohmann::json j_array = nlohmann::json::array ();
9351029 unsigned int index = 0 ;
936- if (RETCODE_OK != (ret = json_serialize_array (data, traits<DynamicType>::narrow<DynamicTypeImpl>(
937- descriptor.element_type ())->resolve_alias_enclosed_type ()->get_kind (), index, bounds, j_array,
1030+ if (RETCODE_OK != (ret = json_serialize_array (data, element_kind, index, bounds, j_array,
9381031 format)))
9391032 {
9401033 EPROSIMA_LOG_ERROR (XTYPES_UTILS , " Error encountered while serializing array collection to JSON." );
@@ -949,7 +1042,7 @@ ReturnCode_t json_serialize_collection(
9491042
9501043ReturnCode_t json_serialize_array (
9511044 const traits<DynamicDataImpl>::ref_type& data,
952- TypeKind member_kind ,
1045+ TypeKind element_kind ,
9531046 unsigned int & index,
9541047 const std::vector<unsigned int >& bounds,
9551048 nlohmann::json& j_array,
@@ -963,7 +1056,7 @@ ReturnCode_t json_serialize_array(
9631056 {
9641057 if (RETCODE_OK !=
9651058 (ret =
966- json_serialize_member (data, static_cast <MemberId>(index++), member_kind , j_array,
1059+ json_serialize_member (data, static_cast <MemberId>(index++), element_kind , j_array,
9671060 format)))
9681061 {
9691062 EPROSIMA_LOG_ERROR (XTYPES_UTILS , " Error encountered while serializing array element to JSON." );
@@ -978,7 +1071,7 @@ ReturnCode_t json_serialize_array(
9781071 nlohmann::json inner_array = nlohmann::json::array ();
9791072 if (RETCODE_OK !=
9801073 (ret =
981- json_serialize_array (data, member_kind , index,
1074+ json_serialize_array (data, element_kind , index,
9821075 std::vector<unsigned int >(bounds.begin () + 1 , bounds.end ()), inner_array, format)))
9831076 {
9841077 EPROSIMA_LOG_ERROR (XTYPES_UTILS ,
0 commit comments