Kaynağa Gözat

Add serializable for SectionPairDocument class

Patrick-Christopher Mattulat 2 yıl önce
ebeveyn
işleme
0b7659cbd2

+ 3 - 0
CMakeLists.txt

@@ -186,6 +186,7 @@ set(SOURCE_FILES_IO
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/io/section-pair/validator/SectionPairIdentifierValidator.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/io/section-pair/validator/SectionPairRowValueValidator.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/io/section-pair/validator/SectionPairSectionIdUnmarshalValidator.cpp
+        ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/io/section-pair/serialization/SerializableSectionPairDocument.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/io/section-pair/serialization/SerializableSectionPairRow.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/io/section-pair/serialization/SerializableSectionPairRowListValue.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/io/section-pair/serialization/SerializableSectionPairRowSingleValue.cpp
@@ -286,6 +287,7 @@ if (${LS_STD_BUILD_WITH_TESTS})
             ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/io/section-pair/model/SectionPairRowSingleValueTest.cpp
             ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/io/section-pair/model/SectionPairRowTest.cpp
             ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/io/section-pair/model/SectionPairSectionTest.cpp
+            ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/io/section-pair/serialization/SerializableSectionPairDocumentTest.cpp
             ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/io/section-pair/serialization/SerializableSectionPairRowListValueTest.cpp
             ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/io/section-pair/serialization/SerializableSectionPairRowSingleValueTest.cpp
             ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/io/section-pair/serialization/SerializableSectionPairRowTest.cpp
@@ -304,6 +306,7 @@ if (${LS_STD_BUILD_WITH_TESTS})
             ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/io/FileWriterTest.cpp
             ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/io/StandardOutputWriterTest.cpp
             ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/io/StorableFileTest.cpp
+            ${CMAKE_CURRENT_SOURCE_DIR}/test/classes/io/section-pair/SectionPairDocumentProvider.cpp
             ${CMAKE_CURRENT_SOURCE_DIR}/test/classes/io/section-pair/SectionPairSectionProvider.cpp
             ${CMAKE_CURRENT_SOURCE_DIR}/test/classes/io/xml/TestDataFactory.cpp
             ${CMAKE_CURRENT_SOURCE_DIR}/test/classes/io/xml/XmlParserTestWrapper.cpp)

+ 43 - 0
include/ls-std/io/section-pair/serialization/SerializableSectionPairDocument.hpp

@@ -0,0 +1,43 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-02-16
+* Changed:         2023-02-16
+*
+* */
+
+#ifndef LS_STD_SERIALIZABLE_SECTION_PAIR_DOCUMENT_HPP
+#define LS_STD_SERIALIZABLE_SECTION_PAIR_DOCUMENT_HPP
+
+#include <ls-std/core/Class.hpp>
+#include <ls-std/core/interface/ISerializable.hpp>
+#include <ls-std/os/dynamic-goal.hpp>
+#include <memory>
+
+namespace ls::std::io
+{
+  class LS_STD_DYNAMIC_GOAL SerializableSectionPairDocument : public ls::std::core::interface_type::ISerializable
+  {
+    public:
+
+      explicit SerializableSectionPairDocument(const ::std::shared_ptr<ls::std::core::Class> &_value);
+      ~SerializableSectionPairDocument() override;
+
+      [[nodiscard]] ::std::shared_ptr<ls::std::core::Class> getValue();
+      [[nodiscard]] ls::std::core::type::byte_field marshal() override;
+      void unmarshal(const ls::std::core::type::byte_field &_data) override;
+
+    private:
+
+      ::std::shared_ptr<ls::std::core::Class> value{};
+
+      [[nodiscard]] static core::type::byte_field _getCurrentRow(size_t _iterations, const ls::std::core::type::byte_field &_serializedDocument);
+      [[nodiscard]] static ls::std::core::type::byte_field _getNextSerializedSection(const ls::std::core::type::byte_field &_serializedDocument);
+      [[nodiscard]] static bool _isNotNewSection(const ls::std::core::type::byte_field &_currentRow);
+      void _setValue(const ::std::shared_ptr<ls::std::core::Class> &_value);
+      void _addSection(const ls::std::core::type::byte_field &_serializedSection);
+  };
+}
+
+#endif

+ 2 - 1
include/ls-std/ls-std-io.hpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2023-02-11
- * Changed:         2023-02-15
+ * Changed:         2023-02-16
  *
  * */
 
@@ -30,6 +30,7 @@
 #include <ls-std/io/section-pair/model/SectionPairRowSingleValue.hpp>
 #include <ls-std/io/section-pair/model/SectionPairRowValue.hpp>
 #include <ls-std/io/section-pair/model/SectionPairSection.hpp>
+#include <ls-std/io/section-pair/serialization/SerializableSectionPairDocument.hpp>
 #include <ls-std/io/section-pair/serialization/SerializableSectionPairRow.hpp>
 #include <ls-std/io/section-pair/serialization/SerializableSectionPairRowListValue.hpp>
 #include <ls-std/io/section-pair/serialization/SerializableSectionPairRowSingleValue.hpp>

+ 106 - 0
source/ls-std/io/section-pair/serialization/SerializableSectionPairDocument.cpp

@@ -0,0 +1,106 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-02-16
+* Changed:         2023-02-16
+*
+* */
+
+#include <ls-std/core/evaluator/NullPointerArgumentEvaluator.hpp>
+#include <ls-std/io/NewLine.hpp>
+#include <ls-std/io/section-pair/model/SectionPairDocument.hpp>
+#include <ls-std/io/section-pair/serialization/SerializableSectionPairDocument.hpp>
+
+ls::std::io::SerializableSectionPairDocument::SerializableSectionPairDocument(const ::std::shared_ptr<ls::std::core::Class> &_value)
+{
+  this->_setValue(_value);
+}
+
+ls::std::io::SerializableSectionPairDocument::~SerializableSectionPairDocument() = default;
+
+::std::shared_ptr<ls::std::core::Class> ls::std::io::SerializableSectionPairDocument::getValue()
+{
+  return this->value;
+}
+
+ls::std::core::type::byte_field ls::std::io::SerializableSectionPairDocument::marshal()
+{
+  ls::std::core::type::byte_field serializedDocument{};
+
+  for (const auto &_section : ::std::dynamic_pointer_cast<ls::std::io::SectionPairDocument>(this->value)->getSectionList())
+  {
+    serializedDocument += _section->marshal();
+  }
+
+  return serializedDocument;
+}
+
+void ls::std::io::SerializableSectionPairDocument::unmarshal(const ls::std::core::type::byte_field &_data)
+{
+  ls::std::core::type::byte_field serializedDocument = _data;
+  ls::std::core::type::byte_field serializedSection{};
+
+  do
+  {
+    serializedSection = ls::std::io::SerializableSectionPairDocument::_getNextSerializedSection(serializedDocument);
+    this->_addSection(serializedSection);
+    serializedDocument = serializedDocument.substr(serializedSection.size());
+  } while (!serializedDocument.empty());
+}
+
+void ls::std::io::SerializableSectionPairDocument::_addSection(const ls::std::core::type::byte_field &_serializedSection)
+{
+  ::std::shared_ptr<ls::std::io::SectionPairSection> section = ::std::make_shared<ls::std::io::SectionPairSection>("tmp-id");
+  section->unmarshal(_serializedSection);
+  ::std::dynamic_pointer_cast<ls::std::io::SectionPairDocument>(this->value)->add(section);
+}
+
+ls::std::core::type::byte_field ls::std::io::SerializableSectionPairDocument::_getCurrentRow(size_t _iterations, const ls::std::core::type::byte_field &_serializedDocument)
+{
+  ::std::string newLine = ls::std::io::NewLine::get();
+  ::std::string currentRow{};
+
+  if (_iterations == 1 || _serializedDocument.find('[') != ::std::string::npos)
+  {
+    currentRow = _serializedDocument.substr(0, _serializedDocument.find(newLine + newLine) + 2 * newLine.size());
+  }
+  else
+  {
+    currentRow = _serializedDocument.substr(0, _serializedDocument.find(newLine) + newLine.size());
+  }
+
+  return currentRow;
+}
+
+ls::std::core::type::byte_field ls::std::io::SerializableSectionPairDocument::_getNextSerializedSection(const ls::std::core::type::byte_field &_serializedDocument)
+{
+  ls::std::core::type::byte_field serializedSection{}, currentRow{};
+  size_t iterations{};
+  ls::std::core::type::byte_field serializedDocument = _serializedDocument;
+  bool isNotNewSection{};
+  ::std::string newLine = ls::std::io::NewLine::get();
+
+  do
+  {
+    ++iterations;
+    currentRow = ls::std::io::SerializableSectionPairDocument::_getCurrentRow(iterations, serializedDocument);
+    isNotNewSection = ls::std::io::SerializableSectionPairDocument::_isNotNewSection(currentRow) && !serializedDocument.empty() || iterations == 1;
+    serializedDocument = serializedDocument.substr(currentRow.size());
+    serializedSection += currentRow;
+  } while (isNotNewSection);
+
+  return serializedDocument.empty() ? serializedSection : serializedSection.substr(0, serializedSection.size() - newLine.size());
+}
+
+bool ls::std::io::SerializableSectionPairDocument::_isNotNewSection(const ls::std::core::type::byte_field &_currentRow)
+{
+  ::std::string newLine = ls::std::io::NewLine::get();
+  return _currentRow.find(newLine + newLine) == ::std::string::npos;
+}
+
+void ls::std::io::SerializableSectionPairDocument::_setValue(const ::std::shared_ptr<ls::std::core::Class> &_value)
+{
+  ls::std::core::NullPointerArgumentEvaluator{_value}.evaluate();
+  this->value = _value;
+}

+ 8 - 3
source/ls-std/io/section-pair/serialization/SerializableSectionPairSection.cpp

@@ -3,7 +3,7 @@
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2023-02-14
-* Changed:         2023-02-15
+* Changed:         2023-02-16
 *
 * */
 
@@ -81,6 +81,11 @@ ls::std::core::type::byte_field ls::std::io::SerializableSectionPairSection::_co
 
   do
   {
+    if (currentRows.empty() && iterations > 1)
+    {
+      break;
+    }
+
     ++iterations;
     currentRow = currentRows.substr(0, currentRows.find(newLine) + newLine.size());
     currentRows = currentRows.substr(currentRow.size());
@@ -131,7 +136,7 @@ ls::std::core::type::byte_field ls::std::io::SerializableSectionPairSection::_ge
 
   if (position != -1)
   {
-    sectionHeader = _data.substr(0, position + newLine.size());
+    sectionHeader = _data.substr(0, position + 2 * newLine.size());
   }
 
   return sectionHeader;
@@ -175,7 +180,7 @@ ls::std::core::type::byte_field ls::std::io::SerializableSectionPairSection::_ma
 
 ls::std::core::type::byte_field ls::std::io::SerializableSectionPairSection::_marshalSectionId()
 {
-  return ls::std::io::NewLine::get() + "[" + ::std::dynamic_pointer_cast<ls::std::io::SectionPairSection>(this->value)->getSectionId() + "]" + ls::std::io::NewLine::get();
+  return ls::std::io::NewLine::get() + "[" + ::std::dynamic_pointer_cast<ls::std::io::SectionPairSection>(this->value)->getSectionId() + "]" + ls::std::io::NewLine::get() + ls::std::io::NewLine::get();
 }
 
 void ls::std::io::SerializableSectionPairSection::_setValue(const ::std::shared_ptr<ls::std::core::Class> &_value)

+ 3 - 3
source/ls-std/io/section-pair/validator/SectionPairSectionIdUnmarshalValidator.cpp

@@ -3,7 +3,7 @@
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2023-02-14
-* Changed:         2023-02-15
+* Changed:         2023-02-16
 *
 * */
 
@@ -20,11 +20,11 @@ bool ls::std::io::SectionPairSectionIdUnmarshalValidator::isValid()
 {
   ::std::string newLine = ls::std::io::NewLine::get();
   bool isValidSectionId = this->data.rfind(newLine, 0) == 0;
-  isValidSectionId = isValidSectionId && this->data.rfind(newLine) == (this->data.size() - newLine.size());
+  isValidSectionId = isValidSectionId && this->data.rfind(newLine + newLine) == (this->data.size() - 2 * newLine.size());
 
   if (isValidSectionId)
   {
-    isValidSectionId = ls::std::io::SectionPairSectionIdUnmarshalValidator::_isValidSection(ls::std::io::SectionPairSectionIdUnmarshalValidator::_trimStartAndEnd(this->data, newLine, newLine));
+    isValidSectionId = ls::std::io::SectionPairSectionIdUnmarshalValidator::_isValidSection(ls::std::io::SectionPairSectionIdUnmarshalValidator::_trimStartAndEnd(this->data, newLine, newLine + newLine));
   }
 
   return isValidSectionId;

+ 3 - 3
test/cases/io/section-pair/model/SectionPairSectionTest.cpp

@@ -144,8 +144,8 @@ namespace
 
   TEST_F(SectionPairSectionTest, marshal)
   {
-    shared_ptr<SectionPairSection> section = SectionPairSectionProvider::createSection();
-    byte_field expected = SectionPairSectionProvider::createSerializedSection();
+    shared_ptr<SectionPairSection> section = SectionPairSectionProvider::createSectionWithTomExample();
+    byte_field expected = SectionPairSectionProvider::createSerializedSectionWithTomExample();
     byte_field actual = section->marshal();
 
     ASSERT_STREQ(expected.c_str(), actual.c_str());
@@ -198,7 +198,7 @@ namespace
   TEST_F(SectionPairSectionTest, unmarshal)
   {
     shared_ptr<SectionPairSection> section = make_shared<SectionPairSection>("tmp-id");
-    section->unmarshal(SectionPairSectionProvider::createSerializedSection());
+    section->unmarshal(SectionPairSectionProvider::createSerializedSectionWithTomExample());
 
     ASSERT_STREQ("general", section->getSectionId().c_str());
     ASSERT_EQ(3, section->getRowAmount());

+ 77 - 0
test/cases/io/section-pair/serialization/SerializableSectionPairDocumentTest.cpp

@@ -0,0 +1,77 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-02-16
+* Changed:         2023-02-16
+*
+* */
+
+#include <gtest/gtest.h>
+#include <ls-std-io-test.hpp>
+#include <ls-std/ls-std-core.hpp>
+#include <ls-std/ls-std-io.hpp>
+#include <memory>
+
+using namespace ls::std::core;
+using namespace ls::std::core::type;
+using namespace ls::std::io;
+using namespace ::std;
+using namespace test::io;
+
+namespace
+{
+  class SerializableSectionPairDocumentTest : public ::testing::Test
+  {
+    protected:
+
+      SerializableSectionPairDocumentTest() = default;
+      ~SerializableSectionPairDocumentTest() override = default;
+
+      void SetUp() override
+      {}
+
+      void TearDown() override
+      {}
+  };
+
+  TEST_F(SerializableSectionPairDocumentTest, constructor_no_value)
+  {
+    EXPECT_THROW(
+        {
+          try
+          {
+            SerializableSectionPairDocument serializable = SerializableSectionPairDocument(nullptr);
+          }
+          catch (const IllegalArgumentException &_exception)
+          {
+            throw;
+          }
+        },
+        IllegalArgumentException);
+  }
+
+  TEST_F(SerializableSectionPairDocumentTest, getValue)
+  {
+    SerializableSectionPairDocument serializable(make_shared<SectionPairDocument>());
+    ASSERT_TRUE(serializable.getValue() != nullptr);
+  }
+
+  TEST_F(SerializableSectionPairDocumentTest, marshal)
+  {
+    SerializableSectionPairDocument serializable(SectionPairDocumentProvider::createDocument());
+    byte_field expected = SectionPairDocumentProvider::createSerializedDocument();
+
+    ASSERT_STREQ(expected.c_str(), serializable.marshal().c_str());
+  }
+
+  TEST_F(SerializableSectionPairDocumentTest, unmarshal)
+  {
+    SerializableSectionPairDocument serializable(make_shared<SectionPairDocument>());
+    serializable.unmarshal(SectionPairDocumentProvider::createSerializedDocument());
+
+    shared_ptr<SectionPairDocument> expected = SectionPairDocumentProvider::createDocument();
+
+    ASSERT_EQ(2, expected->getAmountOfSections());
+  }
+}

+ 38 - 6
test/cases/io/section-pair/serialization/SerializableSectionPairSectionTest.cpp

@@ -3,7 +3,7 @@
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2023-02-14
-* Changed:         2023-02-15
+* Changed:         2023-02-16
 *
 * */
 
@@ -57,21 +57,53 @@ namespace
     ASSERT_TRUE(serializable.getValue() != nullptr);
   }
 
-  TEST_F(SerializableSectionPairSectionTest, marshal)
+  TEST_F(SerializableSectionPairSectionTest, marshal_sandra)
   {
-    shared_ptr<SectionPairSection> section = SectionPairSectionProvider::createSection();
+    shared_ptr<SectionPairSection> section = SectionPairSectionProvider::createSectionWithSandraExample();
     SerializableSectionPairSection serializable{section};
-    byte_field expected = SectionPairSectionProvider::createSerializedSection();
+    byte_field expected = SectionPairSectionProvider::createSerializedSectionWithSandraExample();
     byte_field actual = serializable.marshal();
 
     ASSERT_STREQ(expected.c_str(), actual.c_str());
   }
 
-  TEST_F(SerializableSectionPairSectionTest, unmarshal)
+  TEST_F(SerializableSectionPairSectionTest, marshal_tom)
+  {
+    shared_ptr<SectionPairSection> section = SectionPairSectionProvider::createSectionWithTomExample();
+    SerializableSectionPairSection serializable{section};
+    byte_field expected = SectionPairSectionProvider::createSerializedSectionWithTomExample();
+    byte_field actual = serializable.marshal();
+
+    ASSERT_STREQ(expected.c_str(), actual.c_str());
+  }
+
+  TEST_F(SerializableSectionPairSectionTest, unmarshal_sandra)
+  {
+    shared_ptr<SectionPairSection> section = make_shared<SectionPairSection>("tmp-id");
+    SerializableSectionPairSection serializable{section};
+    serializable.unmarshal(SectionPairSectionProvider::createSerializedSectionWithSandraExample());
+
+    ASSERT_STREQ("general", section->getSectionId().c_str());
+    ASSERT_EQ(3, section->getRowAmount());
+    ASSERT_STREQ("name", section->get(0)->getKey().c_str());
+    ASSERT_STREQ("Sandra", dynamic_pointer_cast<SectionPairRowSingleValue>(section->get(0)->getValue())->get().c_str());
+
+    ASSERT_STREQ("age", section->get(1)->getKey().c_str());
+    ASSERT_STREQ("24", dynamic_pointer_cast<SectionPairRowSingleValue>(section->get(1)->getValue())->get().c_str());
+
+    ASSERT_STREQ("hobbies", section->get(2)->getKey().c_str());
+    shared_ptr<SectionPairRowListValue> listRow = dynamic_pointer_cast<SectionPairRowListValue>(section->get(2)->getValue());
+    ASSERT_EQ(3, listRow->getSize());
+    ASSERT_STREQ("swimming", listRow->get(0).c_str());
+    ASSERT_STREQ("cycling", listRow->get(1).c_str());
+    ASSERT_STREQ("singing", listRow->get(2).c_str());
+  }
+
+  TEST_F(SerializableSectionPairSectionTest, unmarshal_tom)
   {
     shared_ptr<SectionPairSection> section = make_shared<SectionPairSection>("tmp-id");
     SerializableSectionPairSection serializable{section};
-    serializable.unmarshal(SectionPairSectionProvider::createSerializedSection());
+    serializable.unmarshal(SectionPairSectionProvider::createSerializedSectionWithTomExample());
 
     ASSERT_STREQ("general", section->getSectionId().c_str());
     ASSERT_EQ(3, section->getRowAmount());

+ 9 - 6
test/cases/io/section-pair/validator/SectionPairSectionIdUnmarshalValidatorTest.cpp

@@ -3,7 +3,7 @@
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2023-02-14
-* Changed:         2023-02-15
+* Changed:         2023-02-16
 *
 * */
 
@@ -14,6 +14,7 @@
 using namespace ls::std::core;
 using namespace ls::std::core::type;
 using namespace ls::std::io;
+using namespace ::std;
 
 namespace
 {
@@ -38,8 +39,9 @@ namespace
 
   TEST_F(SectionPairSectionIdUnmarshalValidatorTest, isValid)
   {
-    byte_field generalSection = NewLine::get() + "[general]" + NewLine::get();
-    byte_field localServerSection = NewLine::get() + "[local-server]" + NewLine::get();
+    string newLine = NewLine::get();
+    byte_field generalSection = newLine + "[general]" + newLine + newLine;
+    byte_field localServerSection = newLine + "[local-server]" + newLine + newLine;
 
     ASSERT_TRUE(SectionPairSectionIdUnmarshalValidator{generalSection}.isValid());
     ASSERT_TRUE(SectionPairSectionIdUnmarshalValidator{localServerSection}.isValid());
@@ -47,9 +49,10 @@ namespace
 
   TEST_F(SectionPairSectionIdUnmarshalValidatorTest, isValid_not_valid)
   {
-    byte_field generalSection = "[general]" + NewLine::get();
-    byte_field localServerSection = NewLine::get() + "[local-server]";
-    byte_field position = NewLine::get() + "position" + NewLine::get();
+    string newLine = NewLine::get();
+    byte_field generalSection = newLine + "[general]" + newLine;
+    byte_field localServerSection = newLine + "[local-server]";
+    byte_field position = newLine + "position" + newLine;
 
     ASSERT_FALSE(SectionPairSectionIdUnmarshalValidator{generalSection}.isValid());
     ASSERT_FALSE(SectionPairSectionIdUnmarshalValidator{localServerSection}.isValid());

+ 65 - 0
test/classes/io/section-pair/SectionPairDocumentProvider.cpp

@@ -0,0 +1,65 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-02-16
+* Changed:         2023-02-16
+*
+* */
+
+#include "SectionPairDocumentProvider.hpp"
+#include <classes/io/section-pair/SectionPairSectionProvider.hpp>
+#include <ls-std/ls-std-io.hpp>
+
+test::io::SectionPairDocumentProvider::SectionPairDocumentProvider() = default;
+
+test::io::SectionPairDocumentProvider::~SectionPairDocumentProvider() = default;
+
+::std::shared_ptr<ls::std::io::SectionPairDocument> test::io::SectionPairDocumentProvider::createDocument()
+{
+  ::std::shared_ptr<ls::std::io::SectionPairDocument> document = ::std::make_shared<ls::std::io::SectionPairDocument>();
+
+  // general section
+
+  ::std::shared_ptr<ls::std::io::SectionPairSection> generalSection = test::io::SectionPairSectionProvider::createSectionWithSandraExample();
+  document->add(generalSection);
+
+  // physical
+
+  ::std::shared_ptr<ls::std::io::SectionPairSection> physicalSection = ::std::make_shared<ls::std::io::SectionPairSection>("physical");
+
+  ::std::shared_ptr<ls::std::io::SectionPairRow> eyeColor = ::std::make_shared<ls::std::io::SectionPairRow>("eye-color", ls::std::io::SectionPairRowEnumType::SECTION_PAIR_ROW_SINGLE_VALUE);
+  ::std::dynamic_pointer_cast<ls::std::io::SectionPairRowSingleValue>(eyeColor->getValue())->set("blue");
+  physicalSection->add(eyeColor);
+
+  ::std::shared_ptr<ls::std::io::SectionPairRow> hairColor = ::std::make_shared<ls::std::io::SectionPairRow>("hair-color", ls::std::io::SectionPairRowEnumType::SECTION_PAIR_ROW_SINGLE_VALUE);
+  ::std::dynamic_pointer_cast<ls::std::io::SectionPairRowSingleValue>(hairColor->getValue())->set("red");
+  physicalSection->add(hairColor);
+
+  ::std::shared_ptr<ls::std::io::SectionPairRow> height = ::std::make_shared<ls::std::io::SectionPairRow>("height", ls::std::io::SectionPairRowEnumType::SECTION_PAIR_ROW_SINGLE_VALUE);
+  ::std::dynamic_pointer_cast<ls::std::io::SectionPairRowSingleValue>(height->getValue())->set("167");
+  physicalSection->add(height);
+
+  document->add(physicalSection);
+
+  return document;
+}
+
+ls::std::core::type::byte_field test::io::SectionPairDocumentProvider::createSerializedDocument()
+{
+  ls::std::core::type::byte_field serializedDocument{};
+  ::std::string newLine = ls::std::io::NewLine::get();
+
+  // general section
+
+  serializedDocument += test::io::SectionPairSectionProvider::createSerializedSectionWithSandraExample();
+
+  // physical
+
+  serializedDocument += newLine + "[physical]" + newLine + newLine;
+  serializedDocument += "eye-color=blue" + newLine;
+  serializedDocument += "hair-color=red" + newLine;
+  serializedDocument += "height=167" + newLine;
+
+  return serializedDocument;
+}

+ 31 - 0
test/classes/io/section-pair/SectionPairDocumentProvider.hpp

@@ -0,0 +1,31 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-02-16
+* Changed:         2023-02-16
+*
+* */
+
+#ifndef LS_STD_SECTION_PAIR_DOCUMENT_PROVIDER_HPP
+#define LS_STD_SECTION_PAIR_DOCUMENT_PROVIDER_HPP
+
+#include <ls-std/ls-std-core.hpp>
+#include <ls-std/ls-std-io.hpp>
+#include <memory>
+
+namespace test::io
+{
+  class SectionPairDocumentProvider
+  {
+    public:
+
+      SectionPairDocumentProvider();
+      ~SectionPairDocumentProvider();
+
+      static ::std::shared_ptr<ls::std::io::SectionPairDocument> createDocument();
+      static ls::std::core::type::byte_field createSerializedDocument();
+  };
+}
+
+#endif

+ 41 - 4
test/classes/io/section-pair/SectionPairSectionProvider.cpp

@@ -3,7 +3,7 @@
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2023-02-15
-* Changed:         2023-02-15
+* Changed:         2023-02-16
 *
 * */
 
@@ -13,7 +13,28 @@ test::io::SectionPairSectionProvider::SectionPairSectionProvider() = default;
 
 test::io::SectionPairSectionProvider::~SectionPairSectionProvider() = default;
 
-::std::shared_ptr<ls::std::io::SectionPairSection> test::io::SectionPairSectionProvider::createSection()
+::std::shared_ptr<ls::std::io::SectionPairSection> test::io::SectionPairSectionProvider::createSectionWithSandraExample()
+{
+  ::std::shared_ptr<ls::std::io::SectionPairSection> generalSection = ::std::make_shared<ls::std::io::SectionPairSection>("general");
+
+  ::std::shared_ptr<ls::std::io::SectionPairRow> name = ::std::make_shared<ls::std::io::SectionPairRow>("name", ls::std::io::SectionPairRowEnumType::SECTION_PAIR_ROW_SINGLE_VALUE);
+  ::std::dynamic_pointer_cast<ls::std::io::SectionPairRowSingleValue>(name->getValue())->set("Sandra");
+  generalSection->add(name);
+
+  ::std::shared_ptr<ls::std::io::SectionPairRow> age = ::std::make_shared<ls::std::io::SectionPairRow>("age", ls::std::io::SectionPairRowEnumType::SECTION_PAIR_ROW_SINGLE_VALUE);
+  ::std::dynamic_pointer_cast<ls::std::io::SectionPairRowSingleValue>(age->getValue())->set("24");
+  generalSection->add(age);
+
+  ::std::shared_ptr<ls::std::io::SectionPairRow> hobbies = ::std::make_shared<ls::std::io::SectionPairRow>("hobbies", ls::std::io::SectionPairRowEnumType::SECTION_PAIR_ROW_LIST_VALUE);
+  ::std::dynamic_pointer_cast<ls::std::io::SectionPairRowListValue>(hobbies->getValue())->add("swimming");
+  ::std::dynamic_pointer_cast<ls::std::io::SectionPairRowListValue>(hobbies->getValue())->add("cycling");
+  ::std::dynamic_pointer_cast<ls::std::io::SectionPairRowListValue>(hobbies->getValue())->add("singing");
+  generalSection->add(hobbies);
+
+  return generalSection;
+}
+
+::std::shared_ptr<ls::std::io::SectionPairSection> test::io::SectionPairSectionProvider::createSectionWithTomExample()
 {
   ::std::shared_ptr<ls::std::io::SectionPairSection> section = ::std::make_shared<ls::std::io::SectionPairSection>("general");
 
@@ -34,11 +55,27 @@ test::io::SectionPairSectionProvider::~SectionPairSectionProvider() = default;
   return section;
 }
 
-ls::std::core::type::byte_field test::io::SectionPairSectionProvider::createSerializedSection()
+ls::std::core::type::byte_field test::io::SectionPairSectionProvider::createSerializedSectionWithSandraExample()
+{
+  ls::std::core::type::byte_field serializedDocument{};
+  ::std::string newLine = ls::std::io::NewLine::get();
+
+  serializedDocument += newLine + "[general]" + newLine + newLine;
+  serializedDocument += "name=Sandra" + newLine;
+  serializedDocument += "age=24" + newLine;
+  serializedDocument += "hobbies:" + newLine;
+  serializedDocument += "  swimming" + newLine;
+  serializedDocument += "  cycling" + newLine;
+  serializedDocument += "  singing" + newLine;
+
+  return serializedDocument;
+}
+
+ls::std::core::type::byte_field test::io::SectionPairSectionProvider::createSerializedSectionWithTomExample()
 {
   ::std::string newLine = ls::std::io::NewLine::get();
 
-  ls::std::core::type::byte_field serializedSection = newLine + "[general]" + newLine;
+  ls::std::core::type::byte_field serializedSection = newLine + "[general]" + newLine + newLine;
   ls::std::core::type::byte_field serializedNameRow = "name=Tom" + newLine;
   ls::std::core::type::byte_field serializedJobsRow = "jobs:" + newLine + "  Farmer" + newLine + "  Bounty Hunter" + newLine;
   ls::std::core::type::byte_field serializedAgeRow = "age=33" + newLine;

+ 5 - 3
test/classes/io/section-pair/SectionPairSectionProvider.hpp

@@ -3,7 +3,7 @@
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2023-02-15
-* Changed:         2023-02-15
+* Changed:         2023-02-16
 *
 * */
 
@@ -23,8 +23,10 @@ namespace test::io
       SectionPairSectionProvider();
       ~SectionPairSectionProvider();
 
-      static ::std::shared_ptr<ls::std::io::SectionPairSection> createSection();
-      static ls::std::core::type::byte_field createSerializedSection();
+      static ::std::shared_ptr<ls::std::io::SectionPairSection> createSectionWithSandraExample();
+      static ::std::shared_ptr<ls::std::io::SectionPairSection> createSectionWithTomExample();
+      static ls::std::core::type::byte_field createSerializedSectionWithSandraExample();
+      static ls::std::core::type::byte_field createSerializedSectionWithTomExample();
   };
 }
 

+ 2 - 1
test/ls-std-io-test.hpp

@@ -3,13 +3,14 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2022-05-14
- * Changed:         2023-02-15
+ * Changed:         2023-02-16
  *
  * */
 
 #ifndef LS_STD_LS_STD_IO_TEST_HPP
 #define LS_STD_LS_STD_IO_TEST_HPP
 
+#include <classes/io/section-pair/SectionPairDocumentProvider.hpp>
 #include <classes/io/section-pair/SectionPairSectionProvider.hpp>
 
 #include <classes/io/xml/TestDataFactory.hpp>