Tidy up basic_fields, header, and concepts

This commit is contained in:
Vinnie Falco
2017-06-06 16:20:59 -07:00
parent fb2f777b4d
commit f363654300
7 changed files with 253 additions and 167 deletions

View File

@@ -5,6 +5,8 @@ Version 50
* Use allocator more in basic_fields * Use allocator more in basic_fields
* Fix basic_fields allocator awareness * Fix basic_fields allocator awareness
* Use field in basic_fields and call sites * Use field in basic_fields and call sites
* Use field in basic_parser
* Tidy up basic_fields, header, and field concepts
API Changes: API Changes:

View File

@@ -64,39 +64,70 @@ In this table:
[/ [/
/** OutputFields
[section:Fields Fields] Can be serialized by `beast::http::serializer`
*/
public:
// This algorithm produces a set of buffers
// corresponding to the serialized representation
// of the fields
//
struct reader
{
using const_buffers_type = implementation-defined
A type meeting the requirements of [*Fields] represents a container ...
used to store HTTP header fields. };
In this table: protected:
string_view method_impl() const;
string_view target_impl() const;
string_view reason_impl() const;
* `X` denotes a type that meets the requirements of [*Fields]. bool close_impl () const;
bool chunked_impl () const;
* `c` is a value of type `X const`. bool content_length_impl () const;
[table FieldSequence requirements
[[expression][type][semantics, pre/post-conditions]]
[
[]
[]
[
]
]
]
[endsect] /** InputFields
Operations we'd like to perform Can be parsed by `beast::http::parser`
*/
public:
void insert (field f, string_view value);
void insert (string_view name, string_view value);
Determine if a field exists protected:
bool exists(field f) const; void method_impl (string_view s);
bool exists(string_view s) const; void target_impl (string_view s);
void reason_impl (string_view s);
iterator find(field f) const;
iterator find(string_view s);
/** Fields
Has a container interface and supports input and output.
`beast::http:basic_fields` is a model.
*/
public:
bool exists(field f) const;
bool exists(string_view s) const;
iterator find(field f) const;
iterator find(string_view s);
std::size_t erase (field f);
std::size_t erase (string_view s);
iterator erase (iterator);
protected:
void content_length_impl(std::uint64_t n);
void connection_impl(close_t);
void connection_impl(keep_alive_t);
void connection_impl(upgrade_t);
void chunked_impl();
] ]

View File

@@ -338,45 +338,57 @@ public:
swap(basic_fields<Alloc>& lhs, basic_fields<Alloc>& rhs); swap(basic_fields<Alloc>& lhs, basic_fields<Alloc>& rhs);
protected: protected:
//--------------------------------------------------------------------------
// //
// for `header // for serializing
// //
/** Returns the stored request-method string. /** Returns the stored request-method string.
@note This is called by the @ref header implementation. @note This is called by the @ref header implementation.
*/ */
string_view method_impl() const; string_view get_method_impl() const;
/** Returns the stored request-target string. /** Returns the stored request-target string.
@note This is called by the @ref header implementation. @note This is called by the @ref header implementation.
*/ */
string_view target_impl() const; string_view get_target_impl() const;
/** Returns the stored obsolete reason-phrase string. /** Returns the stored obsolete reason-phrase string.
@note This is called by the @ref header implementation. @note This is called by the @ref header implementation.
*/ */
string_view reason_impl() const; string_view get_reason_impl() const;
//--------------------------------------------------------------------------
//
// for parsing
//
/** Set or clear the stored request-method string. /** Set or clear the stored request-method string.
@note This is called by the @ref header implementation. @note This is called by the @ref header implementation.
*/ */
void method_impl(string_view s); void set_method_impl(string_view s);
/** Set or clear the stored request-target string. /** Set or clear the stored request-target string.
@note This is called by the @ref header implementation. @note This is called by the @ref header implementation.
*/ */
void target_impl(string_view s); void set_target_impl(string_view s);
/** Set or clear the stored obsolete reason-phrase string. /** Set or clear the stored obsolete reason-phrase string.
@note This is called by the @ref header implementation. @note This is called by the @ref header implementation.
*/ */
void reason_impl(string_view s); void set_reason_impl(string_view s);
//--------------------------------------------------------------------------
//
// for container
//
/** Set the Content-Length field to the specified value. /** Set the Content-Length field to the specified value.

View File

@@ -365,7 +365,7 @@ template<class Allocator>
inline inline
string_view string_view
basic_fields<Allocator>:: basic_fields<Allocator>::
method_impl() const get_method_impl() const
{ {
return method_; return method_;
} }
@@ -374,7 +374,7 @@ template<class Allocator>
inline inline
string_view string_view
basic_fields<Allocator>:: basic_fields<Allocator>::
target_impl() const get_target_impl() const
{ {
return target_or_reason_; return target_or_reason_;
} }
@@ -383,7 +383,7 @@ template<class Allocator>
inline inline
string_view string_view
basic_fields<Allocator>:: basic_fields<Allocator>::
reason_impl() const get_reason_impl() const
{ {
return target_or_reason_; return target_or_reason_;
} }
@@ -392,7 +392,7 @@ template<class Allocator>
inline inline
void void
basic_fields<Allocator>:: basic_fields<Allocator>::
method_impl(string_view s) set_method_impl(string_view s)
{ {
realloc_string(method_, s); realloc_string(method_, s);
} }
@@ -401,7 +401,7 @@ template<class Allocator>
inline inline
void void
basic_fields<Allocator>:: basic_fields<Allocator>::
target_impl(string_view s) set_target_impl(string_view s)
{ {
realloc_string(target_or_reason_, s); realloc_string(target_or_reason_, s);
} }
@@ -410,11 +410,13 @@ template<class Allocator>
inline inline
void void
basic_fields<Allocator>:: basic_fields<Allocator>::
reason_impl(string_view s) set_reason_impl(string_view s)
{ {
realloc_string(target_or_reason_, s); realloc_string(target_or_reason_, s);
} }
//---
template<class Allocator> template<class Allocator>
inline inline
void void

View File

@@ -19,60 +19,176 @@ namespace beast {
namespace http { namespace http {
template<class Fields> template<class Fields>
template<class> template<class Arg1, class... ArgN, class>
string_view
header<true, Fields>:: header<true, Fields>::
get_method_string() const header(Arg1&& arg1, ArgN&&... argn)
: Fields(std::forward<Arg1>(arg1),
std::forward<ArgN>(argn)...)
{ {
if(method_ != verb::unknown)
return to_string(method_);
return this->method_impl();
} }
template<class Fields> template<class Fields>
template<class> inline
verb
header<true, Fields>::
method() const
{
return method_;
}
template<class Fields>
void void
header<true, Fields>:: header<true, Fields>::
set_method(verb v) method(verb v)
{ {
if(v == verb::unknown) if(v == verb::unknown)
BOOST_THROW_EXCEPTION( BOOST_THROW_EXCEPTION(
std::invalid_argument{"unknown verb"}); std::invalid_argument{"unknown verb"});
method_ = v; method_ = v;
this->method_impl({}); this->set_method_impl({});
}
template<class Fields>
string_view
header<true, Fields>::
method_string() const
{
if(method_ != verb::unknown)
return to_string(method_);
return this->get_method_impl();
} }
template<class Fields> template<class Fields>
template<class>
void void
header<true, Fields>:: header<true, Fields>::
set_method(string_view s) method(string_view s)
{ {
method_ = string_to_verb(s); method_ = string_to_verb(s);
if(method_ != verb::unknown) if(method_ != verb::unknown)
this->method_impl({}); this->set_method_impl({});
else else
this->method_impl(s); this->set_method_impl(s);
}
template<class Fields>
inline
string_view
header<true, Fields>::
target() const
{
return this->get_target_impl();
}
template<class Fields>
inline
void
header<true, Fields>::
target(string_view s)
{
this->set_target_impl(s);
}
template<class Fields>
void
swap(
header<true, Fields>& h1,
header<true, Fields>& h2)
{
using std::swap;
swap(
static_cast<Fields&>(h1),
static_cast<Fields&>(h2));
swap(h1.version, h2.version);
swap(h1.method_, h2.method_);
}
//------------------------------------------------------------------------------
template<class Fields>
template<class Arg1, class... ArgN, class>
header<false, Fields>::
header(Arg1&& arg1, ArgN&&... argn)
: Fields(std::forward<Arg1>(arg1),
std::forward<ArgN>(argn)...)
{
}
template<class Fields>
inline
status
header<false, Fields>::
result() const
{
return int_to_status(
static_cast<int>(result_));
}
template<class Fields>
inline
void
header<false, Fields>::
result(status v)
{
result_ = v;
}
template<class Fields>
inline
void
header<false, Fields>::
result(unsigned v)
{
if(v > 999)
BOOST_THROW_EXCEPTION(
std::invalid_argument{
"invalid result-code"});
result_ = static_cast<status>(v);
}
template<class Fields>
inline
unsigned
header<false, Fields>::
result_int() const
{
return static_cast<unsigned>(result_);
} }
template<class Fields> template<class Fields>
template<class>
string_view string_view
header<false, Fields>:: header<false, Fields>::
get_reason() const reason() const
{ {
auto const s = this->reason_impl(); auto const s = this->get_reason_impl();
if(! s.empty()) if(! s.empty())
return s; return s;
return obsolete_reason(result_); return obsolete_reason(result_);
} }
template<class Fields>
inline
void
header<false, Fields>::
reason(string_view s)
{
this->set_reason_impl(s);
}
template<class Fields>
void
swap(
header<false, Fields>& h1,
header<false, Fields>& h2)
{
using std::swap;
swap(
static_cast<Fields&>(h1),
static_cast<Fields&>(h2));
swap(h1.version, h2.version);
swap(h1.result_, h2.result_);
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace detail {
} // detail
template<bool isRequest, class Body, class Fields> template<bool isRequest, class Body, class Fields>
bool bool
message<isRequest, Body, Fields>:: message<isRequest, Body, Fields>::
@@ -239,34 +355,6 @@ prepare_payload(std::false_type)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template<class Fields>
void
swap(
header<true, Fields>& h1,
header<true, Fields>& h2)
{
using std::swap;
swap(
static_cast<Fields&>(h1),
static_cast<Fields&>(h2));
swap(h1.version, h2.version);
swap(h1.method_, h2.method_);
}
template<class Fields>
void
swap(
header<false, Fields>& h1,
header<false, Fields>& h2)
{
using std::swap;
swap(
static_cast<Fields&>(h1),
static_cast<Fields&>(h2));
swap(h1.version, h2.version);
swap(h1.result_, h2.result_);
}
template<bool isRequest, class Body, class Fields> template<bool isRequest, class Body, class Fields>
void void
swap( swap(

View File

@@ -104,11 +104,7 @@ struct header<true, Fields> : Fields
typename std::decay<Arg1>::type, typename std::decay<Arg1>::type,
header>::value>::type> header>::value>::type>
explicit explicit
header(Arg1&& arg1, ArgN&&... argn) header(Arg1&& arg1, ArgN&&... argn);
: Fields(std::forward<Arg1>(arg1),
std::forward<ArgN>(argn)...)
{
}
/** Return the request-method verb. /** Return the request-method verb.
@@ -121,10 +117,7 @@ struct header<true, Fields> : Fields
@see @ref method_string @see @ref method_string
*/ */
verb verb
method() const method() const;
{
return method_;
}
/** Set the request-method verb. /** Set the request-method verb.
@@ -136,10 +129,7 @@ struct header<true, Fields> : Fields
@throw std::invalid_argument when `v == verb::unknown`. @throw std::invalid_argument when `v == verb::unknown`.
*/ */
void void
method(verb v) method(verb v);
{
set_method(v);
}
/** Return the request-method string. /** Return the request-method string.
@@ -148,10 +138,7 @@ struct header<true, Fields> : Fields
@see @ref method @see @ref method
*/ */
string_view string_view
method_string() const method_string() const;
{
return get_method_string();
}
/** Set the request-method string. /** Set the request-method string.
@@ -164,20 +151,14 @@ struct header<true, Fields> : Fields
@note This function is only available when `isRequest == true`. @note This function is only available when `isRequest == true`.
*/ */
void void
method(string_view s) method(string_view s);
{
set_method(s);
}
/** Returns the request-target string. /** Returns the request-target string.
@note This function is only available when `isRequest == true`. @note This function is only available when `isRequest == true`.
*/ */
string_view string_view
target() const target() const;
{
return this->target_impl();
}
/** Set the request-target string. /** Set the request-target string.
@@ -186,10 +167,7 @@ struct header<true, Fields> : Fields
@note This function is only available when `isRequest == true`. @note This function is only available when `isRequest == true`.
*/ */
void void
target(string_view s) target(string_view s);
{
this->target_impl(s);
}
private: private:
template<bool, class, class> template<bool, class, class>
@@ -200,18 +178,6 @@ private:
void void
swap(header<true, T>& m1, header<true, T>& m2); swap(header<true, T>& m1, header<true, T>& m2);
template<class = void>
string_view
get_method_string() const;
template<class = void>
void
set_method(verb v);
template<class = void>
void
set_method(string_view v);
verb method_ = verb::unknown; verb method_ = verb::unknown;
}; };
@@ -277,11 +243,7 @@ struct header<false, Fields> : Fields
typename std::decay<Arg1>::type, typename std::decay<Arg1>::type,
header>::value>::type> header>::value>::type>
explicit explicit
header(Arg1&& arg1, ArgN&&... argn) header(Arg1&& arg1, ArgN&&... argn);
: Fields(std::forward<Arg1>(arg1),
std::forward<ArgN>(argn)...)
{
}
#endif #endif
/** The response status-code result. /** The response status-code result.
@@ -293,25 +255,18 @@ struct header<false, Fields> : Fields
@note This member is only available when `isRequest == false`. @note This member is only available when `isRequest == false`.
*/ */
status status
result() const result() const;
{
return int_to_status(
static_cast<int>(result_));
}
/** Set the response status-code result. /** Set the response status-code.
@param v The code to set. @param v The code to set.
@note This member is only available when `isRequest == false`. @note This member is only available when `isRequest == false`.
*/ */
void void
result(status v) result(status v);
{
result_ = v;
}
/** Set the raw status-code result as an integer. /** Set the response status-code as an integer.
This sets the status code to the exact number passed in. This sets the status code to the exact number passed in.
If the number does not correspond to one of the known If the number does not correspond to one of the known
@@ -320,26 +275,21 @@ struct header<false, Fields> : Fields
original raw status-code. original raw status-code.
@param v The status-code integer to set. @param v The status-code integer to set.
@throw std::invalid_argument if `v > 999`.
*/ */
void void
result(int v) result(unsigned v);
{
result_ = static_cast<status>(v);
}
/** The response status-code result expressed as an integer. /** The response status-code expressed as an integer.
This returns the raw status code as an integer, even This returns the raw status code as an integer, even
when that code is not in the list of known status codes. when that code is not in the list of known status codes.
@note This member is only available when `isRequest == false`. @note This member is only available when `isRequest == false`.
*/ */
int unsigned
result_int() const result_int() const;
{
return static_cast<int>(result_);
}
/** Return the response reason-phrase. /** Return the response reason-phrase.
@@ -348,10 +298,7 @@ struct header<false, Fields> : Fields
@note This function is only available when `isRequest == false`. @note This function is only available when `isRequest == false`.
*/ */
string_view string_view
reason() const reason() const;
{
return get_reason();
}
/** Set the response reason-phrase (deprecated) /** Set the response reason-phrase (deprecated)
@@ -372,10 +319,7 @@ struct header<false, Fields> : Fields
@note This function is only available when `isRequest == false`. @note This function is only available when `isRequest == false`.
*/ */
void void
reason(string_view s) reason(string_view s);
{
this->reason_impl(s);
}
private: private:
template<bool, class, class> template<bool, class, class>
@@ -386,10 +330,6 @@ private:
void void
swap(header<false, T>& m1, header<false, T>& m2); swap(header<false, T>& m1, header<false, T>& m2);
template<class = void>
string_view
get_reason() const;
status result_; status result_;
}; };

View File

@@ -208,11 +208,22 @@ private:
string_view value, error_code&) string_view value, error_code&)
{ {
if(f != field::unknown) if(f != field::unknown)
// VFALCO Note we are not preserving the {
// capitalization of the field name. #if 1
// This preserves capitalization of field names
if(to_string(f) == name)
m_.insert(f, value);
else
m_.insert(name, value);
#else
// This doesn't.
m_.insert(f, value); m_.insert(f, value);
#endif
}
else else
{
m_.insert(name, value); m_.insert(name, value);
}
} }
void void