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  
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
4  
//
4  
//
5  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
6  
// 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)
7  
//
7  
//
8  
// Official repository: https://github.com/boostorg/url
8  
// Official repository: https://github.com/boostorg/url
9  
//
9  
//
10  

10  

11  
#ifndef BOOST_URL_GRAMMAR_IMPL_RANGE_HPP
11  
#ifndef BOOST_URL_GRAMMAR_IMPL_RANGE_HPP
12  
#define BOOST_URL_GRAMMAR_IMPL_RANGE_HPP
12  
#define BOOST_URL_GRAMMAR_IMPL_RANGE_HPP
13  

13  

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

25  

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

27  

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

31  

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

37  

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

43  

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

51  

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

58  

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

67  

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

77  

78  
//------------------------------------------------
78  
//------------------------------------------------
79  

79  

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

94  

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

98  

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

106  

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

113  

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

123  

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

134  

135  
//------------------------------------------------
135  
//------------------------------------------------
136  

136  

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

148  

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

154  

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

157  

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

160  

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

167  

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

173  

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

181  

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

188  

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

198  

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

209  

210  
//------------------------------------------------
210  
//------------------------------------------------
211  

211  

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

230  

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

234  

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

242  

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

249  

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

260  

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

272  

273  
//------------------------------------------------
273  
//------------------------------------------------
274  

274  

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

289  

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

296  

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

299  

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

302  

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

309  

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

315  

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

323  

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

330  

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

340  

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

351  

352  
//------------------------------------------------
352  
//------------------------------------------------
353  

353  

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

362  

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

371  

372  

372  

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

382  

383  

383  

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

390  

391  

391  

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

398  

399  

399  

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

411  

412  

412  

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

424  

425  

425  

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

432  

433  

433  

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

446  

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

450  

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

455  

456  
//------------------------------------------------
456  
//------------------------------------------------
457  

457  

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

478  

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

482  

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

488  

489  
//------------------------------------------------
489  
//------------------------------------------------
490  

490  

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

500  

501  
//------------------------------------------------
501  
//------------------------------------------------
502  

502  

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

512  

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

518  

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

522  

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

526  

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

539  

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

550  

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

571  

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

590  

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

596  

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

609  

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

615  

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

621  

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

629  

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

632  

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

639  

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

653  

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

661  

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

664  

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

668  

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

681  

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

691  

692  
//------------------------------------------------
692  
//------------------------------------------------
693  

693  

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

701  

702  
//------------------------------------------------
702  
//------------------------------------------------
703  

703  

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

711  

712  
//------------------------------------------------
712  
//------------------------------------------------
713  

713  

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

726  

727  
//------------------------------------------------
727  
//------------------------------------------------
728  

728  

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

741  

742  
//------------------------------------------------
742  
//------------------------------------------------
743  

743  

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

754  

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

811  

812  
//------------------------------------------------
812  
//------------------------------------------------
813  

813  

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

825  

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

879  

880  
} // grammar
880  
} // grammar
881  
} // urls
881  
} // urls
882  
} // boost
882  
} // boost
883  

883  

884  
#endif
884  
#endif