1  
//
1  
//
2  
// Copyright (c) 2021 Vinnie Falco (vinnie dot falco at gmail dot com)
2  
// Copyright (c) 2021 Vinnie Falco (vinnie dot falco at gmail dot 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  
#ifndef BOOST_URL_GRAMMAR_STRING_TOKEN_HPP
10  
#ifndef BOOST_URL_GRAMMAR_STRING_TOKEN_HPP
11  
#define BOOST_URL_GRAMMAR_STRING_TOKEN_HPP
11  
#define BOOST_URL_GRAMMAR_STRING_TOKEN_HPP
12  

12  

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

18  

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

22  

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

24  

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

29  

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

35  

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

38  

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

46  

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

54  

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

64  

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

69  

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

74  

75  
    /// Virtual destructor
75  
    /// Virtual destructor
76  
    virtual ~arg() = default;
76  
    virtual ~arg() = default;
77  

77  

78  
    /// Default constructor
78  
    /// Default constructor
79  
    arg() = default;
79  
    arg() = default;
80  

80  

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

83  

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

86  

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

89  

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

93  

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

95  

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

99  

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

119  

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

121  

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

124  

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

132  

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

135  

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

138  

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

142  

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

145  

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

148  

149  
    @par Semantics
149  
    @par Semantics
150  

150  

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

153  

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

159  

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

168  

169  
    String tokens cannot be reused.
169  
    String tokens cannot be reused.
170  

170  

171  
    @par Exemplars
171  
    @par Exemplars
172  
    String token prototype:
172  
    String token prototype:
173  

173  

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

178  

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

180  

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

184  

185  
    Algorithm prototype:
185  
    Algorithm prototype:
186  

186  

187  
    @code
187  
    @code
188  
    namespace detail {
188  
    namespace detail {
189  

189  

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

196  

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

199  

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

202  

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

206  

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

216  

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

221  

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

225  

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

229  

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

241  

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

243  

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

249  

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

256  

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

262  

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

267  

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

269  

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

272  

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

278  

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

280  

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

289  

290  
    using result_type = string_type&;
290  
    using result_type = string_type&;
291  

291  

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

298  

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

308  

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

314  

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

319  

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

321  

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

324  

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

328  

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

344  

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

346  

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

355  

356  
    using result_type = string_type&;
356  
    using result_type = string_type&;
357  

357  

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

364  

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

371  

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

377  

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

382  

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

384  

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

387  

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

391  

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

407  

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

409  

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

416  

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

420  

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

427  

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

438  

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

445  

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

451  

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

453  

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

456  

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

460  

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

477  

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

481  

482  
} // urls
482  
} // urls
483  
} // boost
483  
} // boost
484  

484  

485  
#endif
485  
#endif