forked from boostorg/beast
Make value optional in param-list
This commit is contained in:
@@ -1,3 +1,9 @@
|
||||
1.0.0-b16
|
||||
|
||||
* Make value optional in param-list
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
1.0.0-b15
|
||||
|
||||
* rfc7230 section 3.3.2 compliance
|
||||
|
@@ -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
|
||||
boost::string_ref
|
||||
trim(boost::string_ref const& s)
|
||||
@@ -258,14 +266,14 @@ struct param_iter
|
||||
using iter_type = boost::string_ref::const_iterator;
|
||||
|
||||
iter_type it;
|
||||
iter_type begin;
|
||||
iter_type end;
|
||||
iter_type first;
|
||||
iter_type last;
|
||||
std::pair<boost::string_ref, boost::string_ref> v;
|
||||
|
||||
bool
|
||||
empty() const
|
||||
{
|
||||
return begin == it;
|
||||
return first == it;
|
||||
}
|
||||
|
||||
template<class = void>
|
||||
@@ -279,59 +287,48 @@ param_iter::
|
||||
increment()
|
||||
{
|
||||
/*
|
||||
ext-list = *( "," OWS ) ext *( OWS "," [ OWS ext ] )
|
||||
ext = token param-list
|
||||
param-list = *( OWS ";" OWS param )
|
||||
param = token OWS "=" OWS ( token / quoted-string )
|
||||
|
||||
quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE
|
||||
qdtext = HTAB / SP / "!" / %x23-5B ; '#'-'[' / %x5D-7E ; ']'-'~' / obs-text
|
||||
quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
|
||||
obs-text = %x80-FF
|
||||
|
||||
Example:
|
||||
chunked;a=b;i=j,gzip;windowBits=12
|
||||
x,y
|
||||
param-list = *( OWS ";" OWS param )
|
||||
param = token OWS [ "=" OWS ( token / quoted-string ) ]
|
||||
quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE
|
||||
qdtext = HTAB / SP / "!" / %x23-5B ; '#'-'[' / %x5D-7E ; ']'-'~' / obs-text
|
||||
quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
|
||||
obs-text = %x80-FF
|
||||
*/
|
||||
auto const err =
|
||||
[&]
|
||||
{
|
||||
it = begin;
|
||||
it = first;
|
||||
};
|
||||
v.first.clear();
|
||||
v.second.clear();
|
||||
detail::skip_ows(it, end);
|
||||
begin = it;
|
||||
if(it == end)
|
||||
detail::skip_ows(it, last);
|
||||
first = it;
|
||||
if(it == last)
|
||||
return err();
|
||||
if(*it != ';')
|
||||
return err();
|
||||
++it;
|
||||
detail::skip_ows(it, end);
|
||||
if(it == end)
|
||||
detail::skip_ows(it, last);
|
||||
if(it == last)
|
||||
return err();
|
||||
// param
|
||||
if(! detail::is_tchar(*it))
|
||||
return err();
|
||||
auto const p0 = it;
|
||||
for(;;)
|
||||
{
|
||||
++it;
|
||||
if(it == end)
|
||||
return err();
|
||||
if(! detail::is_tchar(*it))
|
||||
break;
|
||||
}
|
||||
skip_token(++it, last);
|
||||
auto const p1 = it;
|
||||
detail::skip_ows(it, end);
|
||||
if(it == end)
|
||||
return err();
|
||||
v.first = { &*p0, static_cast<std::size_t>(p1 - p0) };
|
||||
detail::skip_ows(it, last);
|
||||
if(it == last)
|
||||
return;
|
||||
if(*it == ';')
|
||||
return;
|
||||
if(*it != '=')
|
||||
return err();
|
||||
++it;
|
||||
detail::skip_ows(it, end);
|
||||
if(it == end)
|
||||
return err();
|
||||
detail::skip_ows(it, last);
|
||||
if(it == last)
|
||||
return;
|
||||
if(*it == '"')
|
||||
{
|
||||
// quoted-string
|
||||
@@ -339,7 +336,7 @@ increment()
|
||||
++it;
|
||||
for(;;)
|
||||
{
|
||||
if(it == end)
|
||||
if(it == last)
|
||||
return err();
|
||||
auto c = *it++;
|
||||
if(c == '"')
|
||||
@@ -348,13 +345,12 @@ increment()
|
||||
continue;
|
||||
if(c != '\\')
|
||||
return err();
|
||||
if(it == end)
|
||||
if(it == last)
|
||||
return err();
|
||||
c = *it++;
|
||||
if(! detail::is_qpchar(c))
|
||||
return err();
|
||||
}
|
||||
v.first = { &*p0, static_cast<std::size_t>(p1 - p0) };
|
||||
v.second = { &*p2, static_cast<std::size_t>(it - p2) };
|
||||
}
|
||||
else
|
||||
@@ -363,15 +359,7 @@ increment()
|
||||
if(! detail::is_tchar(*it))
|
||||
return err();
|
||||
auto const p2 = it;
|
||||
for(;;)
|
||||
{
|
||||
it++;
|
||||
if(it == end)
|
||||
break;
|
||||
if(! detail::is_tchar(*it))
|
||||
break;
|
||||
}
|
||||
v.first = { &*p0, static_cast<std::size_t>(p1 - p0) };
|
||||
skip_token(++it, last);
|
||||
v.second = { &*p2, static_cast<std::size_t>(it - p2) };
|
||||
}
|
||||
}
|
||||
|
@@ -36,8 +36,8 @@ public:
|
||||
{
|
||||
return
|
||||
other.pi_.it == pi_.it &&
|
||||
other.pi_.end == pi_.end &&
|
||||
other.pi_.begin == pi_.begin;
|
||||
other.pi_.last == pi_.last &&
|
||||
other.pi_.first == pi_.first;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -76,11 +76,11 @@ public:
|
||||
private:
|
||||
friend class param_list;
|
||||
|
||||
const_iterator(iter_type begin, iter_type end)
|
||||
const_iterator(iter_type first, iter_type last)
|
||||
{
|
||||
pi_.it = begin;
|
||||
pi_.begin = begin;
|
||||
pi_.end = end;
|
||||
pi_.it = first;
|
||||
pi_.first = first;
|
||||
pi_.last = last;
|
||||
increment();
|
||||
}
|
||||
|
||||
@@ -158,10 +158,11 @@ increment()
|
||||
pi_.increment();
|
||||
if(pi_.empty())
|
||||
{
|
||||
pi_.it = pi_.end;
|
||||
pi_.begin = pi_.end;
|
||||
pi_.it = pi_.last;
|
||||
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);
|
||||
pi_.v.second = boost::string_ref{
|
||||
@@ -175,8 +176,8 @@ class ext_list::const_iterator
|
||||
{
|
||||
ext_list::value_type v_;
|
||||
iter_type it_;
|
||||
iter_type begin_;
|
||||
iter_type end_;
|
||||
iter_type first_;
|
||||
iter_type last_;
|
||||
|
||||
public:
|
||||
using value_type = ext_list::value_type;
|
||||
@@ -192,8 +193,8 @@ public:
|
||||
{
|
||||
return
|
||||
other.it_ == it_ &&
|
||||
other.begin_ == begin_ &&
|
||||
other.end_ == end_;
|
||||
other.first_ == first_ &&
|
||||
other.last_ == last_;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -235,8 +236,8 @@ private:
|
||||
const_iterator(iter_type begin, iter_type end)
|
||||
{
|
||||
it_ = begin;
|
||||
begin_ = begin;
|
||||
end_ = end;
|
||||
first_ = begin;
|
||||
last_ = end;
|
||||
increment();
|
||||
}
|
||||
|
||||
@@ -320,16 +321,16 @@ increment()
|
||||
auto const err =
|
||||
[&]
|
||||
{
|
||||
it_ = end_;
|
||||
begin_ = end_;
|
||||
it_ = last_;
|
||||
first_ = last_;
|
||||
};
|
||||
auto need_comma = it_ != begin_;
|
||||
auto need_comma = it_ != first_;
|
||||
v_.first = {};
|
||||
begin_ = it_;
|
||||
first_ = it_;
|
||||
for(;;)
|
||||
{
|
||||
detail::skip_ows(it_, end_);
|
||||
if(it_ == end_)
|
||||
detail::skip_ows(it_, last_);
|
||||
if(it_ == last_)
|
||||
return err();
|
||||
auto const c = *it_;
|
||||
if(detail::is_tchar(c))
|
||||
@@ -340,7 +341,7 @@ increment()
|
||||
for(;;)
|
||||
{
|
||||
++it_;
|
||||
if(it_ == end_)
|
||||
if(it_ == last_)
|
||||
break;
|
||||
if(! detail::is_tchar(*it_))
|
||||
break;
|
||||
@@ -349,8 +350,8 @@ increment()
|
||||
static_cast<std::size_t>(it_ - p0)};
|
||||
detail::param_iter pi;
|
||||
pi.it = it_;
|
||||
pi.begin = it_;
|
||||
pi.end = end_;
|
||||
pi.first = it_;
|
||||
pi.last = last_;
|
||||
for(;;)
|
||||
{
|
||||
pi.increment();
|
||||
@@ -375,8 +376,8 @@ class token_list::const_iterator
|
||||
{
|
||||
token_list::value_type v_;
|
||||
iter_type it_;
|
||||
iter_type begin_;
|
||||
iter_type end_;
|
||||
iter_type first_;
|
||||
iter_type last_;
|
||||
|
||||
public:
|
||||
using value_type = token_list::value_type;
|
||||
@@ -392,8 +393,8 @@ public:
|
||||
{
|
||||
return
|
||||
other.it_ == it_ &&
|
||||
other.begin_ == begin_ &&
|
||||
other.end_ == end_;
|
||||
other.first_ == first_ &&
|
||||
other.last_ == last_;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -435,8 +436,8 @@ private:
|
||||
const_iterator(iter_type begin, iter_type end)
|
||||
{
|
||||
it_ = begin;
|
||||
begin_ = begin;
|
||||
end_ = end;
|
||||
first_ = begin;
|
||||
last_ = end;
|
||||
increment();
|
||||
}
|
||||
|
||||
@@ -492,16 +493,16 @@ increment()
|
||||
auto const err =
|
||||
[&]
|
||||
{
|
||||
it_ = end_;
|
||||
begin_ = end_;
|
||||
it_ = last_;
|
||||
first_ = last_;
|
||||
};
|
||||
auto need_comma = it_ != begin_;
|
||||
auto need_comma = it_ != first_;
|
||||
v_ = {};
|
||||
begin_ = it_;
|
||||
first_ = it_;
|
||||
for(;;)
|
||||
{
|
||||
detail::skip_ows(it_, end_);
|
||||
if(it_ == end_)
|
||||
detail::skip_ows(it_, last_);
|
||||
if(it_ == last_)
|
||||
return err();
|
||||
auto const c = *it_;
|
||||
if(detail::is_tchar(c))
|
||||
@@ -512,7 +513,7 @@ increment()
|
||||
for(;;)
|
||||
{
|
||||
++it_;
|
||||
if(it_ == end_)
|
||||
if(it_ == last_)
|
||||
break;
|
||||
if(! detail::is_tchar(*it_))
|
||||
break;
|
||||
|
@@ -15,15 +15,14 @@ namespace http {
|
||||
|
||||
/** A list of parameters in a HTTP extension field value.
|
||||
|
||||
This container allows iteration of the parameter list
|
||||
in a HTTP extension. The parameter list is a series
|
||||
of "name = value" pairs with each pair starting with
|
||||
a semicolon.
|
||||
This container allows iteration of the parameter list in a HTTP
|
||||
extension. The parameter list is a series of name/value pairs
|
||||
with each pair starting with a semicolon. The value is optional.
|
||||
|
||||
BNF:
|
||||
@code
|
||||
param-list = *( OWS ";" OWS param )
|
||||
param = token OWS "=" OWS ( token / quoted-string )
|
||||
param = token OWS [ "=" OWS ( token / quoted-string ) ]
|
||||
@endcode
|
||||
|
||||
If a parsing error is encountered while iterating the string,
|
||||
@@ -48,8 +47,9 @@ class param_list
|
||||
public:
|
||||
/** The type of each element in the list.
|
||||
|
||||
The first string in the pair is the name of the
|
||||
parameter, and the second string in the pair is its value.
|
||||
The first string in the pair is the name of the parameter,
|
||||
and the second string in the pair is its value (which may
|
||||
be empty).
|
||||
*/
|
||||
using value_type =
|
||||
std::pair<boost::string_ref, boost::string_ref>;
|
||||
@@ -101,7 +101,7 @@ public:
|
||||
ext-list = *( "," OWS ) ext *( OWS "," [ OWS ext ] )
|
||||
ext = token param-list
|
||||
param-list = *( OWS ";" OWS param )
|
||||
param = token OWS "=" OWS ( token / quoted-string )
|
||||
param = token OWS [ "=" OWS ( token / quoted-string ) ]
|
||||
@endcode
|
||||
|
||||
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.
|
||||
|
||||
This container allows iteration of the extensions in a HTTP
|
||||
field value. The extension list is a comma separated list of
|
||||
token parameter list pairs.
|
||||
This container allows iteration of a list of items in a
|
||||
header field value. The input is a comma separated list of
|
||||
tokens.
|
||||
|
||||
BNF:
|
||||
@code
|
||||
token-list = *( "," OWS ) token *( OWS "," [ OWS ext ] )
|
||||
token-list = *( "," OWS ) token *( OWS "," [ OWS token ] )
|
||||
@endcode
|
||||
|
||||
If a parsing error is encountered while iterating the string,
|
||||
@@ -226,12 +226,7 @@ class token_list
|
||||
boost::string_ref s_;
|
||||
|
||||
public:
|
||||
/** 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.
|
||||
*/
|
||||
/// The type of each element in the token list.
|
||||
using value_type = boost::string_ref;
|
||||
|
||||
/// A constant iterator to the list
|
||||
|
@@ -43,8 +43,11 @@ public:
|
||||
{
|
||||
s.push_back(';');
|
||||
s.append(str(p.first));
|
||||
s.push_back('=');
|
||||
s.append(str(p.second));
|
||||
if(! p.second.empty())
|
||||
{
|
||||
s.push_back('=');
|
||||
s.append(str(p.second));
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@@ -73,18 +76,19 @@ public:
|
||||
BEAST_EXPECTS(got == good, fmt(got));
|
||||
};
|
||||
|
||||
ce("");
|
||||
ce(";x");
|
||||
ce(";xy");
|
||||
ce(";x;y");
|
||||
|
||||
ce("");
|
||||
cs(" ;\t i =\t 1 \t", ";i=1");
|
||||
cq("\t; \t xyz=1 ; ijk=\"q\\\"t\"", ";xyz=1;ijk=q\"t");
|
||||
ce(";x;y");
|
||||
|
||||
// invalid strings
|
||||
cs(";", "");
|
||||
cs(";,", "");
|
||||
cs(";xy", "");
|
||||
cs(";xy", "");
|
||||
cs(";xy ", "");
|
||||
cs(";xy,", "");
|
||||
|
||||
cq(";x=,", "");
|
||||
cq(";xy=\"", "");
|
||||
cq(";xy=\"\x7f", "");
|
||||
@@ -136,7 +140,6 @@ public:
|
||||
param-list = *( OWS ";" OWS param )
|
||||
param = token OWS "=" OWS ( token / quoted-string )
|
||||
*/
|
||||
ce("");
|
||||
cs(",", "");
|
||||
cs(", ", "");
|
||||
cs(",\t", "");
|
||||
@@ -147,12 +150,16 @@ public:
|
||||
cs("\t , \t", "");
|
||||
cs(",,", "");
|
||||
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("ab");
|
||||
ce("a,b");
|
||||
cs(" a ", "a");
|
||||
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");
|
||||
ce("a;i=1;j=2;k=3");
|
||||
|
Reference in New Issue
Block a user