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 BOOST_SYMBOL_VISIBLE params_view
43  
class BOOST_SYMBOL_VISIBLE 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  
    */
185  
    */
186  
    params_view(
186  
    params_view(
187  
        core::string_view s);
187  
        core::string_view s);
188  

188  

189  
    /** Constructor
189  
    /** Constructor
190  

190  

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

194  

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

198  

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

207  

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

214  

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

219  

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

224  

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

227  

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

230  

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

234  

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

236  

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

240  

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

244  

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

247  

248  
        @par Specification
248  
        @par Specification
249  
        @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"
250  
            >3.4.  Query</a>
250  
            >3.4.  Query</a>
251  
    */
251  
    */
252  
    params_view(
252  
    params_view(
253  
        core::string_view s,
253  
        core::string_view s,
254  
        encoding_opts opt);
254  
        encoding_opts opt);
255  

255  

256  
    /** Assignment
256  
    /** Assignment
257  

257  

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

260  

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

265  

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

270  

271  
        @par Complexity
271  
        @par Complexity
272  
        Constant
272  
        Constant
273  

273  

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

276  

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

284  

285  
} // urls
285  
} // urls
286  
} // boost
286  
} // boost
287  

287  

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

293  

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

303  

304  
#endif
304  
#endif