mirror of
https://github.com/boostorg/url.git
synced 2026-02-21 15:32:13 +00:00
add string_token
This commit is contained in:
@@ -73,6 +73,16 @@
|
||||
# define BOOST_URL_POS BOOST_CURRENT_LOCATION
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_URL_STRTOK_TPARAM
|
||||
#define BOOST_URL_STRTOK_TPARAM(T) class T = string_token::return_string
|
||||
#endif
|
||||
#ifndef BOOST_URL_STRTOK_RETURN
|
||||
#define BOOST_URL_STRTOK_RETURN(T) typename T::result_type
|
||||
#endif
|
||||
#ifndef BOOST_URL_STRTOK_ARG
|
||||
#define BOOST_URL_STRTOK_ARG(T, name) T&& name = {}
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_URL_STACK_BYTES
|
||||
#define BOOST_URL_STACK_BYTES 4096
|
||||
#endif
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <boost/url/grammar/parse.hpp>
|
||||
#include <boost/url/grammar/range_rule.hpp>
|
||||
#include <boost/url/grammar/recycled.hpp>
|
||||
#include <boost/url/grammar/string_token.hpp>
|
||||
#include <boost/url/grammar/token_rule.hpp>
|
||||
#include <boost/url/grammar/tuple_rule.hpp>
|
||||
#include <boost/url/grammar/type_traits.hpp>
|
||||
|
||||
@@ -38,6 +38,18 @@ namespace grammar {
|
||||
the lifetime of the buffer extends until
|
||||
it is no longer referenced by the range.
|
||||
|
||||
@note
|
||||
|
||||
The implementation may use temporary,
|
||||
recycled storage for type-erasure. Objects
|
||||
of type `range` are intended to be used
|
||||
ephemerally. That is, for short durations
|
||||
such as within a function scope. If it is
|
||||
necessary to store the range for a long
|
||||
period of time or with static storage
|
||||
duration, it is necessary to copy the
|
||||
contents to an object of a different type.
|
||||
|
||||
@tparam T The value type of the range
|
||||
|
||||
@see
|
||||
|
||||
348
include/boost/url/grammar/string_token.hpp
Normal file
348
include/boost/url/grammar/string_token.hpp
Normal file
@@ -0,0 +1,348 @@
|
||||
//
|
||||
// Copyright (c) 2021 Vinnie Falco (vinnie dot falco at gmail dot 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/CPPAlliance/url
|
||||
//
|
||||
|
||||
#ifndef BOOST_URL_GRAMMAR_STRING_TOKEN_HPP
|
||||
#define BOOST_URL_GRAMMAR_STRING_TOKEN_HPP
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/string_view.hpp>
|
||||
#include <boost/url/detail/except.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
|
||||
namespace grammar {
|
||||
namespace string_token {
|
||||
|
||||
/** Base class for string tokens, and algorithm parameters
|
||||
|
||||
This abstract interface provides a means
|
||||
for an algorithm to generically obtain a
|
||||
modifiable, contiguous character buffer
|
||||
of prescribed size. As the author of an
|
||||
algorithm simply declare an rvalue
|
||||
reference as a parameter type.
|
||||
|
||||
<br>
|
||||
|
||||
Instances of this type are intended only
|
||||
to be used once and then destroyed.
|
||||
|
||||
@par Example
|
||||
The declared function will accept any
|
||||
temporary instance of `arg` to be
|
||||
used for writing:
|
||||
@code
|
||||
void algorithm( string_token::arg&& dest );
|
||||
@endcode
|
||||
|
||||
To implement the interface for your type
|
||||
or use-case, derive from the class and
|
||||
implement the prepare function.
|
||||
*/
|
||||
struct arg
|
||||
{
|
||||
/** Return a modifiable character buffer
|
||||
|
||||
This function attempts to obtain a
|
||||
character buffer with space for at
|
||||
least `n` characters. Upon success,
|
||||
a pointer to the beginning of the
|
||||
buffer is returned. Ownership is not
|
||||
transferred; the caller should not
|
||||
attempt to free the storage. The
|
||||
buffer shall remain valid until
|
||||
`this` is destroyed.
|
||||
|
||||
@note
|
||||
This function may only be called once.
|
||||
After invoking the function, the only
|
||||
valid operation is destruction.
|
||||
*/
|
||||
virtual char* prepare(std::size_t n) = 0;
|
||||
|
||||
// prevent misuse
|
||||
arg() = default;
|
||||
arg(arg&&) = default;
|
||||
arg(arg const&) = delete;
|
||||
arg& operator=(arg&&) = delete;
|
||||
arg& operator=(arg const&) = delete;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** Metafunction returning true if T is a StringToken
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
template<class T>
|
||||
using is_token = __see_below__;
|
||||
#else
|
||||
template<class T, class = void>
|
||||
struct is_token : std::false_type {};
|
||||
|
||||
template<class T>
|
||||
struct is_token<T, boost::void_t<
|
||||
decltype(std::declval<T&>().prepare(
|
||||
std::declval<std::size_t>())),
|
||||
decltype(std::declval<T&>().result())
|
||||
> > : std::integral_constant<bool,
|
||||
std::is_convertible<decltype(
|
||||
std::declval<T&>().result()),
|
||||
typename T::result_type>::value &&
|
||||
std::is_same<decltype(
|
||||
std::declval<T&>().prepare(0)),
|
||||
char*>::value &&
|
||||
std::is_base_of<arg, T>::value &&
|
||||
std::is_convertible<T const volatile*,
|
||||
arg const volatile*>::value
|
||||
>
|
||||
{
|
||||
};
|
||||
#endif
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** A token for returning a plain string
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
using return_string = __implementation_defined__;
|
||||
#else
|
||||
struct return_string
|
||||
: arg
|
||||
{
|
||||
using result_type = std::string;
|
||||
|
||||
char*
|
||||
prepare(std::size_t n) override
|
||||
{
|
||||
s_.resize(n);
|
||||
return &s_[0];
|
||||
}
|
||||
|
||||
result_type
|
||||
result() noexcept
|
||||
{
|
||||
return std::move(s_);
|
||||
}
|
||||
|
||||
private:
|
||||
result_type s_;
|
||||
};
|
||||
#endif
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** A token for appending to a plain string
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
template<
|
||||
class Allocator =
|
||||
std::allocator<char>>
|
||||
__implementation_defined__
|
||||
append_to(
|
||||
std::basic_string<
|
||||
char,
|
||||
std::char_traits<char>,
|
||||
Allocator>& s);
|
||||
#else
|
||||
template<class Alloc>
|
||||
struct append_to_t
|
||||
: arg
|
||||
{
|
||||
using string_type = std::basic_string<
|
||||
char, std::char_traits<char>,
|
||||
Alloc>;
|
||||
|
||||
using result_type = string_type&;
|
||||
|
||||
explicit
|
||||
append_to_t(
|
||||
string_type& s) noexcept
|
||||
: s_(s)
|
||||
{
|
||||
}
|
||||
|
||||
char*
|
||||
prepare(std::size_t n) override
|
||||
{
|
||||
std::size_t n0 = s_.size();
|
||||
if(n > s_.max_size() - n0)
|
||||
urls::detail::throw_bad_alloc();
|
||||
s_.resize(n0 + n);
|
||||
return &s_[n0];
|
||||
}
|
||||
|
||||
result_type
|
||||
result() noexcept
|
||||
{
|
||||
return s_;
|
||||
}
|
||||
|
||||
private:
|
||||
string_type& s_;
|
||||
};
|
||||
|
||||
template<
|
||||
class Alloc =
|
||||
std::allocator<char>>
|
||||
append_to_t<Alloc>
|
||||
append_to(
|
||||
std::basic_string<
|
||||
char,
|
||||
std::char_traits<char>,
|
||||
Alloc>& s)
|
||||
{
|
||||
return append_to_t<Alloc>(s);
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** A token for assigning to a plain string
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
template<
|
||||
class Allocator =
|
||||
std::allocator<char>>
|
||||
__implementation_defined__
|
||||
assign(
|
||||
std::basic_string<
|
||||
char,
|
||||
std::char_traits<char>,
|
||||
Allocator>& s);
|
||||
#else
|
||||
template<class Alloc>
|
||||
struct assign_to_t
|
||||
: arg
|
||||
{
|
||||
using string_type = std::basic_string<
|
||||
char, std::char_traits<char>,
|
||||
Alloc>;
|
||||
|
||||
using result_type = string_type&;
|
||||
|
||||
explicit
|
||||
assign_to_t(
|
||||
string_type& s) noexcept
|
||||
: s_(s)
|
||||
{
|
||||
}
|
||||
|
||||
char*
|
||||
prepare(std::size_t n) override
|
||||
{
|
||||
s_.resize(n);
|
||||
return &s_[0];
|
||||
}
|
||||
|
||||
result_type
|
||||
result() noexcept
|
||||
{
|
||||
return s_;
|
||||
}
|
||||
|
||||
private:
|
||||
string_type& s_;
|
||||
};
|
||||
|
||||
template<
|
||||
class Alloc =
|
||||
std::allocator<char>>
|
||||
assign_to_t<Alloc>
|
||||
assign_to(
|
||||
std::basic_string<
|
||||
char,
|
||||
std::char_traits<char>,
|
||||
Alloc>& s)
|
||||
{
|
||||
return assign_to_t<Alloc>(s);
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
/** A token for producing a durable string_view from a temporary string
|
||||
*/
|
||||
#ifdef BOOST_URL_DOCS
|
||||
template<
|
||||
class Allocator =
|
||||
std::allocator<char>>
|
||||
__implementation_defined__
|
||||
preserve_size(
|
||||
std::basic_string<
|
||||
char,
|
||||
std::char_traits<char>,
|
||||
Allocator>& s);
|
||||
#else
|
||||
template<class Alloc>
|
||||
struct preserve_size_t
|
||||
: arg
|
||||
{
|
||||
using result_type = string_view;
|
||||
|
||||
using string_type = std::basic_string<
|
||||
char, std::char_traits<char>,
|
||||
Alloc>;
|
||||
|
||||
explicit
|
||||
preserve_size_t(
|
||||
string_type& s) noexcept
|
||||
: s_(s)
|
||||
{
|
||||
}
|
||||
|
||||
char*
|
||||
prepare(std::size_t n) override
|
||||
{
|
||||
n_ = n;
|
||||
// preserve size() to
|
||||
// avoid value-init
|
||||
if(s_.size() < n)
|
||||
s_.resize(n);
|
||||
return &s_[0];
|
||||
}
|
||||
|
||||
result_type
|
||||
result() noexcept
|
||||
{
|
||||
return string_view(
|
||||
s_.data(), n_);
|
||||
}
|
||||
|
||||
private:
|
||||
string_type& s_;
|
||||
std::size_t n_ = 0;
|
||||
};
|
||||
|
||||
template<
|
||||
class Alloc =
|
||||
std::allocator<char>>
|
||||
preserve_size_t<Alloc>
|
||||
preserve_size(
|
||||
std::basic_string<
|
||||
char,
|
||||
std::char_traits<char>,
|
||||
Alloc>& s)
|
||||
{
|
||||
return preserve_size_t<Alloc>(s);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // string_token
|
||||
} // grammar
|
||||
|
||||
namespace string_token = grammar::string_token;
|
||||
|
||||
} // urls
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user