//
// Copyright (c) 2023 Alan de Freitas (alandefreitas@gmail.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/boostorg/url
//

= StringToken

A string token is an rvalue passed to a function template which customizes the return type of the function and also controls how a modifiable character buffer is obtained and presented.
The string token's lifetime extends only for the duration of the function call in which it appears as a parameter.
A string token cannot be copied, moved, or assigned, and must be destroyed when the function returns or throws.

== Requirements

In this table:

* `T` is a type meeting the requirements of __StringToken__
* `t` is an rvalue reference of type T
* `n` is a value of type cpp:std::size_t[]

[cols="1,1,3"]
|===
// Headers
|Expression|Result|Semantics, Pre/Post-conditions

// Row 1, Column 1
|
cpp:std::derived_from<T,string_token::arg>[]

// Row 1, Column 2
|`true`

// Row 1, Column 3
|All string tokens must be publicly and
unambiguously derived from
`string_token::arg`.

// Row 2, Column 1
|`T::result_type`

// Row 2, Column 2
|
// Row 2, Column 3
|This type determines the return type of functions
which accept a string token.

// Row 3, Column 1
|`t.prepare(n);`

// Row 3, Column 2
|`char*`

// Row 3, Column 3
|This function overrides the virtual function in the base.
It must return a pointer to a character buffer of at least
size `n`, otherwise throw an exception.

// Row 4, Column 1
|`t.result();`

// Row 4, Column 3
|`T::result_type`

// Row 4, Column 5
|This function is invoked by the algorithm to receive the result
from the string token.
It is only invoked if `prepare` returned successfuly and the
string token was not destroyed.

|===

== Algorithm Requirements

When an algorithm accepts a string token, it must meet these requirements:

* `prepare` is called only once or not at all,
* `result` is only called after `prepare` returns successfully, and
* The string token is destroyed when the algorithm completes or if an exception is thrown.

String tokens cannot be reused.

== Exemplars

String token prototype:

[source,cpp]
----
struct StringToken : string_token::arg
{
    using result_type = std::string;

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

    result_type result();
};
----

Algorithm prototype:

[source,cpp]
----
namespace detail {

// Algorithm implementation may be placed
// out of line, and written as an ordinary
// function (no template required).

void algorithm_impl( string_token::arg& token )
{
    std::size_t n = 0;

    // calculate space needed in `n`

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

    // write the characters to the buffer
}    

} // detail

// public interface is a function template,
// defaulting to return cpp:std::string[].

template< class StringToken = string_token::return_string >
auto
algorithm( StringToken&& token = {} ) ->
    typename StringToken::result_type
{
    // invoke the algorithm with the token
    algorithm_impl( token );

    // return the result from the token
    return token.result();
}

----

Models

* `string_token::return_string`
* `string_token::assign_to`
* `string_token::preserve_size`
* `string_token::return_string`


