#include "logTypes.hpp" namespace scn { scan_expected scanner::scan(WebStat::QuotedString & value, ContextType & ctx) { static constexpr auto BS_MAP = []() { std::array map {}; map['f'] = '\f'; map['n'] = '\n'; map['r'] = '\r'; map['t'] = '\t'; map['v'] = '\v'; map['"'] = '"'; map['\\'] = '\\'; return map; }(); if (auto empty = scn::scan<>(ctx.range(), R"("")")) { return empty->begin(); } auto simple = scn::scan(ctx.range(), R"("{:[^\"]}")"); if (simple) { value = std::move(simple->value()); return simple->begin(); } if (auto openQuote = scn::scan<>(ctx.range(), R"(")")) { ctx.advance_to(openQuote->begin()); while (true) { if (auto closeQuote = scn::scan<>(ctx.range(), R"(")")) { return closeQuote->begin(); } if (auto plain = scn::scan(ctx.range(), R"({:[^\"]})")) { value.append(plain->value()); ctx.advance_to(plain->begin()); } else if (auto hex = scn::scan(ctx.range(), R"HEX(\x{:.2x})HEX")) { value.append(1, static_cast(hex->value())); ctx.advance_to(hex->begin()); } else if (auto escaped = scn::scan(ctx.range(), R"ESC(\{:.1[fnrtv"\]})ESC")) { value.append(1, BS_MAP[static_cast(escaped->value().front())]); ctx.advance_to(escaped->begin()); } else { return unexpected(simple.error()); } } } return unexpected(simple.error()); } scan_expected scanner::scan(WebStat::QueryString & value, ContextType & ctx) { if (auto null = scn::scan<>(ctx.range(), R"("")")) { return null->begin(); } if (auto empty = scn::scan<>(ctx.range(), R"("?")")) { value.emplace(); return empty->begin(); } auto result = scn::scan(ctx.range(), R"("?{:[^"]}")"); if (!result) { return unexpected(result.error()); } value = std::move(result->value()); return result->begin(); } scan_expected scanner::scan(WebStat::CLFString & value, ContextType & ctx) { if (auto null = scn::scan<>(ctx.range(), R"("-")")) { return null->begin(); } return scn::scanner {}.scan(value.emplace(), ctx); } }