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

67  

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

83  

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

103  

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

125  

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

134  

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

143  

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

158  

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

178  

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

181