diff --git a/include/fastcdr/Cdr.h b/include/fastcdr/Cdr.h index 54e1e3a4..0f9fce6d 100644 --- a/include/fastcdr/Cdr.h +++ b/include/fastcdr/Cdr.h @@ -49,7 +49,6 @@ class Cdr_DllAPI Cdr { public: - //! Represents endianness types. typedef enum : uint8_t { //! @brief Big endianness. @@ -4760,6 +4759,11 @@ class Cdr_DllAPI Cdr EncodingAlgorithmFlag type_encoding, std::function functor); + /*! + * @brief Resets the internal callbacks depending on the current selected Cdr version. + */ + void reset_callbacks(); + using begin_serialize_member_functor = Cdr& (Cdr::*)( const MemberId&, bool, diff --git a/src/cpp/Cdr.cpp b/src/cpp/Cdr.cpp index b9d3d197..2b89f7d8 100644 --- a/src/cpp/Cdr.cpp +++ b/src/cpp/Cdr.cpp @@ -91,6 +91,25 @@ Cdr::Cdr( , offset_(cdrBuffer.begin()) , origin_(cdrBuffer.begin()) , end_(cdrBuffer.end()) +{ + switch (cdr_version_) + { + case CdrVersion::XCDRv2: + align64_ = 4; + break; + case CdrVersion::XCDRv1: + encoding_flag_ = EncodingAlgorithmFlag::PLAIN_CDR; + current_encoding_ = EncodingAlgorithmFlag::PLAIN_CDR; + break; + default: + encoding_flag_ = EncodingAlgorithmFlag::PLAIN_CDR; + current_encoding_ = EncodingAlgorithmFlag::PLAIN_CDR; + break; + } + reset_callbacks(); +} + +void Cdr::reset_callbacks() { switch (cdr_version_) { @@ -102,7 +121,6 @@ Cdr::Cdr( begin_serialize_type_ = &Cdr::xcdr2_begin_serialize_type; end_serialize_type_ = &Cdr::xcdr2_end_serialize_type; deserialize_type_ = &Cdr::xcdr2_deserialize_type; - align64_ = 4; break; case CdrVersion::XCDRv1: begin_serialize_member_ = &Cdr::xcdr1_begin_serialize_member; @@ -112,12 +130,15 @@ Cdr::Cdr( begin_serialize_type_ = &Cdr::xcdr1_begin_serialize_type; end_serialize_type_ = &Cdr::xcdr1_end_serialize_type; deserialize_type_ = &Cdr::xcdr1_deserialize_type; - encoding_flag_ = EncodingAlgorithmFlag::PLAIN_CDR; - current_encoding_ = EncodingAlgorithmFlag::PLAIN_CDR; break; default: - encoding_flag_ = EncodingAlgorithmFlag::PLAIN_CDR; - current_encoding_ = EncodingAlgorithmFlag::PLAIN_CDR; + begin_serialize_member_ = nullptr; + end_serialize_member_ = nullptr; + begin_serialize_opt_member_ = nullptr; + end_serialize_opt_member_ = nullptr; + begin_serialize_type_ = nullptr; + end_serialize_type_ = nullptr; + deserialize_type_ = nullptr; break; } } @@ -158,29 +179,37 @@ Cdr& Cdr::read_encapsulation() case EncodingAlgorithmFlag::PLAIN_CDR2: case EncodingAlgorithmFlag::DELIMIT_CDR2: case EncodingAlgorithmFlag::PL_CDR2: - if (CdrVersion::XCDRv2 != cdr_version_) + if (CdrVersion::XCDRv1 <= cdr_version_) + { + cdr_version_ = CdrVersion::XCDRv2; + } + else { throw BadParamException( "Unexpected encoding algorithm received in Cdr::read_encapsulation. XCDRv2 should be selected."); } break; case EncodingAlgorithmFlag::PL_CDR: - if (CdrVersion::XCDRv1 != cdr_version_) + if (CdrVersion::XCDRv1 <= cdr_version_) + { + cdr_version_ = CdrVersion::XCDRv1; + } + else { throw BadParamException( "Unexpected encoding algorithm received in Cdr::read_encapsulation. XCDRv1 should be selected"); } break; case EncodingAlgorithmFlag::PLAIN_CDR: - if (CdrVersion::XCDRv1 < cdr_version_) + if (CdrVersion::XCDRv1 <= cdr_version_) { - throw BadParamException( - "Unexpected encoding algorithm received in Cdr::read_encapsulation. XCDRv2 shouldn't be selected"); + cdr_version_ = CdrVersion::XCDRv1; } break; default: throw BadParamException("Unexpected encoding algorithm received in Cdr::read_encapsulation for DDS CDR"); } + reset_callbacks(); encoding_flag_ = static_cast(encoding_flag); current_encoding_ = encoding_flag_; diff --git a/test/xcdr/xcdrv1.cpp b/test/xcdr/xcdrv1.cpp index 57434577..174392e5 100644 --- a/test/xcdr/xcdrv1.cpp +++ b/test/xcdr/xcdrv1.cpp @@ -13,11 +13,66 @@ using XCdrStreamValues = std::array, 1 + Cdr::XCdrHeaderSelection::AUTO_WITH_LONG_HEADER_BY_DEFAULT>; -class XCdrv1Test : public ::testing::TestWithParam< Cdr::XCdrHeaderSelection> +class XCdrv1Test : public ::testing::TestWithParam> { }; -TEST_P(XCdrv1Test, pl_octet_opt_member) +class XCdrv1PLTest : public ::testing::TestWithParam< Cdr::XCdrHeaderSelection> +{ +}; + +TEST_P(XCdrv1Test, auto_selection_on_decode) +{ + EncodingAlgorithmFlag encoding = std::get<0>(GetParam()); + Cdr::Endianness endianness = Cdr::Endianness::LITTLE_ENDIANNESS; + auto buffer = + std::unique_ptr{reinterpret_cast(calloc(100, sizeof(char))), free}; + FastBuffer fast_buffer(buffer.get(), 100); + + //{ Encode a ushort and a ulong. + Cdr cdr(fast_buffer, endianness, CdrVersion::XCDRv1); + const uint16_t us {0x01FC}; + const uint32_t ul {0x01FC1FCD}; + cdr.set_encoding_flag(encoding); + cdr.serialize_encapsulation(); + Cdr::state enc_state(cdr); + cdr.begin_serialize_type(enc_state, encoding); + cdr << MemberId(0) << us; + cdr << MemberId(1) << ul; + cdr.end_serialize_type(enc_state); + //} + + //{ Decode a ushort and a ulong. + Cdr dcdr(fast_buffer, endianness, std::get<1>(GetParam())); + uint16_t dus{0}; + uint32_t dul{0}; + dcdr.read_encapsulation(); + ASSERT_EQ(dcdr.get_encoding_flag(), encoding); + ASSERT_EQ(dcdr.endianness(), endianness); + dcdr.deserialize_type(encoding, [&](Cdr& dcdr_inner, const MemberId& mid) -> bool + { + bool ret_value = true; + switch (mid.id) + { + case 0: + dcdr_inner >> dus; + break; + case 1: + dcdr_inner >> dul; + break; + default: + ret_value = false; + break; + } + + return ret_value; + }); + ASSERT_EQ(us, dus); + ASSERT_EQ(ul, dul); +} + +TEST_P(XCdrv1PLTest, pl_octet_opt_member) { constexpr unsigned char octet_value = 0xCD; @@ -113,6 +168,16 @@ TEST_P(XCdrv1Test, pl_octet_opt_member) INSTANTIATE_TEST_SUITE_P( XCdrTest, XCdrv1Test, + ::testing::Values( + std::make_tuple(EncodingAlgorithmFlag::PLAIN_CDR, CdrVersion::XCDRv1), + std::make_tuple(EncodingAlgorithmFlag::PLAIN_CDR, CdrVersion::XCDRv2), + std::make_tuple(EncodingAlgorithmFlag::PL_CDR, CdrVersion::XCDRv1), + std::make_tuple(EncodingAlgorithmFlag::PL_CDR, CdrVersion::XCDRv2) + )); + +INSTANTIATE_TEST_SUITE_P( + XCdrTest, + XCdrv1PLTest, ::testing::Values( Cdr::XCdrHeaderSelection::SHORT_HEADER, Cdr::XCdrHeaderSelection::LONG_HEADER, diff --git a/test/xcdr/xcdrv2.cpp b/test/xcdr/xcdrv2.cpp index ca596748..c18f1189 100644 --- a/test/xcdr/xcdrv2.cpp +++ b/test/xcdr/xcdrv2.cpp @@ -13,11 +13,66 @@ using XCdrStreamValues = std::array, 1 + Cdr::XCdrHeaderSelection::AUTO_WITH_LONG_HEADER_BY_DEFAULT>; -class XCdrv2Test : public ::testing::TestWithParam< Cdr::XCdrHeaderSelection> +class XCdrv2Test : public ::testing::TestWithParam> { }; -TEST_P(XCdrv2Test, pl_octet_opt_member) +class XCdrv2PLTest : public ::testing::TestWithParam< Cdr::XCdrHeaderSelection> +{ +}; + +TEST_P(XCdrv2Test, auto_selection_on_decode) +{ + EncodingAlgorithmFlag encoding = std::get<0>(GetParam()); + Cdr::Endianness endianness = Cdr::Endianness::LITTLE_ENDIANNESS; + auto buffer = + std::unique_ptr{reinterpret_cast(calloc(100, sizeof(char))), free}; + FastBuffer fast_buffer(buffer.get(), 100); + + //{ Encode a ushort and a ulong. + Cdr cdr(fast_buffer, endianness, CdrVersion::XCDRv2); + const uint16_t us {0x01FC}; + const uint32_t ul {0x01FC1FCD}; + cdr.set_encoding_flag(encoding); + cdr.serialize_encapsulation(); + Cdr::state enc_state(cdr); + cdr.begin_serialize_type(enc_state, encoding); + cdr << MemberId(0) << us; + cdr << MemberId(1) << ul; + cdr.end_serialize_type(enc_state); + //} + + //{ Decode a ushort and a ulong. + Cdr dcdr(fast_buffer, endianness, std::get<1>(GetParam())); + uint16_t dus{0}; + uint32_t dul{0}; + dcdr.read_encapsulation(); + ASSERT_EQ(dcdr.get_encoding_flag(), encoding); + ASSERT_EQ(dcdr.endianness(), endianness); + dcdr.deserialize_type(encoding, [&](Cdr& dcdr_inner, const MemberId& mid) -> bool + { + bool ret_value = true; + switch (mid.id) + { + case 0: + dcdr_inner >> dus; + break; + case 1: + dcdr_inner >> dul; + break; + default: + ret_value = false; + break; + } + + return ret_value; + }); + ASSERT_EQ(us, dus); + ASSERT_EQ(ul, dul); +} + +TEST_P(XCdrv2PLTest, pl_octet_opt_member) { constexpr unsigned char octet_value = 0xCD; @@ -109,6 +164,18 @@ TEST_P(XCdrv2Test, pl_octet_opt_member) INSTANTIATE_TEST_SUITE_P( XCdrTest, XCdrv2Test, + ::testing::Values( + std::make_tuple(EncodingAlgorithmFlag::PLAIN_CDR2, CdrVersion::XCDRv1), + std::make_tuple(EncodingAlgorithmFlag::PLAIN_CDR2, CdrVersion::XCDRv2), + std::make_tuple(EncodingAlgorithmFlag::DELIMIT_CDR2, CdrVersion::XCDRv1), + std::make_tuple(EncodingAlgorithmFlag::DELIMIT_CDR2, CdrVersion::XCDRv2), + std::make_tuple(EncodingAlgorithmFlag::PL_CDR2, CdrVersion::XCDRv1), + std::make_tuple(EncodingAlgorithmFlag::PL_CDR2, CdrVersion::XCDRv2) + )); + +INSTANTIATE_TEST_SUITE_P( + XCdrTest, + XCdrv2PLTest, ::testing::Values( Cdr::XCdrHeaderSelection::SHORT_HEADER, Cdr::XCdrHeaderSelection::LONG_HEADER,