SerializableSectionPairSection.cpp 6.9 KB

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