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  

10  

11  
#include <boost/url/detail/config.hpp>
11  
#include <boost/url/detail/config.hpp>
12  
#include <boost/url/decode_view.hpp>
12  
#include <boost/url/decode_view.hpp>
13  
#include <boost/url/grammar/hexdig_chars.hpp>
13  
#include <boost/url/grammar/hexdig_chars.hpp>
14  
#include <ostream>
14  
#include <ostream>
15  

15  

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

18  

19  
//------------------------------------------------
19  
//------------------------------------------------
20  

20  

21  
auto
21  
auto
22  
decode_view::
22  
decode_view::
23  
iterator::
23  
iterator::
24  
operator*() const noexcept ->
24  
operator*() const noexcept ->
25  
    reference
25  
    reference
26  
{
26  
{
27  
    if (space_as_plus_ &&
27  
    if (space_as_plus_ &&
28  
        *pos_ == '+')
28  
        *pos_ == '+')
29  
        return ' ';
29  
        return ' ';
30  
    if (*pos_ != '%')
30  
    if (*pos_ != '%')
31  
        return *pos_;
31  
        return *pos_;
32  
    auto d0 = grammar::hexdig_value(pos_[1]);
32  
    auto d0 = grammar::hexdig_value(pos_[1]);
33  
    auto d1 = grammar::hexdig_value(pos_[2]);
33  
    auto d1 = grammar::hexdig_value(pos_[2]);
34  
    return static_cast<char>(
34  
    return static_cast<char>(
35  
        ((static_cast<
35  
        ((static_cast<
36  
              unsigned char>(d0) << 4) +
36  
              unsigned char>(d0) << 4) +
37  
         (static_cast<
37  
         (static_cast<
38  
             unsigned char>(d1))));
38  
             unsigned char>(d1))));
39  
}
39  
}
40  

40  

41  
void
41  
void
42  
decode_view::
42  
decode_view::
43  
write(std::ostream& os) const
43  
write(std::ostream& os) const
44  
{
44  
{
45  
    auto it = begin();
45  
    auto it = begin();
46  
    auto const end_ = end();
46  
    auto const end_ = end();
47  
    while(it != end_)
47  
    while(it != end_)
48  
        os.put(*it++);
48  
        os.put(*it++);
49  
}
49  
}
50  

50  

51  
void
51  
void
52  
decode_view::
52  
decode_view::
53  
remove_prefix( size_type n )
53  
remove_prefix( size_type n )
54  
{
54  
{
55  
    BOOST_ASSERT(n <= dn_);
55  
    BOOST_ASSERT(n <= dn_);
56  
    auto it = begin();
56  
    auto it = begin();
57  
    auto n0 = n;
57  
    auto n0 = n;
58  
    while (n)
58  
    while (n)
59  
    {
59  
    {
60  
        ++it;
60  
        ++it;
61  
        --n;
61  
        --n;
62  
    }
62  
    }
63  
    n_ -= (it.base() - begin().base());
63  
    n_ -= (it.base() - begin().base());
64  
    dn_ -= n0;
64  
    dn_ -= n0;
65  
    p_ = it.base();
65  
    p_ = it.base();
66  
}
66  
}
67  

67  

68  
void
68  
void
69  
decode_view::
69  
decode_view::
70  
remove_suffix( size_type n )
70  
remove_suffix( size_type n )
71  
{
71  
{
72  
    BOOST_ASSERT(n <= dn_);
72  
    BOOST_ASSERT(n <= dn_);
73  
    auto it = end();
73  
    auto it = end();
74  
    auto n0 = n;
74  
    auto n0 = n;
75  
    while (n)
75  
    while (n)
76  
    {
76  
    {
77  
        --it;
77  
        --it;
78  
        --n;
78  
        --n;
79  
    }
79  
    }
80  
    n_ -= (end().base() - it.base());
80  
    n_ -= (end().base() - it.base());
81  
    dn_ -= n0;
81  
    dn_ -= n0;
82  
}
82  
}
83  

83  

84  
bool
84  
bool
85  
decode_view::
85  
decode_view::
86  
starts_with( core::string_view s ) const noexcept
86  
starts_with( core::string_view s ) const noexcept
87  
{
87  
{
88  
    if (s.size() > size())
88  
    if (s.size() > size())
89  
        return false;
89  
        return false;
90  
    auto it0 = begin();
90  
    auto it0 = begin();
91  
    auto it1 = s.begin();
91  
    auto it1 = s.begin();
92  
    std::size_t n = s.size();
92  
    std::size_t n = s.size();
93  
    while (n)
93  
    while (n)
94  
    {
94  
    {
95  
        if (*it0 != *it1)
95  
        if (*it0 != *it1)
96  
            return false;
96  
            return false;
97  
        ++it0;
97  
        ++it0;
98  
        ++it1;
98  
        ++it1;
99  
        --n;
99  
        --n;
100  
    }
100  
    }
101  
    return true;
101  
    return true;
102  
}
102  
}
103  

103  

104  
bool
104  
bool
105  
decode_view::
105  
decode_view::
106  
ends_with( core::string_view s ) const noexcept
106  
ends_with( core::string_view s ) const noexcept
107  
{
107  
{
108  
    if (s.size() > size())
108  
    if (s.size() > size())
109  
        return false;
109  
        return false;
110  
    auto it0 = end();
110  
    auto it0 = end();
111  
    auto it1 = s.end();
111  
    auto it1 = s.end();
112  
    std::size_t n = s.size();
112  
    std::size_t n = s.size();
113  
    --it0;
113  
    --it0;
114  
    --it1;
114  
    --it1;
115  
    while (n - 1)
115  
    while (n - 1)
116  
    {
116  
    {
117  
        if (*it0 != *it1)
117  
        if (*it0 != *it1)
118  
            return false;
118  
            return false;
119  
        --it0;
119  
        --it0;
120  
        --it1;
120  
        --it1;
121  
        --n;
121  
        --n;
122  
    }
122  
    }
123  
    return *it0 == *it1;
123  
    return *it0 == *it1;
124  
}
124  
}
125  

125  

126  
bool
126  
bool
127  
decode_view::
127  
decode_view::
128  
starts_with( char ch ) const noexcept
128  
starts_with( char ch ) const noexcept
129  
{
129  
{
130  
    return
130  
    return
131  
        !empty() &&
131  
        !empty() &&
132  
        front() == ch;
132  
        front() == ch;
133  
}
133  
}
134  

134  

135  
bool
135  
bool
136  
decode_view::
136  
decode_view::
137  
ends_with( char ch ) const noexcept
137  
ends_with( char ch ) const noexcept
138  
{
138  
{
139  
    return
139  
    return
140  
        !empty() &&
140  
        !empty() &&
141  
        back() == ch;
141  
        back() == ch;
142  
}
142  
}
143  

143  

144  
decode_view::const_iterator
144  
decode_view::const_iterator
145  
decode_view::
145  
decode_view::
146  
find( char ch ) const noexcept
146  
find( char ch ) const noexcept
147  
{
147  
{
148  
    auto it = begin();
148  
    auto it = begin();
149  
    auto end = this->end();
149  
    auto end = this->end();
150  
    while (it != end)
150  
    while (it != end)
151  
    {
151  
    {
152  
        if (*it == ch)
152  
        if (*it == ch)
153  
            return it;
153  
            return it;
154  
        ++it;
154  
        ++it;
155  
    }
155  
    }
156  
    return it;
156  
    return it;
157  
}
157  
}
158  

158  

159  
decode_view::const_iterator
159  
decode_view::const_iterator
160  
decode_view::
160  
decode_view::
161  
rfind( char ch ) const noexcept
161  
rfind( char ch ) const noexcept
162  
{
162  
{
163  
    if (empty())
163  
    if (empty())
164  
        return end();
164  
        return end();
165  
    auto it = end();
165  
    auto it = end();
166  
    auto begin = this->begin();
166  
    auto begin = this->begin();
167  
    --it;
167  
    --it;
168  
    while (it != begin)
168  
    while (it != begin)
169  
    {
169  
    {
170  
        if (*it == ch)
170  
        if (*it == ch)
171  
            return it;
171  
            return it;
172  
        --it;
172  
        --it;
173  
    }
173  
    }
174  
    if (*it == ch)
174  
    if (*it == ch)
175  
        return it;
175  
        return it;
176  
    return end();
176  
    return end();
177  
}
177  
}
178  

178  

179  
} // urls
179  
} // urls
180  
} // boost
180  
} // boost
181  

181