-
Notifications
You must be signed in to change notification settings - Fork 50
/
pct_string_view.hpp
481 lines (386 loc) · 10.9 KB
/
pct_string_view.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
//
// Copyright (c) 2022 Vinnie Falco (vinnie.falco@gmail.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/boostorg/url
//
#ifndef BOOST_URL_PCT_STRING_VIEW_HPP
#define BOOST_URL_PCT_STRING_VIEW_HPP
#include <boost/url/detail/config.hpp>
#include <boost/url/encoding_opts.hpp>
#include <boost/url/error_types.hpp>
#include <boost/core/detail/string_view.hpp>
#include <boost/url/grammar/string_token.hpp>
#include <boost/url/grammar/string_view_base.hpp>
#include <cstddef>
#include <iterator>
#include <string>
#include <type_traits>
#include <utility>
namespace boost {
namespace urls {
//------------------------------------------------
#ifndef BOOST_URL_DOCS
class decode_view;
class pct_string_view;
pct_string_view
make_pct_string_view_unsafe(
char const*, std::size_t,
std::size_t) noexcept;
namespace detail {
core::string_view&
ref(pct_string_view& s) noexcept;
} // detail
#endif
//------------------------------------------------
/** A reference to a valid percent-encoded string
Objects of this type behave like a
`core::string_view` and have the same interface,
but offer an additional invariant: they can
only be constructed from strings containing
valid percent-escapes.
Attempting construction from a string
containing invalid or malformed percent
escapes results in an exception.
@par Operators
The following operators are supported between
@ref pct_string_view and any object that is
convertible to `core::string_view`
@code
bool operator==( pct_string_view, pct_string_view ) noexcept;
bool operator!=( pct_string_view, pct_string_view ) noexcept;
bool operator<=( pct_string_view, pct_string_view ) noexcept;
bool operator< ( pct_string_view, pct_string_view ) noexcept;
bool operator> ( pct_string_view, pct_string_view ) noexcept;
bool operator>=( pct_string_view, pct_string_view ) noexcept;
@endcode
*/
class pct_string_view final
: public grammar::string_view_base
{
std::size_t dn_ = 0;
#ifndef BOOST_URL_DOCS
friend
pct_string_view
make_pct_string_view_unsafe(
char const*, std::size_t,
std::size_t) noexcept;
friend
core::string_view&
detail::ref(pct_string_view&) noexcept;
#endif
// unsafe
pct_string_view(
char const* data,
std::size_t size,
std::size_t dn) noexcept
: string_view_base(data, size)
, dn_(dn)
{
}
BOOST_URL_DECL
void
decode_impl(
string_token::arg& dest,
encoding_opts opt) const;
public:
/** Constructor
Default constructed string are empty.
@par Complexity
Constant.
@par Exception Safety
Throws nothing.
*/
constexpr pct_string_view() = default;
/** Constructor
The copy references the same
underlying character buffer.
Ownership is not transferred.
@par Postconditions
@code
this->data() == other.data()
@endcode
@par Complexity
Constant.
@par Exception Safety
Throws nothing.
@par other The string to copy.
*/
constexpr
pct_string_view(
pct_string_view const& other) = default;
/** Constructor
The newly constructed string references
the specified character buffer.
Ownership is not transferred.
@par Postconditions
@code
this->data() == core::string_view(s).data()
@endcode
@par Complexity
Linear in `core::string_view(s).size()`.
@par Exception Safety
Exceptions thrown on invalid input.
@throw system_error
The string contains an invalid percent encoding.
@tparam String A type convertible to `core::string_view`
@param s The string to construct from.
*/
template<
class String
#ifndef BOOST_URL_DOCS
, class = typename std::enable_if<
std::is_convertible<
String,
core::string_view
>::value>::type
#endif
>
pct_string_view(
String const& s)
: pct_string_view(
detail::to_sv(s))
{
}
/** Constructor (deleted)
*/
pct_string_view(
std::nullptr_t) = delete;
/** Constructor
The newly constructed string references
the specified character buffer. Ownership
is not transferred.
@par Postconditions
@code
this->data() == s && this->size() == len
@endcode
@par Complexity
Linear in `len`.
@par Exception Safety
Exceptions thrown on invalid input.
@throw system_error
The string contains an invalid percent encoding.
@param s, len The string to construct from.
*/
pct_string_view(
char const* s,
std::size_t len)
: pct_string_view(
core::string_view(s, len))
{
}
/** Constructor
The newly constructed string references
the specified character buffer. Ownership
is not transferred.
@par Postconditions
@code
this->data() == s.data() && this->size() == s.size()
@endcode
@par Complexity
Linear in `s.size()`.
@par Exception Safety
Exceptions thrown on invalid input.
@throw system_error
The string contains an invalid percent encoding.
@param s The string to construct from.
*/
BOOST_URL_DECL
pct_string_view(
core::string_view s);
/** Assignment
The copy references the same
underlying character buffer.
Ownership is not transferred.
@par Postconditions
@code
this->data() == other.data()
@endcode
@par Complexity
Constant.
@par Exception Safety
Throws nothing.
@par other The string to copy.
*/
pct_string_view& operator=(
pct_string_view const& other) = default;
/** Return a valid percent-encoded string
If `s` is a valid percent-encoded string,
the function returns the buffer as a valid
view which may be used to perform decoding
or measurements.
Otherwise the result contains an error code.
Upon success, the returned view references
the original character buffer;
Ownership is not transferred.
@par Complexity
Linear in `s.size()`.
@par Exception Safety
Throws nothing.
@param s The string to validate.
*/
friend
BOOST_URL_DECL
system::result<pct_string_view>
make_pct_string_view(
core::string_view s) noexcept;
//--------------------------------------------
/** Return the decoded size
This function returns the number of
characters in the resulting string if
percent escapes were converted into
ordinary characters.
@par Complexity
Constant.
@par Exception Safety
Throws nothing.
*/
std::size_t
decoded_size() const noexcept
{
return dn_;
}
/** Return the string as a range of decoded characters
@par Complexity
Constant.
@par Exception Safety
Throws nothing.
@see
@ref decode_view.
*/
decode_view
operator*() const noexcept;
/** Return the string with percent-decoding
This function converts percent escapes
in the string into ordinary characters
and returns the result.
When called with no arguments, the
return type is `std::string`.
Otherwise, the return type and style
of output is determined by which string
token is passed.
@par Example
@code
assert( pct_string_view( "Program%20Files" ).decode() == "Program Files" );
@endcode
@par Complexity
Linear in `this->size()`.
@par Exception Safety
Calls to allocate may throw.
String tokens may throw exceptions.
@param opt The options for encoding. If
this parameter is omitted, the default
options are used.
@param token An optional string token.
If this parameter is omitted, then
a new `std::string` is returned.
Otherwise, the function return type
is the result type of the token.
@see
@ref encoding_opts,
@ref string_token::return_string.
*/
template<BOOST_URL_STRTOK_TPARAM>
BOOST_URL_STRTOK_RETURN
decode(
encoding_opts opt = {},
BOOST_URL_STRTOK_ARG(token)) const
{
/* If you get a compile error here, it
means that the token you passed does
not meet the requirements stated
in the documentation.
*/
static_assert(
string_token::is_token<
StringToken>::value,
"Type requirements not met");
decode_impl(token, opt);
return token.result();
}
#ifndef BOOST_URL_DOCS
/// Arrow support
pct_string_view const*
operator->() const noexcept
{
return this;
}
#endif
//--------------------------------------------
// VFALCO No idea why this fails in msvc
/** Swap
*/
/*BOOST_CXX14_CONSTEXPR*/ void swap(
pct_string_view& s ) noexcept
{
string_view_base::swap(s);
std::swap(dn_, s.dn_);
}
};
//------------------------------------------------
#ifndef BOOST_URL_DOCS
namespace detail {
// obtain modifiable reference to
// underlying string, to handle
// self-intersection on modifiers.
inline
core::string_view&
ref(pct_string_view& s) noexcept
{
return s.s_;
}
} // detail
#endif
//------------------------------------------------
/** Return a valid percent-encoded string
If `s` is a valid percent-encoded string,
the function returns the buffer as a valid
view which may be used to perform decoding
or measurements.
Otherwise the result contains an error code.
Upon success, the returned view references
the original character buffer;
Ownership is not transferred.
@par Complexity
Linear in `s.size()`.
@par Exception Safety
Throws nothing.
@param s The string to validate.
*/
BOOST_URL_DECL
system::result<pct_string_view>
make_pct_string_view(
core::string_view s) noexcept;
#ifndef BOOST_URL_DOCS
// VFALCO semi-private for now
inline
pct_string_view
make_pct_string_view_unsafe(
char const* data,
std::size_t size,
std::size_t decoded_size) noexcept
{
#if 0
BOOST_ASSERT(! make_pct_string_view(
core::string_view(data, size)).has_error());
#endif
return pct_string_view(
data, size, decoded_size);
}
#endif
#ifndef BOOST_URL_DOCS
namespace detail {
template <>
inline
core::string_view
to_sv(pct_string_view const& s) noexcept
{
return s.substr();
}
} // detail
#endif
} // urls
} // boost
#endif