#pragma once #include "common.h" #include template // windows file block size class BlockMarkupIterator { public: BlockMarkupIterator(const std::istream& stream, const std::basic_string_view(&delimiters)[delimiterCount]) : streambuf(*stream.rdbuf()) { std::copy_n(delimiters, delimiterCount, this->delimiters.begin()); } std::optional, delimiterCount>> Next() { std::array, delimiterCount> results; Find(delimiters[0], true); for (int i = 0; i < delimiterCount; ++i) { const auto delimiter = i + 1 < delimiterCount ? delimiters[i + 1] : end; if (auto found = Find(delimiter, false)) results[i] = std::move(found.value()); else return {}; } return results; } private: std::optional> Find(std::basic_string_view delimiter, bool discard) { for (int i = 0; ;) { int pos = buffer.find(delimiter, i); if (pos != std::string::npos) { auto result = !discard ? std::optional(std::basic_string(buffer.begin(), buffer.begin() + pos)) : std::nullopt; buffer.erase(buffer.begin(), buffer.begin() + pos + delimiter.size()); return result; } int oldSize = buffer.size(); buffer.resize(oldSize + blockSize); if (!streambuf.sgetn((char*)(buffer.data() + oldSize), blockSize * sizeof(C))) return {}; i = max(0, oldSize - (int)delimiter.size()); if (discard) { buffer.erase(0, i); i = 0; } } } static constexpr C endImpl[5] = { '|', 'E', 'N', 'D', '|' }; static constexpr std::basic_string_view end{ endImpl, 5 }; std::basic_streambuf& streambuf; std::basic_string buffer; std::array, delimiterCount> delimiters; };