2
0
mirror of https://github.com/boostorg/url.git synced 2026-01-31 08:42:22 +00:00

elements are not stream parsers

This commit is contained in:
Vinnie Falco
2021-09-03 17:35:07 -07:00
parent 5860390271
commit b599ffa4af
24 changed files with 115 additions and 371 deletions

View File

@@ -25,7 +25,6 @@
#include <boost/url/bnf/parse.hpp>
#include <boost/url/bnf/range.hpp>
#include <boost/url/bnf/repeat.hpp>
#include <boost/url/bnf/sequence.hpp>
#include <boost/url/bnf/token.hpp>
#include <boost/url/bnf/tuple.hpp>
#include <boost/url/bnf/type_traits.hpp>

View File

@@ -1,60 +0,0 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/CPPAlliance/url
//
#ifndef BOOST_URL_BNF_IMPL_SEQUENCE_HPP
#define BOOST_URL_BNF_IMPL_SEQUENCE_HPP
#include <boost/url/bnf/tuple.hpp>
namespace boost {
namespace urls {
namespace bnf {
template<class... Bn>
char const*
sequence<Bn...>::
parse(
char const* const start,
char const* const end,
error_code& ec)
{
auto it = detail::parse(
start, end, ec, &v_[0],
std::integral_constant<
std::size_t, 0>{}, t_);
if(ec)
return start;
return it;
}
template<
std::size_t I, class... Bn>
auto
get(sequence<Bn...>& e) ->
tuple_element<
I, sequence<Bn...>>&
{
return get<I>(e.t_);
}
template<
std::size_t I, class... Bn>
auto
get(sequence<Bn...> const& e) ->
tuple_element<I,
sequence<Bn...>> const&
{
return get<I>(e.t_);
}
} // bnf
} // urls
} // boost
#endif

View File

@@ -12,6 +12,7 @@
#include <boost/url/detail/config.hpp>
#include <boost/url/error.hpp>
#include <boost/url/string.hpp>
#include <boost/optional.hpp>
namespace boost {

View File

@@ -1,93 +0,0 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/CPPAlliance/url
//
#ifndef BOOST_URL_BNF_SEQUENCE_HPP
#define BOOST_URL_BNF_SEQUENCE_HPP
#include <boost/url/detail/config.hpp>
#include <boost/url/error.hpp>
#include <boost/url/string.hpp>
#include <boost/url/bnf/tuple.hpp>
#include <boost/assert.hpp>
#include <array>
namespace boost {
namespace urls {
namespace bnf {
/** A sequence of one or more elements
*/
template<
class... Bn>
class sequence
{
tuple<Bn...> t_;
std::array<
string_view,
sizeof...(Bn)> v_;
public:
using value_type = tuple<Bn...>;
value_type const&
operator*() const noexcept
{
return t_;
}
value_type const*
operator->() const noexcept
{
return &t_;
}
/** Return the matching string for the Ith element
*/
string_view const
operator[](std::size_t i) const
{
BOOST_ASSERT(i <
sizeof...(Bn));
return v_[i];
}
char const*
parse(
char const* const start,
char const* const end,
error_code& ec);
/** Return the Ith element of the sequence `e`
*/
template<
std::size_t I, class... Bn>
friend
auto
get(sequence<Bn...>& e) ->
tuple_element<
I, sequence<Bn...>>&;
/** Return the Ith element of the sequence `e`
*/
template<
std::size_t I, class... Bn>
friend
auto
get(sequence<Bn...> const& e) ->
tuple_element<
I, sequence<Bn...>> const&;
};
} // bnf
} // urls
} // boost
#include <boost/url/bnf/impl/sequence.hpp>
#endif

View File

@@ -140,7 +140,10 @@ constexpr std::uint8_t
slash_char_mask = 0x20;
constexpr std::uint8_t
at_char_mask = 0x40;
alnum_char_mask = 0x40;
constexpr std::uint8_t
at_char_mask = 0x80;
} // rfc
} // urls

View File

@@ -22,11 +22,11 @@ char_table[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x02, 0x00, 0x04, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x24,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x14, 0x02, 0x00, 0x02, 0x00, 0x0c,
0x44, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x00, 0x04, 0x00, 0x01,
0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x14, 0x02, 0x00, 0x02, 0x00, 0x0c,
0x84, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x04, 0x00, 0x04, 0x00, 0x01,
0x00, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -34,7 +34,8 @@ char_table[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
} // detail
} // rfc

View File

@@ -44,7 +44,8 @@ skip:
++it;
if(it == end)
{
ec = error::need_more;
// missing HEXDIG
ec = error::syntax;
return start;
}
if(hex_digit(*it) == -1)
@@ -56,7 +57,8 @@ skip:
++it;
if(it == end)
{
ec = error::need_more;
// missing HEXDIG
ec = error::syntax;
return start;
}
if(hex_digit(*it) == -1)

View File

@@ -43,7 +43,7 @@ parse(
}
host h;
it = parse(
start, end, ec, h);
it, end, ec, h);
if(ec)
return start;
return it;

View File

@@ -56,12 +56,6 @@ parse(
{
t.destroy();
t.kind_ = host_kind::none;
if(start == end)
{
ec = error::need_more;
return start;
}
auto it = start;
if(*it == '[')
{
@@ -87,7 +81,6 @@ parse(
ec = error::syntax;
return start;
}
// IPv4address
{
ipv4_address v;
@@ -100,7 +93,6 @@ parse(
}
ec = {};
}
// reg-name
pct_encoded<
unreserved_char_mask |
@@ -108,7 +100,6 @@ parse(
it = parse(it, end, ec, v);
if(ec)
{
// need more or
// bad reg-name
return start;
}

View File

@@ -26,23 +26,18 @@ parse(
ip_literal& t)
{
using bnf::parse;
if(start == end)
{
ec = error::need_more;
return start;
}
auto it = start;
if(*it != '[')
// '['
auto it = parse(
start, end, ec, '[');
if(ec)
{
// expected '['
ec = error::syntax;
return start;
}
++it;
if(it == end)
{
// expected address
ec = error::need_more;
ec = error::syntax;
return start;
}
if(*it != 'v')

View File

@@ -14,7 +14,6 @@
#include <boost/url/error.hpp>
#include <boost/url/bnf/literal.hpp>
#include <boost/url/bnf/parse.hpp>
#include <boost/url/bnf/sequence.hpp>
#include <boost/url/rfc/char_sets.hpp>
namespace boost {
@@ -37,7 +36,8 @@ struct dec_octet
{
if(start == end)
{
ec = error::need_more;
// expected DIGIT
ec = error::syntax;
return start;
}
auto it = start;

View File

@@ -66,7 +66,8 @@ struct h16
{
if(start == end)
{
ec = error::need_more;
// expected HEXDIG
ec = error::syntax;
return start;
}
auto d = hex_digit(*it);
@@ -140,7 +141,8 @@ parse(
break;
}
BOOST_ASSERT(n > 0);
ec = error::need_more;
// not enough words
ec = error::syntax;
return start;
}
if(*it == ':')
@@ -148,7 +150,8 @@ parse(
++it;
if(it == end)
{
ec = error::need_more;
// missing ':'
ec = error::syntax;
return start;
}
if(*it == ':')

View File

@@ -14,7 +14,6 @@
#include <boost/url/error.hpp>
#include <boost/url/string.hpp>
#include <boost/url/bnf/literal.hpp>
#include <boost/url/bnf/sequence.hpp>
#include <boost/url/rfc/segment.hpp>
namespace boost {
@@ -28,12 +27,10 @@ increment(
char const* const end,
error_code& ec)
{
using namespace bnf;
sequence<
literal<'/'>,
segment> p;
auto it = p.parse(
start, end, ec);
segment t;
using bnf::parse;
auto it = parse(
start, end, ec, '/', t);
if(ec)
{
v_ = {};

View File

@@ -14,7 +14,6 @@
#include <boost/url/error.hpp>
#include <boost/url/string.hpp>
#include <boost/url/bnf/literal.hpp>
#include <boost/url/bnf/sequence.hpp>
#include <boost/url/rfc/segment.hpp>
namespace boost {

View File

@@ -11,36 +11,27 @@
#define BOOST_URL_RFC_IMPL_SCHEME_IPP
#include <boost/url/rfc/scheme.hpp>
#include <boost/url/error.hpp>
#include <boost/url/string.hpp>
#include <boost/url/bnf/parse.hpp>
#include <boost/url/bnf/token.hpp>
#include <boost/url/rfc/char_sets.hpp>
#include <boost/assert.hpp>
namespace boost {
namespace urls {
namespace rfc {
bool
is_scheme_char(char c) noexcept
{
return
is_alpha(c) ||
is_digit(c) ||
c == '+' ||
c == '-' ||
c == '.';
}
char const*
scheme::
parse(
char const* const start,
char const* const end,
error_code& ec)
error_code& ec,
scheme& t)
{
auto it = start;
if(it == end)
{
ec = error::need_more;
// expected alpha
ec = error::syntax;
return start;
}
if(! is_alpha(*it))
@@ -48,8 +39,13 @@ parse(
ec = error::syntax;
return start;
}
scheme_char_set cs;
it = cs.skip(it + 1, end);
bnf::token<
masked_char_set<
alnum_char_mask>> ct;
using bnf::parse;
it = parse(start, end, ec, ct);
BOOST_ASSERT(it != start);
t.s_ = ct.str();
return it;
}

View File

@@ -21,25 +21,37 @@ namespace urls {
namespace rfc {
char const*
segment::
parse(
char const* const start,
char const* const end,
error_code& ec)
error_code& ec,
segment& t)
{
pct_encoded<
unreserved_char_mask +
sub_delims_char_mask +
colon_char_mask +
at_char_mask> p;
auto it = p.parse(
start, end, ec);
at_char_mask> ts;
auto it = parse(
start, end, ec, ts);
if(ec)
return start;
v_.s_ = p->str();
t.v_ = ts.value();
return it;
}
char const*
segment::
parse(
char const* start,
char const* end,
error_code& ec)
{
using bnf::parse;
return rfc::parse(
start, end, ec, *this);
}
char const*
segment_nz::
parse(

View File

@@ -15,7 +15,6 @@
#include <boost/url/string.hpp>
#include <boost/url/rfc/char_sets.hpp>
#include <boost/url/bnf/literal.hpp>
#include <boost/url/bnf/sequence.hpp>
#include <boost/url/rfc/pct_encoded.hpp>
#include <boost/url/rfc/pct_encoding.hpp>

View File

@@ -13,20 +13,11 @@
#include <boost/url/detail/config.hpp>
#include <boost/url/error.hpp>
#include <boost/url/string.hpp>
#include <boost/url/bnf/char_set.hpp>
namespace boost {
namespace urls {
namespace rfc {
BOOST_URL_DECL
bool
is_scheme_char(char c) noexcept;
using scheme_char_set =
bnf::char_set_function<
&is_scheme_char>;
/** BNF for scheme
@par BNF
@@ -39,13 +30,23 @@ using scheme_char_set =
*/
class scheme
{
string_view s_;
public:
string_view
str() const noexcept
{
return s_;
};
BOOST_URL_DECL
friend
char const*
parse(
char const* const start,
char const* const end,
error_code& ec);
error_code& ec,
scheme& t);
};
} // rfc

View File

@@ -12,9 +12,8 @@
#include <boost/url/detail/config.hpp>
#include <boost/url/error.hpp>
#include <boost/url/string.hpp>
#include <boost/url/rfc/pct_encoding.hpp>
#include <boost/url/bnf/repeat.hpp>
#include <boost/url/bnf/parse.hpp>
#include <boost/url/rfc/pct_encoded.hpp>
namespace boost {
namespace urls {
@@ -27,10 +26,6 @@ namespace rfc {
segment = *pchar
pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded = "%" HEXDIG HEXDIG
sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="
@endcode
@see
@@ -38,53 +33,30 @@ namespace rfc {
*/
class segment
{
pct_encoded_value v_;
public:
class value_type
{
friend class segment;
string_view s_;
public:
string_view
encoded_str() const noexcept
{
return s_;
}
template<
class Allocator =
std::allocator<char>>
string_type<Allocator>
str(
Allocator const& a = {}) const
{
return pct_decode_unchecked(
s_, a);
}
};
value_type const&
operator*() const noexcept
pct_encoded_value
value()
{
return v_;
}
value_type const*
operator->() const noexcept
{
return &v_;
}
BOOST_URL_DECL
friend
char const*
parse(
char const* start,
char const* end,
error_code& ec,
segment& t);
BOOST_URL_DECL
char const*
parse(
char const* const start,
char const* const end,
char const* start,
char const* end,
error_code& ec);
private:
value_type v_;
};
/** BNF for segment which is not empty

View File

@@ -36,7 +36,6 @@ set(BOOST_URL_TESTS_FILES
bnf/char_set.cpp
bnf/range.cpp
bnf/repeat.cpp
bnf/sequence.cpp
bnf/token.cpp
bnf/tuple.cpp
bnf/type_traits.cpp

View File

@@ -1,87 +0,0 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/CPPAlliance/url
//
// Test that header file is self-contained.
#include <boost/url/bnf/sequence.hpp>
#include <boost/url/string.hpp>
#include "test_suite.hpp"
namespace boost {
namespace urls {
namespace bnf {
class sequence_test
{
public:
template<char C>
struct CharLiteral
{
char const*
operator->() const noexcept
{
return &c_;
}
char
operator*() const noexcept
{
return c_;
}
char const*
parse(
char const* const start,
char const* const end,
error_code& ec)
{
if(start == end)
{
ec = error::need_more;
return start;
}
if(*start != C)
{
ec = error::syntax;
return start;
}
c_ = C;
return start + 1;
}
private:
char c_ = {};
};
void
run()
{
error_code ec;
string_view s = "12";
sequence<
CharLiteral<'1'>,
CharLiteral<'2'>> p;
p.parse(
s.data(),
s.data() + s.size(),
ec);
BOOST_TEST(*get<0>(p)=='1');
BOOST_TEST(*get<1>(p)=='2');
BOOST_TEST(p[0] == "1");
BOOST_TEST(p[1] == "2");
}
};
TEST_SUITE(
sequence_test,
"boost.url.sequence");
} // bnf
} // urls
} // boost

View File

@@ -40,6 +40,10 @@ public:
string_view question = "?";
string_view colon = ":";
string_view slash = "/";
string_view alnum =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789";
string_view at = "@";
v = {};
@@ -49,7 +53,8 @@ public:
for(std::uint8_t c : question) v[c] |= 0x08;
for(std::uint8_t c : colon) v[c] |= 0x10;
for(std::uint8_t c : slash) v[c] |= 0x20;
for(std::uint8_t c : at) v[c] |= 0x40;
for(std::uint8_t c : alnum) v[c] |= 0x40;
for(std::uint8_t c : at) v[c] |= 0x80;
}
void
@@ -133,6 +138,12 @@ public:
slash_char_mask>(),
"/");
check(masked_char_set<
alnum_char_mask>(),
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789");
check(masked_char_set<
question_char_mask>(),
"?");

View File

@@ -24,9 +24,12 @@ public:
run()
{
using T = host;
bad_ <T>("%");
good_<T>("");
good_<T>("[::]");
good_<T>("1.2.3.4");
good_<T>("boost.org");
good_<T>("999.0.0.1"); // name
}
};

View File

@@ -23,13 +23,13 @@ public:
void
run()
{
bad <scheme>("");
bad <scheme>("1");
bad <scheme>(" ");
bad <scheme>(" http");
bad <scheme>("http ");
good<scheme>("http");
good<scheme>("a1steak");
bad_ <scheme>("");
bad_ <scheme>("1");
bad_ <scheme>(" ");
bad_ <scheme>(" http");
bad_ <scheme>("http ");
good_<scheme>("http");
good_<scheme>("a1steak");
}
};