diff --git a/compiler/extensions/cpp/freemarker/CompoundConstructor.inc.ftl b/compiler/extensions/cpp/freemarker/CompoundConstructor.inc.ftl index cd2652c30..aea8fa2ed 100644 --- a/compiler/extensions/cpp/freemarker/CompoundConstructor.inc.ftl +++ b/compiler/extensions/cpp/freemarker/CompoundConstructor.inc.ftl @@ -35,7 +35,7 @@ ${compoundConstructorsData.compoundName}::${compoundConstructorsData.compoundNam m_areChildrenInitialized(false) <#if withParsingInfoCode> - m_parsingInfo(0, 0) + m_parsingInfo() <#if memberInitializationMacroName != ""> <#if (numExtendedFields > 0)> @@ -101,7 +101,7 @@ ${compoundConstructorsData.compoundName}::${compoundConstructorsData.compoundNam m_areChildrenInitialized(true) <#if withParsingInfoCode> - m_parsingInfo(in.getBitPosition(), 0) + m_parsingInfo(in.getBitPosition()) <#if memberInitializationMacroName != ""> <#if (num_extended_fields(compoundConstructorsData.fieldList) > 0)> @@ -112,7 +112,7 @@ ${compoundConstructorsData.compoundName}::${compoundConstructorsData.compoundNam { <#if withParsingInfoCode> - m_parsingInfo.bitSize = in.getBitPosition() - m_parsingInfo.bitPosition; + m_parsingInfo.initializeBitSize(in.getBitPosition()); } diff --git a/compiler/extensions/cpp/runtime/src/CMakeLists.txt b/compiler/extensions/cpp/runtime/src/CMakeLists.txt index 3d7583208..62b19e423 100644 --- a/compiler/extensions/cpp/runtime/src/CMakeLists.txt +++ b/compiler/extensions/cpp/runtime/src/CMakeLists.txt @@ -84,6 +84,7 @@ set(ZSERIO_CPP_RUNTIME_LIB_SRCS zserio/NoInit.h zserio/OptionalHolder.h zserio/DeltaContext.h + zserio/ParsingInfo.h zserio/PubsubException.h zserio/Reflectable.h zserio/SerializeUtil.h diff --git a/compiler/extensions/cpp/runtime/src/zserio/ParsingInfo.h b/compiler/extensions/cpp/runtime/src/zserio/ParsingInfo.h index bf3f2d029..23daf9215 100644 --- a/compiler/extensions/cpp/runtime/src/zserio/ParsingInfo.h +++ b/compiler/extensions/cpp/runtime/src/zserio/ParsingInfo.h @@ -2,6 +2,9 @@ #define ZSERIO_PARSING_INFO_INC_H #include +#include + +#include "zserio/CppRuntimeException.h" namespace zserio { @@ -10,21 +13,85 @@ namespace zserio * The parsing information returned from parsingInfo() method generated in case of '-withParsingInfo' command * line option. */ -struct ParsingInfo +class ParsingInfo { +public: + /** + * Default constructor. + */ + ParsingInfo() : + m_bitPosition(std::numeric_limits::max()), + m_bitSize(std::numeric_limits::max()) + {} + /** - * Constructor from all fields. + * Constructor from bit position. * - * \param bitPosition_ Bit position in bits. - * \param bitSize_ Bit size in bits. + * \param bitPosition Bit position in bits. */ - ParsingInfo(size_t bitPosition_, size_t bitSize_) : - bitPosition(bitPosition_), - bitSize(bitSize_) + explicit ParsingInfo(size_t bitPosition) : + m_bitPosition(bitPosition), + m_bitSize(std::numeric_limits::max()) {} - size_t bitPosition; /**< blob offset of the object in bits counted from zero */ - size_t bitSize; /**< blob size of the object in bits */ + /** + * Initializes the bit size using the end bit position. + * + * It is supposed that bit position has been already correctly set before this method is called. + * + * \param endBitPosition End bit position to calculate the bit size from. + * + * \throw CppRuntimeException In case of invalid end bit position argument. + */ + void initializeBitSize(size_t endBitPosition) + { + const size_t bitPosition = getBitPosition(); + if (endBitPosition < bitPosition) + { + throw CppRuntimeException("Invalid end bit position argument (") + << endBitPosition << " < " << bitPosition << ")!"; + } + + m_bitSize = endBitPosition - getBitPosition(); + } + + /** + * Gets the bit position. + * + * \return The blob offset of the object in bits counted from zero. + * + * \throw CppRuntimeException In case of invalid (uninitialized) bit position. + */ + size_t getBitPosition() const + { + if (m_bitPosition == std::numeric_limits::max()) + { + throw CppRuntimeException("Invalid bit position, call the reader constructor first!"); + } + + return m_bitPosition; + } + + /** + * Gets the bit size. + * + * \return Blob size of the object in bits. + * + * \throw CppRuntimeException In case of invalid (uninitialized) bit size. + */ + size_t getBitSize() const + { + if (m_bitSize == std::numeric_limits::max()) + { + throw CppRuntimeException("Invalid bit size, call the reader constructor first!"); + } + + return m_bitSize; + } + +private: + size_t m_bitPosition; + size_t m_bitSize; }; } // namespace zserio diff --git a/compiler/extensions/cpp/runtime/test/CMakeLists.txt b/compiler/extensions/cpp/runtime/test/CMakeLists.txt index cb5ba02f0..df2314fa7 100644 --- a/compiler/extensions/cpp/runtime/test/CMakeLists.txt +++ b/compiler/extensions/cpp/runtime/test/CMakeLists.txt @@ -169,6 +169,7 @@ set(ZSERIO_CPP_RUNTIME_TEST_SRCS zserio/FileUtilTest.cpp zserio/MemoryResourceTest.cpp zserio/NewDeleteResourceTest.cpp + zserio/ParsingInfoTest.cpp zserio/PolymorphicAllocatorTest.cpp zserio/PubsubExceptionTest.cpp zserio/ReflectableTest.cpp diff --git a/compiler/extensions/cpp/runtime/test/zserio/ParsingInfoTest.cpp b/compiler/extensions/cpp/runtime/test/zserio/ParsingInfoTest.cpp new file mode 100644 index 000000000..a52b288e3 --- /dev/null +++ b/compiler/extensions/cpp/runtime/test/zserio/ParsingInfoTest.cpp @@ -0,0 +1,45 @@ +#include "gtest/gtest.h" +#include "zserio/CppRuntimeException.h" +#include "zserio/ParsingInfo.h" + +namespace zserio +{ + +TEST(ParsingInfoTest, defaultConstructor) +{ + ParsingInfo parsingInfo; + ASSERT_THROW(parsingInfo.getBitPosition(), CppRuntimeException); + ASSERT_THROW(parsingInfo.getBitSize(), CppRuntimeException); +} + +TEST(ParsingInfoTest, bitPositionConstructor) +{ + ParsingInfo parsingInfo(0); + ASSERT_EQ(0, parsingInfo.getBitPosition()); + ASSERT_THROW(parsingInfo.getBitSize(), CppRuntimeException); +} + +TEST(ParsingInfoTest, initializeBitSize) +{ + ParsingInfo parsingInfo(1); + parsingInfo.initializeBitSize(3); + ASSERT_EQ(1, parsingInfo.getBitPosition()); + ASSERT_EQ(2, parsingInfo.getBitSize()); + + ASSERT_THROW(parsingInfo.initializeBitSize(0), CppRuntimeException); +} + +TEST(ParsingInfoTest, getBitPosition) +{ + ParsingInfo parsingInfo(1); + ASSERT_EQ(1, parsingInfo.getBitPosition()); +} + +TEST(ParsingInfoTest, getBitSize) +{ + ParsingInfo parsingInfo(1); + parsingInfo.initializeBitSize(3); + ASSERT_EQ(2, parsingInfo.getBitSize()); +} + +} // namespace zserio diff --git a/compiler/extensions/cpp/runtime/test/zserio/ReflectableTest.cpp b/compiler/extensions/cpp/runtime/test/zserio/ReflectableTest.cpp index b06bf277b..25036c596 100644 --- a/compiler/extensions/cpp/runtime/test/zserio/ReflectableTest.cpp +++ b/compiler/extensions/cpp/runtime/test/zserio/ReflectableTest.cpp @@ -1981,8 +1981,8 @@ TEST_F(ReflectableTest, reflectableOwner) ASSERT_EQ(bitSizeOfValue, writer.getBitPosition()); const ParsingInfo parsingInfo = reflectable->parsingInfo(); - ASSERT_EQ(0, parsingInfo.bitPosition); - ASSERT_EQ(0, parsingInfo.bitSize); + ASSERT_THROW(parsingInfo.getBitPosition(), CppRuntimeException); + ASSERT_THROW(parsingInfo.getBitSize(), CppRuntimeException); } } // namespace zserio diff --git a/test/arguments/with_parsing_info_code/cpp/WithParsingInfoCodeTest.cpp b/test/arguments/with_parsing_info_code/cpp/WithParsingInfoCodeTest.cpp index 42706c2a8..bceefe74f 100644 --- a/test/arguments/with_parsing_info_code/cpp/WithParsingInfoCodeTest.cpp +++ b/test/arguments/with_parsing_info_code/cpp/WithParsingInfoCodeTest.cpp @@ -78,37 +78,37 @@ class WithParsingInfoCode : public ::testing::Test void checkParsingInfo(const Main& main) { // main - ASSERT_EQ(BIT_POSITION_MAIN, main.parsingInfo().bitPosition); - ASSERT_EQ(BIT_SIZE_MAIN, main.parsingInfo().bitSize); + ASSERT_EQ(BIT_POSITION_MAIN, main.parsingInfo().getBitPosition()); + ASSERT_EQ(BIT_SIZE_MAIN, main.parsingInfo().getBitSize()); // itemChoice - ASSERT_EQ(BIT_POSITION_ITEM_CHOICE, main.getItemChoice().parsingInfo().bitPosition); - ASSERT_EQ(BIT_SIZE_ITEM_CHOICE, main.getItemChoice().parsingInfo().bitSize); + ASSERT_EQ(BIT_POSITION_ITEM_CHOICE, main.getItemChoice().parsingInfo().getBitPosition()); + ASSERT_EQ(BIT_SIZE_ITEM_CHOICE, main.getItemChoice().parsingInfo().getBitSize()); // item - ASSERT_EQ(BIT_POSITION_ITEM, main.getItemChoice().getItem().parsingInfo().bitPosition); - ASSERT_EQ(BIT_SIZE_ITEM, main.getItemChoice().getItem().parsingInfo().bitSize); + ASSERT_EQ(BIT_POSITION_ITEM, main.getItemChoice().getItem().parsingInfo().getBitPosition()); + ASSERT_EQ(BIT_SIZE_ITEM, main.getItemChoice().getItem().parsingInfo().getBitSize()); // valueUnion - ASSERT_EQ(BIT_POSITION_VALUE_UNION, main.getValueUnion().parsingInfo().bitPosition); - ASSERT_EQ(BIT_SIZE_VALUE_UNION, main.getValueUnion().parsingInfo().bitSize); + ASSERT_EQ(BIT_POSITION_VALUE_UNION, main.getValueUnion().parsingInfo().getBitPosition()); + ASSERT_EQ(BIT_SIZE_VALUE_UNION, main.getValueUnion().parsingInfo().getBitSize()); // simpleStruct - ASSERT_EQ(BIT_POSITION_SIMPLE_STRUCT, main.getSimpleStruct().parsingInfo().bitPosition); - ASSERT_EQ(BIT_SIZE_SIMPLE_STRUCT, main.getSimpleStruct().parsingInfo().bitSize); + ASSERT_EQ(BIT_POSITION_SIMPLE_STRUCT, main.getSimpleStruct().parsingInfo().getBitPosition()); + ASSERT_EQ(BIT_SIZE_SIMPLE_STRUCT, main.getSimpleStruct().parsingInfo().getBitSize()); // item - ASSERT_EQ(BIT_POSITION_MAIN_ITEM, main.getItem().parsingInfo().bitPosition); - ASSERT_EQ(BIT_SIZE_MAIN_ITEM, main.getItem().parsingInfo().bitSize); + ASSERT_EQ(BIT_POSITION_MAIN_ITEM, main.getItem().parsingInfo().getBitPosition()); + ASSERT_EQ(BIT_SIZE_MAIN_ITEM, main.getItem().parsingInfo().getBitSize()); // items ASSERT_EQ(3, main.getItems().size()); - ASSERT_EQ(BIT_POSITION_ITEMS0, main.getItems().at(0).parsingInfo().bitPosition); - ASSERT_EQ(BIT_SIZE_ITEMS0, main.getItems().at(0).parsingInfo().bitSize); - ASSERT_EQ(BIT_POSITION_ITEMS1, main.getItems().at(1).parsingInfo().bitPosition); - ASSERT_EQ(BIT_SIZE_ITEMS1, main.getItems().at(1).parsingInfo().bitSize); - ASSERT_EQ(BIT_POSITION_ITEMS2, main.getItems().at(2).parsingInfo().bitPosition); - ASSERT_EQ(BIT_SIZE_ITEMS2, main.getItems().at(2).parsingInfo().bitSize); + ASSERT_EQ(BIT_POSITION_ITEMS0, main.getItems().at(0).parsingInfo().getBitPosition()); + ASSERT_EQ(BIT_SIZE_ITEMS0, main.getItems().at(0).parsingInfo().getBitSize()); + ASSERT_EQ(BIT_POSITION_ITEMS1, main.getItems().at(1).parsingInfo().getBitPosition()); + ASSERT_EQ(BIT_SIZE_ITEMS1, main.getItems().at(1).parsingInfo().getBitSize()); + ASSERT_EQ(BIT_POSITION_ITEMS2, main.getItems().at(2).parsingInfo().getBitPosition()); + ASSERT_EQ(BIT_SIZE_ITEMS2, main.getItems().at(2).parsingInfo().getBitSize()); } static const char* const PATH;