/* * Author: Patrick-Christopher Mattulat * Company: Lynar Studios * E-Mail: webmaster@lynarstudios.com * Created: 2023-02-14 * Changed: 2023-05-19 * * */ #include #include #include #include #include using ls::std::core::Class; using ls::std::core::NullPointerArgumentEvaluator; using ls::std::core::type::byte_field; using ls::std::io::section_pair_row_list_element; using ls::std::io::SectionPairRow; using ls::std::io::SectionPairRowEnumType; using ls::std::io::SectionPairSection; using ls::std::io::SectionPairSectionArgumentEvaluator; using ls::std::io::SerializableSectionPairParameter; using ls::std::io::SerializableSectionPairSection; using std::dynamic_pointer_cast; using std::make_shared; using std::shared_ptr; using std::string; using std::string_view; SerializableSectionPairSection::SerializableSectionPairSection(const SerializableSectionPairParameter &_parameter) : Class("SerializableSectionPairSection"), parameter(_parameter) { string message = this->getClassName() + ": model reference is null!"; NullPointerArgumentEvaluator(_parameter.getValue(), message).evaluate(); } SerializableSectionPairSection::~SerializableSectionPairSection() noexcept = default; shared_ptr SerializableSectionPairSection::getValue() const { return this->parameter.getValue(); } byte_field SerializableSectionPairSection::marshal() { byte_field serializedSection{}; serializedSection += this->_marshalSectionId(); serializedSection += this->_marshalRows(); return serializedSection; } void SerializableSectionPairSection::unmarshal(const byte_field &_data) { SectionPairSectionArgumentEvaluator{_data}.evaluate(); size_t sectionHeaderSize = this->_unmarshalSectionHeader(_data); this->_unmarshalRows(_data.substr(sectionHeaderSize)); } byte_field SerializableSectionPairSection::_collectSectionRow(const byte_field &_currentRows, SectionPairRowEnumType &_type) const { string row{}; string newLine = this->parameter.getNewLine(); string firstRow = _currentRows.substr(0, _currentRows.find(newLine) + newLine.size()); if (SerializableSectionPairSection::_isSingleValueRow(firstRow)) { row = SerializableSectionPairSection::_collectSectionSingleValueRow(firstRow, _type); } if (SerializableSectionPairSection::_isListValueRow(firstRow)) { row = this->_collectSectionListValueRow(_currentRows, _type); } return row; } byte_field SerializableSectionPairSection::_collectSectionListValueRow(const byte_field &_currentRows, SectionPairRowEnumType &_type) const { byte_field currentRows = _currentRows; byte_field currentRow{}; byte_field row{}; string newLine = this->parameter.getNewLine(); _type = SectionPairRowEnumType::SECTION_PAIR_ROW_LIST_VALUE; size_t iterations{}; bool isStillListRow{}; do { if (currentRows.empty() && iterations > 1) { break; } ++iterations; currentRow = currentRows.substr(0, currentRows.find(newLine) + newLine.size()); currentRows = currentRows.substr(currentRow.size()); isStillListRow = !SerializableSectionPairSection::_isStartingValueRow(currentRow) || iterations == 1; if (isStillListRow) { row += currentRow; } } while (isStillListRow); return row; } byte_field SerializableSectionPairSection::_collectSectionSingleValueRow(const byte_field &_firstRow, SectionPairRowEnumType &_type) { _type = SectionPairRowEnumType::SECTION_PAIR_ROW_SINGLE_VALUE; return _firstRow; } size_t SerializableSectionPairSection::_getNthSubStringPosition(string_view _text, string_view _subText) { size_t position = -1; size_t amount{}; for (int index = 0; index < (_text.size() - _subText.size()); index++) { if (_text.substr(index, _subText.size()) == _subText) { ++amount; } if (amount == 2) { position = index; break; } } return position; } byte_field SerializableSectionPairSection::_getSectionHeader(const byte_field &_data) const { byte_field sectionHeader{}; string newLine = this->parameter.getNewLine(); if (size_t position = SerializableSectionPairSection::_getNthSubStringPosition(_data, newLine); position != -1) { sectionHeader = _data.substr(0, position + 2 * newLine.size()); } return sectionHeader; } byte_field SerializableSectionPairSection::_getSectionId(string_view _sectionHeader) { auto sectionId = byte_field{_sectionHeader.substr(_sectionHeader.find('[') + 1)}; return sectionId.substr(0, sectionId.find(']')); } bool SerializableSectionPairSection::_isListValueRow(string_view _currentRow) { return _currentRow.find(':') != string::npos; } bool SerializableSectionPairSection::_isStartingValueRow(const string &_currentRow) { bool isSingleValue = SerializableSectionPairSection::_isSingleValueRow(_currentRow); bool isListValue = SerializableSectionPairSection::_isListValueRow(_currentRow); return isSingleValue || isListValue; } bool SerializableSectionPairSection::_isSingleValueRow(string_view _currentRow) { return _currentRow.find('=') != string::npos; } byte_field SerializableSectionPairSection::_marshalRows() const { byte_field serializedSectionRows{}; for (const auto &_row : dynamic_pointer_cast(this->parameter.getValue())->getList()) { _row->reserveNewLine(this->parameter.getNewLine()); serializedSectionRows += _row->marshal(); } return serializedSectionRows; } byte_field SerializableSectionPairSection::_marshalSectionId() const { string newLine = this->parameter.getNewLine(); return newLine + "[" + dynamic_pointer_cast(this->parameter.getValue())->getSectionId() + "]" + newLine + newLine; } void SerializableSectionPairSection::_unmarshalRow(const string &_sectionRow, SectionPairRowEnumType _type) const { auto row = make_shared("tmp-dir", _type); row->reserveNewLine(this->parameter.getNewLine()); row->unmarshal(_sectionRow); dynamic_pointer_cast(this->parameter.getValue())->add(row); } void SerializableSectionPairSection::_unmarshalRows(const byte_field &_serializedRows) const { string currentRows = _serializedRows; SectionPairRowEnumType type{}; while (!currentRows.empty()) { string sectionRow = this->_collectSectionRow(currentRows, type); this->_unmarshalRow(sectionRow, type); currentRows = currentRows.substr(sectionRow.size()); } } size_t SerializableSectionPairSection::_unmarshalSectionHeader(const byte_field &_data) const { byte_field sectionHeader = this->_getSectionHeader(_data); dynamic_pointer_cast(this->parameter.getValue())->setSectionId(SerializableSectionPairSection::_getSectionId(sectionHeader)); return sectionHeader.size(); }