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  
    auto it = begin();
55  
    auto it = begin();
56  
    auto n0 = n;
56  
    auto n0 = n;
57  
    while (n)
57  
    while (n)
58  
    {
58  
    {
59  
        ++it;
59  
        ++it;
60  
        --n;
60  
        --n;
61  
    }
61  
    }
62  
    n_ -= (it.base() - begin().base());
62  
    n_ -= (it.base() - begin().base());
63  
    dn_ -= n0;
63  
    dn_ -= n0;
64  
    p_ = it.base();
64  
    p_ = it.base();
65  
}
65  
}
66  

66  

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

81  

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

101  

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

123  

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

132  

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

141  

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

156  

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

176  

177  
} // urls
177  
} // urls
178  
} // boost
178  
} // boost
179  

179