#pragma once #include "Orange/Core/Vector.h" #include #include #include #include namespace orange::stream { template Result Parse(const char*& first, const char* end) { T obj; auto result = std::from_chars(first, end, obj); if (result.ec == std::errc{}) { first = result.ptr; return Result::Success(obj); } return Result::Error(BasicErrorCode::NotFound); } template Result Parse(const char*& first, size_t length) { return Parse(first, first + length); } template Result Parse(const char*& first) { return Parse(first, first + strlen(first)); } inline bool EndOfStream(const char* first, const char* end) { return first == end || *first == '\0'; } inline bool CharMatches(char character, StringView delims) { for (auto delim : delims) { if (character == delim) return true; } return false; } inline size_t Consume(const char*& first, const char* end, StringView delims) { size_t count = 0; while (!EndOfStream(first, end) && CharMatches(*first, delims)) { first++; count++; } return count; } inline size_t ConsumeSpace(const char*& first, const char* end) { return Consume(first, end, " \t"); } template > size_t ReadOrAdvance(const char*& first, const char* end, StringView delims, size_t advancement = 0, OutArray* array = nullptr) { size_t count = 0; while (!EndOfStream(first, end) && !CharMatches(*first, delims)) { if (array) array->push_back(*first); first++; count++; } if (EndOfStream(first, end)) return count; first += advancement; return count; } template > size_t ReadString(const char*& first, const char* end, StringView delims, OutArray& array) { return ReadOrAdvance(first, end, delims, 0, &array); } inline size_t AdvancePast(const char*& first, const char* end, StringView delims) { return ReadOrAdvance(first, end, delims, 1); } }