100.00% Lines (25/25)
100.00% Functions (9/9)
| TLA | Baseline | Branch | ||||||
|---|---|---|---|---|---|---|---|---|
| Line | Hits | Code | Line | Hits | Code | |||
| 1 | // | 1 | // | |||||
| 2 | // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) | 2 | // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) | |||||
| 3 | // | 3 | // | |||||
| 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |||||
| 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |||||
| 6 | // | 6 | // | |||||
| 7 | // Official repository: https://github.com/boostorg/url | 7 | // Official repository: https://github.com/boostorg/url | |||||
| 8 | // | 8 | // | |||||
| 9 | 9 | |||||||
| 10 | #ifndef BOOST_URL_GRAMMAR_RANGE_RULE_HPP | 10 | #ifndef BOOST_URL_GRAMMAR_RANGE_RULE_HPP | |||||
| 11 | #define BOOST_URL_GRAMMAR_RANGE_RULE_HPP | 11 | #define BOOST_URL_GRAMMAR_RANGE_RULE_HPP | |||||
| 12 | 12 | |||||||
| 13 | #include <boost/url/detail/config.hpp> | 13 | #include <boost/url/detail/config.hpp> | |||||
| 14 | #include <boost/url/error.hpp> | 14 | #include <boost/url/error.hpp> | |||||
| 15 | #include <boost/core/detail/string_view.hpp> | 15 | #include <boost/core/detail/string_view.hpp> | |||||
| 16 | #include <boost/url/grammar/parse.hpp> | 16 | #include <boost/url/grammar/parse.hpp> | |||||
| 17 | #include <boost/url/grammar/type_traits.hpp> | 17 | #include <boost/url/grammar/type_traits.hpp> | |||||
| 18 | #include <boost/url/grammar/detail/range_rule.hpp> | 18 | #include <boost/url/grammar/detail/range_rule.hpp> | |||||
| 19 | #include <boost/core/detail/static_assert.hpp> | 19 | #include <boost/core/detail/static_assert.hpp> | |||||
| 20 | #include <cstddef> | 20 | #include <cstddef> | |||||
| 21 | #include <iterator> | 21 | #include <iterator> | |||||
| 22 | #include <type_traits> | 22 | #include <type_traits> | |||||
| 23 | #include <utility> | 23 | #include <utility> | |||||
| 24 | #include <stddef.h> // ::max_align_t | 24 | #include <stddef.h> // ::max_align_t | |||||
| 25 | 25 | |||||||
| 26 | namespace boost { | 26 | namespace boost { | |||||
| 27 | namespace urls { | 27 | namespace urls { | |||||
| 28 | namespace grammar { | 28 | namespace grammar { | |||||
| 29 | namespace implementation_defined { | 29 | namespace implementation_defined { | |||||
| 30 | template<class R0, class R1> | 30 | template<class R0, class R1> | |||||
| 31 | struct range_rule_t; | 31 | struct range_rule_t; | |||||
| 32 | } // implementation_defined | 32 | } // implementation_defined | |||||
| 33 | 33 | |||||||
| 34 | namespace implementation_defined | 34 | namespace implementation_defined | |||||
| 35 | { | 35 | { | |||||
| 36 | template<class RangeRule, class = void> | 36 | template<class RangeRule, class = void> | |||||
| 37 | struct range_value_type | 37 | struct range_value_type | |||||
| 38 | { | 38 | { | |||||
| 39 | using type = void; | 39 | using type = void; | |||||
| 40 | }; | 40 | }; | |||||
| 41 | 41 | |||||||
| 42 | template<class RangeRule> | 42 | template<class RangeRule> | |||||
| 43 | struct range_value_type< | 43 | struct range_value_type< | |||||
| 44 | RangeRule, | 44 | RangeRule, | |||||
| 45 | urls::void_t<typename RangeRule::value_type>> | 45 | urls::void_t<typename RangeRule::value_type>> | |||||
| 46 | { | 46 | { | |||||
| 47 | using type = typename RangeRule::value_type; | 47 | using type = typename RangeRule::value_type; | |||||
| 48 | }; | 48 | }; | |||||
| 49 | 49 | |||||||
| 50 | template<class RangeRule, class ValueType, class = void> | 50 | template<class RangeRule, class ValueType, class = void> | |||||
| 51 | struct is_range_rule : std::false_type | 51 | struct is_range_rule : std::false_type | |||||
| 52 | { | 52 | { | |||||
| 53 | }; | 53 | }; | |||||
| 54 | 54 | |||||||
| 55 | template<class RangeRule, class ValueType> | 55 | template<class RangeRule, class ValueType> | |||||
| 56 | struct is_range_rule< | 56 | struct is_range_rule< | |||||
| 57 | RangeRule, | 57 | RangeRule, | |||||
| 58 | ValueType, | 58 | ValueType, | |||||
| 59 | urls::void_t< | 59 | urls::void_t< | |||||
| 60 | decltype(std::declval<RangeRule const&>().first( | 60 | decltype(std::declval<RangeRule const&>().first( | |||||
| 61 | std::declval<char const*&>(), | 61 | std::declval<char const*&>(), | |||||
| 62 | std::declval<char const*>())), | 62 | std::declval<char const*>())), | |||||
| 63 | decltype(std::declval<RangeRule const&>().next( | 63 | decltype(std::declval<RangeRule const&>().next( | |||||
| 64 | std::declval<char const*&>(), | 64 | std::declval<char const*&>(), | |||||
| 65 | std::declval<char const*>()))>> | 65 | std::declval<char const*>()))>> | |||||
| 66 | : std::integral_constant<bool, | 66 | : std::integral_constant<bool, | |||||
| 67 | std::is_same< | 67 | std::is_same< | |||||
| 68 | decltype(std::declval<RangeRule const&>().first( | 68 | decltype(std::declval<RangeRule const&>().first( | |||||
| 69 | std::declval<char const*&>(), | 69 | std::declval<char const*&>(), | |||||
| 70 | std::declval<char const*>())), | 70 | std::declval<char const*>())), | |||||
| 71 | system::result<ValueType>>::value && | 71 | system::result<ValueType>>::value && | |||||
| 72 | std::is_same< | 72 | std::is_same< | |||||
| 73 | decltype(std::declval<RangeRule const&>().next( | 73 | decltype(std::declval<RangeRule const&>().next( | |||||
| 74 | std::declval<char const*&>(), | 74 | std::declval<char const*&>(), | |||||
| 75 | std::declval<char const*>())), | 75 | std::declval<char const*>())), | |||||
| 76 | system::result<ValueType>>::value> | 76 | system::result<ValueType>>::value> | |||||
| 77 | { | 77 | { | |||||
| 78 | }; | 78 | }; | |||||
| 79 | } | 79 | } | |||||
| 80 | 80 | |||||||
| 81 | template<class RangeRule> | 81 | template<class RangeRule> | |||||
| 82 | using is_range_rule = implementation_defined::is_range_rule< | 82 | using is_range_rule = implementation_defined::is_range_rule< | |||||
| 83 | RangeRule, | 83 | RangeRule, | |||||
| 84 | typename implementation_defined::range_value_type< | 84 | typename implementation_defined::range_value_type< | |||||
| 85 | RangeRule>::type>; | 85 | RangeRule>::type>; | |||||
| 86 | 86 | |||||||
| 87 | #ifdef BOOST_URL_HAS_CONCEPTS | 87 | #ifdef BOOST_URL_HAS_CONCEPTS | |||||
| 88 | template <class T> | 88 | template <class T> | |||||
| 89 | concept RangeRule = | 89 | concept RangeRule = | |||||
| 90 | requires (T r, char const*& it, char const* end) | 90 | requires (T r, char const*& it, char const* end) | |||||
| 91 | { | 91 | { | |||||
| 92 | typename T::value_type; | 92 | typename T::value_type; | |||||
| 93 | { r.first(it, end) } -> std::same_as<system::result<typename T::value_type>>; | 93 | { r.first(it, end) } -> std::same_as<system::result<typename T::value_type>>; | |||||
| 94 | { r.next(it, end) } -> std::same_as<system::result<typename T::value_type>>; | 94 | { r.next(it, end) } -> std::same_as<system::result<typename T::value_type>>; | |||||
| 95 | }; | 95 | }; | |||||
| 96 | #endif | 96 | #endif | |||||
| 97 | 97 | |||||||
| 98 | template<class T> | 98 | template<class T> | |||||
| 99 | class any_rule; | 99 | class any_rule; | |||||
| 100 | 100 | |||||||
| 101 | template<class T> | 101 | template<class T> | |||||
| 102 | class any_rule | 102 | class any_rule | |||||
| 103 | { | 103 | { | |||||
| 104 | public: | 104 | public: | |||||
| 105 | using value_type = T; | 105 | using value_type = T; | |||||
| 106 | 106 | |||||||
| 107 | any_rule() noexcept; | 107 | any_rule() noexcept; | |||||
| 108 | any_rule(any_rule const&) noexcept; | 108 | any_rule(any_rule const&) noexcept; | |||||
| 109 | any_rule(any_rule&&) noexcept; | 109 | any_rule(any_rule&&) noexcept; | |||||
| 110 | any_rule& operator=(any_rule const&) noexcept; | 110 | any_rule& operator=(any_rule const&) noexcept; | |||||
| 111 | any_rule& operator=(any_rule&&) noexcept; | 111 | any_rule& operator=(any_rule&&) noexcept; | |||||
| 112 | ~any_rule(); | 112 | ~any_rule(); | |||||
| 113 | 113 | |||||||
| 114 | template<class R> | 114 | template<class R> | |||||
| 115 | explicit | 115 | explicit | |||||
| 116 | any_rule(R const& next); | 116 | any_rule(R const& next); | |||||
| 117 | 117 | |||||||
| 118 | template<class R0, class R1> | 118 | template<class R0, class R1> | |||||
| 119 | any_rule( | 119 | any_rule( | |||||
| 120 | R0 const& first, | 120 | R0 const& first, | |||||
| 121 | R1 const& next); | 121 | R1 const& next); | |||||
| 122 | 122 | |||||||
| 123 | system::result<T> | 123 | system::result<T> | |||||
| 124 | first( | 124 | first( | |||||
| 125 | char const*& it, | 125 | char const*& it, | |||||
| 126 | char const* end) const noexcept; | 126 | char const* end) const noexcept; | |||||
| 127 | 127 | |||||||
| 128 | system::result<T> | 128 | system::result<T> | |||||
| 129 | next( | 129 | next( | |||||
| 130 | char const*& it, | 130 | char const*& it, | |||||
| 131 | char const* end) const noexcept; | 131 | char const* end) const noexcept; | |||||
| 132 | 132 | |||||||
| 133 | private: | 133 | private: | |||||
| 134 | static constexpr | 134 | static constexpr | |||||
| 135 | std::size_t BufferSize = 128; | 135 | std::size_t BufferSize = 128; | |||||
| 136 | 136 | |||||||
| 137 | struct small_buffer | 137 | struct small_buffer | |||||
| 138 | { | 138 | { | |||||
| 139 | alignas(alignof(::max_align_t)) | 139 | alignas(alignof(::max_align_t)) | |||||
| 140 | unsigned char buf[BufferSize]; | 140 | unsigned char buf[BufferSize]; | |||||
| 141 | 141 | |||||||
| HITCBC | 142 | 711 | void const* addr() const noexcept | 142 | 711 | void const* addr() const noexcept | ||
| 143 | { | 143 | { | |||||
| HITCBC | 144 | 711 | return buf; | 144 | 711 | return buf; | ||
| 145 | } | 145 | } | |||||
| 146 | 146 | |||||||
| HITCBC | 147 | 2732 | void* addr() noexcept | 147 | 2732 | void* addr() noexcept | ||
| 148 | { | 148 | { | |||||
| HITCBC | 149 | 2732 | return buf; | 149 | 2732 | return buf; | ||
| 150 | } | 150 | } | |||||
| 151 | }; | 151 | }; | |||||
| 152 | 152 | |||||||
| 153 | struct impl_base; | 153 | struct impl_base; | |||||
| 154 | 154 | |||||||
| 155 | template<class R, bool> | 155 | template<class R, bool> | |||||
| 156 | struct impl1; | 156 | struct impl1; | |||||
| 157 | 157 | |||||||
| 158 | template< | 158 | template< | |||||
| 159 | class R0, class R1, bool> | 159 | class R0, class R1, bool> | |||||
| 160 | struct impl2; | 160 | struct impl2; | |||||
| 161 | 161 | |||||||
| 162 | impl_base& | 162 | impl_base& | |||||
| 163 | get() noexcept; | 163 | get() noexcept; | |||||
| 164 | 164 | |||||||
| 165 | impl_base const& | 165 | impl_base const& | |||||
| 166 | get() const noexcept; | 166 | get() const noexcept; | |||||
| 167 | 167 | |||||||
| 168 | small_buffer sb_; | 168 | small_buffer sb_; | |||||
| 169 | }; | 169 | }; | |||||
| 170 | 170 | |||||||
| 171 | /** A forward range of parsed elements | 171 | /** A forward range of parsed elements | |||||
| 172 | 172 | |||||||
| 173 | Objects of this type are forward ranges | 173 | Objects of this type are forward ranges | |||||
| 174 | returned when parsing using the | 174 | returned when parsing using the | |||||
| 175 | @ref range_rule. | 175 | @ref range_rule. | |||||
| 176 | Iteration is performed by re-parsing the | 176 | Iteration is performed by re-parsing the | |||||
| 177 | underlying character buffer. Ownership | 177 | underlying character buffer. Ownership | |||||
| 178 | of the buffer is not transferred; the | 178 | of the buffer is not transferred; the | |||||
| 179 | caller is responsible for ensuring that | 179 | caller is responsible for ensuring that | |||||
| 180 | the lifetime of the buffer extends until | 180 | the lifetime of the buffer extends until | |||||
| 181 | it is no longer referenced by the range. | 181 | it is no longer referenced by the range. | |||||
| 182 | 182 | |||||||
| 183 | @note | 183 | @note | |||||
| 184 | 184 | |||||||
| 185 | The implementation may type-erase the | 185 | The implementation may type-erase the | |||||
| 186 | rule responsible for iterating the | 186 | rule responsible for iterating the | |||||
| 187 | underlying character buffer. Objects | 187 | underlying character buffer. Objects | |||||
| 188 | of type `range` are intended to be used | 188 | of type `range` are intended to be used | |||||
| 189 | ephemerally. That is, for short durations | 189 | ephemerally. That is, for short durations | |||||
| 190 | such as within a function scope. If it is | 190 | such as within a function scope. If it is | |||||
| 191 | necessary to store the range for a long | 191 | necessary to store the range for a long | |||||
| 192 | period of time or with static storage | 192 | period of time or with static storage | |||||
| 193 | duration, it is necessary to copy the | 193 | duration, it is necessary to copy the | |||||
| 194 | contents to an object of a different type. | 194 | contents to an object of a different type. | |||||
| 195 | 195 | |||||||
| 196 | @tparam T The value type of the range | 196 | @tparam T The value type of the range | |||||
| 197 | @tparam RangeRule The implementation used to | 197 | @tparam RangeRule The implementation used to | |||||
| 198 | iterate the range. The default is a | 198 | iterate the range. The default is a | |||||
| 199 | type-erased rule. | 199 | type-erased rule. | |||||
| 200 | 200 | |||||||
| 201 | @see | 201 | @see | |||||
| 202 | @ref parse, | 202 | @ref parse, | |||||
| 203 | @ref range_rule. | 203 | @ref range_rule. | |||||
| 204 | */ | 204 | */ | |||||
| 205 | template< | 205 | template< | |||||
| 206 | class T, | 206 | class T, | |||||
| 207 | class RangeRule = any_rule<T>> | 207 | class RangeRule = any_rule<T>> | |||||
| 208 | class range | 208 | class range | |||||
| 209 | : private detail::range_base_storage< | 209 | : private detail::range_base_storage< | |||||
| 210 | RangeRule> | 210 | RangeRule> | |||||
| 211 | { | 211 | { | |||||
| 212 | private: | 212 | private: | |||||
| 213 | #ifdef BOOST_URL_HAS_CONCEPTS | 213 | #ifdef BOOST_URL_HAS_CONCEPTS | |||||
| 214 | static_assert( | 214 | static_assert( | |||||
| 215 | ::boost::urls::grammar::RangeRule<RangeRule>, | 215 | ::boost::urls::grammar::RangeRule<RangeRule>, | |||||
| 216 | "RangeRule requirements not met"); | 216 | "RangeRule requirements not met"); | |||||
| 217 | #else | 217 | #else | |||||
| 218 | static_assert( | 218 | static_assert( | |||||
| 219 | ::boost::urls::grammar::is_range_rule<RangeRule>::value, | 219 | ::boost::urls::grammar::is_range_rule<RangeRule>::value, | |||||
| 220 | "RangeRule requirements not met"); | 220 | "RangeRule requirements not met"); | |||||
| 221 | #endif | 221 | #endif | |||||
| 222 | 222 | |||||||
| 223 | static_assert( | 223 | static_assert( | |||||
| 224 | std::is_class< | 224 | std::is_class< | |||||
| 225 | detail::range_base_storage< | 225 | detail::range_base_storage< | |||||
| 226 | RangeRule>>::value, | 226 | RangeRule>>::value, | |||||
| 227 | "range_base_storage requirements not met"); | 227 | "range_base_storage requirements not met"); | |||||
| 228 | 228 | |||||||
| 229 | using storage_type = | 229 | using storage_type = | |||||
| 230 | detail::range_base_storage< | 230 | detail::range_base_storage< | |||||
| 231 | RangeRule>; | 231 | RangeRule>; | |||||
| 232 | 232 | |||||||
| 233 | using storage_type::rule; | 233 | using storage_type::rule; | |||||
| 234 | 234 | |||||||
| 235 | core::string_view s_; | 235 | core::string_view s_; | |||||
| 236 | std::size_t n_ = 0; | 236 | std::size_t n_ = 0; | |||||
| 237 | 237 | |||||||
| 238 | template< | 238 | template< | |||||
| 239 | class R0, class R1> | 239 | class R0, class R1> | |||||
| 240 | friend struct implementation_defined::range_rule_t; | 240 | friend struct implementation_defined::range_rule_t; | |||||
| 241 | 241 | |||||||
| 242 | range( | 242 | range( | |||||
| 243 | core::string_view s, | 243 | core::string_view s, | |||||
| 244 | std::size_t n, | 244 | std::size_t n, | |||||
| 245 | RangeRule const& rule) noexcept; | 245 | RangeRule const& rule) noexcept; | |||||
| 246 | 246 | |||||||
| 247 | range( | 247 | range( | |||||
| 248 | core::string_view s, | 248 | core::string_view s, | |||||
| 249 | std::size_t n, | 249 | std::size_t n, | |||||
| 250 | RangeRule&& rule) noexcept; | 250 | RangeRule&& rule) noexcept; | |||||
| 251 | 251 | |||||||
| 252 | public: | 252 | public: | |||||
| 253 | /** The type of each element of the range | 253 | /** The type of each element of the range | |||||
| 254 | */ | 254 | */ | |||||
| 255 | using value_type = T; | 255 | using value_type = T; | |||||
| 256 | 256 | |||||||
| 257 | /** The type of each element of the range | 257 | /** The type of each element of the range | |||||
| 258 | */ | 258 | */ | |||||
| 259 | using reference = T const&; | 259 | using reference = T const&; | |||||
| 260 | 260 | |||||||
| 261 | /** The type of each element of the range | 261 | /** The type of each element of the range | |||||
| 262 | */ | 262 | */ | |||||
| 263 | using const_reference = T const&; | 263 | using const_reference = T const&; | |||||
| 264 | 264 | |||||||
| 265 | /** Provided for compatibility, unused | 265 | /** Provided for compatibility, unused | |||||
| 266 | */ | 266 | */ | |||||
| 267 | using pointer = void const*; | 267 | using pointer = void const*; | |||||
| 268 | 268 | |||||||
| 269 | /** The type used to represent unsigned integers | 269 | /** The type used to represent unsigned integers | |||||
| 270 | */ | 270 | */ | |||||
| 271 | using size_type = std::size_t; | 271 | using size_type = std::size_t; | |||||
| 272 | 272 | |||||||
| 273 | /** The type used to represent signed integers | 273 | /** The type used to represent signed integers | |||||
| 274 | */ | 274 | */ | |||||
| 275 | using difference_type = std::ptrdiff_t; | 275 | using difference_type = std::ptrdiff_t; | |||||
| 276 | 276 | |||||||
| 277 | /** A constant, forward iterator to elements of the range | 277 | /** A constant, forward iterator to elements of the range | |||||
| 278 | */ | 278 | */ | |||||
| 279 | class iterator; | 279 | class iterator; | |||||
| 280 | 280 | |||||||
| 281 | /** A constant, forward iterator to elements of the range | 281 | /** A constant, forward iterator to elements of the range | |||||
| 282 | */ | 282 | */ | |||||
| 283 | using const_iterator = iterator; | 283 | using const_iterator = iterator; | |||||
| 284 | 284 | |||||||
| 285 | /** Destructor | 285 | /** Destructor | |||||
| 286 | */ | 286 | */ | |||||
| 287 | ~range(); | 287 | ~range(); | |||||
| 288 | 288 | |||||||
| 289 | /** Constructor | 289 | /** Constructor | |||||
| 290 | 290 | |||||||
| 291 | Default-constructed ranges have | 291 | Default-constructed ranges have | |||||
| 292 | zero elements. | 292 | zero elements. | |||||
| 293 | 293 | |||||||
| 294 | @par Exception Safety | 294 | @par Exception Safety | |||||
| 295 | Throws nothing. | 295 | Throws nothing. | |||||
| 296 | */ | 296 | */ | |||||
| 297 | range() noexcept; | 297 | range() noexcept; | |||||
| 298 | 298 | |||||||
| 299 | /** Constructor | 299 | /** Constructor | |||||
| 300 | 300 | |||||||
| 301 | The new range references the | 301 | The new range references the | |||||
| 302 | same underlying character buffer. | 302 | same underlying character buffer. | |||||
| 303 | Ownership is not transferred; the | 303 | Ownership is not transferred; the | |||||
| 304 | caller is responsible for ensuring | 304 | caller is responsible for ensuring | |||||
| 305 | that the lifetime of the buffer | 305 | that the lifetime of the buffer | |||||
| 306 | extends until it is no longer | 306 | extends until it is no longer | |||||
| 307 | referenced. The moved-from object | 307 | referenced. The moved-from object | |||||
| 308 | becomes as if default-constructed. | 308 | becomes as if default-constructed. | |||||
| 309 | 309 | |||||||
| 310 | @par Exception Safety | 310 | @par Exception Safety | |||||
| 311 | Throws nothing. | 311 | Throws nothing. | |||||
| 312 | */ | 312 | */ | |||||
| 313 | range(range&&) noexcept; | 313 | range(range&&) noexcept; | |||||
| 314 | 314 | |||||||
| 315 | /** Constructor | 315 | /** Constructor | |||||
| 316 | 316 | |||||||
| 317 | The copy references the same | 317 | The copy references the same | |||||
| 318 | underlying character buffer. | 318 | underlying character buffer. | |||||
| 319 | Ownership is not transferred; the | 319 | Ownership is not transferred; the | |||||
| 320 | caller is responsible for ensuring | 320 | caller is responsible for ensuring | |||||
| 321 | that the lifetime of the buffer | 321 | that the lifetime of the buffer | |||||
| 322 | extends until it is no longer | 322 | extends until it is no longer | |||||
| 323 | referenced. | 323 | referenced. | |||||
| 324 | 324 | |||||||
| 325 | @par Exception Safety | 325 | @par Exception Safety | |||||
| 326 | Throws nothing. | 326 | Throws nothing. | |||||
| 327 | */ | 327 | */ | |||||
| 328 | range(range const&) noexcept; | 328 | range(range const&) noexcept; | |||||
| 329 | 329 | |||||||
| 330 | /** Assignment | 330 | /** Assignment | |||||
| 331 | 331 | |||||||
| 332 | After the move, this references the | 332 | After the move, this references the | |||||
| 333 | same underlying character buffer. Ownership | 333 | same underlying character buffer. Ownership | |||||
| 334 | is not transferred; the caller is responsible | 334 | is not transferred; the caller is responsible | |||||
| 335 | for ensuring that the lifetime of the buffer | 335 | for ensuring that the lifetime of the buffer | |||||
| 336 | extends until it is no longer referenced. | 336 | extends until it is no longer referenced. | |||||
| 337 | The moved-from object becomes as if | 337 | The moved-from object becomes as if | |||||
| 338 | default-constructed. | 338 | default-constructed. | |||||
| 339 | 339 | |||||||
| 340 | @par Exception Safety | 340 | @par Exception Safety | |||||
| 341 | Throws nothing. | 341 | Throws nothing. | |||||
| 342 | 342 | |||||||
| 343 | @return `*this` | 343 | @return `*this` | |||||
| 344 | */ | 344 | */ | |||||
| 345 | range& | 345 | range& | |||||
| 346 | operator=(range&&) noexcept; | 346 | operator=(range&&) noexcept; | |||||
| 347 | 347 | |||||||
| 348 | /** Assignment | 348 | /** Assignment | |||||
| 349 | 349 | |||||||
| 350 | The copy references the same | 350 | The copy references the same | |||||
| 351 | underlying character buffer. | 351 | underlying character buffer. | |||||
| 352 | Ownership is not transferred; the | 352 | Ownership is not transferred; the | |||||
| 353 | caller is responsible for ensuring | 353 | caller is responsible for ensuring | |||||
| 354 | that the lifetime of the buffer | 354 | that the lifetime of the buffer | |||||
| 355 | extends until it is no longer | 355 | extends until it is no longer | |||||
| 356 | referenced. | 356 | referenced. | |||||
| 357 | 357 | |||||||
| 358 | @par Exception Safety | 358 | @par Exception Safety | |||||
| 359 | Throws nothing. | 359 | Throws nothing. | |||||
| 360 | 360 | |||||||
| 361 | @return `*this` | 361 | @return `*this` | |||||
| 362 | */ | 362 | */ | |||||
| 363 | range& | 363 | range& | |||||
| 364 | operator=(range const&) noexcept; | 364 | operator=(range const&) noexcept; | |||||
| 365 | 365 | |||||||
| 366 | /** Return an iterator to the beginning | 366 | /** Return an iterator to the beginning | |||||
| 367 | 367 | |||||||
| 368 | @return An iterator to the first element | 368 | @return An iterator to the first element | |||||
| 369 | */ | 369 | */ | |||||
| 370 | iterator begin() const noexcept; | 370 | iterator begin() const noexcept; | |||||
| 371 | 371 | |||||||
| 372 | /** Return an iterator to the end | 372 | /** Return an iterator to the end | |||||
| 373 | 373 | |||||||
| 374 | @return An iterator to one past the last element | 374 | @return An iterator to one past the last element | |||||
| 375 | */ | 375 | */ | |||||
| 376 | iterator end() const noexcept; | 376 | iterator end() const noexcept; | |||||
| 377 | 377 | |||||||
| 378 | /** Return true if the range is empty | 378 | /** Return true if the range is empty | |||||
| 379 | 379 | |||||||
| 380 | @return `true` if the range is empty | 380 | @return `true` if the range is empty | |||||
| 381 | */ | 381 | */ | |||||
| 382 | bool | 382 | bool | |||||
| HITCBC | 383 | 12 | empty() const noexcept | 383 | 12 | empty() const noexcept | ||
| 384 | { | 384 | { | |||||
| HITCBC | 385 | 12 | return n_ == 0; | 385 | 12 | return n_ == 0; | ||
| 386 | } | 386 | } | |||||
| 387 | 387 | |||||||
| 388 | /** Return the number of elements in the range | 388 | /** Return the number of elements in the range | |||||
| 389 | 389 | |||||||
| 390 | @return The number of elements | 390 | @return The number of elements | |||||
| 391 | */ | 391 | */ | |||||
| 392 | std::size_t | 392 | std::size_t | |||||
| HITCBC | 393 | 29 | size() const noexcept | 393 | 29 | size() const noexcept | ||
| 394 | { | 394 | { | |||||
| HITCBC | 395 | 29 | return n_; | 395 | 29 | return n_; | ||
| 396 | } | 396 | } | |||||
| 397 | 397 | |||||||
| 398 | /** Return the matching part of the string | 398 | /** Return the matching part of the string | |||||
| 399 | 399 | |||||||
| 400 | @return A string view representing the range | 400 | @return A string view representing the range | |||||
| 401 | */ | 401 | */ | |||||
| 402 | core::string_view | 402 | core::string_view | |||||
| HITCBC | 403 | 6 | string() const noexcept | 403 | 6 | string() const noexcept | ||
| 404 | { | 404 | { | |||||
| HITCBC | 405 | 6 | return s_; | 405 | 6 | return s_; | ||
| 406 | } | 406 | } | |||||
| 407 | }; | 407 | }; | |||||
| 408 | 408 | |||||||
| 409 | //------------------------------------------------ | 409 | //------------------------------------------------ | |||||
| 410 | 410 | |||||||
| 411 | namespace implementation_defined { | 411 | namespace implementation_defined { | |||||
| 412 | template< | 412 | template< | |||||
| 413 | class R0, | 413 | class R0, | |||||
| 414 | class R1 = void> | 414 | class R1 = void> | |||||
| 415 | struct range_rule_t; | 415 | struct range_rule_t; | |||||
| 416 | } | 416 | } | |||||
| 417 | 417 | |||||||
| 418 | //------------------------------------------------ | 418 | //------------------------------------------------ | |||||
| 419 | 419 | |||||||
| 420 | namespace implementation_defined { | 420 | namespace implementation_defined { | |||||
| 421 | template<class R> | 421 | template<class R> | |||||
| 422 | struct range_rule_t<R> | 422 | struct range_rule_t<R> | |||||
| 423 | { | 423 | { | |||||
| 424 | using value_type = | 424 | using value_type = | |||||
| 425 | range<typename R::value_type>; | 425 | range<typename R::value_type>; | |||||
| 426 | 426 | |||||||
| 427 | BOOST_URL_CXX20_CONSTEXPR | 427 | BOOST_URL_CXX20_CONSTEXPR | |||||
| 428 | system::result<value_type> | 428 | system::result<value_type> | |||||
| 429 | parse( | 429 | parse( | |||||
| 430 | char const*& it, | 430 | char const*& it, | |||||
| 431 | char const* end) const; | 431 | char const* end) const; | |||||
| 432 | 432 | |||||||
| 433 | constexpr | 433 | constexpr | |||||
| HITCBC | 434 | 1 | range_rule_t( | 434 | 1 | range_rule_t( | ||
| 435 | R const& next, | 435 | R const& next, | |||||
| 436 | std::size_t N, | 436 | std::size_t N, | |||||
| 437 | std::size_t M) noexcept | 437 | std::size_t M) noexcept | |||||
| HITCBC | 438 | 1 | : next_(next) | 438 | 1 | : next_(next) | ||
| HITCBC | 439 | 1 | , N_(N) | 439 | 1 | , N_(N) | ||
| HITCBC | 440 | 1 | , M_(M) | 440 | 1 | , M_(M) | ||
| 441 | { | 441 | { | |||||
| HITCBC | 442 | 1 | } | 442 | 1 | } | ||
| 443 | 443 | |||||||
| 444 | private: | 444 | private: | |||||
| 445 | R const next_; | 445 | R const next_; | |||||
| 446 | std::size_t N_; | 446 | std::size_t N_; | |||||
| 447 | std::size_t M_; | 447 | std::size_t M_; | |||||
| 448 | }; | 448 | }; | |||||
| 449 | } // implementation_defined | 449 | } // implementation_defined | |||||
| 450 | 450 | |||||||
| 451 | /** Match a repeating number of elements | 451 | /** Match a repeating number of elements | |||||
| 452 | 452 | |||||||
| 453 | Elements are matched using the passed rule. | 453 | Elements are matched using the passed rule. | |||||
| 454 | <br> | 454 | <br> | |||||
| 455 | Normally when the rule returns an error, | 455 | Normally when the rule returns an error, | |||||
| 456 | the range ends and the input is rewound to | 456 | the range ends and the input is rewound to | |||||
| 457 | one past the last character that matched | 457 | one past the last character that matched | |||||
| 458 | successfully. However, if the rule returns | 458 | successfully. However, if the rule returns | |||||
| 459 | the special value @ref error::end_of_range, the | 459 | the special value @ref error::end_of_range, the | |||||
| 460 | input is not rewound. This allows for rules | 460 | input is not rewound. This allows for rules | |||||
| 461 | which consume input without producing | 461 | which consume input without producing | |||||
| 462 | elements in the range. For example, to | 462 | elements in the range. For example, to | |||||
| 463 | relax the grammar for a comma-delimited | 463 | relax the grammar for a comma-delimited | |||||
| 464 | list by allowing extra commas in between | 464 | list by allowing extra commas in between | |||||
| 465 | elements. | 465 | elements. | |||||
| 466 | 466 | |||||||
| 467 | @par Value Type | 467 | @par Value Type | |||||
| 468 | @code | 468 | @code | |||||
| 469 | using value_type = range< typename Rule::value_type >; | 469 | using value_type = range< typename Rule::value_type >; | |||||
| 470 | @endcode | 470 | @endcode | |||||
| 471 | 471 | |||||||
| 472 | @par Example | 472 | @par Example | |||||
| 473 | Rules are used with the function @ref parse. | 473 | Rules are used with the function @ref parse. | |||||
| 474 | @code | 474 | @code | |||||
| 475 | // range = 1*( ";" token ) | 475 | // range = 1*( ";" token ) | |||||
| 476 | 476 | |||||||
| 477 | system::result< range<core::string_view> > rv = parse( ";alpha;xray;charlie", | 477 | system::result< range<core::string_view> > rv = parse( ";alpha;xray;charlie", | |||||
| 478 | range_rule( | 478 | range_rule( | |||||
| 479 | tuple_rule( | 479 | tuple_rule( | |||||
| 480 | squelch( delim_rule( ';' ) ), | 480 | squelch( delim_rule( ';' ) ), | |||||
| 481 | token_rule( alpha_chars ) ), | 481 | token_rule( alpha_chars ) ), | |||||
| 482 | 1 ) ); | 482 | 1 ) ); | |||||
| 483 | @endcode | 483 | @endcode | |||||
| 484 | 484 | |||||||
| 485 | @par BNF | 485 | @par BNF | |||||
| 486 | @code | 486 | @code | |||||
| 487 | range = <N>*<M>next | 487 | range = <N>*<M>next | |||||
| 488 | @endcode | 488 | @endcode | |||||
| 489 | 489 | |||||||
| 490 | @par Specification | 490 | @par Specification | |||||
| 491 | @li <a href="https://datatracker.ietf.org/doc/html/rfc5234#section-3.6" | 491 | @li <a href="https://datatracker.ietf.org/doc/html/rfc5234#section-3.6" | |||||
| 492 | >3.6. Variable Repetition (rfc5234)</a> | 492 | >3.6. Variable Repetition (rfc5234)</a> | |||||
| 493 | 493 | |||||||
| 494 | @param next The rule to use for matching | 494 | @param next The rule to use for matching | |||||
| 495 | each element. The range extends until this | 495 | each element. The range extends until this | |||||
| 496 | rule returns an error. | 496 | rule returns an error. | |||||
| 497 | 497 | |||||||
| 498 | @param N The minimum number of elements for | 498 | @param N The minimum number of elements for | |||||
| 499 | the range to be valid. If omitted, this | 499 | the range to be valid. If omitted, this | |||||
| 500 | defaults to zero. | 500 | defaults to zero. | |||||
| 501 | 501 | |||||||
| 502 | @param M The maximum number of elements for | 502 | @param M The maximum number of elements for | |||||
| 503 | the range to be valid. If omitted, this | 503 | the range to be valid. If omitted, this | |||||
| 504 | defaults to unlimited. | 504 | defaults to unlimited. | |||||
| 505 | 505 | |||||||
| 506 | @return A rule that matches the range. | 506 | @return A rule that matches the range. | |||||
| 507 | 507 | |||||||
| 508 | @see | 508 | @see | |||||
| 509 | @ref alpha_chars, | 509 | @ref alpha_chars, | |||||
| 510 | @ref delim_rule, | 510 | @ref delim_rule, | |||||
| 511 | @ref error::end_of_range, | 511 | @ref error::end_of_range, | |||||
| 512 | @ref parse, | 512 | @ref parse, | |||||
| 513 | @ref range, | 513 | @ref range, | |||||
| 514 | @ref tuple_rule, | 514 | @ref tuple_rule, | |||||
| 515 | @ref squelch. | 515 | @ref squelch. | |||||
| 516 | */ | 516 | */ | |||||
| 517 | template<BOOST_URL_CONSTRAINT(Rule) R> | 517 | template<BOOST_URL_CONSTRAINT(Rule) R> | |||||
| 518 | constexpr | 518 | constexpr | |||||
| 519 | implementation_defined::range_rule_t<R> | 519 | implementation_defined::range_rule_t<R> | |||||
| HITCBC | 520 | 1 | range_rule( | 520 | 1 | range_rule( | ||
| 521 | R const& next, | 521 | R const& next, | |||||
| 522 | std::size_t N = 0, | 522 | std::size_t N = 0, | |||||
| 523 | std::size_t M = | 523 | std::size_t M = | |||||
| 524 | std::size_t(-1)) noexcept | 524 | std::size_t(-1)) noexcept | |||||
| 525 | { | 525 | { | |||||
| 526 | // If you get a compile error here it | 526 | // If you get a compile error here it | |||||
| 527 | // means that your rule does not meet | 527 | // means that your rule does not meet | |||||
| 528 | // the type requirements. Please check | 528 | // the type requirements. Please check | |||||
| 529 | // the documentation. | 529 | // the documentation. | |||||
| 530 | static_assert( | 530 | static_assert( | |||||
| 531 | is_rule<R>::value, | 531 | is_rule<R>::value, | |||||
| 532 | "Rule requirements not met"); | 532 | "Rule requirements not met"); | |||||
| 533 | 533 | |||||||
| 534 | return implementation_defined::range_rule_t<R>{ | 534 | return implementation_defined::range_rule_t<R>{ | |||||
| HITCBC | 535 | 1 | next, N, M}; | 535 | 1 | next, N, M}; | ||
| 536 | } | 536 | } | |||||
| 537 | 537 | |||||||
| 538 | //------------------------------------------------ | 538 | //------------------------------------------------ | |||||
| 539 | 539 | |||||||
| 540 | namespace implementation_defined { | 540 | namespace implementation_defined { | |||||
| 541 | template<class R0, class R1> | 541 | template<class R0, class R1> | |||||
| 542 | struct range_rule_t | 542 | struct range_rule_t | |||||
| 543 | { | 543 | { | |||||
| 544 | using value_type = | 544 | using value_type = | |||||
| 545 | range<typename R0::value_type>; | 545 | range<typename R0::value_type>; | |||||
| 546 | 546 | |||||||
| 547 | BOOST_URL_CXX20_CONSTEXPR | 547 | BOOST_URL_CXX20_CONSTEXPR | |||||
| 548 | system::result<value_type> | 548 | system::result<value_type> | |||||
| 549 | parse( | 549 | parse( | |||||
| 550 | char const*& it, | 550 | char const*& it, | |||||
| 551 | char const* end) const; | 551 | char const* end) const; | |||||
| 552 | 552 | |||||||
| 553 | constexpr | 553 | constexpr | |||||
| HITCBC | 554 | 1 | range_rule_t( | 554 | 1 | range_rule_t( | ||
| 555 | R0 const& first, | 555 | R0 const& first, | |||||
| 556 | R1 const& next, | 556 | R1 const& next, | |||||
| 557 | std::size_t N, | 557 | std::size_t N, | |||||
| 558 | std::size_t M) noexcept | 558 | std::size_t M) noexcept | |||||
| HITCBC | 559 | 1 | : first_(first) | 559 | 1 | : first_(first) | ||
| HITCBC | 560 | 1 | , next_(next) | 560 | 1 | , next_(next) | ||
| HITCBC | 561 | 1 | , N_(N) | 561 | 1 | , N_(N) | ||
| HITCBC | 562 | 1 | , M_(M) | 562 | 1 | , M_(M) | ||
| 563 | { | 563 | { | |||||
| HITCBC | 564 | 1 | } | 564 | 1 | } | ||
| 565 | 565 | |||||||
| 566 | private: | 566 | private: | |||||
| 567 | R0 const first_; | 567 | R0 const first_; | |||||
| 568 | R1 const next_; | 568 | R1 const next_; | |||||
| 569 | std::size_t N_; | 569 | std::size_t N_; | |||||
| 570 | std::size_t M_; | 570 | std::size_t M_; | |||||
| 571 | }; | 571 | }; | |||||
| 572 | } // implementation_defined | 572 | } // implementation_defined | |||||
| 573 | 573 | |||||||
| 574 | /** Match a repeating number of elements | 574 | /** Match a repeating number of elements | |||||
| 575 | 575 | |||||||
| 576 | Two rules are used for match. The rule | 576 | Two rules are used for match. The rule | |||||
| 577 | `first` is used for matching the first | 577 | `first` is used for matching the first | |||||
| 578 | element, while the `next` rule is used | 578 | element, while the `next` rule is used | |||||
| 579 | to match every subsequent element. | 579 | to match every subsequent element. | |||||
| 580 | <br> | 580 | <br> | |||||
| 581 | Normally when the rule returns an error, | 581 | Normally when the rule returns an error, | |||||
| 582 | the range ends and the input is rewound to | 582 | the range ends and the input is rewound to | |||||
| 583 | one past the last character that matched | 583 | one past the last character that matched | |||||
| 584 | successfully. However, if the rule returns | 584 | successfully. However, if the rule returns | |||||
| 585 | the special value @ref error::end_of_range, the | 585 | the special value @ref error::end_of_range, the | |||||
| 586 | input is not rewound. This allows for rules | 586 | input is not rewound. This allows for rules | |||||
| 587 | which consume input without producing | 587 | which consume input without producing | |||||
| 588 | elements in the range. For example, to | 588 | elements in the range. For example, to | |||||
| 589 | relax the grammar for a comma-delimited | 589 | relax the grammar for a comma-delimited | |||||
| 590 | list by allowing extra commas in between | 590 | list by allowing extra commas in between | |||||
| 591 | elements. | 591 | elements. | |||||
| 592 | 592 | |||||||
| 593 | @par Value Type | 593 | @par Value Type | |||||
| 594 | @code | 594 | @code | |||||
| 595 | using value_type = range< typename Rule::value_type >; | 595 | using value_type = range< typename Rule::value_type >; | |||||
| 596 | @endcode | 596 | @endcode | |||||
| 597 | 597 | |||||||
| 598 | @par Example | 598 | @par Example | |||||
| 599 | Rules are used with the function @ref parse. | 599 | Rules are used with the function @ref parse. | |||||
| 600 | @code | 600 | @code | |||||
| 601 | // range = [ token ] *( "," token ) | 601 | // range = [ token ] *( "," token ) | |||||
| 602 | 602 | |||||||
| 603 | system::result< range< core::string_view > > rv = parse( "whiskey,tango,foxtrot", | 603 | system::result< range< core::string_view > > rv = parse( "whiskey,tango,foxtrot", | |||||
| 604 | range_rule( | 604 | range_rule( | |||||
| 605 | token_rule( alpha_chars ), // first | 605 | token_rule( alpha_chars ), // first | |||||
| 606 | tuple_rule( // next | 606 | tuple_rule( // next | |||||
| 607 | squelch( delim_rule(',') ), | 607 | squelch( delim_rule(',') ), | |||||
| 608 | token_rule( alpha_chars ) ) ) ); | 608 | token_rule( alpha_chars ) ) ) ); | |||||
| 609 | @endcode | 609 | @endcode | |||||
| 610 | 610 | |||||||
| 611 | @par BNF | 611 | @par BNF | |||||
| 612 | @code | 612 | @code | |||||
| 613 | range = <1>*<1>first | 613 | range = <1>*<1>first | |||||
| 614 | / first <N-1>*<M-1>next | 614 | / first <N-1>*<M-1>next | |||||
| 615 | @endcode | 615 | @endcode | |||||
| 616 | 616 | |||||||
| 617 | @par Specification | 617 | @par Specification | |||||
| 618 | @li <a href="https://datatracker.ietf.org/doc/html/rfc5234#section-3.6" | 618 | @li <a href="https://datatracker.ietf.org/doc/html/rfc5234#section-3.6" | |||||
| 619 | >3.6. Variable Repetition (rfc5234)</a> | 619 | >3.6. Variable Repetition (rfc5234)</a> | |||||
| 620 | 620 | |||||||
| 621 | @param first The rule to use for matching | 621 | @param first The rule to use for matching | |||||
| 622 | the first element. If this rule returns | 622 | the first element. If this rule returns | |||||
| 623 | an error, the range is empty. | 623 | an error, the range is empty. | |||||
| 624 | 624 | |||||||
| 625 | @param next The rule to use for matching | 625 | @param next The rule to use for matching | |||||
| 626 | each subsequent element. The range extends | 626 | each subsequent element. The range extends | |||||
| 627 | until this rule returns an error. | 627 | until this rule returns an error. | |||||
| 628 | 628 | |||||||
| 629 | @param N The minimum number of elements for | 629 | @param N The minimum number of elements for | |||||
| 630 | the range to be valid. If omitted, this | 630 | the range to be valid. If omitted, this | |||||
| 631 | defaults to zero. | 631 | defaults to zero. | |||||
| 632 | 632 | |||||||
| 633 | @param M The maximum number of elements for | 633 | @param M The maximum number of elements for | |||||
| 634 | the range to be valid. If omitted, this | 634 | the range to be valid. If omitted, this | |||||
| 635 | defaults to unlimited. | 635 | defaults to unlimited. | |||||
| 636 | 636 | |||||||
| 637 | @return A rule that matches the range. | 637 | @return A rule that matches the range. | |||||
| 638 | 638 | |||||||
| 639 | @see | 639 | @see | |||||
| 640 | @ref alpha_chars, | 640 | @ref alpha_chars, | |||||
| 641 | @ref delim_rule, | 641 | @ref delim_rule, | |||||
| 642 | @ref error::end_of_range, | 642 | @ref error::end_of_range, | |||||
| 643 | @ref parse, | 643 | @ref parse, | |||||
| 644 | @ref range, | 644 | @ref range, | |||||
| 645 | @ref tuple_rule, | 645 | @ref tuple_rule, | |||||
| 646 | @ref squelch. | 646 | @ref squelch. | |||||
| 647 | */ | 647 | */ | |||||
| 648 | template< | 648 | template< | |||||
| 649 | BOOST_URL_CONSTRAINT(Rule) R1, | 649 | BOOST_URL_CONSTRAINT(Rule) R1, | |||||
| 650 | BOOST_URL_CONSTRAINT(Rule) R2> | 650 | BOOST_URL_CONSTRAINT(Rule) R2> | |||||
| 651 | constexpr | 651 | constexpr | |||||
| 652 | auto | 652 | auto | |||||
| HITCBC | 653 | 1 | range_rule( | 653 | 1 | range_rule( | ||
| 654 | R1 const& first, | 654 | R1 const& first, | |||||
| 655 | R2 const& next, | 655 | R2 const& next, | |||||
| 656 | std::size_t N = 0, | 656 | std::size_t N = 0, | |||||
| 657 | std::size_t M = | 657 | std::size_t M = | |||||
| 658 | std::size_t(-1)) noexcept -> | 658 | std::size_t(-1)) noexcept -> | |||||
| 659 | #if 1 | 659 | #if 1 | |||||
| 660 | typename std::enable_if< | 660 | typename std::enable_if< | |||||
| 661 | ! std::is_integral<R2>::value, | 661 | ! std::is_integral<R2>::value, | |||||
| 662 | implementation_defined::range_rule_t<R1, R2>>::type | 662 | implementation_defined::range_rule_t<R1, R2>>::type | |||||
| 663 | #else | 663 | #else | |||||
| 664 | range_rule_t<R1, R2> | 664 | range_rule_t<R1, R2> | |||||
| 665 | #endif | 665 | #endif | |||||
| 666 | { | 666 | { | |||||
| 667 | // If you get a compile error here it | 667 | // If you get a compile error here it | |||||
| 668 | // means that your rule does not meet | 668 | // means that your rule does not meet | |||||
| 669 | // the type requirements. Please check | 669 | // the type requirements. Please check | |||||
| 670 | // the documentation. | 670 | // the documentation. | |||||
| 671 | static_assert( | 671 | static_assert( | |||||
| 672 | is_rule<R1>::value, | 672 | is_rule<R1>::value, | |||||
| 673 | "Rule requirements not met"); | 673 | "Rule requirements not met"); | |||||
| 674 | static_assert( | 674 | static_assert( | |||||
| 675 | is_rule<R2>::value, | 675 | is_rule<R2>::value, | |||||
| 676 | "Rule requirements not met"); | 676 | "Rule requirements not met"); | |||||
| 677 | 677 | |||||||
| 678 | // If you get a compile error here it | 678 | // If you get a compile error here it | |||||
| 679 | // means that your rules do not have | 679 | // means that your rules do not have | |||||
| 680 | // the exact same value_type. Please | 680 | // the exact same value_type. Please | |||||
| 681 | // check the documentation. | 681 | // check the documentation. | |||||
| 682 | static_assert( | 682 | static_assert( | |||||
| 683 | std::is_same< | 683 | std::is_same< | |||||
| 684 | typename R1::value_type, | 684 | typename R1::value_type, | |||||
| 685 | typename R2::value_type>::value, | 685 | typename R2::value_type>::value, | |||||
| 686 | "Rule requirements not met"); | 686 | "Rule requirements not met"); | |||||
| 687 | 687 | |||||||
| 688 | return implementation_defined::range_rule_t<R1, R2>{ | 688 | return implementation_defined::range_rule_t<R1, R2>{ | |||||
| HITCBC | 689 | 1 | first, next, N, M}; | 689 | 1 | first, next, N, M}; | ||
| 690 | } | 690 | } | |||||
| 691 | 691 | |||||||
| 692 | } // grammar | 692 | } // grammar | |||||
| 693 | } // urls | 693 | } // urls | |||||
| 694 | } // boost | 694 | } // boost | |||||
| 695 | 695 | |||||||
| 696 | #include <boost/url/grammar/impl/range_rule.hpp> | 696 | #include <boost/url/grammar/impl/range_rule.hpp> | |||||
| 697 | 697 | |||||||
| 698 | #endif | 698 | #endif | |||||