diff --git a/include/boost/url.hpp b/include/boost/url.hpp index 527dd35b..3dd17db7 100644 --- a/include/boost/url.hpp +++ b/include/boost/url.hpp @@ -25,12 +25,9 @@ #include #include #include -#include -#include #include #include -#include #include #include #include @@ -41,6 +38,7 @@ #include #include #include +#include #include #include diff --git a/include/boost/url/bnf/char_set.hpp b/include/boost/url/bnf/char_set.hpp index 3397c55b..3fc96fb2 100644 --- a/include/boost/url/bnf/char_set.hpp +++ b/include/boost/url/bnf/char_set.hpp @@ -7,80 +7,181 @@ // Official repository: https://github.com/CPPAlliance/url // -#ifndef BOOST_URL_CHAR_SET_HPP -#define BOOST_URL_CHAR_SET_HPP +#ifndef BOOST_URL_BNF_CHAR_SET_HPP +#define BOOST_URL_BNF_CHAR_SET_HPP #include +#include +#include namespace boost { namespace urls { namespace bnf { -template -class char_set -{ -public: - template - Char* - skip( - Char* first, - char const* const end) - const noexcept - { - auto const& self = - *static_cast(this); - while(first != end) - { - if(! self.contains( - *first)) - break; - ++first; - } - return first; - } -}; +/** Set of alphanumeric characters -/** A table-driven character set + @par BNF + @code + ALNUM = ALPHA / DIGIT + + ALPHA = %x41-5A / %x61-7A + ; A-Z / a-z + + DIGIT = %x30-39 + ; 0-9 + @endcode + + @see + find_if, find_if_not + @li [RFC5234] B.1. Core Rules */ -class char_set_table - : public char_set +struct alnum_chars { - char const* const tab_; - -public: - char_set_table( - char const* tab) noexcept - : tab_(tab) - { - } - + constexpr bool - contains( - char c) const noexcept + operator()(char c) const noexcept { - auto const u = static_cast< - unsigned char>(c); - return tab_[u] != 0; + return + (c >= '0' && c <= '9') || + (c >= 'A' && c <= 'Z') || + (c >= 'a' && c <= 'z'); } }; +/** Set of alpha characters + + @par BNF + @code + ALPHA = %x41-5A / %x61-7A + ; A-Z / a-z + @endcode + + @see + find_if, find_if_not + @li [RFC5234] B.1. Core Rules +*/ +struct alpha_chars +{ + constexpr + bool + operator()(char c) const noexcept + { + return + (c >= 'A' && c <= 'Z') || + (c >= 'a' && c <= 'z'); + } +}; + +/** Set of digit characters + + @par BNF + @code + DIGIT = %x30-39 + ; 0-9 + @endcode + + @see + find_if, find_if_not + @li [RFC5234] B.1. Core Rules +*/ +struct digit_chars +{ + constexpr + bool + operator()(char c) const noexcept + { + return c >= '0' && c <= '9'; + } +}; + +/** Set of hexadecimal digit characters + + @par BNF + @code + HEXDIG = DIGIT + / "A" / "B" / "C" / "D" / "E" / "F" + / "a" / "b" / "c" / "d" / "e" / "f" + @endcode + + @note The RFCs are inconsistent on the case + sensitivity of hexadecimal digits. Existing + uses suggest case-insensitivity is a de-facto + standard. + + @see + find_if, find_if_not + @li [RFC5234] B.1. Core Rules + @li https://datatracker.ietf.org/doc/html/rfc7230#section-1.2 + @li https://datatracker.ietf.org/doc/html/rfc5234#appendix-B.1 + @li https://datatracker.ietf.org/doc/html/rfc5952#section-2.3 + @li https://datatracker.ietf.org/doc/html/rfc5952#section-4.3 +*/ +struct hexdig_chars +{ + constexpr + bool + operator()(char c) const noexcept + { + return + (c >= '0' && c <= '9') || + (c >= 'A' && c <= 'F') || + (c >= 'a' && c <= 'f'); + } +}; + +// VFALCO We can declare +// these later if needed +// +//struct hexdig_upper_chars; +//struct hexdig_lower_chars; + +/** Return the numeric value of a HEXDIG, or -1 if invalid +*/ +constexpr +char +hexdig_value(char c) noexcept +{ + if(c >= '0' && c <= '9') + return c - '0'; + if(c >= 'A' && c <= 'F') + return 10 + c - 'A'; + if(c >= 'a' && c <= 'f') + return 10 + c - 'a'; + return -1; +} + //------------------------------------------------ -template -class char_set_function - : public char_set> +/** Find the first characer in the string that is in CharSet +*/ +template +char const* +find_if( + char const* first, + char const* last, + CharSet const& cs) noexcept { -public: - bool - contains( - char c) const noexcept - { - auto const u = static_cast< - unsigned char>(c); - return F(u) != 0; - } -}; + BOOST_STATIC_ASSERT( + detail::is_char_set_pred::value); + return detail::find_if(first, last, cs, + detail::has_find_if{}); +} + +/** Find the first characer in the string that is not in CharSet +*/ +template +constexpr +char const* +find_if_not( + char const* first, + char const* last, + CharSet const& cs) noexcept +{ + BOOST_STATIC_ASSERT( + detail::is_char_set_pred::value); + return detail::find_if_not(first, last, cs, + detail::has_find_if_not{}); +} } // bnf } // urls diff --git a/include/boost/url/bnf/detail/char_set.hpp b/include/boost/url/bnf/detail/char_set.hpp new file mode 100644 index 00000000..88c3d85a --- /dev/null +++ b/include/boost/url/bnf/detail/char_set.hpp @@ -0,0 +1,129 @@ +// +// 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_DETAIL_CHAR_SET_HPP +#define BOOST_URL_BNF_DETAIL_CHAR_SET_HPP + +#include +#include + +namespace boost { +namespace urls { +namespace bnf { +namespace detail { + +template +struct is_char_set_pred : std::false_type {}; + +template +struct is_char_set_pred() = + std::declval().operator()( + std::declval()) + ) > > : std::true_type +{ +}; + +template +struct has_find_if : std::false_type {}; + +template +struct has_find_if() = + std::declval().find_if( + std::declval(), + std::declval()) + )>> : std::true_type +{ +}; + +template +struct has_find_if_not : std::false_type {}; + +template +struct has_find_if_not() = + std::declval().find_if_not( + std::declval(), + std::declval()) + )>> : std::true_type +{ +}; + +template +constexpr +char const* +find_if( + char const* first, + char const* const last, + Pred const& pred, + std::false_type) noexcept +{ + while(first != last) + { + if(pred(*first)) + break; + ++first; + } + return first; +} + +template +constexpr +char const* +find_if( + char const* first, + char const* const last, + Pred const& pred, + std::true_type) noexcept +{ + return pred.find_if( + first, last); +} + +template +constexpr +char const* +find_if_not( + char const* first, + char const* const last, + Pred const& pred, + std::false_type) noexcept +{ + while(first != last) + { + if(! pred(*first)) + break; + ++first; + } + return first; +} + +template +constexpr +char const* +find_if_not( + char const* first, + char const* const last, + Pred const& pred, + std::true_type) noexcept +{ + return pred.find_if_not( + first, last); +} + +} // detail +} // bnf +} // urls +} // boost + +#endif diff --git a/include/boost/url/bnf/impl/repeat.hpp b/include/boost/url/bnf/impl/repeat.hpp index e4917390..86a56099 100644 --- a/include/boost/url/bnf/impl/repeat.hpp +++ b/include/boost/url/bnf/impl/repeat.hpp @@ -11,109 +11,68 @@ #define BOOST_URL_BNF_IMPL_REPEAT_HPP #include +#include #include namespace boost { namespace urls { namespace bnf { -template< - class Element, - std::size_t N, - std::size_t M> +namespace detail { + +template char const* -repeat:: -parse( - char const* start, - char const* end, - error_code& ec) +parse_repeat( + char const* const start, + char const* const end, + error_code& ec, + std::size_t N, + std::size_t M, + std::size_t& n) { - auto it = begin( - start, end, ec); - if(ec == error::end) - { - ec = {}; - return start; - } + T v; + auto it = start; + n = 0; for(;;) { - it = increment( - it, end, ec); - if(ec == error::end) - break; + it = parse( + it, end, ec, v); if(ec) - return start; + break; + ++n; + if(n == M) + break; + } + if(n < N) + { + // too few + ec = error::syntax; + return start; } - ec = {}; return it; } -template< - class Element, - std::size_t N, - std::size_t M> -char const* -repeat:: -begin( - char const* start, - char const* end, - error_code& ec) -{ - n_ = 0; - v_.clear(); - return increment( - start, end, ec); -} +} // detail template< - class Element, + class T, std::size_t N, std::size_t M> char const* -repeat:: -increment( - char const* start, - char const* end, - error_code& ec) +parse( + char const* const start, + char const* const end, + error_code& ec, + repeat const& t) { - if(start == end) - { - if(n_ < N) - { - ec = error::need_more; - return start; - } - ec = error::end; + std::size_t n; + auto it = detail::parse_repeat( + start, end, ec, N, M, n); + if(ec) return start; - } - auto it = e_.parse( - start, end, ec); - if(ec == error::need_more) - return start; - if(! ec) - { - if(n_ < v_.capacity()) - { - BOOST_ASSERT( - v_.size() == n_); - v_.push_back(*e_); - } - ++n_; - if(n_ <= M) - return it; - // treat as end - ec = error::end; - return start; - } - if(n_ >= N) - { - // treat as end - ec = error::end; - return start; - } - // too few elements - ec = error::syntax; - return start; + t.v = string_view( + start, it - start); + return it; } } // bnf diff --git a/include/boost/url/bnf/impl/token.hpp b/include/boost/url/bnf/impl/token.hpp index de339a00..ffd727ea 100644 --- a/include/boost/url/bnf/impl/token.hpp +++ b/include/boost/url/bnf/impl/token.hpp @@ -10,7 +10,7 @@ #ifndef BOOST_URL_BNF_IMPL_TOKEN_HPP #define BOOST_URL_BNF_IMPL_TOKEN_HPP -#include +#include namespace boost { namespace urls { @@ -22,12 +22,11 @@ parse( char const* const start, char const* const end, error_code& ec, - token& t) + token const& t) { - CharSet cs; - auto it = cs.skip( - start, end); - t.s_ = string_view( + auto it = find_if_not( + start, end, CharSet{}); + t.v = string_view( start, it - start); ec = {}; return it; diff --git a/include/boost/url/bnf/repeat.hpp b/include/boost/url/bnf/repeat.hpp index 70df6919..39524019 100644 --- a/include/boost/url/bnf/repeat.hpp +++ b/include/boost/url/bnf/repeat.hpp @@ -12,10 +12,8 @@ #include #include -#include -#include +#include #include -#include #include namespace boost { @@ -29,7 +27,7 @@ namespace bnf { @par BNF @code - sequence = *element + sequence = *element *element => <0>*element *element => *element @@ -41,75 +39,34 @@ namespace bnf { @see https://datatracker.ietf.org/doc/html/rfc5234#section-3.6 - @tparam Element The element type to repeat + @tparam T The element type to repeat @tparam N The minimum number of repetitions, which may be zero @tparam M The maximum number of repetitions. */ template< - class Element, + class T, std::size_t N = 0, std::size_t M = std::size_t(-1)> -class repeat +struct repeat { -public: - using value_type = - boost::container::static_vector< - typename Element::value_type, - M < 20 ? M : 0>; + BOOST_STATIC_ASSERT(M > 0); + BOOST_STATIC_ASSERT(M >= N); - value_type const& - operator*() const noexcept - { - return v_; - } - - value_type const* - operator->() const noexcept - { - return &v_; - } + string_view& v; + template< + class T, + std::size_t N, + std::size_t M> + friend char const* parse( char const* start, char const* end, - error_code& ec); - - char const* - begin( - char const* start, - char const* end, - error_code& ec); - - char const* - increment( - char const* start, - char const* end, - error_code& ec); - -private: - BOOST_STATIC_ASSERT(M > 0); - BOOST_STATIC_ASSERT(M >= N); - //BOOST_STATIC_ASSERT( - // is_element::value); - - Element e_; - std::size_t n_; - value_type v_; + error_code& ec, + repeat const& t); }; -//------------------------------------------------ - -/** A BNF rule for zero or more repetitions of element -*/ -template -using zero_or_more = repeat; - -/** A BNF rule for one or more repetitions of element -*/ -template -using one_or_more = repeat; - } // bnf } // urls } // boost diff --git a/include/boost/url/bnf/token.hpp b/include/boost/url/bnf/token.hpp index ebf977e7..fb3ab301 100644 --- a/include/boost/url/bnf/token.hpp +++ b/include/boost/url/bnf/token.hpp @@ -13,6 +13,8 @@ #include #include #include +#include +#include namespace boost { namespace urls { @@ -21,16 +23,13 @@ namespace bnf { /** BNF for a series of characters in a char set */ template -class token +struct token { - string_view s_; + BOOST_STATIC_ASSERT( + detail::is_char_set_pred< + CharSet>::value); -public: - string_view - str() const noexcept - { - return s_; - } + string_view& v; template friend @@ -39,7 +38,7 @@ public: char const* start, char const* end, error_code& ec, - token& t); + token const& t); }; } // bnf diff --git a/include/boost/url/bnf/tuple.hpp b/include/boost/url/bnf/tuple.hpp deleted file mode 100644 index 06db0ec8..00000000 --- a/include/boost/url/bnf/tuple.hpp +++ /dev/null @@ -1,245 +0,0 @@ -// -// Copyright (c) 2016-2019 Damian Jarek (damian dot jarek93 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/boostorg/beast -// - -#ifndef BOOST_URL_BNF_TUPLE_HPP -#define BOOST_URL_BNF_TUPLE_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace urls { -namespace bnf { - -template -struct tuple_element_impl -{ - T t; - - tuple_element_impl() = default; - - tuple_element_impl(T const& t_) - : t(t_) - { - } - - tuple_element_impl(T&& t_) - : t(std::move(t_)) - { - } -}; - -template -struct tuple_element_impl -{ - T& t; - - tuple_element_impl() = default; - - tuple_element_impl(T& t_) - : t(t_) - { - } -}; - -template -struct tuple_impl; - -template -struct tuple_impl< - boost::mp11::index_sequence, Ts...> - : tuple_element_impl... -{ - tuple_impl() = default; - - template - explicit tuple_impl(Us&&... us) - : tuple_element_impl( - std::forward(us))... - { - } -}; - -template -struct tuple : tuple_impl< - boost::mp11::index_sequence_for, Ts...> -{ - tuple() = default; - - template - explicit tuple(Us&&... us) - : tuple_impl< - boost::mp11::index_sequence_for, Ts...>{ - std::forward(us)...} - { - } -}; - -template -T& -get(tuple_element_impl& te) -{ - return te.t; -} - -template -T const& -get(tuple_element_impl const& te) -{ - return te.t; -} - -template -T&& -get(tuple_element_impl&& te) -{ - return std::move(te.t); -} - -template -T& -get(tuple_element_impl&& te) -{ - return te.t; -} - -template -using tuple_element = typename boost::copy_cv< - mp11::mp_at_c::type, I>, T>::type; - -namespace detail { - -template< - class... Args> -char const* -parse( - char const* const start, - char const* const end, - error_code& ec, - string_view* ps, - std::integral_constant< - std::size_t, sizeof...(Args)-1>, - tuple& t) -{ - auto constexpr I = - sizeof...(Args)-1; - auto it = get(t).parse( - start, end, ec); - if(ec) - return start; - *ps = string_view( - start, it - start); - return it; -} - -template< - std::size_t I, - class... Args> -char const* -parse( - char const* const start, - char const* const end, - error_code& ec, - string_view* ps, - std::integral_constant< - std::size_t, I>, - tuple& t) -{ - auto it = get(t).parse( - start, end, ec); - if(ec) - return start; - *ps = string_view( - start, it - start); - return parse( - it, end, ec, ps + 1, - std::integral_constant< - std::size_t, I+1>{}, - t); -} - -template< - class... Tn> -char const* -parse_tuple( - char const* const start, - char const* const end, - error_code& ec, - std::integral_constant< - std::size_t, sizeof...(Tn)-1>, - tuple& t) -{ - auto constexpr I = - sizeof...(Tn)-1; - auto it = parse( - start, end, ec, - get(t)); - if(ec) - return start; - return it; -} - -template< - std::size_t I, - class... Args> -char const* -parse_tuple( - char const* const start, - char const* const end, - error_code& ec, - std::integral_constant< - std::size_t, I>, - tuple& t) -{ - using bnf::parse; - auto it = parse( - start, end, ec, - get(t)); - if(ec) - return start; - it = parse(it, end, ec, - get(t)); - if(ec) - return start; - return it; -} - -} // detail - -template -char const* -parse( - char const* const start, - char const* const end, - error_code& ec, - tuple& t) -{ - auto it = - detail::parse_tuple( - start, end, ec, - std::integral_constant< - std::size_t, 0>{}, t); - if(ec) - return start; - return it; -} - -} // bnf -} // urls -} // boost - -#endif \ No newline at end of file diff --git a/include/boost/url/bnf/type_traits.hpp b/include/boost/url/bnf/type_traits.hpp deleted file mode 100644 index 33fa18c7..00000000 --- a/include/boost/url/bnf/type_traits.hpp +++ /dev/null @@ -1,172 +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_TYPE_TRAITS_HPP -#define BOOST_URL_BNF_TYPE_TRAITS_HPP - -#include -#include -#include -#include -#include - -namespace boost { -namespace urls { -namespace bnf { - -/** Alias for std::true_type if T satisfies Element - - To satisfy _Element_, T must satisfy - _DefaultConstructible_, _CopyConstructible_, - _CopyAssignable_, and also meet these - requirements: - - @par Valid expressions - @code - char const* - T::parse( - char const* start, - char const* end, - error_code& ec); - @endcode - - @par Exemplar - @code - struct T - { - char const* parse( char const*, char const*, error_code& ); - }; - @endcode -*/ -#if BOOST_URL_DOCS -template -using is_element = __see_below__; - -#else -template -struct is_element : std::false_type {}; - -template -struct is_element.operator->(), - //std::declval.operator*(), - std::declval() = std::declval().parse( - std::declval(), - std::declval(), - std::declval()) - )>> : std::integral_constant::value && - std::is_copy_constructible::value && - std::is_copy_assignable::value> -{ -}; - -#endif - -/** Alias for std::true_type if T satisfies List - - To satisfy _List_, T must satisfy - _DefaultConstructible_, _CopyConstructible_, - _CopyAssignable_, and also meet these - requirements: - - @par Valid expressions - @code - char const* - T::begin( - char const* start, - char const* end, - error_code& ec); - - char const* - T::increment( - char const* start, - char const* end, - error_code& ec); - @endcode - - @par Exemplar - @code - struct T - { - char const* begin( char const*, char const*, error_code& ); - char const* increment( char const*, char const*, error_code& ); - }; - @endcode -*/ -#if BOOST_URL_DOCS -template -using is_list = __see_below__; - -#else -template -struct is_list : std::false_type {}; - -template -struct is_list() = std::declval().begin( - std::declval(), - std::declval(), - std::declval()), - std::declval() = std::declval().increment( - std::declval(), - std::declval(), - std::declval()) - )>> : std::integral_constant::value && - std::is_copy_constructible::value && - std::is_copy_assignable::value> -{ -}; - -#endif - -/** Alias for true_type if T is an element or list -*/ -template -using is_bnf = std::integral_constant::value || is_list::value>; - -/** Alias for std::true_type if T is a bnf with a value - - @par Valid expressions - @code - auto - T::operator->(); - - auto - T::operator*(); - @endcode -*/ -#if BOOST_URL_DOCS -template -using has_value = __see_below__; - -#else -template -struct has_value : std::false_type {}; - -template -struct has_value().operator->(), - std::declval().operator*() - )>> : std::integral_constant::value> -{ -}; - -#endif - -} // bnf -} // urls -} // boost - -#endif diff --git a/include/boost/url/detail/char_type.hpp b/include/boost/url/detail/char_type.hpp index 3f3a70c2..d0b60ed8 100644 --- a/include/boost/url/detail/char_type.hpp +++ b/include/boost/url/detail/char_type.hpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include namespace boost { @@ -124,8 +124,8 @@ public: ec = error::incomplete_pct_encoding; } else if( - rfc::hex_digit(p[0]) == -1 || - rfc::hex_digit(p[1]) == -1) + bnf::hexdig_value(p[0]) == -1 || + bnf::hexdig_value(p[1]) == -1) { ec = error::bad_pct_encoding_digit; } @@ -245,9 +245,9 @@ public: } *dest++ = static_cast( (static_cast( - rfc::hex_digit(p[1])) << 4) + + bnf::hexdig_value(p[1])) << 4) + static_cast( - rfc::hex_digit(p[2]))); + bnf::hexdig_value(p[2]))); p += 3; } return dest; @@ -475,9 +475,9 @@ key_equal( BOOST_ASSERT(e0 - p0 >= 3); auto const ch = static_cast( (static_cast( - rfc::hex_digit(p0[1])) << 4) + + bnf::hexdig_value(p0[1])) << 4) + static_cast( - rfc::hex_digit(p0[2]))); + bnf::hexdig_value(p0[2]))); if(ch != *p1++) return false; p0 += 3; diff --git a/include/boost/url/detail/parse.hpp b/include/boost/url/detail/parse.hpp index cf1bba83..b3d6cb0e 100644 --- a/include/boost/url/detail/parse.hpp +++ b/include/boost/url/detail/parse.hpp @@ -12,7 +12,7 @@ #include #include -#include +#include #include namespace boost { @@ -391,7 +391,7 @@ struct parser { BOOST_ASSERT(p_ != end_); auto digit = - rfc::hex_digit(*p_); + bnf::hexdig_value(*p_); if(digit == -1) { ec = error::syntax; @@ -403,7 +403,7 @@ struct parser if(p_ == end_) return v; digit = - rfc::hex_digit(*p_); + bnf::hexdig_value(*p_); if(digit == -1) return v; v = 16 * v + digit; @@ -412,7 +412,7 @@ struct parser if(p_ == end_) return v; digit = - rfc::hex_digit(*p_); + bnf::hexdig_value(*p_); if(digit == -1) return v; v = 16 * v + digit; @@ -421,7 +421,7 @@ struct parser if(p_ == end_) return v; digit = - rfc::hex_digit(*p_); + bnf::hexdig_value(*p_); if(digit == -1) return v; v = 16 * v + digit; @@ -565,7 +565,8 @@ struct parser } return; } - else if(b && rfc::hex_digit(*p_) == -1) + else if(b && + bnf::hexdig_value(*p_) == -1) { // end in "::" break; diff --git a/include/boost/url/rfc/char_sets.hpp b/include/boost/url/rfc/char_sets.hpp index 0b74ba3b..439f929e 100644 --- a/include/boost/url/rfc/char_sets.hpp +++ b/include/boost/url/rfc/char_sets.hpp @@ -12,81 +12,41 @@ #include #include -#include #include namespace boost { namespace urls { namespace rfc { -/** Return true if c is a low-ASCII letter +#ifndef BOOST_URL_DOCS +namespace detail { +BOOST_URL_DECL +extern +std::uint8_t +char_set_flags[256]; +} // detail +#endif - @par BNF - @code - ALPHA = %x41-5A / %x61-7A - ; A-Z / a-z - @endcode - - @see - https://datatracker.ietf.org/doc/html/rfc2234#section-6.1 +/** Character set using bitmasks for membership */ -inline -bool -is_alpha(char c) noexcept; +template +class masked_char_set +{ + std::uint8_t const* tab_ = + detail::char_set_flags; -/** Return true if c is a decimal digit +public: + bool + operator()(char c) const noexcept + { + return (tab_[static_cast< + std::uint8_t>(c)] & Mask) != 0; + } +}; - @par BNF - @code - DIGIT = %x30-39 - ; 0-9 - @endcode +//------------------------------------------------ - @see - https://datatracker.ietf.org/doc/html/rfc2234#section-6.1 -*/ -inline -bool -is_digit(char c) noexcept; - -/** Return true if c is a hexadecimal digit - - @par BNF - @code - HEXDIG = DIGIT - / "A" / "B" / "C" / "D" / "E" / "F" - / "a" / "b" / "c" / "d" / "e" / "f" - @endcode - - @note The RFCs are inconsistent on the case - sensitivity of hexadecimal digits. - - @see - https://datatracker.ietf.org/doc/html/rfc7230#section-1.2 - https://datatracker.ietf.org/doc/html/rfc5234#appendix-B.1 - https://datatracker.ietf.org/doc/html/rfc5952#section-2.3 - https://datatracker.ietf.org/doc/html/rfc5952#section-4.3 -*/ -inline -bool -is_hexdig(char c) noexcept; - -/** Return true if c is in sub-delims - - @par BNF - @code - sub-delims = "!" / "$" / "&" / "'" / "(" / ")" - / "*" / "+" / "," / ";" / "=" - @endcode - - @see - https://datatracker.ietf.org/doc/html/rfc3986#section-2.2 -*/ -inline -bool -is_sub_delims(char c) noexcept; - -/** Return true if c is unreserved +/** Mask for the unreserved character set @par BNF @code @@ -96,59 +56,123 @@ is_sub_delims(char c) noexcept; @see https://datatracker.ietf.org/doc/html/rfc3986#section-2.3 */ -inline -bool -is_unreserved(char c) noexcept; - -//------------------------------------------------ - -template -class masked_char_set - : public bnf::char_set< - masked_char_set> -{ - std::uint8_t const* tab_ = - detail::char_table; - -public: - bool - contains(char c) const noexcept - { - return (tab_[static_cast< - std::uint8_t>(c)] & Mask) != 0; - } -}; - -//------------------------------------------------ - constexpr std::uint8_t unreserved_char_mask = 0x01; +/** Mask for character set of sub-delims + + @par BNF + @code + sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + / "*" / "+" / "," / ";" / "=" + @endcode + + @see + @ref masked_char_set + https://datatracker.ietf.org/doc/html/rfc3986#section-2.2 +*/ constexpr std::uint8_t sub_delims_char_mask = 0x02; +/** Mask for character set of gen-delims + + @par BNF + @code + gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" + @endcode + + @see + @ref masked_char_set + https://datatracker.ietf.org/doc/html/rfc3986#section-2.2 +*/ constexpr std::uint8_t gen_delims_char_mask = 0x04; +/** Mask for a character set containing '?' + + @par BNF + @code + QUESTION = "?" + @endcode + + @see + @ref masked_char_set +*/ constexpr std::uint8_t question_char_mask = 0x08; -constexpr std::uint8_t - colon_char_mask = 0x10; +/** Mask for a character set containing '=' -constexpr std::uint8_t - slash_char_mask = 0x20; + @par BNF + @code + EQUALS = "=" + @endcode + @see + @ref masked_char_set +*/ constexpr std::uint8_t - alnum_char_mask = 0x40; + equals_char_mask = 0x10; +/** Mask for a character set containing ':' + + @par BNF + @code + COLON = ":" + @endcode + + @see + @ref masked_char_set +*/ +constexpr std::uint8_t + colon_char_mask = 0x20; + +/** Mask for a character set containing '/' + + @par BNF + @code + SLASH = "/" + @endcode + + @see + @ref masked_char_set +*/ +constexpr std::uint8_t + slash_char_mask = 0x40; + +/** Mask for a character set containing '@' + + @par BNF + @code + AT = "Q" + @endcode + + @see + @ref masked_char_set +*/ constexpr std::uint8_t at_char_mask = 0x80; +/** Mask for a character set containing pchars + + @par BNF + @code + pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + @endcode + + @see + @ref masked_char_set + @ref pct_encoded + https://datatracker.ietf.org/doc/html/rfc3986#section-3.3 +*/ +constexpr std::uint8_t pchar_mask = + unreserved_char_mask | + sub_delims_char_mask | + colon_char_mask | + at_char_mask; + } // rfc } // urls } // boost -#include - #endif diff --git a/include/boost/url/rfc/detail/paths.hpp b/include/boost/url/rfc/detail/paths.hpp index 36fc618d..10e03927 100644 --- a/include/boost/url/rfc/detail/paths.hpp +++ b/include/boost/url/rfc/detail/paths.hpp @@ -33,11 +33,7 @@ struct segment error_code& ec, segment const& t) { - pct_encoded< - unreserved_char_mask | - sub_delims_char_mask | - colon_char_mask | - at_char_mask> p; + pct_encoded p; using bnf::parse; auto it = parse( start, end, ec, p); @@ -62,11 +58,7 @@ struct segment_nz error_code& ec, segment_nz const& t) { - pct_encoded< - unreserved_char_mask | - sub_delims_char_mask | - colon_char_mask | - at_char_mask> p; + pct_encoded p; using bnf::parse; auto it = parse( start, end, ec, p); @@ -98,9 +90,8 @@ struct segment_nz_nc segment_nz_nc const& t) { pct_encoded< - unreserved_char_mask | - sub_delims_char_mask | - at_char_mask> p; + pchar_mask & + ~colon_char_mask> p; using bnf::parse; auto it = parse( start, end, ec, p); diff --git a/include/boost/url/rfc/detail/pct_encoding.hpp b/include/boost/url/rfc/detail/pct_encoding.hpp index fa02620e..b9066a22 100644 --- a/include/boost/url/rfc/detail/pct_encoding.hpp +++ b/include/boost/url/rfc/detail/pct_encoding.hpp @@ -10,8 +10,9 @@ #ifndef BOOST_URL_RFC_DETAIL_PCT_ENCODING_HPP #define BOOST_URL_RFC_DETAIL_PCT_ENCODING_HPP -#include +#include #include +#include #include namespace boost { @@ -28,12 +29,14 @@ parse_pct_encoded_impl( char const* const end, error_code& ec) noexcept { + using namespace bnf; std::size_t n = 0; auto it = start; char const* it0; skip: it0 = it; - it = cs.skip(it0, end); + it = find_if_not( + it0, end, cs); n += it - it0; if(it == end) goto finish; @@ -48,7 +51,7 @@ skip: ec = error::syntax; return start; } - if(hex_digit(*it) == -1) + if(hexdig_value(*it) == -1) { // expected HEXDIG ec = error::bad_pct_encoding_digit; @@ -61,7 +64,7 @@ skip: ec = error::syntax; return start; } - if(hex_digit(*it) == -1) + if(hexdig_value(*it) == -1) { // expected HEXDIG ec = error::bad_pct_encoding_digit; diff --git a/include/boost/url/rfc/hexdig.hpp b/include/boost/url/rfc/hexdig.hpp deleted file mode 100644 index 5298454d..00000000 --- a/include/boost/url/rfc/hexdig.hpp +++ /dev/null @@ -1,53 +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_RFC_HEXDIG_HPP -#define BOOST_URL_RFC_HEXDIG_HPP - -#include - -namespace boost { -namespace urls { -namespace rfc { - -/** Return true if c is a hexadecimal digit - - @par BNF - @code - HEXDIG = DIGIT - / "A" / "B" / "C" / "D" / "E" / "F" - / "a" / "b" / "c" / "d" / "e" / "f" - @endcode - - @note The RFCs are inconsistent on the case - sensitivity of hexadecimal digits. - - @see - https://datatracker.ietf.org/doc/html/rfc7230#section-1.2 - https://datatracker.ietf.org/doc/html/rfc5234#appendix-B.1 - https://datatracker.ietf.org/doc/html/rfc5952#section-2.3 - https://datatracker.ietf.org/doc/html/rfc5952#section-4.3 -*/ -inline -bool -is_hexdig(char c) noexcept; - -/** Return the numeric value of a hex char, or -1 if invalid -*/ -inline -char -hex_digit(char c) noexcept; - -} // rfc -} // urls -} // boost - -#include - -#endif diff --git a/include/boost/url/rfc/impl/char_sets.hpp b/include/boost/url/rfc/impl/char_sets.hpp deleted file mode 100644 index 4c031ea3..00000000 --- a/include/boost/url/rfc/impl/char_sets.hpp +++ /dev/null @@ -1,72 +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/urls -// - -#ifndef BOOST_URL_RFC_IMPL_CHAR_SETS_HPP -#define BOOST_URL_RFC_IMPL_CHAR_SETS_HPP - -namespace boost { -namespace urls { -namespace rfc { - -bool -is_alpha(char c) noexcept -{ - return - (c >= 'A' && c <= 'Z') || - (c >= 'a' && c <= 'z'); -} - -bool -is_digit(char c) noexcept -{ - return static_cast< - unsigned char>(c-'0') < 10; -} - -bool -is_sub_delims(char c) noexcept -{ - switch(c) - { - case '!': case '$': case '&': - case '\'': case '(': case ')': - case '*': case '+': case ',': - case ';': case '=': - return true; - default: - break; - } - return false; -} - -bool -is_unreserved(char c) noexcept -{ - if(is_alpha(c)) - return true; - if(is_digit(c)) - return true; - switch(c) - { - case '-': - case '.': - case '_': - case '~': - return true; - default: - break; - } - return false; -} - -} // bnf -} // urls -} // boost - -#endif diff --git a/include/boost/url/rfc/detail/impl/char_table.ipp b/include/boost/url/rfc/impl/char_sets.ipp similarity index 68% rename from include/boost/url/rfc/detail/impl/char_table.ipp rename to include/boost/url/rfc/impl/char_sets.ipp index fed3ad70..be0fbd88 100644 --- a/include/boost/url/rfc/detail/impl/char_table.ipp +++ b/include/boost/url/rfc/impl/char_sets.ipp @@ -7,10 +7,10 @@ // Official repository: https://github.com/CPPAlliance/url // -#ifndef BOOST_URL_RFC_DETAIL_IMPL_CHAR_TABLE_IPP -#define BOOST_URL_RFC_DETAIL_IMPL_CHAR_TABLE_IPP +#ifndef BOOST_URL_RFC_IMPL_CHAR_SETS_IPP +#define BOOST_URL_RFC_IMPL_CHAR_SETS_IPP -#include +#include namespace boost { namespace urls { @@ -18,15 +18,15 @@ namespace rfc { namespace detail { std::uint8_t -char_table[256] = { +char_set_flags[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, - 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, 0x02, 0x00, 0x04, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x44, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x24, 0x02, 0x00, 0x12, 0x00, 0x0c, + 0x84, 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, 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, diff --git a/include/boost/url/rfc/impl/hexdig.hpp b/include/boost/url/rfc/impl/hexdig.hpp deleted file mode 100644 index 06995a94..00000000 --- a/include/boost/url/rfc/impl/hexdig.hpp +++ /dev/null @@ -1,67 +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_RFC_IMPL_HEXDIG_HPP -#define BOOST_URL_RFC_IMPL_HEXDIG_HPP - -namespace boost { -namespace urls { -namespace rfc { - -bool -is_hexdig(char c) noexcept -{ - switch(c) - { - case '0': case '1': case '2': - case '3': case '4': case '5': - case '6': case '7': case '8': - case '9': - case 'A': case 'B': case 'C': - case 'D': case 'E': case 'F': - case 'a': case 'b': case 'c': - case 'd': case 'e': case 'f': - return true; - default: - break; - } - return false; -} - -char -hex_digit(char c) noexcept -{ - static constexpr char tab[] = - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" // 0...15 - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" // 16...31 - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" // 32...47 - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\xff\xff\xff\xff\xff\xff" // 48...63 - "\xff\x0a\x0b\x0c\x0d\x0e\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff" // 64...79 - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" // 80...95 - "\xff\x0a\x0b\x0c\x0d\x0e\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff" // 96..111 - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" // 112..127 - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" // 128..143 - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" // 144..159 - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" // 160..175 - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" // 176..191 - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" // 192..207 - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" // 208..223 - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" // 224..239 - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" // 240..255 - ; - return tab[static_cast(c)]; -} - -} // rfc -} // urls -} // boost - -#include - -#endif diff --git a/include/boost/url/rfc/impl/ipv4_address.ipp b/include/boost/url/rfc/impl/ipv4_address.ipp index 42c5441b..40e06228 100644 --- a/include/boost/url/rfc/impl/ipv4_address.ipp +++ b/include/boost/url/rfc/impl/ipv4_address.ipp @@ -34,6 +34,7 @@ struct dec_octet error_code& ec, dec_octet& t) { + bnf::digit_chars dc; if(start == end) { // expected DIGIT @@ -41,7 +42,7 @@ struct dec_octet return start; } auto it = start; - if(! is_digit(*it)) + if(! dc(*it)) { ec = error::syntax; return start; @@ -55,7 +56,7 @@ struct dec_octet ec = {}; return it; } - if(! is_digit(*it)) + if(! dc(*it)) { t.value = static_cast< std::uint8_t>(v); @@ -77,7 +78,7 @@ struct dec_octet ec = {}; return it; } - if(! is_digit(*it)) + if(! dc(*it)) { t.value = static_cast< std::uint8_t>(v); diff --git a/include/boost/url/rfc/impl/ipv6_address.ipp b/include/boost/url/rfc/impl/ipv6_address.ipp index 5d13cffb..059b2c3a 100644 --- a/include/boost/url/rfc/impl/ipv6_address.ipp +++ b/include/boost/url/rfc/impl/ipv6_address.ipp @@ -12,9 +12,9 @@ #include #include +#include #include #include -#include #include #include #include @@ -70,7 +70,8 @@ struct h16 ec = error::syntax; return start; } - auto d = hex_digit(*it); + auto d = + bnf::hexdig_value(*it); if(d == -1) { ec = error::syntax; @@ -80,21 +81,21 @@ struct h16 ++it; if(it == end) break; - d = hex_digit(*it); + d = bnf::hexdig_value(*it); if(d == -1) break; v = (16 * v) + d; ++it; if(it == end) break; - d = hex_digit(*it); + d = bnf::hexdig_value(*it); if(d == -1) break; v = (16 * v) + d; ++it; if(it == end) break; - d = hex_digit(*it); + d = bnf::hexdig_value(*it); if(d == -1) break; v = (16 * v) + d; @@ -225,7 +226,7 @@ parse( break; } if( b != -1 && - hex_digit(*it) == -1) + bnf::hexdig_value(*it) == -1) { // ends in "::" break; diff --git a/include/boost/url/rfc/impl/ipv_future.ipp b/include/boost/url/rfc/impl/ipv_future.ipp index 79430f67..34fec880 100644 --- a/include/boost/url/rfc/impl/ipv_future.ipp +++ b/include/boost/url/rfc/impl/ipv_future.ipp @@ -11,9 +11,9 @@ #define BOOST_URL_BNF_IMPL_IPV_FUTURE_IPP #include +#include #include #include -#include namespace boost { namespace urls { @@ -26,26 +26,26 @@ parse( error_code& ec, ipv_future& t) { - using bnf::parse; - bnf::token< - bnf::char_set_function< - &is_hexdig>> v0; - bnf::token< - masked_char_set< + using namespace bnf; + string_view v0; + string_view v1; + auto it = parse(start, end, ec, + 'v', + token{v0}, + '.', + token> v1; - auto it = parse(start, end, ec, - 'v', v0, '.', v1); + colon_char_mask>>{v1}); if(ec) return start; - if(v0.str().empty()) + if(v0.empty()) { // can't be empty ec = error::syntax; return start; } - if(v1.str().empty()) + if(v1.empty()) { // can't be empty ec = error::syntax; diff --git a/include/boost/url/rfc/impl/pct_encoding.ipp b/include/boost/url/rfc/impl/pct_encoding.ipp index 2ea4d6cb..5d370feb 100644 --- a/include/boost/url/rfc/impl/pct_encoding.ipp +++ b/include/boost/url/rfc/impl/pct_encoding.ipp @@ -54,9 +54,9 @@ pct_decode_unchecked( } *dest++ = static_cast( (static_cast( - rfc::hex_digit(it[1])) << 4) + + bnf::hexdig_value(it[1])) << 4) + static_cast( - rfc::hex_digit(it[2]))); + bnf::hexdig_value(it[2]))); it += 3; } return dest; diff --git a/include/boost/url/rfc/impl/port.ipp b/include/boost/url/rfc/impl/port.ipp index fbc93998..1274e365 100644 --- a/include/boost/url/rfc/impl/port.ipp +++ b/include/boost/url/rfc/impl/port.ipp @@ -26,15 +26,14 @@ parse( error_code& ec, port& t) { - bnf::token< - bnf::char_set_function< - &is_digit>> tk; - using bnf::parse; + using namespace bnf; + string_view s; auto it = parse( - start, end, ec, tk); + start, end, ec, + token{s}); if(ec) return start; - t.s_ = tk.str(); + t.s_ = s; t.v_.reset(); return it; } diff --git a/include/boost/url/rfc/impl/query.ipp b/include/boost/url/rfc/impl/query.ipp new file mode 100644 index 00000000..ac9a47d1 --- /dev/null +++ b/include/boost/url/rfc/impl/query.ipp @@ -0,0 +1,50 @@ +// +// 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_RFC_IMPL_QUERY_IPP +#define BOOST_URL_RFC_IMPL_QUERY_IPP + +#include +#include +#include +#include + +namespace boost { +namespace urls { +namespace rfc { + +char const* +query:: +begin( + char const* const start, + char const* const end, + error_code& ec, + query_param& t) noexcept +{ + return increment( + start, end, ec, t); +} + +char const* +query:: +increment( + char const* const start, + char const* const end, + error_code& ec, + query_param& t) noexcept +{ + //pct_encoded +#include #include -#include +#include #include #include @@ -27,25 +28,25 @@ parse( error_code& ec, scheme& t) { - auto it = start; - if(it == end) + using namespace bnf; + if(start == end) { // expected alpha ec = error::syntax; return start; } - if(! is_alpha(*it)) + auto it = start; + if(! alpha_chars{}(*it)) { + // expected alpha ec = error::syntax; return start; } - 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(); + it = find_if_not( + it + 1, end, + alnum_chars{}); + t.s_ = string_view( + start, it - start); return it; } diff --git a/include/boost/url/rfc/pct_encoding.hpp b/include/boost/url/rfc/pct_encoding.hpp index 7039b79a..fc1f6dfc 100644 --- a/include/boost/url/rfc/pct_encoding.hpp +++ b/include/boost/url/rfc/pct_encoding.hpp @@ -13,7 +13,6 @@ #include #include #include -#include namespace boost { namespace urls { diff --git a/include/boost/url/rfc/query.hpp b/include/boost/url/rfc/query.hpp new file mode 100644 index 00000000..8e49c4c8 --- /dev/null +++ b/include/boost/url/rfc/query.hpp @@ -0,0 +1,99 @@ +// +// 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_RFC_QUERY_HPP +#define BOOST_URL_RFC_QUERY_HPP + +#include +#include +#include +#include +#include + +namespace boost { +namespace urls { +namespace rfc { + +class query_param +{ + friend struct query; + + pct_encoded_value key_; + optional< + pct_encoded_value> value_; + +public: + pct_encoded_value const& + key() const noexcept + { + return key_; + } + + optional< + pct_encoded_value> const& + value() const noexcept + { + return value_; + } +}; + +/** BNF for query + + @par BNF + @code + query = *( pchar / "/" / "?" ) + / path-absolute + / path-rootless + / path-empty + @endcode + + @see + https://datatracker.ietf.org/doc/html/rfc3986#section-3.4 +*/ +struct query +{ + bnf::range< + query_param>& v; + + BOOST_URL_DECL + static + char const* + begin( + char const* const start, + char const* const end, + error_code& ec, + query_param& t) noexcept; + + BOOST_URL_DECL + static + char const* + increment( + char const* const start, + char const* const end, + error_code& ec, + query_param& t) noexcept; + + friend + char const* + parse( + char const* const start, + char const* const end, + error_code& ec, + query const& t) + { + return bnf::parse_range( + start, end, ec, t.v, t); + } +}; + +} // rfc +} // urls +} // boost + +#endif diff --git a/include/boost/url/src.hpp b/include/boost/url/src.hpp index 8b1bfd91..3b091a68 100644 --- a/include/boost/url/src.hpp +++ b/include/boost/url/src.hpp @@ -33,9 +33,8 @@ in a translation unit of the program. #include #include -#include - #include +#include #include #include #include @@ -45,6 +44,7 @@ in a translation unit of the program. #include #include #include +#include #include #include diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index cda62b80..4327835e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -33,14 +33,12 @@ set(BOOST_URL_TESTS_FILES url_view.cpp urls.cpp bnf/char_set.cpp + bnf/parse.cpp bnf/range.cpp bnf/repeat.cpp bnf/token.cpp - bnf/tuple.cpp - bnf/type_traits.cpp rfc/authority.cpp rfc/char_sets.cpp - rfc/hexdig.cpp rfc/hier_part.cpp rfc/host.cpp rfc/ip_literal.cpp @@ -51,6 +49,7 @@ set(BOOST_URL_TESTS_FILES rfc/pct_encoded.cpp rfc/pct_encoding.cpp rfc/port.cpp + rfc/query.cpp rfc/scheme.cpp rfc/userinfo.cpp ) diff --git a/test/bnf/char_set.cpp b/test/bnf/char_set.cpp index aeaadf3e..481daf4f 100644 --- a/test/bnf/char_set.cpp +++ b/test/bnf/char_set.cpp @@ -10,19 +10,124 @@ // Test that header file is self-contained. #include +#include #include "test_suite.hpp" #include "test_bnf.hpp" namespace boost { namespace urls { -namespace rfc { +namespace bnf { + +BOOST_STATIC_ASSERT( + detail::is_char_set_pred< + alnum_chars>::value); + +BOOST_STATIC_ASSERT( + detail::is_char_set_pred< + alpha_chars>::value); + +BOOST_STATIC_ASSERT( + detail::is_char_set_pred< + digit_chars>::value); + +BOOST_STATIC_ASSERT( + detail::is_char_set_pred< + hexdig_chars>::value); class char_set_test { public: + struct test_chars + { + std::size_t& n0; + std::size_t& n1; + + bool operator()( + char c) const noexcept + { + return c == 'x'; + } + + char const* + find_if( + char const* first, + char const* last) const noexcept + { + ++n0; + while(first != last) + { + if(*first == 'x') + break; + ++first; + } + return first; + } + + char const* + find_if_not( + char const* first, + char const* last) const noexcept + { + ++n1; + while(first != last) + { + if(*first != 'x') + break; + ++first; + } + return first; + } + }; + + BOOST_STATIC_ASSERT( + detail::has_find_if< + test_chars>::value); + + BOOST_STATIC_ASSERT( + detail::has_find_if_not< + test_chars>::value); + void run() { + std::size_t n0 = 0; + std::size_t n1 = 0; + test_char_set( + test_chars{n0, n1}, "x"); + BOOST_TEST(n0 > 0); + BOOST_TEST(n1 > 0); + + test_char_set( + alnum_chars{}, + "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"); + + test_char_set( + alpha_chars{}, + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"); + + test_char_set( + digit_chars{}, + "0123456789"); + + test_char_set( + hexdig_chars{}, + "0123456789" + "ABCDEF" + "abcdef"); + + for_each_char( + [](char c) + { + if(hexdig_chars{}(c)) + BOOST_TEST( + hexdig_value(c) != -1); + else + BOOST_TEST( + hexdig_value(c) == -1); + }); } }; @@ -30,6 +135,6 @@ TEST_SUITE( char_set_test, "boost.url.char_set"); -} // rfc +} // bnf } // urls } // boost diff --git a/include/boost/url/rfc/detail/char_table.hpp b/test/bnf/parse.cpp similarity index 58% rename from include/boost/url/rfc/detail/char_table.hpp rename to test/bnf/parse.cpp index 8c48a7da..f0e5b0f5 100644 --- a/include/boost/url/rfc/detail/char_table.hpp +++ b/test/bnf/parse.cpp @@ -7,25 +7,28 @@ // Official repository: https://github.com/CPPAlliance/url // -#ifndef BOOST_URL_RFC_DETAIL_CHAR_TABLE_HPP -#define BOOST_URL_RFC_DETAIL_CHAR_TABLE_HPP +// Test that header file is self-contained. +#include -#include -#include +#include "test_suite.hpp" namespace boost { namespace urls { -namespace rfc { -namespace detail { +namespace bnf { -BOOST_URL_DECL -extern -std::uint8_t -char_table[256]; +class parse_test +{ +public: + void + run() + { + } +}; -} // detail -} // rfc +TEST_SUITE( + parse_test, + "boost.url.parse"); + +} // bnf } // urls } // boost - -#endif diff --git a/test/bnf/tuple.cpp b/test/bnf/tuple.cpp deleted file mode 100644 index 5419c70d..00000000 --- a/test/bnf/tuple.cpp +++ /dev/null @@ -1,11 +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 diff --git a/test/bnf/type_traits.cpp b/test/bnf/type_traits.cpp deleted file mode 100644 index ddfb63be..00000000 --- a/test/bnf/type_traits.cpp +++ /dev/null @@ -1,11 +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 diff --git a/test/include/test_bnf.hpp b/test/include/test_bnf.hpp index 1e6852ab..848b1e0d 100644 --- a/test/include/test_bnf.hpp +++ b/test/include/test_bnf.hpp @@ -7,9 +7,10 @@ // Official repository: https://github.com/CPPAlliance/url // -#ifndef BOOST_URL_TEST_TEST_BNF_HPP -#define BOOST_URL_TEST_TEST_BNF_HPP +#ifndef BOOST_URL_TEST_BNF_HPP +#define BOOST_URL_TEST_BNF_HPP +#include #include #include @@ -18,9 +19,64 @@ namespace boost { namespace urls { +template +void +for_each_char(F const& f) +{ + unsigned char u = 0; + do + { + f(static_cast< + char>(u)); + } + while(++u != 0); +} + +template +void +test_char_set( + CharSet const& cs, + string_view s) noexcept +{ + // each char in s is in the set. + for(char c : s) + BOOST_TEST(cs(c)); + + // number of chars in + // set equals s.size() + int n = 0; + for_each_char( + [&cs, &n](char c) + { + if(cs(c)) + ++n; + }); + BOOST_TEST(n == s.size()); + + // test find_if and find_if_not + for_each_char( + [&cs](char c) + { + if(cs(c)) + { + BOOST_TEST(bnf::find_if( + &c, &c+1, cs) == &c); + BOOST_TEST(bnf::find_if_not( + &c, &c+1, cs) == &c+1); + } + else + { + BOOST_TEST(bnf::find_if( + &c, &c+1, cs) == &c+1); + BOOST_TEST(bnf::find_if_not( + &c, &c+1, cs) == &c); + } + }); +} + template void -bad_(string_view s) +bad(string_view s) { BOOST_TEST_THROWS( bnf::validate_(s), @@ -30,7 +86,7 @@ bad_(string_view s) template void -good_(string_view s) +good(string_view s) { BOOST_TEST_NO_THROW( bnf::validate_(s)); diff --git a/test/rfc/authority.cpp b/test/rfc/authority.cpp index cf7f1ead..b836a89b 100644 --- a/test/rfc/authority.cpp +++ b/test/rfc/authority.cpp @@ -23,9 +23,9 @@ public: void run() { - good_("me@you.com"); - good_("user:pass@"); - good_("user:1234"); + good("me@you.com"); + good("user:pass@"); + good("user:1234"); } }; diff --git a/test/rfc/char_sets.cpp b/test/rfc/char_sets.cpp index ef1aab1d..9fa26cb1 100644 --- a/test/rfc/char_sets.cpp +++ b/test/rfc/char_sets.cpp @@ -11,7 +11,9 @@ #include #include +#include "test_bnf.hpp" #include "test_suite.hpp" + #include #include @@ -38,12 +40,9 @@ public: string_view sub_delims = "!$&'()*+,;="; string_view gen_delims = ":/?#[]@"; string_view question = "?"; + string_view equals = "="; string_view colon = ":"; string_view slash = "/"; - string_view alnum = - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789"; string_view at = "@"; v = {}; @@ -51,9 +50,9 @@ public: for(std::uint8_t c : sub_delims) v[c] |= 0x02; for(std::uint8_t c : gen_delims) v[c] |= 0x04; 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 : alnum) v[c] |= 0x40; + for(std::uint8_t c : equals) v[c] |= 0x10; + for(std::uint8_t c : colon) v[c] |= 0x20; + for(std::uint8_t c : slash) v[c] |= 0x40; for(std::uint8_t c : at) v[c] |= 0x80; } @@ -85,66 +84,43 @@ public: dout.flush(); } - // Verify that a char_set contains - // exactly the specified characters - template - void - check(T cs, string_view s) - { - int n = 0; - unsigned char u = 0; - do - { - char const c = - static_cast(u); - if(cs.contains(c)) - ++n; - } - while(++u != 0); - BOOST_TEST(n == s.size()); - for(char c : s) - BOOST_TEST(cs.contains(c)); - } - void run() { //print_table(); - check(masked_char_set< + test_char_set(masked_char_set< unreserved_char_mask>(), "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789" "-._~"); - check(masked_char_set< + test_char_set(masked_char_set< sub_delims_char_mask>(), "!$&'()*+,;="); - check(masked_char_set< + test_char_set(masked_char_set< gen_delims_char_mask>(), ":/?#[]@"); - check(masked_char_set< + test_char_set(masked_char_set< + equals_char_mask>(), + "="); + + test_char_set(masked_char_set< colon_char_mask>(), ":"); - check(masked_char_set< + test_char_set(masked_char_set< at_char_mask>(), "@"); - check(masked_char_set< + test_char_set(masked_char_set< slash_char_mask>(), "/"); - check(masked_char_set< - alnum_char_mask>(), - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789"); - - check(masked_char_set< + test_char_set(masked_char_set< question_char_mask>(), "?"); } diff --git a/test/rfc/hexdig.cpp b/test/rfc/hexdig.cpp deleted file mode 100644 index 47aa0faa..00000000 --- a/test/rfc/hexdig.cpp +++ /dev/null @@ -1,62 +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 - -#include "test_suite.hpp" - -namespace boost { -namespace urls { -namespace rfc { - -class hexdig_test -{ -public: - void - run() - { - for(int i = 0; - i < 256; ++i) - { - auto const c = static_cast(i); - switch(i) - { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - BOOST_TEST(is_hexdig(c)); - BOOST_TEST(hex_digit(c) == i - '0'); - break; - - case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - BOOST_TEST(is_hexdig(c)); - BOOST_TEST(hex_digit(c) == 10 + i - 'A'); - break; - - case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - BOOST_TEST(is_hexdig(c)); - BOOST_TEST(hex_digit(c) == 10 + i - 'a'); - break; - - default: - BOOST_TEST(! is_hexdig( - static_cast(i))); - break; - } - } - } -}; - -TEST_SUITE( - hexdig_test, - "boost.url.hexdig"); - -} // rfc -} // urls -} // boost diff --git a/test/rfc/hier_part.cpp b/test/rfc/hier_part.cpp index 298fc634..a0ed7237 100644 --- a/test/rfc/hier_part.cpp +++ b/test/rfc/hier_part.cpp @@ -27,26 +27,26 @@ public: { using T = hier_part; - bad_ ("/"); + bad ("/"); - good_("//"); - good_("//user:pass@"); - good_("//boost.org"); - good_("//1.2.3.4:8080"); - good_("//1.2.3.4:8080/"); - good_("//1.2.3.4:8080/x"); - good_("//1.2.3.4:8080/x/"); - good_("//1.2.3.4:8080////"); - good_("/x"); - good_("/x/"); - good_("/x/y"); - good_("/x/y//"); - good_("x"); - good_("x/"); - good_("x//"); - good_("x/y/z"); - good_("x//y///z///"); - good_(""); + good("//"); + good("//user:pass@"); + good("//boost.org"); + good("//1.2.3.4:8080"); + good("//1.2.3.4:8080/"); + good("//1.2.3.4:8080/x"); + good("//1.2.3.4:8080/x/"); + good("//1.2.3.4:8080////"); + good("/x"); + good("/x/"); + good("/x/y"); + good("/x/y//"); + good("x"); + good("x/"); + good("x//"); + good("x/y/z"); + good("x//y///z///"); + good(""); hier_part p; error_code ec; diff --git a/test/rfc/host.cpp b/test/rfc/host.cpp index 31837326..be04b2a2 100644 --- a/test/rfc/host.cpp +++ b/test/rfc/host.cpp @@ -24,12 +24,12 @@ public: run() { using T = host; - bad_ ("%"); - good_(""); - good_("[::]"); - good_("1.2.3.4"); - good_("boost.org"); - good_("999.0.0.1"); // name + bad ("%"); + good(""); + good("[::]"); + good("1.2.3.4"); + good("boost.org"); + good("999.0.0.1"); // name } }; diff --git a/test/rfc/ip_literal.cpp b/test/rfc/ip_literal.cpp index a4dc991d..5eca42e6 100644 --- a/test/rfc/ip_literal.cpp +++ b/test/rfc/ip_literal.cpp @@ -24,10 +24,10 @@ public: run() { using T = ip_literal; - bad_ ("::"); - bad_ ("[v8]"); - good_("[::]"); - good_("[v1.0]"); + bad ("::"); + bad ("[v8]"); + good("[::]"); + good("[v1.0]"); } }; diff --git a/test/rfc/ipv4_address.cpp b/test/rfc/ipv4_address.cpp index 71468ee2..66cf94bb 100644 --- a/test/rfc/ipv4_address.cpp +++ b/test/rfc/ipv4_address.cpp @@ -48,19 +48,19 @@ public: void run() { - bad_ ("0"); - bad_ ("0."); - bad_ ("0.0"); - bad_ ("0.0."); - bad_ ("0.0.0"); - bad_ ("0.0.0."); - bad_ ("0.0.0.256"); - bad_ ("1.2.3.4."); - bad_ ("1.2.3.4x"); - bad_ ("1.2.3.300"); + bad ("0"); + bad ("0."); + bad ("0.0"); + bad ("0.0."); + bad ("0.0.0"); + bad ("0.0.0."); + bad ("0.0.0.256"); + bad ("1.2.3.4."); + bad ("1.2.3.4x"); + bad ("1.2.3.300"); - good_("0.0.0.0"); - good_("1.2.3.4"); + good("0.0.0.0"); + good("1.2.3.4"); check("0.0.0.0", 0x00000000); check("1.2.3.4", 0x01020304); diff --git a/test/rfc/ipv6_address.cpp b/test/rfc/ipv6_address.cpp index 2c44911b..f1e041dc 100644 --- a/test/rfc/ipv6_address.cpp +++ b/test/rfc/ipv6_address.cpp @@ -62,11 +62,7 @@ public: void run() { - auto const bad = - [](string_view s) - { - bad_(s); - }; + using T = ipv6_address; check("0:0:0:0:0:0:0:0", 0, 0); check("0:0:0:0:0:0:0.0.0.0", 0, 0); @@ -119,32 +115,31 @@ public: BOOST_TEST(! check("::", 0, 0).trailing_ipv4); BOOST_TEST(check("0:0:0:0:0:0:1.2.3.4", 0, 0x01020304).trailing_ipv4); - bad("http://[0"); - bad("//[0:1.2.3.4"); - bad("//[0:0:0:0:0:0:0::1.2.3.4"); - bad("http://[0:0:0:0:0:0:0:1.2.3.4"); - bad("http://[::FFFF:999.2.3.4"); + bad("http://[0"); + bad("//[0:1.2.3.4"); + bad("//[0:0:0:0:0:0:0::1.2.3.4"); + bad("http://[0:0:0:0:0:0:0:1.2.3.4"); + bad("http://[::FFFF:999.2.3.4"); - // coverage - bad(""); - bad("0"); - bad(":"); - bad("::0::"); - bad(":0::"); - bad("0::0:x"); - bad("x::"); - bad("0:12"); - bad("0:123"); - bad("::1."); - bad("::1.2"); - bad("::1.2"); - bad("::1.2x"); - bad("::1.2."); - bad("::1.2.3"); - bad("::1.2.3"); - bad("::1.2.3x"); - bad("::1.2.3."); - bad("::1.2.3.4x"); + bad(""); + bad("0"); + bad(":"); + bad("::0::"); + bad(":0::"); + bad("0::0:x"); + bad("x::"); + bad("0:12"); + bad("0:123"); + bad("::1."); + bad("::1.2"); + bad("::1.2"); + bad("::1.2x"); + bad("::1.2."); + bad("::1.2.3"); + bad("::1.2.3"); + bad("::1.2.3x"); + bad("::1.2.3."); + bad("::1.2.3.4x"); } }; diff --git a/test/rfc/ipv_future.cpp b/test/rfc/ipv_future.cpp index b0190e27..679c2fca 100644 --- a/test/rfc/ipv_future.cpp +++ b/test/rfc/ipv_future.cpp @@ -25,14 +25,14 @@ public: { using T = ipv_future; - bad_ ("v"); - bad_ ("v1"); - bad_ ("v1."); - bad_ ("v1.@$"); - bad_ ("v.1"); + bad ("v"); + bad ("v1"); + bad ("v1."); + bad ("v1.@$"); + bad ("v.1"); - good_("v1.0"); - good_("v1.minor"); + good("v1.0"); + good("v1.minor"); } }; diff --git a/test/rfc/port.cpp b/test/rfc/port.cpp index 10709921..da68a7de 100644 --- a/test/rfc/port.cpp +++ b/test/rfc/port.cpp @@ -46,7 +46,7 @@ public: using T = optional< port::number_type>; - bad_ ("x"); + bad ("x"); // VFALCO TODO check("0", "0", boost::none);//T(0)); diff --git a/test/rfc/query.cpp b/test/rfc/query.cpp new file mode 100644 index 00000000..a0ed7237 --- /dev/null +++ b/test/rfc/query.cpp @@ -0,0 +1,66 @@ +// +// 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 + +#include "test_suite.hpp" +#include "test_bnf.hpp" + +#include + +namespace boost { +namespace urls { +namespace rfc { + +class hier_part_test +{ +public: + void + run() + { + using T = hier_part; + + bad ("/"); + + good("//"); + good("//user:pass@"); + good("//boost.org"); + good("//1.2.3.4:8080"); + good("//1.2.3.4:8080/"); + good("//1.2.3.4:8080/x"); + good("//1.2.3.4:8080/x/"); + good("//1.2.3.4:8080////"); + good("/x"); + good("/x/"); + good("/x/y"); + good("/x/y//"); + good("x"); + good("x/"); + good("x//"); + good("x/y/z"); + good("x//y///z///"); + good(""); + + hier_part p; + error_code ec; + using bnf::parse; + parse("/1/2/3/4/5", ec, p); + for(auto const& t : p.path()) + std::cout << t.str() << std::endl; + } +}; + +TEST_SUITE( + hier_part_test, + "boost.url.hier_part"); + +} // rfc +} // urls +} // boost diff --git a/test/rfc/scheme.cpp b/test/rfc/scheme.cpp index 5e8ef996..e3eb91cf 100644 --- a/test/rfc/scheme.cpp +++ b/test/rfc/scheme.cpp @@ -23,13 +23,13 @@ public: void run() { - bad_ (""); - bad_ ("1"); - bad_ (" "); - bad_ (" http"); - bad_ ("http "); - good_("http"); - good_("a1steak"); + bad (""); + bad ("1"); + bad (" "); + bad (" http"); + bad ("http "); + good("http"); + good("a1steak"); } }; diff --git a/test/rfc/userinfo.cpp b/test/rfc/userinfo.cpp index 7e9b91b3..bb12b2a2 100644 --- a/test/rfc/userinfo.cpp +++ b/test/rfc/userinfo.cpp @@ -54,16 +54,16 @@ public: void run() { - bad_ ("@"); + bad ("@"); - good_(""); - good_("x"); - good_("xy"); - good_("x:"); - good_("x:y"); - good_("x:y:"); - good_("x:y:z"); - good_("%41"); + good(""); + good("x"); + good("xy"); + good("x:"); + good("x:y"); + good("x:y:"); + good("x:y:z"); + good("%41"); using T = optional; check("x", "x", "x", boost::none);