1  
//
1  
//
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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_PARAMS_VIEW_HPP
11  
#ifndef BOOST_URL_PARAMS_VIEW_HPP
12  
#define BOOST_URL_PARAMS_VIEW_HPP
12  
#define BOOST_URL_PARAMS_VIEW_HPP
13  

13  

14  
#include <boost/url/detail/config.hpp>
14  
#include <boost/url/detail/config.hpp>
15  
#include <boost/url/params_base.hpp>
15  
#include <boost/url/params_base.hpp>
16  

16  

17  
namespace boost {
17  
namespace boost {
18  
namespace urls {
18  
namespace urls {
19  

19  

20  
/** Non-owning decoded query parameter view
20  
/** Non-owning decoded query parameter view
21  

21  

22  
    This read-only range interprets the query
22  
    This read-only range interprets the query
23  
    string of a URL as bidirectional key/value
23  
    string of a URL as bidirectional key/value
24  
    pairs with percent-decoding applied on
24  
    pairs with percent-decoding applied on
25  
    access. It merely references the original
25  
    access. It merely references the original
26  
    character buffer; callers must keep that
26  
    character buffer; callers must keep that
27  
    buffer alive while the view is used.
27  
    buffer alive while the view is used.
28  

28  

29  
    @par Example
29  
    @par Example
30  
    @code
30  
    @code
31  
    url_view u( "?first=John&last=Doe" );
31  
    url_view u( "?first=John&last=Doe" );
32  

32  

33  
    params_view p = u.params();
33  
    params_view p = u.params();
34  
    @endcode
34  
    @endcode
35  

35  

36  
    Strings retrieved from the iterators are
36  
    Strings retrieved from the iterators are
37  
    automatically percent-decoded.
37  
    automatically percent-decoded.
38  

38  

39  
    @par Iterator Invalidation
39  
    @par Iterator Invalidation
40  
    Changes to the underlying character buffer
40  
    Changes to the underlying character buffer
41  
    can invalidate iterators which reference it.
41  
    can invalidate iterators which reference it.
42  
*/
42  
*/
43 -
class params_view
43 +
class BOOST_URL_DECL params_view
44  
    : public params_base
44  
    : public params_base
45  
{
45  
{
46  
    friend class url_view_base;
46  
    friend class url_view_base;
47  
    friend class params_encoded_view;
47  
    friend class params_encoded_view;
48  
    friend class params_ref;
48  
    friend class params_ref;
49  

49  

50  
    params_view(
50  
    params_view(
51  
        detail::query_ref const& ref,
51  
        detail::query_ref const& ref,
52  
        encoding_opts opt) noexcept;
52  
        encoding_opts opt) noexcept;
53  

53  

54  
public:
54  
public:
55  
    /** Constructor
55  
    /** Constructor
56  

56  

57  
        Default-constructed params have
57  
        Default-constructed params have
58  
        zero elements.
58  
        zero elements.
59  

59  

60  
        @par Example
60  
        @par Example
61  
        @code
61  
        @code
62  
        params_view qp;
62  
        params_view qp;
63  
        @endcode
63  
        @endcode
64  

64  

65  
        @par Effects
65  
        @par Effects
66  
        @code
66  
        @code
67  
        return params_view( "" );
67  
        return params_view( "" );
68  
        @endcode
68  
        @endcode
69  

69  

70  
        @par Complexity
70  
        @par Complexity
71  
        Constant.
71  
        Constant.
72  

72  

73  
        @par Exception Safety
73  
        @par Exception Safety
74  
        Throws nothing.
74  
        Throws nothing.
75  
    */
75  
    */
76  
    params_view() = default;
76  
    params_view() = default;
77  

77  

78  
    /** Constructor
78  
    /** Constructor
79  

79  

80  
        After construction both views reference
80  
        After construction both views reference
81  
        the same character buffer.
81  
        the same character buffer.
82  

82  

83  
        Ownership is not transferred; the caller
83  
        Ownership is not transferred; the caller
84  
        is responsible for ensuring the lifetime
84  
        is responsible for ensuring the lifetime
85  
        of the buffer extends until it is no
85  
        of the buffer extends until it is no
86  
        longer referenced.
86  
        longer referenced.
87  

87  

88  
        @par Postconditions
88  
        @par Postconditions
89  
        @code
89  
        @code
90  
        this->buffer().data() == other.buffer().data()
90  
        this->buffer().data() == other.buffer().data()
91  
        @endcode
91  
        @endcode
92  

92  

93  
        @par Complexity
93  
        @par Complexity
94  
        Constant.
94  
        Constant.
95  

95  

96  
        @par Exception Safety
96  
        @par Exception Safety
97  
        Throws nothing
97  
        Throws nothing
98  

98  

99  
        @param other The object to copy
99  
        @param other The object to copy
100  
    */
100  
    */
101  
    params_view(
101  
    params_view(
102  
        params_view const& other) = default;
102  
        params_view const& other) = default;
103  

103  

104  
    /** Constructor
104  
    /** Constructor
105  

105  

106  
        After construction both views will
106  
        After construction both views will
107  
        reference the same character buffer
107  
        reference the same character buffer
108  
        but this instance will use the specified
108  
        but this instance will use the specified
109  
        @ref encoding_opts when the values
109  
        @ref encoding_opts when the values
110  
        are decoded.
110  
        are decoded.
111  

111  

112  
        Ownership is not transferred; the caller
112  
        Ownership is not transferred; the caller
113  
        is responsible for ensuring the lifetime
113  
        is responsible for ensuring the lifetime
114  
        of the buffer extends until it is no
114  
        of the buffer extends until it is no
115  
        longer referenced.
115  
        longer referenced.
116  

116  

117  
        @par Postconditions
117  
        @par Postconditions
118  
        @code
118  
        @code
119  
        this->buffer().data() == other.buffer().data()
119  
        this->buffer().data() == other.buffer().data()
120  
        @endcode
120  
        @endcode
121  

121  

122  
        @par Complexity
122  
        @par Complexity
123  
        Constant.
123  
        Constant.
124  

124  

125  
        @par Exception Safety
125  
        @par Exception Safety
126  
        Throws nothing
126  
        Throws nothing
127  

127  

128  
        @param other The object to copy
128  
        @param other The object to copy
129  
        @param opt The options for decoding
129  
        @param opt The options for decoding
130  
    */
130  
    */
131  
    params_view(
131  
    params_view(
132  
        params_view const& other,
132  
        params_view const& other,
133  
        encoding_opts opt) noexcept;
133  
        encoding_opts opt) noexcept;
134  

134  

135  
    /** Constructor
135  
    /** Constructor
136  

136  

137  
        This function constructs params from
137  
        This function constructs params from
138  
        a valid query parameter string, which
138  
        a valid query parameter string, which
139  
        can contain percent escapes. Unlike
139  
        can contain percent escapes. Unlike
140  
        the parameters in URLs, the string
140  
        the parameters in URLs, the string
141  
        passed here should not start with "?".
141  
        passed here should not start with "?".
142  
        Upon construction, the view references
142  
        Upon construction, the view references
143  
        the character buffer pointed to by `s`.
143  
        the character buffer pointed to by `s`.
144  
        The caller is responsible for ensuring
144  
        The caller is responsible for ensuring
145  
        that the lifetime of the buffer extends
145  
        that the lifetime of the buffer extends
146  
        until it is no longer referenced.
146  
        until it is no longer referenced.
147  

147  

148  
        @par Example
148  
        @par Example
149  
        @code
149  
        @code
150  
        params_view qp( "first=John&last=Doe" );
150  
        params_view qp( "first=John&last=Doe" );
151  
        @endcode
151  
        @endcode
152  

152  

153  
        @par Effects
153  
        @par Effects
154  
        @code
154  
        @code
155  
        return parse_query( s ).value();
155  
        return parse_query( s ).value();
156  
        @endcode
156  
        @endcode
157  

157  

158  
        @par Postconditions
158  
        @par Postconditions
159  
        @code
159  
        @code
160  
        this->buffer().data() == s.data()
160  
        this->buffer().data() == s.data()
161  
        @endcode
161  
        @endcode
162  

162  

163  
        @par Complexity
163  
        @par Complexity
164  
        Linear in `s`.
164  
        Linear in `s`.
165  

165  

166  
        @par Exception Safety
166  
        @par Exception Safety
167  
        Exceptions thrown on invalid input.
167  
        Exceptions thrown on invalid input.
168  

168  

169  
        @throw system_error
169  
        @throw system_error
170  
        `s` contains an invalid query parameter
170  
        `s` contains an invalid query parameter
171  
        string.
171  
        string.
172  

172  

173  
        @param s The string to parse.
173  
        @param s The string to parse.
174  

174  

175  
        @par BNF
175  
        @par BNF
176  
        @code
176  
        @code
177  
        query-params    = [ query-param ] *( "&" query-param )
177  
        query-params    = [ query-param ] *( "&" query-param )
178  

178  

179  
        query-param     = key [ "=" value ]
179  
        query-param     = key [ "=" value ]
180  
        @endcode
180  
        @endcode
181  

181  

182  
        @par Specification
182  
        @par Specification
183  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.4"
183  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.4"
184  
            >3.4.  Query</a>
184  
            >3.4.  Query</a>
185 -
    BOOST_URL_DECL
 
186  
    */
185  
    */
187  
    params_view(
186  
    params_view(
188  
        core::string_view s);
187  
        core::string_view s);
189  

188  

190  
    /** Constructor
189  
    /** Constructor
191  

190  

192  
        This function constructs params from
191  
        This function constructs params from
193  
        a valid query parameter string, which
192  
        a valid query parameter string, which
194  
        can contain percent escapes.
193  
        can contain percent escapes.
195  

194  

196  
        This instance will use the specified
195  
        This instance will use the specified
197  
        @ref encoding_opts when the values
196  
        @ref encoding_opts when the values
198  
        are decoded.
197  
        are decoded.
199  

198  

200  
        Unlike the parameters in URLs, the string
199  
        Unlike the parameters in URLs, the string
201  
        passed here should not start with "?".
200  
        passed here should not start with "?".
202  
        Upon construction, the view will
201  
        Upon construction, the view will
203  
        reference the character buffer pointed
202  
        reference the character buffer pointed
204  
        to by `s`. The caller is responsible
203  
        to by `s`. The caller is responsible
205  
        for ensuring that the lifetime of the
204  
        for ensuring that the lifetime of the
206  
        buffer extends until it is no longer
205  
        buffer extends until it is no longer
207  
        referenced.
206  
        referenced.
208  

207  

209  
        @par Example
208  
        @par Example
210  
        @code
209  
        @code
211  
        encoding_opts opt;
210  
        encoding_opts opt;
212  
        opt.space_as_plus = true;
211  
        opt.space_as_plus = true;
213  
        params_view qp( "name=John+Doe", opt );
212  
        params_view qp( "name=John+Doe", opt );
214  
        @endcode
213  
        @endcode
215  

214  

216  
        @par Effects
215  
        @par Effects
217  
        @code
216  
        @code
218  
        return params_view(parse_query( s ).value(), opt);
217  
        return params_view(parse_query( s ).value(), opt);
219  
        @endcode
218  
        @endcode
220  

219  

221  
        @par Postconditions
220  
        @par Postconditions
222  
        @code
221  
        @code
223  
        this->buffer().data() == s.data()
222  
        this->buffer().data() == s.data()
224  
        @endcode
223  
        @endcode
225  

224  

226  
        @par Complexity
225  
        @par Complexity
227  
        Linear in `s`.
226  
        Linear in `s`.
228  

227  

229  
        @par Exception Safety
228  
        @par Exception Safety
230  
        Exceptions thrown on invalid input.
229  
        Exceptions thrown on invalid input.
231  

230  

232  
        @throw system_error
231  
        @throw system_error
233  
        `s` contains an invalid query parameter
232  
        `s` contains an invalid query parameter
234  
        string.
233  
        string.
235  

234  

236  
        @param s The string to parse.
235  
        @param s The string to parse.
237  

236  

238  
        @param opt The options for decoding. If
237  
        @param opt The options for decoding. If
239  
        this parameter is omitted, `space_as_plus`
238  
        this parameter is omitted, `space_as_plus`
240  
        is used.
239  
        is used.
241  

240  

242  
        @par BNF
241  
        @par BNF
243  
        @code
242  
        @code
244  
        query-params    = [ query-param ] *( "&" query-param )
243  
        query-params    = [ query-param ] *( "&" query-param )
245  

244  

246  
        query-param     = key [ "=" value ]
245  
        query-param     = key [ "=" value ]
247  
        @endcode
246  
        @endcode
248  

247  

249  
        @par Specification
248  
        @par Specification
250  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.4"
249  
        @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.4"
251  
            >3.4.  Query</a>
250  
            >3.4.  Query</a>
252 -
    BOOST_URL_DECL
 
253  
    */
251  
    */
254  
    params_view(
252  
    params_view(
255  
        core::string_view s,
253  
        core::string_view s,
256  
        encoding_opts opt);
254  
        encoding_opts opt);
257  

255  

258  
    /** Assignment
256  
    /** Assignment
259  

257  

260  
        After assignment, both views reference
258  
        After assignment, both views reference
261  
        the same underlying character buffer.
259  
        the same underlying character buffer.
262  

260  

263  
        Ownership is not transferred; the caller
261  
        Ownership is not transferred; the caller
264  
        is responsible for ensuring the lifetime
262  
        is responsible for ensuring the lifetime
265  
        of the buffer extends until it is no
263  
        of the buffer extends until it is no
266  
        longer referenced.
264  
        longer referenced.
267  

265  

268  
        @par Postconditions
266  
        @par Postconditions
269  
        @code
267  
        @code
270  
        this->buffer().data() == other.buffer().data()
268  
        this->buffer().data() == other.buffer().data()
271  
        @endcode
269  
        @endcode
272  

270  

273  
        @par Complexity
271  
        @par Complexity
274  
        Constant
272  
        Constant
275  

273  

276  
        @par Exception Safety
274  
        @par Exception Safety
277  
        Throws nothing
275  
        Throws nothing
278  

276  

279  
        @param other The object to assign
277  
        @param other The object to assign
280  
        @return A reference to this object
278  
        @return A reference to this object
281  
    */
279  
    */
282  
    params_view&
280  
    params_view&
283  
    operator=(
281  
    operator=(
284  
        params_view const& other) = default;
282  
        params_view const& other) = default;
285  
};
283  
};
286  

284  

287  
} // urls
285  
} // urls
288  
} // boost
286  
} // boost
289  

287  

290  
//------------------------------------------------
288  
//------------------------------------------------
291  
//
289  
//
292  
// std::ranges::enable_borrowed_range
290  
// std::ranges::enable_borrowed_range
293  
//
291  
//
294  
//------------------------------------------------
292  
//------------------------------------------------
295  

293  

296  
#ifdef BOOST_URL_HAS_CONCEPTS
294  
#ifdef BOOST_URL_HAS_CONCEPTS
297  
#include <ranges>
295  
#include <ranges>
298  
namespace std::ranges {
296  
namespace std::ranges {
299  
    template<>
297  
    template<>
300  
    inline constexpr bool
298  
    inline constexpr bool
301  
        enable_borrowed_range<
299  
        enable_borrowed_range<
302  
            boost::urls::params_view> = true;
300  
            boost::urls::params_view> = true;
303  
} // std::ranges
301  
} // std::ranges
304  
#endif
302  
#endif
305  

303  

306  
#endif
304  
#endif