#ifndef seafire__protocol__token_hxx_ #define seafire__protocol__token_hxx_ #include #include #include #include #include namespace seafire::protocol { class token_t { public: token_t(); token_t(std::string); token_t(char const*); bool empty() const; std::string const& str() const; auto operator<=>(token_t const&) const = default; static bool validate_token(std::string const&); private: std::string str_; }; std::ostream& operator<<(std::ostream&, token_t const&); /// Vector of tokens. /// using tokens_t = std::vector; /// Attempt to parse a token. /// template std::optional try_parse_token(Iterator& begin, Iterator end) { std::string token; while (begin != end && grammar::is_space(*begin)) { ++begin; } while (begin != end && grammar::is_tchar(*begin)) { token += *begin++; } if (token.empty()) { return std::nullopt; } return token; } template std::optional try_parse_token(Iterator& begin, Iterator end, std::error_code& ec) { ec = {}; std::string token; while (begin != end && grammar::is_space(*begin)) { ++begin; } while (begin != end && grammar::is_tchar(*begin)) { token += *begin++; } if (token.empty()) { return std::nullopt; } return token; } /// Attempt to parse tokens. /// template std::optional try_parse_tokens(Iterator& begin, Iterator end) { tokens_t tokens; while (begin != end) { while (begin != end && grammar::is_space(*begin)) { ++begin; } auto token = try_parse_token(begin, end); if (!token) { return std::nullopt; } tokens.emplace_back(std::move(*token)); while (begin != end && grammar::is_space(*begin)) { ++begin; } if (begin == end || *begin != ',') { break; } ++begin; // skips ',' } return tokens; } /// Attempt to parse tokens. /// template std::optional try_parse_tokens(Iterator& begin, Iterator end, std::error_code& ec) { tokens_t tokens; while (begin != end) { while (begin != end && grammar::is_space(*begin)) { ++begin; } auto token = try_parse_token(begin, end, ec); if (ec) { return std::nullopt; } if (!token) { return std::nullopt; } tokens.emplace_back(std::move(*token)); while (begin != end && grammar::is_space(*begin)) { ++begin; } if (begin == end || *begin != ',') { break; } ++begin; // skips ',' } return tokens; } } // namespace seafire::protocol #endif