Make value optional in param-list

This commit is contained in:
Vinnie Falco
2016-06-05 13:39:13 -04:00
parent ad966d6217
commit fbc8ddbc81
5 changed files with 108 additions and 111 deletions

View File

@@ -1,3 +1,9 @@
1.0.0-b16
* Make value optional in param-list
--------------------------------------------------------------------------------
1.0.0-b15 1.0.0-b15
* rfc7230 section 3.3.2 compliance * rfc7230 section 3.3.2 compliance

View File

@@ -233,6 +233,14 @@ skip_ows(FwdIt& it, FwdIt const& end)
} }
} }
template<class FwdIt>
void
skip_token(FwdIt& it, FwdIt const& last)
{
while(it != last && is_tchar(*it))
++it;
}
inline inline
boost::string_ref boost::string_ref
trim(boost::string_ref const& s) trim(boost::string_ref const& s)
@@ -258,14 +266,14 @@ struct param_iter
using iter_type = boost::string_ref::const_iterator; using iter_type = boost::string_ref::const_iterator;
iter_type it; iter_type it;
iter_type begin; iter_type first;
iter_type end; iter_type last;
std::pair<boost::string_ref, boost::string_ref> v; std::pair<boost::string_ref, boost::string_ref> v;
bool bool
empty() const empty() const
{ {
return begin == it; return first == it;
} }
template<class = void> template<class = void>
@@ -279,59 +287,48 @@ param_iter::
increment() increment()
{ {
/* /*
ext-list = *( "," OWS ) ext *( OWS "," [ OWS ext ] )
ext = token param-list
param-list = *( OWS ";" OWS param ) param-list = *( OWS ";" OWS param )
param = token OWS "=" OWS ( token / quoted-string ) param = token OWS [ "=" OWS ( token / quoted-string ) ]
quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE
qdtext = HTAB / SP / "!" / %x23-5B ; '#'-'[' / %x5D-7E ; ']'-'~' / obs-text qdtext = HTAB / SP / "!" / %x23-5B ; '#'-'[' / %x5D-7E ; ']'-'~' / obs-text
quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text ) quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
obs-text = %x80-FF obs-text = %x80-FF
Example:
chunked;a=b;i=j,gzip;windowBits=12
x,y
*/ */
auto const err = auto const err =
[&] [&]
{ {
it = begin; it = first;
}; };
v.first.clear(); v.first.clear();
v.second.clear(); v.second.clear();
detail::skip_ows(it, end); detail::skip_ows(it, last);
begin = it; first = it;
if(it == end) if(it == last)
return err(); return err();
if(*it != ';') if(*it != ';')
return err(); return err();
++it; ++it;
detail::skip_ows(it, end); detail::skip_ows(it, last);
if(it == end) if(it == last)
return err(); return err();
// param // param
if(! detail::is_tchar(*it)) if(! detail::is_tchar(*it))
return err(); return err();
auto const p0 = it; auto const p0 = it;
for(;;) skip_token(++it, last);
{
++it;
if(it == end)
return err();
if(! detail::is_tchar(*it))
break;
}
auto const p1 = it; auto const p1 = it;
detail::skip_ows(it, end); v.first = { &*p0, static_cast<std::size_t>(p1 - p0) };
if(it == end) detail::skip_ows(it, last);
return err(); if(it == last)
return;
if(*it == ';')
return;
if(*it != '=') if(*it != '=')
return err(); return err();
++it; ++it;
detail::skip_ows(it, end); detail::skip_ows(it, last);
if(it == end) if(it == last)
return err(); return;
if(*it == '"') if(*it == '"')
{ {
// quoted-string // quoted-string
@@ -339,7 +336,7 @@ increment()
++it; ++it;
for(;;) for(;;)
{ {
if(it == end) if(it == last)
return err(); return err();
auto c = *it++; auto c = *it++;
if(c == '"') if(c == '"')
@@ -348,13 +345,12 @@ increment()
continue; continue;
if(c != '\\') if(c != '\\')
return err(); return err();
if(it == end) if(it == last)
return err(); return err();
c = *it++; c = *it++;
if(! detail::is_qpchar(c)) if(! detail::is_qpchar(c))
return err(); return err();
} }
v.first = { &*p0, static_cast<std::size_t>(p1 - p0) };
v.second = { &*p2, static_cast<std::size_t>(it - p2) }; v.second = { &*p2, static_cast<std::size_t>(it - p2) };
} }
else else
@@ -363,15 +359,7 @@ increment()
if(! detail::is_tchar(*it)) if(! detail::is_tchar(*it))
return err(); return err();
auto const p2 = it; auto const p2 = it;
for(;;) skip_token(++it, last);
{
it++;
if(it == end)
break;
if(! detail::is_tchar(*it))
break;
}
v.first = { &*p0, static_cast<std::size_t>(p1 - p0) };
v.second = { &*p2, static_cast<std::size_t>(it - p2) }; v.second = { &*p2, static_cast<std::size_t>(it - p2) };
} }
} }

View File

@@ -36,8 +36,8 @@ public:
{ {
return return
other.pi_.it == pi_.it && other.pi_.it == pi_.it &&
other.pi_.end == pi_.end && other.pi_.last == pi_.last &&
other.pi_.begin == pi_.begin; other.pi_.first == pi_.first;
} }
bool bool
@@ -76,11 +76,11 @@ public:
private: private:
friend class param_list; friend class param_list;
const_iterator(iter_type begin, iter_type end) const_iterator(iter_type first, iter_type last)
{ {
pi_.it = begin; pi_.it = first;
pi_.begin = begin; pi_.first = first;
pi_.end = end; pi_.last = last;
increment(); increment();
} }
@@ -158,10 +158,11 @@ increment()
pi_.increment(); pi_.increment();
if(pi_.empty()) if(pi_.empty())
{ {
pi_.it = pi_.end; pi_.it = pi_.last;
pi_.begin = pi_.end; pi_.first = pi_.last;
} }
else if(pi_.v.second.front() == '"') else if(! pi_.v.second.empty() &&
pi_.v.second.front() == '"')
{ {
s_ = unquote(pi_.v.second); s_ = unquote(pi_.v.second);
pi_.v.second = boost::string_ref{ pi_.v.second = boost::string_ref{
@@ -175,8 +176,8 @@ class ext_list::const_iterator
{ {
ext_list::value_type v_; ext_list::value_type v_;
iter_type it_; iter_type it_;
iter_type begin_; iter_type first_;
iter_type end_; iter_type last_;
public: public:
using value_type = ext_list::value_type; using value_type = ext_list::value_type;
@@ -192,8 +193,8 @@ public:
{ {
return return
other.it_ == it_ && other.it_ == it_ &&
other.begin_ == begin_ && other.first_ == first_ &&
other.end_ == end_; other.last_ == last_;
} }
bool bool
@@ -235,8 +236,8 @@ private:
const_iterator(iter_type begin, iter_type end) const_iterator(iter_type begin, iter_type end)
{ {
it_ = begin; it_ = begin;
begin_ = begin; first_ = begin;
end_ = end; last_ = end;
increment(); increment();
} }
@@ -320,16 +321,16 @@ increment()
auto const err = auto const err =
[&] [&]
{ {
it_ = end_; it_ = last_;
begin_ = end_; first_ = last_;
}; };
auto need_comma = it_ != begin_; auto need_comma = it_ != first_;
v_.first = {}; v_.first = {};
begin_ = it_; first_ = it_;
for(;;) for(;;)
{ {
detail::skip_ows(it_, end_); detail::skip_ows(it_, last_);
if(it_ == end_) if(it_ == last_)
return err(); return err();
auto const c = *it_; auto const c = *it_;
if(detail::is_tchar(c)) if(detail::is_tchar(c))
@@ -340,7 +341,7 @@ increment()
for(;;) for(;;)
{ {
++it_; ++it_;
if(it_ == end_) if(it_ == last_)
break; break;
if(! detail::is_tchar(*it_)) if(! detail::is_tchar(*it_))
break; break;
@@ -349,8 +350,8 @@ increment()
static_cast<std::size_t>(it_ - p0)}; static_cast<std::size_t>(it_ - p0)};
detail::param_iter pi; detail::param_iter pi;
pi.it = it_; pi.it = it_;
pi.begin = it_; pi.first = it_;
pi.end = end_; pi.last = last_;
for(;;) for(;;)
{ {
pi.increment(); pi.increment();
@@ -375,8 +376,8 @@ class token_list::const_iterator
{ {
token_list::value_type v_; token_list::value_type v_;
iter_type it_; iter_type it_;
iter_type begin_; iter_type first_;
iter_type end_; iter_type last_;
public: public:
using value_type = token_list::value_type; using value_type = token_list::value_type;
@@ -392,8 +393,8 @@ public:
{ {
return return
other.it_ == it_ && other.it_ == it_ &&
other.begin_ == begin_ && other.first_ == first_ &&
other.end_ == end_; other.last_ == last_;
} }
bool bool
@@ -435,8 +436,8 @@ private:
const_iterator(iter_type begin, iter_type end) const_iterator(iter_type begin, iter_type end)
{ {
it_ = begin; it_ = begin;
begin_ = begin; first_ = begin;
end_ = end; last_ = end;
increment(); increment();
} }
@@ -492,16 +493,16 @@ increment()
auto const err = auto const err =
[&] [&]
{ {
it_ = end_; it_ = last_;
begin_ = end_; first_ = last_;
}; };
auto need_comma = it_ != begin_; auto need_comma = it_ != first_;
v_ = {}; v_ = {};
begin_ = it_; first_ = it_;
for(;;) for(;;)
{ {
detail::skip_ows(it_, end_); detail::skip_ows(it_, last_);
if(it_ == end_) if(it_ == last_)
return err(); return err();
auto const c = *it_; auto const c = *it_;
if(detail::is_tchar(c)) if(detail::is_tchar(c))
@@ -512,7 +513,7 @@ increment()
for(;;) for(;;)
{ {
++it_; ++it_;
if(it_ == end_) if(it_ == last_)
break; break;
if(! detail::is_tchar(*it_)) if(! detail::is_tchar(*it_))
break; break;

View File

@@ -15,15 +15,14 @@ namespace http {
/** A list of parameters in a HTTP extension field value. /** A list of parameters in a HTTP extension field value.
This container allows iteration of the parameter list This container allows iteration of the parameter list in a HTTP
in a HTTP extension. The parameter list is a series extension. The parameter list is a series of name/value pairs
of "name = value" pairs with each pair starting with with each pair starting with a semicolon. The value is optional.
a semicolon.
BNF: BNF:
@code @code
param-list = *( OWS ";" OWS param ) param-list = *( OWS ";" OWS param )
param = token OWS "=" OWS ( token / quoted-string ) param = token OWS [ "=" OWS ( token / quoted-string ) ]
@endcode @endcode
If a parsing error is encountered while iterating the string, If a parsing error is encountered while iterating the string,
@@ -48,8 +47,9 @@ class param_list
public: public:
/** The type of each element in the list. /** The type of each element in the list.
The first string in the pair is the name of the The first string in the pair is the name of the parameter,
parameter, and the second string in the pair is its value. and the second string in the pair is its value (which may
be empty).
*/ */
using value_type = using value_type =
std::pair<boost::string_ref, boost::string_ref>; std::pair<boost::string_ref, boost::string_ref>;
@@ -101,7 +101,7 @@ public:
ext-list = *( "," OWS ) ext *( OWS "," [ OWS ext ] ) ext-list = *( "," OWS ) ext *( OWS "," [ OWS ext ] )
ext = token param-list ext = token param-list
param-list = *( OWS ";" OWS param ) param-list = *( OWS ";" OWS param )
param = token OWS "=" OWS ( token / quoted-string ) param = token OWS [ "=" OWS ( token / quoted-string ) ]
@endcode @endcode
If a parsing error is encountered while iterating the string, If a parsing error is encountered while iterating the string,
@@ -196,13 +196,13 @@ public:
/** A list of tokens in a comma separated HTTP field value. /** A list of tokens in a comma separated HTTP field value.
This container allows iteration of the extensions in a HTTP This container allows iteration of a list of items in a
field value. The extension list is a comma separated list of header field value. The input is a comma separated list of
token parameter list pairs. tokens.
BNF: BNF:
@code @code
token-list = *( "," OWS ) token *( OWS "," [ OWS ext ] ) token-list = *( "," OWS ) token *( OWS "," [ OWS token ] )
@endcode @endcode
If a parsing error is encountered while iterating the string, If a parsing error is encountered while iterating the string,
@@ -226,12 +226,7 @@ class token_list
boost::string_ref s_; boost::string_ref s_;
public: public:
/** The type of each element in the token list. /// The type of each element in the token list.
The first element of the pair is the extension token, and the
second element of the pair is an iterable container holding the
extension's name/value parameters.
*/
using value_type = boost::string_ref; using value_type = boost::string_ref;
/// A constant iterator to the list /// A constant iterator to the list

View File

@@ -43,9 +43,12 @@ public:
{ {
s.push_back(';'); s.push_back(';');
s.append(str(p.first)); s.append(str(p.first));
if(! p.second.empty())
{
s.push_back('='); s.push_back('=');
s.append(str(p.second)); s.append(str(p.second));
} }
}
return s; return s;
} }
@@ -73,18 +76,19 @@ public:
BEAST_EXPECTS(got == good, fmt(got)); BEAST_EXPECTS(got == good, fmt(got));
}; };
ce("");
ce(";x");
ce(";xy");
ce(";x;y");
ce(""); ce("");
cs(" ;\t i =\t 1 \t", ";i=1"); cs(" ;\t i =\t 1 \t", ";i=1");
cq("\t; \t xyz=1 ; ijk=\"q\\\"t\"", ";xyz=1;ijk=q\"t"); cq("\t; \t xyz=1 ; ijk=\"q\\\"t\"", ";xyz=1;ijk=q\"t");
ce(";x;y");
// invalid strings // invalid strings
cs(";", ""); cs(";", "");
cs(";,", ""); cs(";,", "");
cs(";xy", "");
cs(";xy", "");
cs(";xy ", "");
cs(";xy,", "");
cq(";x=,", ""); cq(";x=,", "");
cq(";xy=\"", ""); cq(";xy=\"", "");
cq(";xy=\"\x7f", ""); cq(";xy=\"\x7f", "");
@@ -136,7 +140,6 @@ public:
param-list = *( OWS ";" OWS param ) param-list = *( OWS ";" OWS param )
param = token OWS "=" OWS ( token / quoted-string ) param = token OWS "=" OWS ( token / quoted-string )
*/ */
ce("");
cs(",", ""); cs(",", "");
cs(", ", ""); cs(", ", "");
cs(",\t", ""); cs(",\t", "");
@@ -147,12 +150,16 @@ public:
cs("\t , \t", ""); cs("\t , \t", "");
cs(",,", ""); cs(",,", "");
cs(" , \t,, \t,", ""); cs(" , \t,, \t,", "");
cs( "permessage-deflate; client_no_context_takeover; client_max_window_bits",
"permessage-deflate;client_no_context_takeover;client_max_window_bits");
ce("a"); ce("a");
ce("ab"); ce("ab");
ce("a,b"); ce("a,b");
cs(" a ", "a"); cs(" a ", "a");
cs("\t a, b\t , c\t", "a,b,c"); cs("\t a, b\t , c\t", "a,b,c");
ce("a;b");
ce("a;b;c");
cs("a; \t i\t=\t \t1\t ", "a;i=1"); cs("a; \t i\t=\t \t1\t ", "a;i=1");
ce("a;i=1;j=2;k=3"); ce("a;i=1;j=2;k=3");