Mgr::QueryParams::Parse(Parser::Tokenizer &tok, QueryParams &aParams)
{
    static const CharacterSet nameChars = CharacterSet("param-name", "_") + CharacterSet::ALPHA + CharacterSet::DIGIT;
    static const CharacterSet valueChars = CharacterSet("param-value", "&= #").complement();
    static const CharacterSet delimChars("param-delim", "&");

    while (!tok.atEnd()) {

        // TODO: remove '#' processing when AnyP::Uri splits 'query#fragment' properly
        // #fragment handled by caller. Do not throw.
        if (tok.remaining()[0] == '#')
            return;

        if (tok.skipAll(delimChars))
            continue;

        SBuf nameStr;
        if (!tok.prefix(nameStr, nameChars))
            throw TextException("invalid query parameter name", Here());
        if (!tok.skip('='))
            throw TextException("missing parameter value", Here());

        SBuf valueStr;
        if (!tok.prefix(valueStr, valueChars))
            throw TextException("missing or malformed parameter value", Here());

        const auto name = SBufToString(nameStr);
        const auto value = ParseParamValue(valueStr);
        aParams.params.emplace_back(name, value);
    }
}
Mgr::QueryParams::Parse(Parser::Tokenizer &tok, QueryParams &aParams)
{
    static const CharacterSet nameChars = CharacterSet("param-name", "_") + CharacterSet::ALPHA + CharacterSet::DIGIT;
    static const CharacterSet valueChars = CharacterSet("param-value", "&= #").complement();
    static const CharacterSet delimChars("param-delim", "&");

    while (!tok.atEnd()) {

         
         
        if (tok.remaining()[0] == '#')
            return;

        if (tok.skipAll(delimChars))
            continue;

        SBuf nameStr;
        if (!tok.prefix(nameStr, nameChars))
            throw TextException("invalid query parameter name", Here());
        if (!tok.skip('='))
            throw TextException("missing parameter value", Here());

        SBuf valueStr;
        if (!tok.prefix(valueStr, valueChars))
            throw TextException("missing or malformed parameter value", Here());

        const auto name = SBufToString(nameStr);
        const auto value = ParseParamValue(valueStr);
        aParams.params.emplace_back(name, value);
    }
}