2
0
mirror of https://github.com/boostorg/json.git synced 2026-02-12 00:02:14 +00:00

string work

This commit is contained in:
Vinnie Falco
2019-10-06 12:21:19 -07:00
parent b591a79340
commit a44fc4f453
13 changed files with 2210 additions and 149 deletions

View File

@@ -80,7 +80,7 @@ class array
table* tab_ = nullptr;
storage_ptr sp_;
struct undo;
struct undo_create;
struct undo_insert;
public:

View File

@@ -87,6 +87,26 @@ struct array::table
//------------------------------------------------------------------------------
struct array::undo_create
{
table* tab;
storage_ptr const& sp;
undo_create(
size_type n,
storage_ptr const& sp_)
: tab(table::create(n, sp_))
, sp(sp_)
{
}
~undo_create()
{
if(tab)
table::destroy(tab, sp);
}
};
struct array::undo_insert
{
value* it;
@@ -117,7 +137,8 @@ array(
InputIt first, InputIt last)
: array(
first, last,
default_storage())
default_storage(),
iter_cat<InputIt>{})
{
static_assert(
std::is_constructible<value,
@@ -129,10 +150,10 @@ template<class InputIt, class>
array::
array(
InputIt first, InputIt last,
storage_ptr store)
storage_ptr sp)
: array(
first, last,
std::move(store),
std::move(sp),
iter_cat<InputIt>{})
{
static_assert(
@@ -185,26 +206,31 @@ template<class InputIt>
array::
array(
InputIt first, InputIt last,
storage_ptr store,
storage_ptr sp,
std::input_iterator_tag)
: sp_(std::move(store))
: sp_(std::move(sp))
{
while(first != last)
emplace_impl(end(), *first++);
}
template<class InputIt>
array::
array(
InputIt first, InputIt last,
storage_ptr store,
storage_ptr sp,
std::forward_iterator_tag)
: sp_(std::move(store))
: sp_(std::move(sp))
{
reserve(std::distance(first, last));
undo_create u(
std::distance(first, last), sp_);
while(first != last)
emplace_impl(end(), *first++);
{
::new(u.tab->end()) value(
*first++, sp_);
++u.tab->d.size;
}
std::swap(tab_, u.tab);
}
template<class InputIt>
auto
array::

View File

@@ -89,20 +89,6 @@ relocate(
//------------------------------------------------------------------------------
struct array::undo
{
table* tab;
storage_ptr const& sp;
~undo()
{
if(tab)
table::destroy(tab, sp);
}
};
//------------------------------------------------------------------------------
array::
undo_insert::
undo_insert(
@@ -197,8 +183,7 @@ array(
if(count == 0)
return;
undo u{table::create(
count, sp_), sp_};
undo_create u(count, sp_);
while(count--)
{
::new(u.tab->end()) value(v, sp_);
@@ -825,8 +810,7 @@ copy(array const& other)
return;
}
undo u{table::create(
other.size(), sp_), sp_};
undo_create u(other.size(), sp_);
for(auto const& v : other)
{
::new(u.tab->end()) value(v, sp_);
@@ -873,8 +857,7 @@ assign(
return;
}
undo u{table::create(
init.size(), sp_), sp_};
undo_create u(init.size(), sp_);
for(auto const& v : init)
{
::new(u.tab->end()) value(v, sp_);

View File

@@ -0,0 +1,126 @@
//
// Copyright (c) 2018-2019 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/vinniefalco/json
//
#ifndef BOOST_JSON_IMPL_STRING_HPP
#define BOOST_JSON_IMPL_STRING_HPP
namespace boost {
namespace json {
//------------------------------------------------------------------------------
struct string::impl
{
size_type size;
size_type capacity;
static
impl*
construct(
size_type capacity,
storage_ptr const& sp)
{
auto s = ::new(sp->allocate(
sizeof(impl) + capacity + 1,
sizeof(impl))) impl;
s->capacity = capacity;
return s;
}
static
impl*
construct(
size_type size,
size_type capacity,
storage_ptr const& sp)
{
auto s = construct(capacity, sp);
s->term(size);
return s;
}
static
void
destroy(
impl* s,
storage_ptr const& sp) noexcept
{
sp->deallocate(s,
sizeof(impl) + s->capacity + 1,
sizeof(impl));
}
char*
data() noexcept
{
return reinterpret_cast<
char*>(this+1);
}
char*
end() noexcept
{
return data() + size;
}
void
term() noexcept
{
data()[size] = 0;
}
void
term(size_type n) noexcept
{
size = n;
data()[size] = 0;
}
};
//------------------------------------------------------------------------------
template<class InputIt, class>
string::
string(
InputIt first,
InputIt last,
storage_ptr sp)
: sp_(std::move(sp))
{
assign(first, last);
}
template<class InputIt, class>
string&
string::
assign(
InputIt first,
InputIt last)
{
maybe_raw_resize(
first, last, iter_cat<InputIt>{});
char* p = s_->data();
while(first != last)
*p++ = *first++;
*p = 0;
return *this;
}
template<class InputIt, class>
string&
string::
append(InputIt, InputIt)
{
return *this;
}
} // json
} // boost
#endif

View File

@@ -0,0 +1,749 @@
//
// Copyright (c) 2018-2019 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/vinniefalco/json
//
#ifndef BOOST_JSON_IMPL_STRING_IPP
#define BOOST_JSON_IMPL_STRING_IPP
#include <boost/core/exchange.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/throw_exception.hpp>
#include <algorithm>
#include <new>
#include <stdexcept>
#include <utility>
namespace boost {
namespace json {
string::
~string()
{
if(s_)
impl::destroy(s_, sp_);
}
string::
string() noexcept
: sp_(default_storage())
{
}
string::
string(storage_ptr sp) noexcept
: sp_(std::move(sp))
{
}
string::
string(
size_type count,
char ch,
storage_ptr sp)
: sp_(std::move(sp))
{
assign(count, ch);
}
string::
string(
string const& other,
size_type pos,
size_type count,
storage_ptr sp)
: sp_(std::move(sp))
{
assign(other, pos, count);
}
string::
string(
char const* s,
storage_ptr sp)
: sp_(std::move(sp))
{
assign(s);
}
string::
string(
char const* s,
size_type count,
storage_ptr sp)
: sp_(std::move(sp))
{
assign(s, count);
}
string::
string(string const& other)
: sp_(default_storage())
{
assign(other);
}
string::
string(
string const& other,
storage_ptr sp)
: sp_(std::move(sp))
{
assign(other);
}
string::
string(pilfered<string> p) noexcept
: s_(boost::exchange(
p.get().s_, nullptr))
, sp_(std::move(p.get().sp_))
{
}
string::
string(string&& other) noexcept
: s_(boost::exchange(
other.s_, nullptr))
, sp_(other.sp_)
{
}
string::
string(
string&& other,
storage_ptr sp)
: sp_(std::move(sp))
{
assign(std::move(other));
}
string::
string(
std::initializer_list<char> init,
storage_ptr sp)
: sp_(std::move(sp))
{
assign(init);
}
string::
string(
string_view sv,
storage_ptr sp)
: sp_(std::move(sp))
{
assign(sv);
}
string::
string(
string_view sv,
size_type pos,
size_type n,
storage_ptr sp)
: sp_(std::move(sp))
{
assign(sv.substr(pos, n));
}
//------------------------------------------------------------------------------
string&
string::
operator=(string const& other)
{
assign(other);
return *this;
}
string&
string::
operator=(string&& other)
{
assign(std::move(other));
return *this;
}
string&
string::
operator=(char const* s)
{
assign(s);
return *this;
}
string&
string::
operator=(char ch)
{
raw_resize(1);
traits_type::assign(
s_->data(), 1, ch);
return *this;
}
string&
string::
operator=(
std::initializer_list<char> init)
{
assign(init);
return *this;
}
string&
string::
operator=(string_view sv)
{
assign(sv);
return *this;
}
//------------------------------------------------------------------------------
string&
string::
assign(
size_type count,
char ch)
{
raw_resize(count);
traits_type::assign(
s_->data(), count, ch);
return *this;
}
string&
string::
assign(
string const& other)
{
raw_resize(other.size());
traits_type::copy(data(),
other.data(), other.size());
return *this;
}
string&
string::
assign(
string const& other,
size_type pos,
size_type count)
{
return assign(
other.substr(pos, count));
}
string&
string::
assign(string&& other)
{
if(*sp_ != *other.sp_)
return assign(other);
auto s = s_;
s_ = other.s_;
other.s_ = nullptr;
if(s)
impl::destroy(s, sp_);
return *this;
}
string&
string::
assign(
char const* s,
size_type count)
{
raw_resize(count);
traits_type::copy(
data(), s, count);
return *this;
}
string&
string::
assign(
char const* s)
{
return assign(s,
traits_type::length(s));
}
string&
string::
assign(std::initializer_list<char> init)
{
raw_resize(init.size());
std::copy(
init.begin(),
init.end(),
s_->data());
return *this;
}
string&
string::
assign(string_view sv)
{
return assign(
sv.data(), sv.size());
}
string&
string::
assign(
string_view sv,
size_type pos,
size_type count)
{
return assign(
sv.substr(pos, count));
}
//------------------------------------------------------------------------------
//
// Element Access
//
//------------------------------------------------------------------------------
char&
string::
at(size_type pos)
{
if(pos >= size())
BOOST_THROW_EXCEPTION(
std::out_of_range(
"pos >= size()"));
return s_->data()[pos];
}
char const&
string::
at(size_type pos) const
{
if(pos >= size())
BOOST_THROW_EXCEPTION(
std::out_of_range(
"pos >= size()"));
return s_->data()[pos];
}
char&
string::
operator[](size_type pos)
{
return s_->data()[pos];
}
const char&
string::
operator[](size_type pos) const
{
return s_->data()[pos];
}
char&
string::
front()
{
return s_->data()[0];
}
char const&
string::
front() const
{
return s_->data()[0];
}
char&
string::
back()
{
return s_->data()[s_->size - 1];
}
char const&
string::
back() const
{
return s_->data()[s_->size - 1];
}
char*
string::
data() noexcept
{
if(! s_)
return const_cast<
char*>("");
return s_->data();
}
char const*
string::
data() const noexcept
{
if(! s_)
return "";
return s_->data();
}
char const*
string::
c_str() const noexcept
{
return data();
}
string::
operator string_view() const noexcept
{
return {data(), size()};
}
//------------------------------------------------------------------------------
//
// Iterators
//
//------------------------------------------------------------------------------
auto
string::
begin() noexcept ->
iterator
{
if(! s_)
return nullptr;
return s_->data();
}
auto
string::
begin() const noexcept ->
const_iterator
{
if(! s_)
return nullptr;
return s_->data();
}
auto
string::
end() noexcept ->
iterator
{
if(! s_)
return nullptr;
return s_->end();
}
auto
string::
end() const noexcept ->
const_iterator
{
if(! s_)
return nullptr;
return s_->end();
}
auto
string::
rbegin() noexcept ->
reverse_iterator
{
if(! s_)
return reverse_iterator(nullptr);
return reverse_iterator(s_->end());
}
auto
string::
rbegin() const noexcept ->
const_reverse_iterator
{
if(! s_)
return reverse_iterator(nullptr);
return const_reverse_iterator(s_->end());
}
auto
string::
rend() noexcept ->
reverse_iterator
{
if(! s_)
return reverse_iterator(nullptr);
return reverse_iterator(s_->data());
}
auto
string::
rend() const noexcept ->
const_reverse_iterator
{
if(! s_)
return reverse_iterator(nullptr);
return const_reverse_iterator(s_->data());
}
//------------------------------------------------------------------------------
//
// Capacity
//
//------------------------------------------------------------------------------
bool
string::
empty() const noexcept
{
if(! s_)
return true;
return s_->size == 0;
}
auto
string::
size() const noexcept ->
size_type
{
if(! s_)
return 0;
return s_->size;
}
void
string::
reserve(size_type new_capacity)
{
if(new_capacity <= capacity())
return;
auto s = impl::construct(
size(), new_capacity, sp_);
traits_type::copy(
s->data(), data(), size());
impl::destroy(
boost::exchange(s_, s), sp_);
}
auto
string::
capacity() const noexcept ->
size_type
{
if(! s_)
return 0;
return s_->capacity;
}
//------------------------------------------------------------------------------
//
// Operations
//
//------------------------------------------------------------------------------
void
string::
clear() noexcept
{
if(s_)
s_->term(0);
}
//------------------------------------------------------------------------------
void
string::
push_back(char ch)
{
s_->data()[s_->size++] = ch;
s_->data()[s_->size] = 0;
}
void
string::
pop_back()
{
s_->data()[--s_->size] = 0;
}
//------------------------------------------------------------------------------
string&
string::
append(size_type count, char ch)
{
traits_type::assign(
raw_insert(size(), count),
count, ch);
return *this;
}
string&
string::
append(string const& str)
{
return append(
str.data(), str.size());
}
string&
string::
append(
string const& str,
size_type pos,
size_type count)
{
return append(str.substr(pos, count));
}
string&
string::
append(
char const* s,
size_type count)
{
traits_type::copy(
raw_insert(size(), count),
s, count);
return *this;
}
string&
string::
append(char const* s)
{
return append(s,
traits_type::length(s));
}
string&
string::
append(std::initializer_list<char> init)
{
// TODO
boost::ignore_unused(init);
return *this;
}
string&
string::
append(string_view sv)
{
return append(
sv.data(), sv.size());
}
//------------------------------------------------------------------------------
string_view
string::
substr(
size_type pos ,
size_type count) const
{
if(pos > size())
BOOST_THROW_EXCEPTION(
std::out_of_range("pos > size()"));
if(! s_)
return {};
return {
s_->data() + pos,
std::min<size_type>(
s_->size - pos,
count)};
}
//------------------------------------------------------------------------------
void
string::
raw_resize(size_type n)
{
if(n <= capacity())
{
if(s_)
s_->term(n);
return;
}
auto s = boost::exchange(s_,
impl::construct(n, n, sp_));
if(s)
impl::destroy(s, sp_);
}
// insert `n` uninitialized chars at `pos`,
// reallocating as needed. does nothing if n==0.
// returns the insertion point
char*
string::
raw_insert(
size_type pos,
size_type n)
{
if( n > max_size() ||
size() > max_size() - n)
BOOST_THROW_EXCEPTION(
std::out_of_range(
"size() + n > max_size()"));
if(pos > size())
BOOST_THROW_EXCEPTION(
std::out_of_range(
"pos > size()"));
auto const new_size = size() + n;
if(new_size <= capacity())
{
if(s_)
{
traits_type::move(
s_->data() + pos + n,
s_->data() + pos,
s_->size + 1 - pos);
s_->size = new_size;
}
}
else
{
auto s = impl::construct(
new_size, sp_);
if(s_)
{
traits_type::copy(
s->data(),
s_->data(),
pos);
traits_type::copy(
s->data() + pos + n,
s_->data() + pos,
s_->size + 1 - pos);
s->size = new_size;
impl::destroy(s_, sp_);
}
else
{
s->term(n);
}
s_ = s;
}
return s_->data() + pos;
}
std::ostream&
operator<<(std::ostream& os, string const& s)
{
os.write(s.data(), s.size());
return os;
}
} // json
} // boost
#endif

View File

@@ -143,8 +143,7 @@ value(
case json::kind::string:
::new(&str_) string(
string::allocator_type(
std::move(sp)));
std::move(sp));
break;
case json::kind::number:
@@ -188,10 +187,8 @@ value(
break;
case json::kind::string:
// workaround for some stdlibs
construct_string(
other.str_,
std::move(sp));
::new(&str_) string(
other.str_, std::move(sp));
break;
case json::kind::number:
@@ -318,8 +315,7 @@ value(
break;
case json::kind::string:
// workaround for some stdlibs
construct_string(
::new(&str_) string(
std::move(other.str_),
std::move(sp));
break;
@@ -424,11 +420,11 @@ value::
value(
string str,
storage_ptr sp)
{
// workaround for some stdlibs
construct_string(
: str_(
std::move(str),
std::move(sp));
std::move(sp))
, kind_(json::kind::string)
{
}
value::
@@ -591,7 +587,7 @@ maybe_object(
//
//------------------------------------------------------------------------------
storage_ptr
storage_ptr const&
value::
get_storage() const noexcept
{
@@ -604,7 +600,7 @@ get_storage() const noexcept
return arr_.get_storage();
case json::kind::string:
return str_.get_allocator().get_storage();
return str_.get_storage();
default:
break;
@@ -1004,48 +1000,6 @@ pop_back()
//------------------------------------------------------------------------------
// private
template<class S>
auto
value::
construct_string(
S&& str, storage_ptr sp) ->
typename std::enable_if<
! std::is_constructible<S, string,
typename string::allocator_type
>::value>::type
{
// workaround for missing std::string
// ctors in some stdlib versions
auto s = string(typename
string::allocator_type(
std::move(sp)));
s = std::move(str);
::new(&str_) string(
std::move(s));
kind_ = json::kind::string;
}
template<class S>
auto
value::
construct_string(
S&& str, storage_ptr sp) ->
typename std::enable_if<
std::is_constructible<S, string,
typename string::allocator_type
>::value>::type
{
::new(&str_) string(std::move(str),
typename string::allocator_type(
std::move(sp)));
kind_ = json::kind::string;
}
//------------------------------------------------------------------------------
// friends
std::ostream&

View File

@@ -11,23 +11,685 @@
#define BOOST_JSON_STRING_HPP
#include <boost/json/detail/config.hpp>
#include <boost/json/allocator.hpp>
#include <boost/json/storage.hpp>
#include <boost/pilfer.hpp>
#include <boost/utility/string_view.hpp>
#include <algorithm>
#include <initializer_list>
#include <iosfwd>
#include <iterator>
#include <limits>
#include <string>
#include <type_traits>
namespace boost {
namespace json {
class value;
/** The native type of string values
*/
using string =
std::basic_string<
char,
std::char_traits<char>,
allocator<char>>;
class string
{
struct impl;
impl* s_ = nullptr;
storage_ptr sp_;
public:
using traits_type = std::char_traits<char>;
using value_type = char;
using size_type = unsigned long;
using difference_type = long;
using pointer = char*;
using reference = char&;
using iterator = char*;
using const_pointer = char const*;
using const_reference = const char&;
using const_iterator = char const*;
using reverse_iterator =
std::reverse_iterator<iterator>;
using const_reverse_iterator =
std::reverse_iterator<const_iterator>;
/// A special index
static constexpr size_type npos =
(std::numeric_limits<size_type>::max)();
BOOST_JSON_DECL
~string();
BOOST_JSON_DECL
string() noexcept;
BOOST_JSON_DECL
explicit
string(storage_ptr sp) noexcept;
BOOST_JSON_DECL
string(
size_type count,
char ch,
storage_ptr sp =
default_storage());
BOOST_JSON_DECL
string(
string const& other,
size_type pos,
size_type count = npos,
storage_ptr sp =
default_storage());
BOOST_JSON_DECL
string(
char const* s,
storage_ptr sp =
default_storage());
BOOST_JSON_DECL
string(
char const* s,
size_type count,
storage_ptr sp =
default_storage());
template<class InputIt
#ifndef GENERATING_DOCUMENTATION
,class = typename std::enable_if<
std::is_convertible<
typename std::iterator_traits<
InputIt>::value_type,
char>::value>::type
#endif
>
string(
InputIt first,
InputIt last,
storage_ptr sp =
default_storage());
BOOST_JSON_DECL
string(string const& other);
BOOST_JSON_DECL
string(
string const& other,
storage_ptr sp);
BOOST_JSON_DECL
string(pilfered<string> other) noexcept;
BOOST_JSON_DECL
string(string&& other) noexcept;
BOOST_JSON_DECL
string(
string&& other,
storage_ptr sp);
BOOST_JSON_DECL
string(
std::initializer_list<char> init,
storage_ptr sp = default_storage());
BOOST_JSON_DECL
string(
string_view sv,
storage_ptr sp =
default_storage());
BOOST_JSON_DECL
string(
string_view sv,
size_type pos,
size_type n,
storage_ptr sp =
default_storage());
//--------------------------------------------------------------------------
BOOST_JSON_DECL
string&
operator=(string const& other);
BOOST_JSON_DECL
string&
operator=(string&& other);
BOOST_JSON_DECL
string&
operator=(char const* s);
BOOST_JSON_DECL
string&
operator=(char ch);
BOOST_JSON_DECL
string&
operator=(std::initializer_list<char> init);
BOOST_JSON_DECL
string&
operator=(string_view sv);
//--------------------------------------------------------------------------
BOOST_JSON_DECL
string&
assign(
size_type count,
char ch);
BOOST_JSON_DECL
string&
assign(
string const& other);
BOOST_JSON_DECL
string&
assign(
string const& other,
size_type pos,
size_type count);
BOOST_JSON_DECL
string&
assign(string&& other);
BOOST_JSON_DECL
string&
assign(
char const* s,
size_type count);
BOOST_JSON_DECL
string&
assign(
char const* s);
template<class InputIt
#ifndef GENERATING_DOCUMENTATION
,class = typename std::enable_if<
std::is_convertible<
typename std::iterator_traits<
InputIt>::value_type,
char>::value>::type
#endif
>
string&
assign(
InputIt first,
InputIt last);
BOOST_JSON_DECL
string&
assign(std::initializer_list<char> init);
BOOST_JSON_DECL
string&
assign(string_view sv);
BOOST_JSON_DECL
string&
assign(
string_view sv,
size_type pos,
size_type count = npos);
//--------------------------------------------------------------------------
storage_ptr const&
get_storage() const noexcept
{
return sp_;
}
//--------------------------------------------------------------------------
//
// Element Access
//
//--------------------------------------------------------------------------
BOOST_JSON_DECL
char&
at(size_type pos);
BOOST_JSON_DECL
char const&
at(size_type pos) const;
BOOST_JSON_DECL
char&
operator[](size_type pos);
BOOST_JSON_DECL
const char&
operator[](size_type pos) const;
BOOST_JSON_DECL
char&
front();
BOOST_JSON_DECL
char const&
front() const;
BOOST_JSON_DECL
char&
back();
BOOST_JSON_DECL
char const&
back() const;
BOOST_JSON_DECL
char*
data() noexcept;
BOOST_JSON_DECL
char const*
data() const noexcept;
BOOST_JSON_DECL
char const*
c_str() const noexcept;
BOOST_JSON_DECL
operator string_view() const noexcept;
//--------------------------------------------------------------------------
//
// Iterators
//
//--------------------------------------------------------------------------
/** Return an iterator to the first character
If the container is empty, the returned iterator
will be equal to @ref end().
@par Complexity
Constant.
*/
BOOST_JSON_DECL
iterator
begin() noexcept;
/** Return an iterator to the first character
If the container is empty, the returned iterator
will be equal to @ref end().
@par Complexity
Constant.
*/
BOOST_JSON_DECL
const_iterator
begin() const noexcept;
/** Return an iterator to the first character
If the container is empty, the returned iterator
will be equal to @ref end().
@par Complexity
Constant.
*/
BOOST_JSON_DECL
const_iterator
cbegin() const noexcept
{
return begin();
}
/** Return an iterator to the character following the last character
The character acts as a placeholder; attempting to
access it results in undefined behavior.
@par Complexity
Constant.
*/
BOOST_JSON_DECL
iterator
end() noexcept;
/** Return an iterator to the character following the last character
The character acts as a placeholder; attempting to
access it results in undefined behavior.
@par Complexity
Constant.
*/
BOOST_JSON_DECL
const_iterator
end() const noexcept;
/** Return an iterator to the character following the last character
The character acts as a placeholder; attempting to
access it results in undefined behavior.
@par Complexity
Constant.
*/
BOOST_JSON_DECL
const_iterator
cend() const noexcept
{
return end();
}
/** Return a reverse iterator to the first character of the reversed container
The pointed-to character corresponds to the last character
of the non-reversed container. If the container is empty,
the returned iterator is equal to @ref rend()
@par Complexity
Constant.
*/
BOOST_JSON_DECL
reverse_iterator
rbegin() noexcept;
/** Return a reverse iterator to the first character of the reversed container
The pointed-to character corresponds to the last character
of the non-reversed container. If the container is empty,
the returned iterator is equal to @ref rend()
@par Complexity
Constant.
*/
BOOST_JSON_DECL
const_reverse_iterator
rbegin() const noexcept;
/** Return a reverse iterator to the first character of the reversed container
The pointed-to character corresponds to the last character
of the non-reversed container. If the container is empty,
the returned iterator is equal to @ref rend()
@par Complexity
Constant.
*/
BOOST_JSON_DECL
const_reverse_iterator
crbegin() const noexcept
{
return rbegin();
}
/** Return a reverse iterator to the character following the last character of the reversed container
The pointed-to character corresponds to the character
preceding the first character of the non-reversed container.
This character acts as a placeholder, attempting to access
it results in undefined behavior.
@par Complexity
Constant.
*/
BOOST_JSON_DECL
reverse_iterator
rend() noexcept;
/** Return a reverse iterator to the character following the last character of the reversed container
The pointed-to character corresponds to the character
preceding the first character of the non-reversed container.
This character acts as a placeholder, attempting to access
it results in undefined behavior.
@par Complexity
Constant.
*/
BOOST_JSON_DECL
const_reverse_iterator
rend() const noexcept;
/** Return a reverse iterator to the character following the last character of the reversed container
The pointed-to character corresponds to the character
preceding the first character of the non-reversed container.
This character acts as a placeholder, attempting to access
it results in undefined behavior.
@par Complexity
Constant.
*/
BOOST_JSON_DECL
const_reverse_iterator
crend() const noexcept
{
return rend();
}
//--------------------------------------------------------------------------
//
// Capacity
//
//--------------------------------------------------------------------------
BOOST_JSON_DECL
bool
empty() const noexcept;
BOOST_JSON_DECL
size_type
size() const noexcept;
size_type
length() const noexcept
{
return size();
}
size_type
max_size() const noexcept
{
return npos - 1;
}
BOOST_JSON_DECL
void
reserve(size_type new_capacity);
BOOST_JSON_DECL
size_type
capacity() const noexcept;
//--------------------------------------------------------------------------
//
// Operations
//
//--------------------------------------------------------------------------
BOOST_JSON_DECL
void
clear() noexcept;
//--------------------------------------------------------------------------
// insert
//--------------------------------------------------------------------------
BOOST_JSON_DECL
string&
erase(
size_type index = 0,
size_type count = npos);
BOOST_JSON_DECL
iterator
erase(const_iterator pos);
BOOST_JSON_DECL
iterator
erase(
const_iterator first,
const_iterator last);
//--------------------------------------------------------------------------
BOOST_JSON_DECL
void
push_back(char ch);
BOOST_JSON_DECL
void
pop_back();
//--------------------------------------------------------------------------
BOOST_JSON_DECL
string&
append(size_type count, char ch);
BOOST_JSON_DECL
string&
append(string const& str );
BOOST_JSON_DECL
string&
append(
string const& str,
size_type pos,
size_type count = npos);
BOOST_JSON_DECL
string&
append(
char const* s,
size_type count);
BOOST_JSON_DECL
string&
append(char const* s);
template<class InputIt
#ifndef GENERATING_DOCUMENTATION
,class = typename std::enable_if<
std::is_convertible<
typename std::iterator_traits<
InputIt>::value_type,
char>::value>::type
#endif
>
string&
append(InputIt first, InputIt last);
BOOST_JSON_DECL
string&
append(std::initializer_list<char> init);
BOOST_JSON_DECL
string&
append(string_view sv);
//--------------------------------------------------------------------------
//
// Observers
//
//--------------------------------------------------------------------------
BOOST_JSON_DECL
string_view
substr(
size_type pos = 0,
size_type count = npos) const;
private:
template<class It>
using iter_cat = typename
std::iterator_traits<It>::iterator_category;
BOOST_JSON_DECL
void
raw_resize(
size_type size);
BOOST_JSON_DECL
char*
raw_insert(
size_type pos,
size_type n);
template<class InputIt>
void
maybe_raw_resize(
InputIt, InputIt,
std::input_iterator_tag)
{
}
template<class InputIt>
void
maybe_raw_resize(
InputIt first,
InputIt last,
std::forward_iterator_tag)
{
raw_resize(std::distance(
first, last));
}
};
inline
bool
operator==(string const& lhs, string const& rhs)
{
return std::lexicographical_compare(
lhs.begin(), lhs.end(),
rhs.begin(), rhs.end())
== 0;
}
inline
bool
operator==(char const* lhs, string const& rhs)
{
return std::lexicographical_compare(
lhs, lhs + std::char_traits<char>::length(lhs),
rhs.begin(), rhs.end())
== 0;
}
inline
bool
operator==(string const& lhs, char const* rhs)
{
return std::lexicographical_compare(
lhs.begin(), lhs.end(),
rhs, rhs + std::char_traits<char>::length(rhs))
== 0;
}
BOOST_JSON_DECL
std::ostream&
operator<<(std::ostream& os, string const& s);
} // json
} // boost
#include <boost/json/impl/string.hpp>
#if BOOST_JSON_HEADER_ONLY
#include <boost/json/impl/string.ipp>
#endif
#endif

View File

@@ -767,7 +767,7 @@ public:
//--------------------------------------------------------------------------
BOOST_JSON_DECL
storage_ptr
storage_ptr const&
get_storage() const noexcept;
object&
@@ -1079,24 +1079,6 @@ private:
construct(
json::kind, storage_ptr) noexcept;
template<class S>
auto
construct_string(
S&& str, storage_ptr store) ->
typename std::enable_if<
! std::is_constructible<S, string,
typename string::allocator_type
>::value>::type;
template<class S>
auto
construct_string(
S&& str, storage_ptr store) ->
typename std::enable_if<
std::is_constructible<S, string,
typename string::allocator_type
>::value>::type;
BOOST_JSON_DECL
friend
std::ostream&