1  
//
1  
//
2  
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
2  
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.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_IMPL_PCT_ENCODED_VIEW_HPP
10  
#ifndef BOOST_URL_IMPL_PCT_ENCODED_VIEW_HPP
11  
#define BOOST_URL_IMPL_PCT_ENCODED_VIEW_HPP
11  
#define BOOST_URL_IMPL_PCT_ENCODED_VIEW_HPP
12  

12  

13  
#include <boost/url/grammar/type_traits.hpp>
13  
#include <boost/url/grammar/type_traits.hpp>
14  
#include <boost/core/detail/static_assert.hpp>
14  
#include <boost/core/detail/static_assert.hpp>
15  

15  

16  
namespace boost {
16  
namespace boost {
17  
namespace urls {
17  
namespace urls {
18  

18  

19  
class decode_view::iterator
19  
class decode_view::iterator
20  
{
20  
{
21  
    char const* begin_ = nullptr;
21  
    char const* begin_ = nullptr;
22  
    char const* pos_ = nullptr;
22  
    char const* pos_ = nullptr;
23  
    bool space_as_plus_ = true;
23  
    bool space_as_plus_ = true;
24  

24  

25  
    friend decode_view;
25  
    friend decode_view;
26  

26  

27  
    iterator(
27  
    iterator(
28  
        char const* str,
28  
        char const* str,
29  
        bool space_as_plus) noexcept
29  
        bool space_as_plus) noexcept
30  
        : begin_(str)
30  
        : begin_(str)
31  
        , pos_(str)
31  
        , pos_(str)
32  
        , space_as_plus_(
32  
        , space_as_plus_(
33  
            space_as_plus)
33  
            space_as_plus)
34  
    {
34  
    {
35  
    }
35  
    }
36  

36  

37  
    // end ctor
37  
    // end ctor
38  
    iterator(
38  
    iterator(
39  
        char const* str,
39  
        char const* str,
40  
        size_type n,
40  
        size_type n,
41  
        bool space_as_plus) noexcept
41  
        bool space_as_plus) noexcept
42  
        : begin_(str)
42  
        : begin_(str)
43  
        , pos_(str + n)
43  
        , pos_(str + n)
44  
        , space_as_plus_(space_as_plus)
44  
        , space_as_plus_(space_as_plus)
45  
    {
45  
    {
46  
    }
46  
    }
47  

47  

48  
public:
48  
public:
49  
    using value_type = char;
49  
    using value_type = char;
50  
    using reference = char;
50  
    using reference = char;
51  
    using pointer = void const*;
51  
    using pointer = void const*;
52  
    using const_reference = char;
52  
    using const_reference = char;
53  
    using size_type = std::size_t;
53  
    using size_type = std::size_t;
54  
    using difference_type = std::ptrdiff_t;
54  
    using difference_type = std::ptrdiff_t;
55  
    using iterator_category =
55  
    using iterator_category =
56  
        std::bidirectional_iterator_tag;
56  
        std::bidirectional_iterator_tag;
57  

57  

58  
    iterator() = default;
58  
    iterator() = default;
59  

59  

60  
    iterator(iterator const&) = default;
60  
    iterator(iterator const&) = default;
61  

61  

62  
    iterator&
62  
    iterator&
63  
    operator=(iterator const&) = default;
63  
    operator=(iterator const&) = default;
64  

64  

65  
    BOOST_URL_DECL
65  
    BOOST_URL_DECL
66  
    reference
66  
    reference
67  
    operator*() const noexcept;
67  
    operator*() const noexcept;
68  

68  

69  
    iterator&
69  
    iterator&
70  
    operator++() noexcept
70  
    operator++() noexcept
71  
    {
71  
    {
72  
        BOOST_ASSERT(pos_ != nullptr);
72  
        BOOST_ASSERT(pos_ != nullptr);
73  
        if (*pos_ != '%')
73  
        if (*pos_ != '%')
74  
            ++pos_;
74  
            ++pos_;
75  
        else
75  
        else
76  
            pos_ += 3;
76  
            pos_ += 3;
77  
        return *this;
77  
        return *this;
78  
    }
78  
    }
79  

79  

80  
    iterator&
80  
    iterator&
81  
    operator--() noexcept
81  
    operator--() noexcept
82  
    {
82  
    {
83  
        BOOST_ASSERT(pos_ != begin_);
83  
        BOOST_ASSERT(pos_ != begin_);
84  
        if (pos_ - begin_ < 3 ||
84  
        if (pos_ - begin_ < 3 ||
85  
                pos_[-3] != '%')
85  
                pos_[-3] != '%')
86  
            --pos_;
86  
            --pos_;
87  
        else
87  
        else
88  
            pos_ -= 3;
88  
            pos_ -= 3;
89  
        return *this;
89  
        return *this;
90  
    }
90  
    }
91  

91  

92  
    iterator
92  
    iterator
93  
    operator++(int) noexcept
93  
    operator++(int) noexcept
94  
    {
94  
    {
95  
        auto tmp = *this;
95  
        auto tmp = *this;
96  
        ++*this;
96  
        ++*this;
97  
        return tmp;
97  
        return tmp;
98  
    }
98  
    }
99  

99  

100  
    iterator
100  
    iterator
101  
    operator--(int) noexcept
101  
    operator--(int) noexcept
102  
    {
102  
    {
103  
        auto tmp = *this;
103  
        auto tmp = *this;
104  
        --*this;
104  
        --*this;
105  
        return tmp;
105  
        return tmp;
106  
    }
106  
    }
107  

107  

108  
    char const*
108  
    char const*
109  
    base()
109  
    base()
110  
    {
110  
    {
111  
        return pos_;
111  
        return pos_;
112  
    }
112  
    }
113  

113  

114  
    bool
114  
    bool
115  
    operator==(
115  
    operator==(
116  
        iterator const& other) const noexcept
116  
        iterator const& other) const noexcept
117  
    {
117  
    {
118  
        return pos_ == other.pos_;
118  
        return pos_ == other.pos_;
119  
    }
119  
    }
120  

120  

121  
    bool
121  
    bool
122  
    operator!=(
122  
    operator!=(
123  
        iterator const& other) const noexcept
123  
        iterator const& other) const noexcept
124  
    {
124  
    {
125  
        return !(*this == other);
125  
        return !(*this == other);
126  
    }
126  
    }
127  
};
127  
};
128  

128  

129  
//------------------------------------------------
129  
//------------------------------------------------
130  

130  

131  
inline
131  
inline
132  
auto
132  
auto
133  
decode_view::
133  
decode_view::
134  
begin() const noexcept ->
134  
begin() const noexcept ->
135  
    const_iterator
135  
    const_iterator
136  
{
136  
{
137  
    return {p_, space_as_plus_};
137  
    return {p_, space_as_plus_};
138  
}
138  
}
139  

139  

140  
inline
140  
inline
141  
auto
141  
auto
142  
decode_view::
142  
decode_view::
143  
end() const noexcept ->
143  
end() const noexcept ->
144  
    const_iterator
144  
    const_iterator
145  
{
145  
{
146  
    return {p_, n_, space_as_plus_};
146  
    return {p_, n_, space_as_plus_};
147  
}
147  
}
148  

148  

149  
inline
149  
inline
150  
auto
150  
auto
151  
decode_view::
151  
decode_view::
152  
front() const noexcept ->
152  
front() const noexcept ->
153  
    const_reference
153  
    const_reference
154  
{
154  
{
155  
    BOOST_ASSERT( !empty() );
155  
    BOOST_ASSERT( !empty() );
156  
    return *begin();
156  
    return *begin();
157  
}
157  
}
158  

158  

159  
inline
159  
inline
160  
auto
160  
auto
161  
decode_view::
161  
decode_view::
162  
back() const noexcept ->
162  
back() const noexcept ->
163  
    const_reference
163  
    const_reference
164  
{
164  
{
165  
    BOOST_ASSERT( !empty() );
165  
    BOOST_ASSERT( !empty() );
166  
    return *--end();
166  
    return *--end();
167  
}
167  
}
168  

168  

169  
namespace detail {
169  
namespace detail {
170  

170  

171  
template <class T>
171  
template <class T>
172  
BOOST_CXX14_CONSTEXPR
172  
BOOST_CXX14_CONSTEXPR
173  
int
173  
int
174  
decoded_strcmp(decode_view s0, T s1)
174  
decoded_strcmp(decode_view s0, T s1)
175  
{
175  
{
176  
    auto const n0 = s0.size();
176  
    auto const n0 = s0.size();
177  
    auto const n1 = s1.size();
177  
    auto const n1 = s1.size();
178  
    auto n = (std::min)(n0, n1);
178  
    auto n = (std::min)(n0, n1);
179  
    auto it0 = s0.begin();
179  
    auto it0 = s0.begin();
180  
    auto it1 = s1.begin();
180  
    auto it1 = s1.begin();
181  
    while (n--)
181  
    while (n--)
182  
    {
182  
    {
183  
        const char c0 = *it0++;
183  
        const char c0 = *it0++;
184  
        const char c1 = *it1++;
184  
        const char c1 = *it1++;
185  
        if (c0 == c1)
185  
        if (c0 == c1)
186  
            continue;
186  
            continue;
187  
        return 1 - 2 * (static_cast<unsigned char>(c0)
187  
        return 1 - 2 * (static_cast<unsigned char>(c0)
188  
                      < static_cast<unsigned char>(c1));
188  
                      < static_cast<unsigned char>(c1));
189  
    }
189  
    }
190  
    return 1 - (n0 == n1) - 2 * (n0 < n1);
190  
    return 1 - (n0 == n1) - 2 * (n0 < n1);
191  
}
191  
}
192  

192  

193  
} // detail
193  
} // detail
194  

194  

195  

195  

196  
#if defined(BOOST_NO_CXX14_CONSTEXPR)
196  
#if defined(BOOST_NO_CXX14_CONSTEXPR)
197  
inline
197  
inline
198  
#else
198  
#else
199  
BOOST_CXX14_CONSTEXPR
199  
BOOST_CXX14_CONSTEXPR
200  
#endif
200  
#endif
201  
int
201  
int
202  
decode_view::
202  
decode_view::
203  
compare(core::string_view other) const noexcept
203  
compare(core::string_view other) const noexcept
204  
{
204  
{
205  
    return detail::decoded_strcmp(*this, other);
205  
    return detail::decoded_strcmp(*this, other);
206  
}
206  
}
207  

207  

208  
#if defined(BOOST_NO_CXX14_CONSTEXPR)
208  
#if defined(BOOST_NO_CXX14_CONSTEXPR)
209  
inline
209  
inline
210  
#else
210  
#else
211  
BOOST_CXX14_CONSTEXPR
211  
BOOST_CXX14_CONSTEXPR
212  
#endif
212  
#endif
213  
int
213  
int
214  
decode_view::
214  
decode_view::
215  
compare(decode_view other) const noexcept
215  
compare(decode_view other) const noexcept
216  
{
216  
{
217  
    return detail::decoded_strcmp(*this, other);
217  
    return detail::decoded_strcmp(*this, other);
218  
}
218  
}
219  

219  

220  
} // urls
220  
} // urls
221  
} // boost
221  
} // boost
222  

222  

223  
#endif
223  
#endif