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 +
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
3  
//
4  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5  
// 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)
6  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
7  
//
7  
// Official repository: https://github.com/boostorg/url
8  
// Official repository: https://github.com/boostorg/url
8  
//
9  
//
9  

10  

10  
#ifndef BOOST_URL_GRAMMAR_IMPL_RANGE_HPP
11  
#ifndef BOOST_URL_GRAMMAR_IMPL_RANGE_HPP
11  
#define BOOST_URL_GRAMMAR_IMPL_RANGE_HPP
12  
#define BOOST_URL_GRAMMAR_IMPL_RANGE_HPP
12  

13  

13  
#include <boost/url/detail/except.hpp>
14  
#include <boost/url/detail/except.hpp>
14  
#include <boost/url/grammar/error.hpp>
15  
#include <boost/url/grammar/error.hpp>
15  
#include <boost/url/grammar/recycled.hpp>
16  
#include <boost/url/grammar/recycled.hpp>
16  
#include <boost/core/empty_value.hpp>
17  
#include <boost/core/empty_value.hpp>
17  
#include <boost/assert.hpp>
18  
#include <boost/assert.hpp>
18  
#include <boost/core/detail/static_assert.hpp>
19  
#include <boost/core/detail/static_assert.hpp>
19  
#include <exception>
20  
#include <exception>
20  
#include <iterator>
21  
#include <iterator>
21  
#include <new>
22  
#include <new>
22  
#include <utility>
23  
#include <utility>
23  
#include <type_traits>
24  
#include <type_traits>
24  

25  

25  
#include <stddef.h> // ::max_align_t
26  
#include <stddef.h> // ::max_align_t
26  

27  

27  
namespace boost {
28  
namespace boost {
28  
namespace urls {
29  
namespace urls {
29  
namespace grammar {
30  
namespace grammar {
30  

31  

31  
//------------------------------------------------
32  
//------------------------------------------------
32  
//
33  
//
33  
// any_rule
34  
// any_rule
34  
//
35  
//
35  
//------------------------------------------------
36  
//------------------------------------------------
36  

37  

37  
template<class T>
38  
template<class T>
38  
struct any_rule<T>::impl_base
39  
struct any_rule<T>::impl_base
39  
{
40  
{
40  
    virtual
41  
    virtual
41  
    ~impl_base() = default;
42  
    ~impl_base() = default;
42  

43  

43  
    virtual
44  
    virtual
44  
    void
45  
    void
45  
    move(void* dest) noexcept
46  
    move(void* dest) noexcept
46  
    {
47  
    {
47  
        ::new(dest) impl_base(
48  
        ::new(dest) impl_base(
48  
            std::move(*this));
49  
            std::move(*this));
49  
    }
50  
    }
50  

51  

51  
    virtual
52  
    virtual
52  
    void
53  
    void
53  
    copy(void* dest) const noexcept
54  
    copy(void* dest) const noexcept
54  
    {
55  
    {
55  
        ::new(dest) impl_base(*this);
56  
        ::new(dest) impl_base(*this);
56  
    }
57  
    }
57  

58  

58  
    virtual
59  
    virtual
59  
    system::result<T>
60  
    system::result<T>
60  
    first(
61  
    first(
61  
        char const*&,
62  
        char const*&,
62  
        char const*) const noexcept
63  
        char const*) const noexcept
63  
    {
64  
    {
64  
        return system::error_code{};
65  
        return system::error_code{};
65  
    }
66  
    }
66  

67  

67  
    virtual
68  
    virtual
68  
    system::result<T>
69  
    system::result<T>
69  
    next(
70  
    next(
70  
        char const*&,
71  
        char const*&,
71  
        char const*) const noexcept
72  
        char const*) const noexcept
72  
    {
73  
    {
73  
        return system::error_code{};
74  
        return system::error_code{};
74  
    }
75  
    }
75  
};
76  
};
76  

77  

77  
//------------------------------------------------
78  
//------------------------------------------------
78  

79  

79  
// small
80  
// small
80  
template<class T>
81  
template<class T>
81  
template<class R, bool Small>
82  
template<class R, bool Small>
82  
struct any_rule<T>::impl1
83  
struct any_rule<T>::impl1
83  
    : impl_base
84  
    : impl_base
84  
    , private empty_value<R>
85  
    , private empty_value<R>
85  
{
86  
{
86  
    explicit
87  
    explicit
87  
    impl1(R const& next) noexcept
88  
    impl1(R const& next) noexcept
88  
        : empty_value<R>(
89  
        : empty_value<R>(
89  
            empty_init,
90  
            empty_init,
90  
            next)
91  
            next)
91  
    {
92  
    {
92  
    }
93  
    }
93  

94  

94  
private:
95  
private:
95  
    impl1(impl1&&) noexcept = default;
96  
    impl1(impl1&&) noexcept = default;
96  
    impl1(impl1 const&) noexcept = default;
97  
    impl1(impl1 const&) noexcept = default;
97  

98  

98  
    void
99  
    void
99  
    move(void* dest
100  
    move(void* dest
100  
        ) noexcept override
101  
        ) noexcept override
101  
    {
102  
    {
102  
        ::new(dest) impl1(
103  
        ::new(dest) impl1(
103  
            std::move(*this));
104  
            std::move(*this));
104  
    }
105  
    }
105  

106  

106  
    void
107  
    void
107  
    copy(void* dest
108  
    copy(void* dest
108  
        ) const noexcept override
109  
        ) const noexcept override
109  
    {
110  
    {
110  
        ::new(dest) impl1(*this);
111  
        ::new(dest) impl1(*this);
111  
    }
112  
    }
112  

113  

113  
    system::result<T>
114  
    system::result<T>
114  
    first(
115  
    first(
115  
        char const*& it,
116  
        char const*& it,
116  
        char const* end)
117  
        char const* end)
117  
            const noexcept override
118  
            const noexcept override
118  
    {
119  
    {
119  
        return grammar::parse(
120  
        return grammar::parse(
120  
            it, end, this->get());
121  
            it, end, this->get());
121  
    }
122  
    }
122  

123  

123  
    system::result<T>
124  
    system::result<T>
124  
    next(
125  
    next(
125  
        char const*& it,
126  
        char const*& it,
126  
        char const* end)
127  
        char const* end)
127  
            const noexcept override
128  
            const noexcept override
128  
    {
129  
    {
129  
        return grammar::parse(
130  
        return grammar::parse(
130  
            it, end, this->get());
131  
            it, end, this->get());
131  
    }
132  
    }
132  
};
133  
};
133  

134  

134  
//------------------------------------------------
135  
//------------------------------------------------
135  

136  

136  
// big
137  
// big
137  
template<class T>
138  
template<class T>
138  
template<class R>
139  
template<class R>
139  
struct any_rule<T>::impl1<R, false>
140  
struct any_rule<T>::impl1<R, false>
140  
    : impl_base
141  
    : impl_base
141  
{
142  
{
142  
    explicit
143  
    explicit
143  
    impl1(R const& next) noexcept
144  
    impl1(R const& next) noexcept
144  
    {
145  
    {
145  
        ::new(p_->addr()) impl{next};
146  
        ::new(p_->addr()) impl{next};
146  
    }
147  
    }
147  

148  

148  
private:
149  
private:
149  
    struct impl
150  
    struct impl
150  
    {
151  
    {
151  
        R r;
152  
        R r;
152  
    };
153  
    };
153  

154  

154  
    recycled_ptr<
155  
    recycled_ptr<
155  
        aligned_storage<impl>> p_;
156  
        aligned_storage<impl>> p_;
156  

157  

157  
    impl1(impl1&&) noexcept = default;
158  
    impl1(impl1&&) noexcept = default;
158  
    impl1(impl1 const&) noexcept = default;
159  
    impl1(impl1 const&) noexcept = default;
159  

160  

160  
    impl const&
161  
    impl const&
161  
    get() const noexcept
162  
    get() const noexcept
162  
    {
163  
    {
163  
        return *reinterpret_cast<
164  
        return *reinterpret_cast<
164  
            impl const*>(p_->addr());
165  
            impl const*>(p_->addr());
165  
    }
166  
    }
166  

167  

167  
    ~impl1()
168  
    ~impl1()
168  
    {
169  
    {
169  
        if(p_)
170  
        if(p_)
170  
            get().~impl();
171  
            get().~impl();
171  
    }
172  
    }
172  

173  

173  
    void
174  
    void
174  
    move(void* dest
175  
    move(void* dest
175  
        ) noexcept override
176  
        ) noexcept override
176  
    {
177  
    {
177  
        ::new(dest) impl1(
178  
        ::new(dest) impl1(
178  
            std::move(*this));
179  
            std::move(*this));
179  
    }
180  
    }
180  

181  

181  
    void
182  
    void
182  
    copy(void* dest
183  
    copy(void* dest
183  
        ) const noexcept override
184  
        ) const noexcept override
184  
    {
185  
    {
185  
        ::new(dest) impl1(*this);
186  
        ::new(dest) impl1(*this);
186  
    }
187  
    }
187  

188  

188  
    system::result<T>
189  
    system::result<T>
189  
    first(
190  
    first(
190  
        char const*& it,
191  
        char const*& it,
191  
        char const* end)
192  
        char const* end)
192  
            const noexcept override
193  
            const noexcept override
193  
    {
194  
    {
194  
        return grammar::parse(
195  
        return grammar::parse(
195  
            it, end, this->get().r);
196  
            it, end, this->get().r);
196  
    }
197  
    }
197  

198  

198  
    system::result<T>
199  
    system::result<T>
199  
    next(
200  
    next(
200  
        char const*& it,
201  
        char const*& it,
201  
        char const* end)
202  
        char const* end)
202  
            const noexcept override
203  
            const noexcept override
203  
    {
204  
    {
204  
        return grammar::parse(
205  
        return grammar::parse(
205  
            it, end, this->get().r);
206  
            it, end, this->get().r);
206  
    }
207  
    }
207  
};
208  
};
208  

209  

209  
//------------------------------------------------
210  
//------------------------------------------------
210  

211  

211  
// small
212  
// small
212  
template<class T>
213  
template<class T>
213  
template<
214  
template<
214  
    class R0, class R1, bool Small>
215  
    class R0, class R1, bool Small>
215  
struct any_rule<T>::impl2
216  
struct any_rule<T>::impl2
216  
    : impl_base
217  
    : impl_base
217  
    , private empty_value<R0, 0>
218  
    , private empty_value<R0, 0>
218  
    , private empty_value<R1, 1>
219  
    , private empty_value<R1, 1>
219  
{
220  
{
220  
    impl2(
221  
    impl2(
221  
        R0 const& first,
222  
        R0 const& first,
222  
        R1 const& next) noexcept
223  
        R1 const& next) noexcept
223  
        : empty_value<R0,0>(
224  
        : empty_value<R0,0>(
224  
            empty_init, first)
225  
            empty_init, first)
225  
        , empty_value<R1,1>(
226  
        , empty_value<R1,1>(
226  
            empty_init, next)
227  
            empty_init, next)
227  
    {
228  
    {
228  
    }
229  
    }
229  

230  

230  
private:
231  
private:
231  
    impl2(impl2&&) noexcept = default;
232  
    impl2(impl2&&) noexcept = default;
232  
    impl2(impl2 const&) noexcept = default;
233  
    impl2(impl2 const&) noexcept = default;
233  

234  

234  
    void
235  
    void
235  
    move(void* dest
236  
    move(void* dest
236  
        ) noexcept override
237  
        ) noexcept override
237  
    {
238  
    {
238  
        ::new(dest) impl2(
239  
        ::new(dest) impl2(
239  
            std::move(*this));
240  
            std::move(*this));
240  
    }
241  
    }
241  

242  

242  
    void
243  
    void
243  
    copy(void* dest
244  
    copy(void* dest
244  
        ) const noexcept override
245  
        ) const noexcept override
245  
    {
246  
    {
246  
        ::new(dest) impl2(*this);
247  
        ::new(dest) impl2(*this);
247  
    }
248  
    }
248  

249  

249  
    system::result<T>
250  
    system::result<T>
250  
    first(
251  
    first(
251  
        char const*& it,
252  
        char const*& it,
252  
        char const* end)
253  
        char const* end)
253  
            const noexcept override
254  
            const noexcept override
254  
    {
255  
    {
255  
        return grammar::parse(it, end,
256  
        return grammar::parse(it, end,
256  
            empty_value<
257  
            empty_value<
257  
                R0,0>::get());
258  
                R0,0>::get());
258  
    }
259  
    }
259  

260  

260  
    system::result<T>
261  
    system::result<T>
261  
    next(
262  
    next(
262  
        char const*& it,
263  
        char const*& it,
263  
        char const* end)
264  
        char const* end)
264  
            const noexcept override
265  
            const noexcept override
265  
    {
266  
    {
266  
        return grammar::parse(it, end,
267  
        return grammar::parse(it, end,
267  
            empty_value<
268  
            empty_value<
268  
                R1,1>::get());
269  
                R1,1>::get());
269  
    }
270  
    }
270  
};
271  
};
271  

272  

272  
//------------------------------------------------
273  
//------------------------------------------------
273  

274  

274  
// big
275  
// big
275  
template<class T>
276  
template<class T>
276  
template<
277  
template<
277  
    class R0, class R1>
278  
    class R0, class R1>
278  
struct any_rule<T>::impl2<R0, R1, false>
279  
struct any_rule<T>::impl2<R0, R1, false>
279  
    : impl_base
280  
    : impl_base
280  
{
281  
{
281  
    impl2(
282  
    impl2(
282  
        R0 const& first,
283  
        R0 const& first,
283  
        R1 const& next) noexcept
284  
        R1 const& next) noexcept
284  
    {
285  
    {
285  
        ::new(p_->addr()) impl{
286  
        ::new(p_->addr()) impl{
286  
            first, next};
287  
            first, next};
287  
    }
288  
    }
288  

289  

289  
private:
290  
private:
290  
    struct impl
291  
    struct impl
291  
    {
292  
    {
292  
        R0 first;
293  
        R0 first;
293  
        R1 next;
294  
        R1 next;
294  
    };
295  
    };
295  

296  

296  
    recycled_ptr<
297  
    recycled_ptr<
297  
        aligned_storage<impl>> p_;
298  
        aligned_storage<impl>> p_;
298  

299  

299  
    impl2(impl2&&) noexcept = default;
300  
    impl2(impl2&&) noexcept = default;
300  
    impl2(impl2 const&) noexcept = default;
301  
    impl2(impl2 const&) noexcept = default;
301  

302  

302  
    impl const&
303  
    impl const&
303  
    get() const noexcept
304  
    get() const noexcept
304  
    {
305  
    {
305  
        return *reinterpret_cast<
306  
        return *reinterpret_cast<
306  
            impl const*>(p_->addr());
307  
            impl const*>(p_->addr());
307  
    }
308  
    }
308  

309  

309  
    ~impl2()
310  
    ~impl2()
310  
    {
311  
    {
311  
        if(p_)
312  
        if(p_)
312  
            get().~impl();
313  
            get().~impl();
313  
    }
314  
    }
314  

315  

315  
    void
316  
    void
316  
    move(void* dest
317  
    move(void* dest
317  
        ) noexcept override
318  
        ) noexcept override
318  
    {
319  
    {
319  
        ::new(dest) impl2(
320  
        ::new(dest) impl2(
320  
            std::move(*this));
321  
            std::move(*this));
321  
    }
322  
    }
322  

323  

323  
    void
324  
    void
324  
    copy(void* dest
325  
    copy(void* dest
325  
        ) const noexcept override
326  
        ) const noexcept override
326  
    {
327  
    {
327  
        ::new(dest) impl2(*this);
328  
        ::new(dest) impl2(*this);
328  
    }
329  
    }
329  

330  

330  
    system::result<T>
331  
    system::result<T>
331  
    first(
332  
    first(
332  
        char const*& it,
333  
        char const*& it,
333  
        char const* end)
334  
        char const* end)
334  
            const noexcept override
335  
            const noexcept override
335  
    {
336  
    {
336  
        return grammar::parse(
337  
        return grammar::parse(
337  
            it, end, get().first);
338  
            it, end, get().first);
338  
    }
339  
    }
339  

340  

340  
    system::result<T>
341  
    system::result<T>
341  
    next(
342  
    next(
342  
        char const*& it,
343  
        char const*& it,
343  
        char const* end)
344  
        char const* end)
344  
            const noexcept override
345  
            const noexcept override
345  
    {
346  
    {
346  
        return grammar::parse(
347  
        return grammar::parse(
347  
            it, end, get().next);
348  
            it, end, get().next);
348  
    }
349  
    }
349  
};
350  
};
350  

351  

351  
//------------------------------------------------
352  
//------------------------------------------------
352  

353  

353  
template<class T>
354  
template<class T>
354  
typename any_rule<T>::impl_base&
355  
typename any_rule<T>::impl_base&
355  
any_rule<T>::
356  
any_rule<T>::
356  
get() noexcept
357  
get() noexcept
357  
{
358  
{
358  
    return *reinterpret_cast<
359  
    return *reinterpret_cast<
359  
        impl_base*>(sb_.addr());
360  
        impl_base*>(sb_.addr());
360  
}
361  
}
361  

362  

362  
template<class T>
363  
template<class T>
363  
typename any_rule<T>::impl_base const&
364  
typename any_rule<T>::impl_base const&
364  
any_rule<T>::
365  
any_rule<T>::
365  
get() const noexcept
366  
get() const noexcept
366  
{
367  
{
367  
    return *reinterpret_cast<
368  
    return *reinterpret_cast<
368  
        impl_base const*>(sb_.addr());
369  
        impl_base const*>(sb_.addr());
369  
}
370  
}
370  

371  

371  

372  

372  
template<class T>
373  
template<class T>
373  
any_rule<T>::
374  
any_rule<T>::
374  
any_rule() noexcept
375  
any_rule() noexcept
375  
{
376  
{
376  
    ::new(sb_.addr()) impl_base{};
377  
    ::new(sb_.addr()) impl_base{};
377  
    char const* it = nullptr;
378  
    char const* it = nullptr;
378  
    get().first(it, nullptr);
379  
    get().first(it, nullptr);
379  
    get().next(it, nullptr);
380  
    get().next(it, nullptr);
380  
}
381  
}
381  

382  

382  

383  

383  
template<class T>
384  
template<class T>
384  
any_rule<T>::
385  
any_rule<T>::
385  
any_rule(any_rule&& other) noexcept
386  
any_rule(any_rule&& other) noexcept
386  
{
387  
{
387  
    other.get().move(sb_.addr());
388  
    other.get().move(sb_.addr());
388  
}
389  
}
389  

390  

390  

391  

391  
template<class T>
392  
template<class T>
392  
any_rule<T>::
393  
any_rule<T>::
393  
any_rule(any_rule const& other) noexcept
394  
any_rule(any_rule const& other) noexcept
394  
{
395  
{
395  
    other.get().copy(sb_.addr());
396  
    other.get().copy(sb_.addr());
396  
}
397  
}
397  

398  

398  

399  

399  
template<class T>
400  
template<class T>
400  
any_rule<T>&
401  
any_rule<T>&
401  
any_rule<T>::
402  
any_rule<T>::
402  
operator=(any_rule&& other) noexcept
403  
operator=(any_rule&& other) noexcept
403  
{
404  
{
404  
    if(this == &other)
405  
    if(this == &other)
405  
        return *this;
406  
        return *this;
406  
    get().~impl_base();
407  
    get().~impl_base();
407  
    other.get().move(sb_.addr());
408  
    other.get().move(sb_.addr());
408  
    return *this;
409  
    return *this;
409  
}
410  
}
410  

411  

411  

412  

412  
template<class T>
413  
template<class T>
413  
any_rule<T>&
414  
any_rule<T>&
414  
any_rule<T>::
415  
any_rule<T>::
415  
operator=(any_rule const& other) noexcept
416  
operator=(any_rule const& other) noexcept
416  
{
417  
{
417  
    if(this == &other)
418  
    if(this == &other)
418  
        return *this;
419  
        return *this;
419  
    get().~impl_base();
420  
    get().~impl_base();
420  
    other.get().copy(sb_.addr());
421  
    other.get().copy(sb_.addr());
421  
    return *this;
422  
    return *this;
422  
}
423  
}
423  

424  

424  

425  

425  
template<class T>
426  
template<class T>
426  
any_rule<T>::
427  
any_rule<T>::
427  
~any_rule()
428  
~any_rule()
428  
{
429  
{
429  
    get().~impl_base();
430  
    get().~impl_base();
430  
}
431  
}
431  

432  

432  

433  

433  
template<class T>
434  
template<class T>
434  
template<class R>
435  
template<class R>
435  
any_rule<T>::
436  
any_rule<T>::
436  
any_rule(
437  
any_rule(
437  
    R const& next)
438  
    R const& next)
438  
{
439  
{
439  
    static_assert(
440  
    static_assert(
440  
        ::boost::urls::grammar::is_rule<R>::value,
441  
        ::boost::urls::grammar::is_rule<R>::value,
441  
        "Rule requirements not met");
442  
        "Rule requirements not met");
442  
    static_assert(
443  
    static_assert(
443  
        std::is_same<typename R::value_type, T>::value,
444  
        std::is_same<typename R::value_type, T>::value,
444  
        "Rule value_type mismatch");
445  
        "Rule value_type mismatch");
445  

446  

446  
    BOOST_CORE_STATIC_ASSERT(
447  
    BOOST_CORE_STATIC_ASSERT(
447  
        sizeof(impl1<R, false>) <=
448  
        sizeof(impl1<R, false>) <=
448  
            BufferSize);
449  
            BufferSize);
449  

450  

450  
    ::new(sb_.addr()) impl1<R,
451  
    ::new(sb_.addr()) impl1<R,
451  
        sizeof(impl1<R, true>) <=
452  
        sizeof(impl1<R, true>) <=
452  
            BufferSize>(next);
453  
            BufferSize>(next);
453  
}
454  
}
454  

455  

455  
//------------------------------------------------
456  
//------------------------------------------------
456  

457  

457  
template<class T>
458  
template<class T>
458  
template<
459  
template<
459  
    class R0, class R1>
460  
    class R0, class R1>
460  
any_rule<T>::
461  
any_rule<T>::
461  
any_rule(
462  
any_rule(
462  
    R0 const& first,
463  
    R0 const& first,
463  
    R1 const& next)
464  
    R1 const& next)
464  
{
465  
{
465  
    static_assert(
466  
    static_assert(
466  
        ::boost::urls::grammar::is_rule<R0>::value,
467  
        ::boost::urls::grammar::is_rule<R0>::value,
467  
        "Rule requirements not met");
468  
        "Rule requirements not met");
468  
    static_assert(
469  
    static_assert(
469  
        ::boost::urls::grammar::is_rule<R1>::value,
470  
        ::boost::urls::grammar::is_rule<R1>::value,
470  
        "Rule requirements not met");
471  
        "Rule requirements not met");
471  
    static_assert(
472  
    static_assert(
472  
        std::is_same<typename R0::value_type, T>::value,
473  
        std::is_same<typename R0::value_type, T>::value,
473  
        "First rule value_type mismatch");
474  
        "First rule value_type mismatch");
474  
    static_assert(
475  
    static_assert(
475  
        std::is_same<typename R1::value_type, T>::value,
476  
        std::is_same<typename R1::value_type, T>::value,
476  
        "Next rule value_type mismatch");
477  
        "Next rule value_type mismatch");
477  

478  

478  
    BOOST_CORE_STATIC_ASSERT(
479  
    BOOST_CORE_STATIC_ASSERT(
479  
        sizeof(impl2<R0, R1, false>) <=
480  
        sizeof(impl2<R0, R1, false>) <=
480  
            BufferSize);
481  
            BufferSize);
481  

482  

482  
    ::new(sb_.addr()) impl2<R0, R1,
483  
    ::new(sb_.addr()) impl2<R0, R1,
483  
        sizeof(impl2<R0, R1, true>
484  
        sizeof(impl2<R0, R1, true>
484  
            ) <= BufferSize>(
485  
            ) <= BufferSize>(
485  
                first, next);
486  
                first, next);
486  
}
487  
}
487  

488  

488  
//------------------------------------------------
489  
//------------------------------------------------
489  

490  

490  
template<class T>
491  
template<class T>
491  
system::result<T>
492  
system::result<T>
492  
any_rule<T>::
493  
any_rule<T>::
493  
first(
494  
first(
494  
    char const*& it,
495  
    char const*& it,
495  
    char const* end) const noexcept
496  
    char const* end) const noexcept
496  
{
497  
{
497  
    return get().first(it, end);
498  
    return get().first(it, end);
498  
}
499  
}
499  

500  

500  
//------------------------------------------------
501  
//------------------------------------------------
501  

502  

502  
template<class T>
503  
template<class T>
503  
system::result<T>
504  
system::result<T>
504  
any_rule<T>::
505  
any_rule<T>::
505  
next(
506  
next(
506  
    char const*& it,
507  
    char const*& it,
507  
    char const* end) const noexcept
508  
    char const* end) const noexcept
508  
{
509  
{
509  
    return get().next(it, end);
510  
    return get().next(it, end);
510  
}
511  
}
511  

512  

512  
//------------------------------------------------
513  
//------------------------------------------------
513  
//
514  
//
514  
// range
515  
// range
515  
//
516  
//
516  
//------------------------------------------------
517  
//------------------------------------------------
517  

518  

518  
template<class T, class RangeRule>
519  
template<class T, class RangeRule>
519  
range<T, RangeRule>::
520  
range<T, RangeRule>::
520  
~range() = default;
521  
~range() = default;
521  

522  

522  
template<class T, class RangeRule>
523  
template<class T, class RangeRule>
523  
range<T, RangeRule>::
524  
range<T, RangeRule>::
524  
range() noexcept = default;
525  
range() noexcept = default;
525  

526  

526  
template<class T, class RangeRule>
527  
template<class T, class RangeRule>
527  
range<T, RangeRule>::
528  
range<T, RangeRule>::
528  
range(
529  
range(
529  
    range&& other) noexcept
530  
    range&& other) noexcept
530  
    : detail::range_base_storage<
531  
    : detail::range_base_storage<
531  
        RangeRule>(std::move(other.rule()))
532  
        RangeRule>(std::move(other.rule()))
532  
    , s_(other.s_)
533  
    , s_(other.s_)
533  
    , n_(other.n_)
534  
    , n_(other.n_)
534  
{
535  
{
535  
    other.s_ = {};
536  
    other.s_ = {};
536  
    other.n_ = 0;
537  
    other.n_ = 0;
537  
}
538  
}
538  

539  

539  
template<class T, class RangeRule>
540  
template<class T, class RangeRule>
540  
range<T, RangeRule>::
541  
range<T, RangeRule>::
541  
range(
542  
range(
542  
    range const& other) noexcept
543  
    range const& other) noexcept
543  
    : detail::range_base_storage<
544  
    : detail::range_base_storage<
544  
        RangeRule>(other.rule())
545  
        RangeRule>(other.rule())
545  
    , s_(other.s_)
546  
    , s_(other.s_)
546  
    , n_(other.n_)
547  
    , n_(other.n_)
547  
{
548  
{
548  
}
549  
}
549  

550  

550  
template<class T, class RangeRule>
551  
template<class T, class RangeRule>
551  
auto
552  
auto
552  
range<T, RangeRule>::
553  
range<T, RangeRule>::
553  
operator=(range&& other) noexcept
554  
operator=(range&& other) noexcept
554  
    -> range&
555  
    -> range&
555  
{
556  
{
556  
    if(this == &other)
557  
    if(this == &other)
557  
        return *this;
558  
        return *this;
558  
    static_cast<
559  
    static_cast<
559  
        detail::range_base_storage<
560  
        detail::range_base_storage<
560  
            RangeRule>&>(*this) =
561  
            RangeRule>&>(*this) =
561  
        std::move(static_cast<
562  
        std::move(static_cast<
562  
            detail::range_base_storage<
563  
            detail::range_base_storage<
563  
                RangeRule>&>(other));
564  
                RangeRule>&>(other));
564  
    s_ = other.s_;
565  
    s_ = other.s_;
565  
    n_ = other.n_;
566  
    n_ = other.n_;
566  
    other.s_ = {};
567  
    other.s_ = {};
567  
    other.n_ = 0;
568  
    other.n_ = 0;
568  
    return *this;
569  
    return *this;
569  
}
570  
}
570  

571  

571  
template<class T, class RangeRule>
572  
template<class T, class RangeRule>
572  
auto
573  
auto
573  
range<T, RangeRule>::
574  
range<T, RangeRule>::
574  
operator=(range const& other) noexcept
575  
operator=(range const& other) noexcept
575  
    -> range&
576  
    -> range&
576  
{
577  
{
577  
    if(this == &other)
578  
    if(this == &other)
578  
        return *this;
579  
        return *this;
579  
    static_cast<
580  
    static_cast<
580  
        detail::range_base_storage<
581  
        detail::range_base_storage<
581  
            RangeRule>&>(*this) =
582  
            RangeRule>&>(*this) =
582  
        static_cast<
583  
        static_cast<
583  
            detail::range_base_storage<
584  
            detail::range_base_storage<
584  
                RangeRule> const&>(other);
585  
                RangeRule> const&>(other);
585  
    s_ = other.s_;
586  
    s_ = other.s_;
586  
    n_ = other.n_;
587  
    n_ = other.n_;
587  
    return *this;
588  
    return *this;
588  
}
589  
}
589  

590  

590  
//------------------------------------------------
591  
//------------------------------------------------
591  
//
592  
//
592  
// iterator
593  
// iterator
593  
//
594  
//
594  
//------------------------------------------------
595  
//------------------------------------------------
595  

596  

596  
template<class T, class RangeRule>
597  
template<class T, class RangeRule>
597  
class range<T, RangeRule>::
598  
class range<T, RangeRule>::
598  
    iterator
599  
    iterator
599  
{
600  
{
600  
public:
601  
public:
601  
    using value_type = T;
602  
    using value_type = T;
602  
    using reference = T const&;
603  
    using reference = T const&;
603  
    using pointer = void const*;
604  
    using pointer = void const*;
604  
    using difference_type =
605  
    using difference_type =
605  
        std::ptrdiff_t;
606  
        std::ptrdiff_t;
606  
    using iterator_category =
607  
    using iterator_category =
607  
        std::forward_iterator_tag;
608  
        std::forward_iterator_tag;
608  

609  

609  
    iterator() = default;
610  
    iterator() = default;
610  
    iterator(
611  
    iterator(
611  
        iterator const&) = default;
612  
        iterator const&) = default;
612  
    iterator& operator=(
613  
    iterator& operator=(
613  
        iterator const&) = default;
614  
        iterator const&) = default;
614  

615  

615  
    reference
616  
    reference
616  
    operator*() const noexcept
617  
    operator*() const noexcept
617  
    {
618  
    {
618  
        return *rv_;
619  
        return *rv_;
619  
    }
620  
    }
620  

621  

621  
    bool
622  
    bool
622  
    operator==(
623  
    operator==(
623  
        iterator const& other) const noexcept
624  
        iterator const& other) const noexcept
624  
    {
625  
    {
625  
        // can't compare iterators
626  
        // can't compare iterators
626  
        // from different containers!
627  
        // from different containers!
627  
        BOOST_ASSERT(r_ == other.r_);
628  
        BOOST_ASSERT(r_ == other.r_);
628  

629  

629  
        return p_ == other.p_;
630  
        return p_ == other.p_;
630  
    }
631  
    }
631  

632  

632  
    bool
633  
    bool
633  
    operator!=(
634  
    operator!=(
634  
        iterator const& other) const noexcept
635  
        iterator const& other) const noexcept
635  
    {
636  
    {
636  
        return !(*this == other);
637  
        return !(*this == other);
637  
    }
638  
    }
638  

639  

639  
    iterator&
640  
    iterator&
640  
    operator++() noexcept
641  
    operator++() noexcept
641  
    {
642  
    {
642  
        BOOST_ASSERT(
643  
        BOOST_ASSERT(
643  
            p_ != nullptr);
644  
            p_ != nullptr);
644  
        auto const end =
645  
        auto const end =
645  
            r_->s_.data() +
646  
            r_->s_.data() +
646  
            r_->s_.size();
647  
            r_->s_.size();
647  
        rv_ = r_->rule().next(p_, end);
648  
        rv_ = r_->rule().next(p_, end);
648  
        if( !rv_ )
649  
        if( !rv_ )
649  
            p_ = nullptr;
650  
            p_ = nullptr;
650  
        return *this;
651  
        return *this;
651  
    }
652  
    }
652  

653  

653  
    iterator
654  
    iterator
654  
    operator++(int) noexcept
655  
    operator++(int) noexcept
655  
    {
656  
    {
656  
        auto tmp = *this;
657  
        auto tmp = *this;
657  
        ++*this;
658  
        ++*this;
658  
        return tmp;
659  
        return tmp;
659  
    }
660  
    }
660  

661  

661  
private:
662  
private:
662  
    friend class range<T, RangeRule>;
663  
    friend class range<T, RangeRule>;
663  

664  

664  
    range<T, RangeRule> const* r_ = nullptr;
665  
    range<T, RangeRule> const* r_ = nullptr;
665  
    char const* p_ = nullptr;
666  
    char const* p_ = nullptr;
666  
    system::result<T> rv_;
667  
    system::result<T> rv_;
667  

668  

668  
    iterator(
669  
    iterator(
669  
        range<T, RangeRule> const& r) noexcept
670  
        range<T, RangeRule> const& r) noexcept
670  
        : r_(&r)
671  
        : r_(&r)
671  
        , p_(r.s_.data())
672  
        , p_(r.s_.data())
672  
    {
673  
    {
673  
        auto const end =
674  
        auto const end =
674  
            r_->s_.data() +
675  
            r_->s_.data() +
675  
            r_->s_.size();
676  
            r_->s_.size();
676  
        rv_ = r_->rule().first(p_, end);
677  
        rv_ = r_->rule().first(p_, end);
677  
        if( !rv_ )
678  
        if( !rv_ )
678  
            p_ = nullptr;
679  
            p_ = nullptr;
679  
    }
680  
    }
680  

681  

681  
    constexpr
682  
    constexpr
682  
    iterator(
683  
    iterator(
683  
        range<T, RangeRule> const& r,
684  
        range<T, RangeRule> const& r,
684  
        int) noexcept
685  
        int) noexcept
685  
        : r_(&r)
686  
        : r_(&r)
686  
        , p_(nullptr)
687  
        , p_(nullptr)
687  
    {
688  
    {
688  
    }
689  
    }
689  
};
690  
};
690  

691  

691  
//------------------------------------------------
692  
//------------------------------------------------
692  

693  

693  
template<class T, class RangeRule>
694  
template<class T, class RangeRule>
694  
typename range<T, RangeRule>::iterator
695  
typename range<T, RangeRule>::iterator
695  
range<T, RangeRule>::
696  
range<T, RangeRule>::
696  
begin() const noexcept
697  
begin() const noexcept
697  
{
698  
{
698  
    return iterator(*this);
699  
    return iterator(*this);
699  
}
700  
}
700  

701  

701  
//------------------------------------------------
702  
//------------------------------------------------
702  

703  

703  
template<class T, class RangeRule>
704  
template<class T, class RangeRule>
704  
typename range<T, RangeRule>::iterator
705  
typename range<T, RangeRule>::iterator
705  
range<T, RangeRule>::
706  
range<T, RangeRule>::
706  
end() const noexcept
707  
end() const noexcept
707  
{
708  
{
708  
    return iterator(*this, 0);
709  
    return iterator(*this, 0);
709  
}
710  
}
710  

711  

711  
//------------------------------------------------
712  
//------------------------------------------------
712  

713  

713  
template<class T, class RangeRule>
714  
template<class T, class RangeRule>
714  
range<T, RangeRule>::
715  
range<T, RangeRule>::
715  
range(
716  
range(
716  
    core::string_view s,
717  
    core::string_view s,
717  
    std::size_t n,
718  
    std::size_t n,
718  
    RangeRule const& rule) noexcept
719  
    RangeRule const& rule) noexcept
719  
    : detail::range_base_storage<
720  
    : detail::range_base_storage<
720  
        RangeRule>(rule)
721  
        RangeRule>(rule)
721  
    , s_(s)
722  
    , s_(s)
722  
    , n_(n)
723  
    , n_(n)
723  
{
724  
{
724  
}
725  
}
725  

726  

726  
//------------------------------------------------
727  
//------------------------------------------------
727  

728  

728  
template<class T, class RangeRule>
729  
template<class T, class RangeRule>
729  
range<T, RangeRule>::
730  
range<T, RangeRule>::
730  
range(
731  
range(
731  
    core::string_view s,
732  
    core::string_view s,
732  
    std::size_t n,
733  
    std::size_t n,
733  
    RangeRule&& rule) noexcept
734  
    RangeRule&& rule) noexcept
734  
    : detail::range_base_storage<
735  
    : detail::range_base_storage<
735  
        RangeRule>(std::move(rule))
736  
        RangeRule>(std::move(rule))
736  
    , s_(s)
737  
    , s_(s)
737  
    , n_(n)
738  
    , n_(n)
738  
{
739  
{
739  
}
740  
}
740  

741  

741  
//------------------------------------------------
742  
//------------------------------------------------
742  

743  

743  
template<class R>
744  
template<class R>
744  
auto
745  
auto
745  
implementation_defined::range_rule_t<R>::
746  
implementation_defined::range_rule_t<R>::
746  
parse(
747  
parse(
747  
    char const*& it,
748  
    char const*& it,
748  
    char const* end) const ->
749  
    char const* end) const ->
749  
        system::result<value_type>
750  
        system::result<value_type>
750  
{
751  
{
751  
    using T = typename R::value_type;
752  
    using T = typename R::value_type;
752  

753  

753  
    std::size_t n = 0;
754  
    std::size_t n = 0;
754  
    auto const it0 = it;
755  
    auto const it0 = it;
755  
    auto it1 = it;
756  
    auto it1 = it;
756  
    auto rv = (grammar::parse)(
757  
    auto rv = (grammar::parse)(
757  
        it, end, next_);
758  
        it, end, next_);
758  
    if( !rv )
759  
    if( !rv )
759  
    {
760  
    {
760  
        if(rv.error() != error::end_of_range)
761  
        if(rv.error() != error::end_of_range)
761  
        {
762  
        {
762  
            // rewind unless error::end_of_range
763  
            // rewind unless error::end_of_range
763  
            it = it1;
764  
            it = it1;
764  
        }
765  
        }
765  
        if(n < N_)
766  
        if(n < N_)
766  
        {
767  
        {
767  
            // too few
768  
            // too few
768 -
            BOOST_URL_RETURN_EC(
769 +
            BOOST_URL_CONSTEXPR_RETURN_EC(
769  
                error::mismatch);
770  
                error::mismatch);
770  
        }
771  
        }
771  
        // good
772  
        // good
772  
        return range<T>(
773  
        return range<T>(
773  
            core::string_view(it0, it - it0),
774  
            core::string_view(it0, it - it0),
774  
                n, any_rule<T>(next_));
775  
                n, any_rule<T>(next_));
775  
    }
776  
    }
776  
    for(;;)
777  
    for(;;)
777  
    {
778  
    {
778  
        ++n;
779  
        ++n;
779  
        it1 = it;
780  
        it1 = it;
780  
        rv = (grammar::parse)(
781  
        rv = (grammar::parse)(
781  
            it, end, next_);
782  
            it, end, next_);
782  
        if( !rv )
783  
        if( !rv )
783  
        {
784  
        {
784  
            if(rv.error() != error::end_of_range)
785  
            if(rv.error() != error::end_of_range)
785  
            {
786  
            {
786  
                // rewind unless error::end_of_range
787  
                // rewind unless error::end_of_range
787  
                it = it1;
788  
                it = it1;
788  
            }
789  
            }
789  
            break;
790  
            break;
790  
        }
791  
        }
791  
        if(n >= M_)
792  
        if(n >= M_)
792  
        {
793  
        {
793  
            // too many
794  
            // too many
794 -
            BOOST_URL_RETURN_EC(
795 +
            BOOST_URL_CONSTEXPR_RETURN_EC(
795  
                error::mismatch);
796  
                error::mismatch);
796  
        }
797  
        }
797  
    }
798  
    }
798  
    if(n < N_)
799  
    if(n < N_)
799  
    {
800  
    {
800  
        // too few
801  
        // too few
801 -
        BOOST_URL_RETURN_EC(
802 +
        BOOST_URL_CONSTEXPR_RETURN_EC(
802  
            error::mismatch);
803  
            error::mismatch);
803  
    }
804  
    }
804  
    // good
805  
    // good
805  
    return range<T>(
806  
    return range<T>(
806  
        core::string_view(it0, it - it0),
807  
        core::string_view(it0, it - it0),
807  
            n, any_rule<T>(next_));
808  
            n, any_rule<T>(next_));
808  
}
809  
}
809  

810  

810  
//------------------------------------------------
811  
//------------------------------------------------
811  

812  

812  
template<class R0, class R1>
813  
template<class R0, class R1>
813  
auto
814  
auto
814  
implementation_defined::range_rule_t<R0, R1>::
815  
implementation_defined::range_rule_t<R0, R1>::
815  
parse(
816  
parse(
816  
    char const*& it,
817  
    char const*& it,
817  
    char const* end) const ->
818  
    char const* end) const ->
818  
        system::result<range<typename
819  
        system::result<range<typename
819  
            R0::value_type>>
820  
            R0::value_type>>
820  
{
821  
{
821  
    using T = typename R0::value_type;
822  
    using T = typename R0::value_type;
822  

823  

823  
    std::size_t n = 0;
824  
    std::size_t n = 0;
824  
    auto const it0 = it;
825  
    auto const it0 = it;
825  
    auto it1 = it;
826  
    auto it1 = it;
826  
    auto rv = (grammar::parse)(
827  
    auto rv = (grammar::parse)(
827  
        it, end, first_);
828  
        it, end, first_);
828  
    if( !rv )
829  
    if( !rv )
829  
    {
830  
    {
830  
        if(rv.error() != error::end_of_range)
831  
        if(rv.error() != error::end_of_range)
831  
        {
832  
        {
832  
            it = it1;
833  
            it = it1;
833  
        }
834  
        }
834  
        if(n < N_)
835  
        if(n < N_)
835  
        {
836  
        {
836 -
            BOOST_URL_RETURN_EC(
837 +
            BOOST_URL_CONSTEXPR_RETURN_EC(
837  
                error::mismatch);
838  
                error::mismatch);
838  
        }
839  
        }
839  
        return range<T>(
840  
        return range<T>(
840  
            core::string_view(it0, it - it0),
841  
            core::string_view(it0, it - it0),
841  
                n, any_rule<T>(first_, next_));
842  
                n, any_rule<T>(first_, next_));
842  
    }
843  
    }
843  
    for(;;)
844  
    for(;;)
844  
    {
845  
    {
845  
        ++n;
846  
        ++n;
846  
        it1 = it;
847  
        it1 = it;
847  
        rv = (grammar::parse)(
848  
        rv = (grammar::parse)(
848  
            it, end, next_);
849  
            it, end, next_);
849  
        if( !rv )
850  
        if( !rv )
850  
        {
851  
        {
851  
            if(rv.error() != error::end_of_range)
852  
            if(rv.error() != error::end_of_range)
852  
            {
853  
            {
853  
                // rewind unless error::end_of_range
854  
                // rewind unless error::end_of_range
854  
                it = it1;
855  
                it = it1;
855  
            }
856  
            }
856  
            break;
857  
            break;
857  
        }
858  
        }
858  
        if(n >= M_)
859  
        if(n >= M_)
859  
        {
860  
        {
860  
            // too many
861  
            // too many
861 -
            BOOST_URL_RETURN_EC(
862 +
            BOOST_URL_CONSTEXPR_RETURN_EC(
862  
                error::mismatch);
863  
                error::mismatch);
863  
        }
864  
        }
864  
    }
865  
    }
865  
    if(n < N_)
866  
    if(n < N_)
866  
    {
867  
    {
867  
        // too few
868  
        // too few
868 -
        BOOST_URL_RETURN_EC(
869 +
        BOOST_URL_CONSTEXPR_RETURN_EC(
869  
            error::mismatch);
870  
            error::mismatch);
870  
    }
871  
    }
871  
    // good
872  
    // good
872  
    return range<T>(
873  
    return range<T>(
873  
        core::string_view(it0, it - it0),
874  
        core::string_view(it0, it - it0),
874  
            n, any_rule<T>(first_, next_));
875  
            n, any_rule<T>(first_, next_));
875  
}
876  
}
876  

877  

877  
} // grammar
878  
} // grammar
878  
} // urls
879  
} // urls
879  
} // boost
880  
} // boost
880  

881  

881  
#endif
882  
#endif