SerializableSectionPairSection.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /*
  2. * Author: Patrick-Christopher Mattulat
  3. * Co-Author: Claude Sonnet 4.6 (LLM)
  4. * Company: Lynar Studios
  5. * E-Mail: webmaster@lynarstudios.com
  6. * Created: 2023-02-14
  7. * Changed: 2026-06-23
  8. *
  9. * */
  10. #include <ls-std/core/evaluator/NullPointerArgumentEvaluator.hpp>
  11. #include <ls-std/io/section-pair/evaluator/SectionPairSectionArgumentEvaluator.hpp>
  12. #include <ls-std/io/section-pair/model/SectionPairRow.hpp>
  13. #include <ls-std/io/section-pair/model/SectionPairSection.hpp>
  14. #include <ls-std/io/section-pair/serialization/SerializableSectionPairSection.hpp>
  15. using ls::standard::core::Class;
  16. using ls::standard::core::NullPointerArgumentEvaluator;
  17. using ls::standard::core::type::byte_field;
  18. using ls::standard::io::section_pair_row_list_element;
  19. using ls::standard::io::SectionPairRow;
  20. using ls::standard::io::SectionPairRowEnumType;
  21. using ls::standard::io::SectionPairSection;
  22. using ls::standard::io::SectionPairSectionArgumentEvaluator;
  23. using ls::standard::io::SerializableSectionPairParameter;
  24. using ls::standard::io::SerializableSectionPairSection;
  25. using std::dynamic_pointer_cast;
  26. using std::make_shared;
  27. using std::shared_ptr;
  28. using std::string;
  29. using std::string_view;
  30. SerializableSectionPairSection::SerializableSectionPairSection(const SerializableSectionPairParameter &_parameter) : Class("SerializableSectionPairSection"), parameter(_parameter)
  31. {
  32. const string message = this->getClassName() + ": model reference is null!";
  33. NullPointerArgumentEvaluator(_parameter.getValue(), message).evaluate();
  34. }
  35. SerializableSectionPairSection::~SerializableSectionPairSection() noexcept = default;
  36. shared_ptr<Class> SerializableSectionPairSection::getValue() const
  37. {
  38. return this->parameter.getValue();
  39. }
  40. byte_field SerializableSectionPairSection::marshal()
  41. {
  42. byte_field serializedSection{};
  43. serializedSection += this->_marshalSectionId();
  44. serializedSection += this->_marshalRows();
  45. return serializedSection;
  46. }
  47. void SerializableSectionPairSection::unmarshal(const byte_field &_data)
  48. {
  49. SectionPairSectionArgumentEvaluator{_data}.evaluate();
  50. const size_t sectionHeaderSize = this->_unmarshalSectionHeader(_data);
  51. this->_unmarshalRows(_data.substr(sectionHeaderSize));
  52. }
  53. byte_field SerializableSectionPairSection::_collectSectionRow(const byte_field &_currentRows, SectionPairRowEnumType &_type) const
  54. {
  55. string row{};
  56. const string newLine = this->parameter.getNewLine();
  57. const string firstRow = _currentRows.substr(0, _currentRows.find(newLine) + newLine.size());
  58. if (_isSingleValueRow(firstRow))
  59. {
  60. row = _collectSectionSingleValueRow(firstRow, _type);
  61. }
  62. if (_isListValueRow(firstRow))
  63. {
  64. row = this->_collectSectionListValueRow(_currentRows, _type);
  65. }
  66. return row;
  67. }
  68. byte_field SerializableSectionPairSection::_collectSectionListValueRow(const byte_field &_currentRows, SectionPairRowEnumType &_type) const
  69. {
  70. byte_field currentRows = _currentRows;
  71. byte_field currentRow{};
  72. byte_field row{};
  73. const string newLine = this->parameter.getNewLine();
  74. _type = SectionPairRowEnumType::SECTION_PAIR_ROW_LIST_VALUE;
  75. size_t iterations{};
  76. bool isStillListRow{};
  77. do
  78. {
  79. if (currentRows.empty() && iterations > 1)
  80. {
  81. break;
  82. }
  83. ++iterations;
  84. currentRow = currentRows.substr(0, currentRows.find(newLine) + newLine.size());
  85. currentRows = currentRows.substr(currentRow.size());
  86. isStillListRow = !SerializableSectionPairSection::_isStartingValueRow(currentRow) || iterations == 1;
  87. if (isStillListRow)
  88. {
  89. row += currentRow;
  90. }
  91. } while (isStillListRow);
  92. return row;
  93. }
  94. byte_field SerializableSectionPairSection::_collectSectionSingleValueRow(const byte_field &_firstRow, SectionPairRowEnumType &_type)
  95. {
  96. _type = SectionPairRowEnumType::SECTION_PAIR_ROW_SINGLE_VALUE;
  97. return _firstRow;
  98. }
  99. size_t SerializableSectionPairSection::_getNthSubStringPosition(const string_view _text, const string_view _subText)
  100. {
  101. size_t position = string::npos;
  102. size_t amount{};
  103. for (size_t index = 0; index < (_text.size() - _subText.size()); index++)
  104. {
  105. if (_text.substr(index, _subText.size()) == _subText)
  106. {
  107. ++amount;
  108. }
  109. if (amount == 2)
  110. {
  111. position = index;
  112. break;
  113. }
  114. }
  115. return position;
  116. }
  117. byte_field SerializableSectionPairSection::_getSectionHeader(const byte_field &_data) const
  118. {
  119. byte_field sectionHeader{};
  120. const string newLine = this->parameter.getNewLine();
  121. if (const size_t position = _getNthSubStringPosition(_data, newLine); position != string::npos)
  122. {
  123. sectionHeader = _data.substr(0, position + 2 * newLine.size());
  124. }
  125. return sectionHeader;
  126. }
  127. byte_field SerializableSectionPairSection::_getSectionId(const string_view _sectionHeader)
  128. {
  129. auto sectionId = byte_field{_sectionHeader.substr(_sectionHeader.find('[') + 1)};
  130. return sectionId.substr(0, sectionId.find(']'));
  131. }
  132. bool SerializableSectionPairSection::_isListValueRow(const string_view _currentRow)
  133. {
  134. return _currentRow.find(':') != string::npos;
  135. }
  136. bool SerializableSectionPairSection::_isStartingValueRow(const string &_currentRow)
  137. {
  138. const bool isSingleValue = _isSingleValueRow(_currentRow);
  139. const bool isListValue = _isListValueRow(_currentRow);
  140. return isSingleValue || isListValue;
  141. }
  142. bool SerializableSectionPairSection::_isSingleValueRow(const string_view _currentRow)
  143. {
  144. return _currentRow.find('=') != string::npos;
  145. }
  146. byte_field SerializableSectionPairSection::_marshalRows() const
  147. {
  148. byte_field serializedSectionRows{};
  149. for (const auto &_row : dynamic_pointer_cast<SectionPairSection>(this->parameter.getValue())->getList())
  150. {
  151. _row->reserveNewLine(this->parameter.getNewLine());
  152. serializedSectionRows += _row->marshal();
  153. }
  154. return serializedSectionRows;
  155. }
  156. byte_field SerializableSectionPairSection::_marshalSectionId() const
  157. {
  158. const string newLine = this->parameter.getNewLine();
  159. return newLine + "[" + dynamic_pointer_cast<SectionPairSection>(this->parameter.getValue())->getSectionId() + "]" + newLine + newLine;
  160. }
  161. void SerializableSectionPairSection::_unmarshalRow(const string &_sectionRow, SectionPairRowEnumType _type) const
  162. {
  163. const auto row = make_shared<SectionPairRow>("tmp-dir", _type);
  164. row->reserveNewLine(this->parameter.getNewLine());
  165. row->unmarshal(_sectionRow);
  166. dynamic_pointer_cast<SectionPairSection>(this->parameter.getValue())->add(row);
  167. }
  168. void SerializableSectionPairSection::_unmarshalRows(const byte_field &_serializedRows) const
  169. {
  170. string currentRows = _serializedRows;
  171. SectionPairRowEnumType type{};
  172. while (!currentRows.empty())
  173. {
  174. string sectionRow = this->_collectSectionRow(currentRows, type);
  175. this->_unmarshalRow(sectionRow, type);
  176. currentRows = currentRows.substr(sectionRow.size());
  177. }
  178. }
  179. size_t SerializableSectionPairSection::_unmarshalSectionHeader(const byte_field &_data) const
  180. {
  181. const byte_field sectionHeader = this->_getSectionHeader(_data);
  182. dynamic_pointer_cast<SectionPairSection>(this->parameter.getValue())->setSectionId(SerializableSectionPairSection::_getSectionId(sectionHeader));
  183. return sectionHeader.size();
  184. }