0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-06-02 18:18:56 +02:00

ircd::http: Elaborate the query string interface with indexing.

This commit is contained in:
Jason Volk 2019-03-06 17:17:59 -08:00
parent 654901d7df
commit 6af4782922
2 changed files with 101 additions and 20 deletions

View file

@ -142,10 +142,17 @@ struct ircd::http::query::string
using closure = std::function<bool (const query &)>;
bool for_each(const closure &) const;
string_view at(const string_view &key) const;
bool for_each(const string_view &key, const closure &) const;
string_view _get(const string_view &key, size_t idx = 0) const;
template<class T = string_view> T get(const string_view &key, const T &def = {}, const size_t &idx = 0) const;
string_view operator[](const string_view &key) const;
template<class T> T at(const string_view &key) const;
template<class T = string_view> T get(const string_view &key, const T &def = {}) const;
string_view at(const string_view &key, const size_t &idx = 0) const;
template<class T> T at(const string_view &key, const size_t &idx = 0) const;
size_t count(const string_view &key) const;
bool has(const string_view &key) const;
using string_view::string_view;
};
@ -336,10 +343,11 @@ enum ircd::http::code
template<class T>
T
ircd::http::query::string::get(const string_view &key,
const T &def)
const T &def,
const size_t &idx)
const try
{
const auto val(operator[](key));
const auto val(_get(key, idx));
return val? lex_cast<T>(val) : def;
}
catch(const bad_lex_cast &)
@ -349,10 +357,11 @@ catch(const bad_lex_cast &)
template<class T>
T
ircd::http::query::string::at(const string_view &key)
ircd::http::query::string::at(const string_view &key,
const size_t &idx)
const
{
return lex_cast<T>(at(key));
return lex_cast<T>(at(key, idx));
}
template<size_t BUFSIZE,

View file

@ -698,17 +698,58 @@ ircd::http::line::line(parse::capstan &pc)
{
}
ircd::string_view
ircd::http::query::string::at(const string_view &key)
//
// query::string
//
bool
ircd::http::query::string::has(const string_view &key)
const
{
const auto ret(operator[](key));
if(ret.empty())
bool ret{false};
for_each(key, [&ret]
(const auto &)
{
ret = true;
return false;
});
return ret;
}
size_t
ircd::http::query::string::count(const string_view &key)
const
{
size_t ret{0};
for_each(key, [&ret]
(const auto &)
{
++ret;
return true;
});
return ret;
}
ircd::string_view
ircd::http::query::string::at(const string_view &key,
const size_t &idx)
const
{
const string_view &ret
{
_get(key, idx)
};
if(!ret)
{
thread_local char buf[1024];
const string_view msg{fmt::sprintf
{
buf, "Failed to find value for required query string key '%s'", key
buf, "Failed to find value for required query string key '%s' #%zu.",
key,
idx
}};
throw std::out_of_range
@ -723,20 +764,43 @@ const
ircd::string_view
ircd::http::query::string::operator[](const string_view &key)
const
{
return _get(key, 0);
}
ircd::string_view
ircd::http::query::string::_get(const string_view &key,
size_t idx)
const
{
string_view ret;
const auto match{[&key, &ret]
(const query &query) -> bool
for_each(key, [&idx, &ret]
(const auto &query)
{
if(!idx--)
{
ret = query.second;
return false;
}
else return true;
});
return ret;
}
bool
ircd::http::query::string::for_each(const string_view &key,
const closure &closure)
const
{
return for_each([&key, &closure]
(const auto &query)
{
if(query.first != key)
return true;
ret = query.second;
return false; // false to break out of for_each()
}};
for_each(match);
return ret;
return closure(query);
});
}
bool
@ -759,6 +823,10 @@ const
return qi::parse(start, stop, grammar);
}
//
// parser util
//
size_t
ircd::http::parser::content_length(const string_view &str)
{
@ -779,6 +847,10 @@ ircd::http::parser::content_length(const string_view &str)
return ret;
}
//
// util
//
ircd::const_buffer
ircd::http::writechunk(const mutable_buffer &buf,
const uint32_t &chunk_size)