• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

boostorg / url / #418

06 Mar 2025 04:05PM UTC coverage: 99.206%. Remained the same
#418

push

travis-ci

alandefreitas
ci: always enable b2 warnings as errors

8369 of 8436 relevant lines covered (99.21%)

3173.06 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.67
include/boost/url/grammar/string_token.hpp
1
//
2
// Copyright (c) 2021 Vinnie Falco (vinnie dot falco at gmail dot com)
3
//
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)
6
//
7
// Official repository: https://github.com/boostorg/url
8
//
9

10
#ifndef BOOST_URL_GRAMMAR_STRING_TOKEN_HPP
11
#define BOOST_URL_GRAMMAR_STRING_TOKEN_HPP
12

13
#include <boost/url/detail/config.hpp>
14
#include <boost/core/detail/string_view.hpp>
15
#include <boost/url/detail/except.hpp>
16
#include <memory>
17
#include <string>
18

19
namespace boost {
20
namespace urls {
21
namespace string_token {
22

23
/** Base class for string tokens, and algorithm parameters
24

25
    This abstract interface provides a means
26
    for an algorithm to generically obtain a
27
    modifiable, contiguous character buffer
28
    of prescribed size.
29

30
    A @ref StringToken should be derived
31
    from this class. As the author of an
32
    algorithm using a @ref StringToken,
33
    simply declare an rvalue reference
34
    as a parameter type.
35

36
    Instances of this type are intended only
37
    to be used once and then destroyed.
38

39
    @par Example
40
    The declared function accepts any
41
    temporary instance of `arg` to be
42
    used for writing:
43
    @code
44
    void algorithm( string_token::arg&& dest );
45
    @endcode
46

47
    To implement the interface for your type
48
    or use-case, derive from the class and
49
    implement the prepare function.
50
*/
51
struct arg
52
{
53
    /** Return a modifiable character buffer
54

55
        This function attempts to obtain a
56
        character buffer with space for at
57
        least `n` characters. Upon success,
58
        a pointer to the beginning of the
59
        buffer is returned. Ownership is not
60
        transferred; the caller should not
61
        attempt to free the storage. The
62
        buffer shall remain valid until
63
        `this` is destroyed.
64

65
        @note
66
        This function may only be called once.
67
        After invoking the function, the only
68
        valid operation is destruction.
69

70
        @param n The number of characters needed
71
        @return A pointer to the buffer
72
    */
73
    virtual char* prepare(std::size_t n) = 0;
74

75
    /// Virtual destructor
76
    virtual ~arg() = default;
6,800✔
77

78
    /// Default constructor
79
    arg() = default;
6,800✔
80

81
    /// Default move constructor
82
    arg(arg&&) = default;
83

84
    /// Deleted copy constructor
85
    arg(arg const&) = delete;
86

87
    /// Deleted move assignment
88
    arg& operator=(arg&&) = delete;
89

90
    /// Deleted copy assignment
91
    arg& operator=(arg const&) = delete;
92
};
93

94
//------------------------------------------------
95

96
namespace implementation_defined {
97
template<class T, class = void>
98
struct is_token : std::false_type {};
99

100
template<class T>
101
struct is_token<T, void_t<
102
    decltype(std::declval<T&>().prepare(
103
        std::declval<std::size_t>())),
104
    decltype(std::declval<T&>().result())
105
    > > : std::integral_constant<bool,
106
        std::is_convertible<decltype(
107
            std::declval<T&>().result()),
108
            typename T::result_type>::value &&
109
        std::is_same<decltype(
110
            std::declval<T&>().prepare(0)),
111
            char*>::value &&
112
        std::is_base_of<arg, T>::value &&
113
        std::is_convertible<T const volatile*,
114
            arg const volatile*>::value
115
    >
116
{
117
};
118
} // implementation_defined
119

120
/** Trait to determine if a type is a string token
121

122
    This trait returns `true` if `T` is a valid
123
    @ref StringToken type, and `false` otherwise.
124

125
    @par Example
126
    @code
127
    static_assert( string_token::is_token<T>::value );
128
    @endcode
129
 */
130
template<class T>
131
using is_token = implementation_defined::is_token<T>;
132

133
#ifdef BOOST_URL_HAS_CONCEPTS
134
/** Concept for a string token
135

136
    This concept is satisfied if `T` is a
137
    valid string token type.
138

139
    A string token is an rvalue passed to a function template
140
    which customizes the return type of the function and also
141
    controls how a modifiable character buffer is obtained and presented.
142

143
    The string token's lifetime extends only for the duration of the
144
    function call in which it appears as a parameter.
145

146
    A string token cannot be copied, moved, or assigned, and must be
147
    destroyed when the function returns or throws.
148

149
    @par Semantics
150

151
    `T::result_type` determines the return type of functions
152
    that accept a string token.
153

154
    The `prepare()` function overrides the virtual function
155
    in the base class @ref arg. It must return a pointer to
156
    a character buffer of at least size `n`, otherwise
157
    throw an exception. This function is called only
158
    once or not at all.
159

160
    The `result()` function is invoked by the algorithm
161
    to receive the result from the string token.
162
    It is only invoked if `prepare()` returned
163
    successfully and the string token was not destroyed.
164
    It is only called after `prepare()` returns
165
    successfully, and the string token is destroyed
166
    when the algorithm completes or if an exception
167
    is thrown.
168

169
    String tokens cannot be reused.
170

171
    @par Exemplars
172
    String token prototype:
173

174
    @code
175
    struct StringToken : string_token::arg
176
    {
177
        using result_type = std::string;
178

179
        char* prepare( std::size_t n ) override;
180

181
        result_type result();
182
    };
183
    @endcode
184

185
    Algorithm prototype:
186

187
    @code
188
    namespace detail {
189

190
    // Algorithm implementation may be placed
191
    // out of line, and written as an ordinary
192
    // function (no template required).
193
    void algorithm_impl( string_token::arg& token )
194
    {
195
        std::size_t n = 0;
196

197
        // calculate space needed in n
198
        // ...
199

200
        // acquire a destination buffer
201
        char* dest = token.prepare( n );
202

203
        // write the characters to the buffer
204
    }
205
    } // detail
206

207
    // public interface is a function template,
208
    // defaulting to return std::string.
209
    template< class StringToken = string_token::return_string >
210
    auto
211
    algorithm( StringToken&& token = {} ) ->
212
        typename StringToken::result_type
213
    {
214
        // invoke the algorithm with the token
215
        algorithm_impl( token );
216

217
        // return the result from the token
218
        return token.result();
219
    }
220
    @endcode
221

222
    @par Models
223
    The following classes and functions implement and
224
    generate string tokens.
225

226
    @li @ref return_string
227
    @li @ref assign_to
228
    @li @ref preserve_size
229

230
 */
231
template <class T>
232
concept StringToken =
233
    std::derived_from<T, string_token::arg> &&
234
    requires (T t, std::size_t n)
235
{
236
    typename T::result_type;
237
    { t.prepare(n) } -> std::same_as<char*>;
238
    { t.result() } -> std::convertible_to<typename T::result_type>;
239
};
240
#endif
241

242
//------------------------------------------------
243

244
namespace implementation_defined {
245
struct return_string
246
    : arg
247
{
248
    using result_type = std::string;
249

250
    char*
251
    prepare(std::size_t n) override
6,112✔
252
    {
253
        s_.resize(n);
6,112✔
254
        return &s_[0];
6,112✔
255
    }
256

257
    result_type
258
    result() noexcept
6,112✔
259
    {
260
        return std::move(s_);
6,112✔
261
    }
262

263
private:
264
    result_type s_;
265
};
266
} // implementation_defined
267

268
/** A string token for returning a plain string
269

270
    This @ref StringToken is used to customize
271
    a function to return a plain string.
272

273
    This is default token type used by
274
    the methods of @ref url_view_base
275
    that return decoded strings.
276
 */
277
using return_string = implementation_defined::return_string;
278

279
//------------------------------------------------
280

281
namespace implementation_defined {
282
template<class Alloc>
283
struct append_to_t
284
    : arg
285
{
286
    using string_type = std::basic_string<
287
        char, std::char_traits<char>,
288
            Alloc>;
289

290
    using result_type = string_type&;
291

292
    explicit
293
    append_to_t(
6✔
294
        string_type& s) noexcept
295
        : s_(s)
6✔
296
    {
297
    }
6✔
298

299
    char*
300
    prepare(std::size_t n) override
6✔
301
    {
302
        std::size_t n0 = s_.size();
6✔
303
        if(n > s_.max_size() - n0)
6✔
304
            urls::detail::throw_length_error();
×
305
        s_.resize(n0 + n);
6✔
306
        return &s_[n0];
6✔
307
    }
308

309
    result_type
310
    result() noexcept
6✔
311
    {
312
        return s_;
6✔
313
    }
314

315
private:
316
    string_type& s_;
317
};
318
} // implementation_defined
319

320
/** Create a string token for appending to a plain string
321

322
    This function creates a @ref StringToken
323
    which appends to an existing plain string.
324

325
    Functions using this token will append
326
    the result to the existing string and
327
    return a reference to it.
328

329
    @param s The string to append
330
    @return A string token
331
 */
332
template<
333
    class Alloc =
334
        std::allocator<char>>
335
implementation_defined::append_to_t<Alloc>
336
append_to(
6✔
337
    std::basic_string<
338
        char,
339
        std::char_traits<char>,
340
        Alloc>& s)
341
{
342
    return implementation_defined::append_to_t<Alloc>(s);
6✔
343
}
344

345
//------------------------------------------------
346

347
namespace implementation_defined {
348
template<class Alloc>
349
struct assign_to_t
350
    : arg
351
{
352
    using string_type = std::basic_string<
353
        char, std::char_traits<char>,
354
            Alloc>;
355

356
    using result_type = string_type&;
357

358
    explicit
359
    assign_to_t(
674✔
360
        string_type& s) noexcept
361
        : s_(s)
674✔
362
    {
363
    }
674✔
364

365
    char*
366
    prepare(std::size_t n) override
674✔
367
    {
368
        s_.resize(n);
674✔
369
        return &s_[0];
674✔
370
    }
371

372
    result_type
373
    result() noexcept
674✔
374
    {
375
        return s_;
674✔
376
    }
377

378
private:
379
    string_type& s_;
380
};
381
} // implementation_defined
382

383
/** Create a string token for assigning to a plain string
384

385
    This function creates a @ref StringToken
386
    which assigns to an existing plain string.
387

388
    Functions using this token will assign
389
    the result to the existing string and
390
    return a reference to it.
391

392
    @param s The string to assign
393
    @return A string token
394
 */
395
template<
396
    class Alloc =
397
        std::allocator<char>>
398
implementation_defined::assign_to_t<Alloc>
399
assign_to(
674✔
400
    std::basic_string<
401
        char,
402
        std::char_traits<char>,
403
        Alloc>& s)
404
{
405
    return implementation_defined::assign_to_t<Alloc>(s);
674✔
406
}
407

408
//------------------------------------------------
409

410
namespace implementation_defined {
411
template<class Alloc>
412
struct preserve_size_t
413
    : arg
414
{
415
    using result_type = core::string_view;
416

417
    using string_type = std::basic_string<
418
        char, std::char_traits<char>,
419
            Alloc>;
420

421
    explicit
422
    preserve_size_t(
8✔
423
        string_type& s) noexcept
424
        : s_(s)
8✔
425
    {
426
    }
8✔
427

428
    char*
429
    prepare(std::size_t n) override
8✔
430
    {
431
        n_ = n;
8✔
432
        // preserve size() to
433
        // avoid value-init
434
        if(s_.size() < n)
8✔
435
            s_.resize(n);
4✔
436
        return &s_[0];
8✔
437
    }
438

439
    result_type
440
    result() noexcept
8✔
441
    {
442
        return core::string_view(
8✔
443
            s_.data(), n_);
16✔
444
    }
445

446
private:
447
    string_type& s_;
448
    std::size_t n_ = 0;
449
};
450
} // implementation_defined
451

452
/** Create a string token for a durable core::string_view
453

454
    This function creates a @ref StringToken
455
    which assigns to an existing plain string.
456

457
    Functions using this token will assign
458
    the result to the existing string and
459
    return a `core::string_view` to it.
460

461
    @param s The string to preserve
462
    @return A string token
463
 */
464
template<
465
    class Alloc =
466
        std::allocator<char>>
467
implementation_defined::preserve_size_t<Alloc>
468
preserve_size(
8✔
469
    std::basic_string<
470
        char,
471
        std::char_traits<char>,
472
        Alloc>& s)
473
{
474
    return implementation_defined::preserve_size_t<Alloc>(s);
8✔
475
}
476
} // string_token
477

478
namespace grammar {
479
namespace string_token = ::boost::urls::string_token;
480
} // grammar
481

482
} // urls
483
} // boost
484

485
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc