feat():initial version
This commit is contained in:
554
install/boost_1_75_0/include/boost/json/impl/array.hpp
Normal file
554
install/boost_1_75_0/include/boost/json/impl/array.hpp
Normal file
@@ -0,0 +1,554 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_ARRAY_HPP
|
||||
#define BOOST_JSON_IMPL_ARRAY_HPP
|
||||
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/json/detail/except.hpp>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
struct alignas(value)
|
||||
array::table
|
||||
{
|
||||
std::uint32_t size = 0;
|
||||
std::uint32_t capacity = 0;
|
||||
|
||||
constexpr table();
|
||||
|
||||
value&
|
||||
operator[](std::size_t pos) noexcept
|
||||
{
|
||||
return (reinterpret_cast<
|
||||
value*>(this + 1))[pos];
|
||||
}
|
||||
|
||||
BOOST_JSON_DECL
|
||||
static
|
||||
table*
|
||||
allocate(
|
||||
std::size_t capacity,
|
||||
storage_ptr const& sp);
|
||||
|
||||
BOOST_JSON_DECL
|
||||
static
|
||||
void
|
||||
deallocate(
|
||||
table* p,
|
||||
storage_ptr const& sp);
|
||||
};
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
class array::revert_construct
|
||||
{
|
||||
array* arr_;
|
||||
|
||||
public:
|
||||
explicit
|
||||
revert_construct(
|
||||
array& arr) noexcept
|
||||
: arr_(&arr)
|
||||
{
|
||||
}
|
||||
|
||||
~revert_construct()
|
||||
{
|
||||
if(! arr_)
|
||||
return;
|
||||
arr_->destroy();
|
||||
}
|
||||
|
||||
void
|
||||
commit() noexcept
|
||||
{
|
||||
arr_ = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
class array::revert_insert
|
||||
{
|
||||
array* arr_;
|
||||
std::size_t const i_;
|
||||
std::size_t const n_;
|
||||
|
||||
public:
|
||||
value* p;
|
||||
|
||||
BOOST_JSON_DECL
|
||||
revert_insert(
|
||||
const_iterator pos,
|
||||
std::size_t n,
|
||||
array& arr);
|
||||
|
||||
BOOST_JSON_DECL
|
||||
~revert_insert();
|
||||
|
||||
value*
|
||||
commit() noexcept
|
||||
{
|
||||
auto it =
|
||||
arr_->data() + i_;
|
||||
arr_ = nullptr;
|
||||
return it;
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
array::
|
||||
relocate(
|
||||
value* dest,
|
||||
value* src,
|
||||
std::size_t n) noexcept
|
||||
{
|
||||
if(n == 0)
|
||||
return;
|
||||
std::memmove(
|
||||
static_cast<void*>(dest),
|
||||
static_cast<void const*>(src),
|
||||
n * sizeof(value));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Construction
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
template<class InputIt, class>
|
||||
array::
|
||||
array(
|
||||
InputIt first, InputIt last,
|
||||
storage_ptr sp)
|
||||
: array(
|
||||
first, last,
|
||||
std::move(sp),
|
||||
iter_cat<InputIt>{})
|
||||
{
|
||||
BOOST_STATIC_ASSERT(
|
||||
std::is_constructible<value,
|
||||
decltype(*first)>::value);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Modifiers
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
template<class InputIt, class>
|
||||
auto
|
||||
array::
|
||||
insert(
|
||||
const_iterator pos,
|
||||
InputIt first, InputIt last) ->
|
||||
iterator
|
||||
{
|
||||
BOOST_STATIC_ASSERT(
|
||||
std::is_constructible<value,
|
||||
decltype(*first)>::value);
|
||||
return insert(pos, first, last,
|
||||
iter_cat<InputIt>{});
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
auto
|
||||
array::
|
||||
emplace(
|
||||
const_iterator pos,
|
||||
Arg&& arg) ->
|
||||
iterator
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
pos >= begin() &&
|
||||
pos <= end());
|
||||
value jv(
|
||||
std::forward<Arg>(arg),
|
||||
storage());
|
||||
return insert(pos, pilfer(jv));
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
value&
|
||||
array::
|
||||
emplace_back(Arg&& arg)
|
||||
{
|
||||
value jv(
|
||||
std::forward<Arg>(arg),
|
||||
storage());
|
||||
return push_back(pilfer(jv));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Element access
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
value&
|
||||
array::
|
||||
at(std::size_t pos)
|
||||
{
|
||||
if(pos >= t_->size)
|
||||
detail::throw_out_of_range(
|
||||
BOOST_CURRENT_LOCATION);
|
||||
return (*t_)[pos];
|
||||
}
|
||||
|
||||
value const&
|
||||
array::
|
||||
at(std::size_t pos) const
|
||||
{
|
||||
if(pos >= t_->size)
|
||||
detail::throw_out_of_range(
|
||||
BOOST_CURRENT_LOCATION);
|
||||
return (*t_)[pos];
|
||||
}
|
||||
|
||||
value&
|
||||
array::
|
||||
operator[](std::size_t pos) noexcept
|
||||
{
|
||||
BOOST_ASSERT(pos < t_->size);
|
||||
return (*t_)[pos];
|
||||
}
|
||||
|
||||
value const&
|
||||
array::
|
||||
operator[](std::size_t pos) const noexcept
|
||||
{
|
||||
BOOST_ASSERT(pos < t_->size);
|
||||
return (*t_)[pos];
|
||||
}
|
||||
|
||||
value&
|
||||
array::
|
||||
front() noexcept
|
||||
{
|
||||
BOOST_ASSERT(t_->size > 0);
|
||||
return (*t_)[0];
|
||||
}
|
||||
|
||||
value const&
|
||||
array::
|
||||
front() const noexcept
|
||||
{
|
||||
BOOST_ASSERT(t_->size > 0);
|
||||
return (*t_)[0];
|
||||
}
|
||||
|
||||
value&
|
||||
array::
|
||||
back() noexcept
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
t_->size > 0);
|
||||
return (*t_)[t_->size - 1];
|
||||
}
|
||||
|
||||
value const&
|
||||
array::
|
||||
back() const noexcept
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
t_->size > 0);
|
||||
return (*t_)[t_->size - 1];
|
||||
}
|
||||
|
||||
value*
|
||||
array::
|
||||
data() noexcept
|
||||
{
|
||||
return &(*t_)[0];
|
||||
}
|
||||
|
||||
value const*
|
||||
array::
|
||||
data() const noexcept
|
||||
{
|
||||
return &(*t_)[0];
|
||||
}
|
||||
|
||||
value const*
|
||||
array::
|
||||
if_contains(
|
||||
std::size_t pos) const noexcept
|
||||
{
|
||||
if( pos < t_->size )
|
||||
return &(*t_)[pos];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
value*
|
||||
array::
|
||||
if_contains(
|
||||
std::size_t pos) noexcept
|
||||
{
|
||||
if( pos < t_->size )
|
||||
return &(*t_)[pos];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Iterators
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
auto
|
||||
array::
|
||||
begin() noexcept ->
|
||||
iterator
|
||||
{
|
||||
return &(*t_)[0];
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
begin() const noexcept ->
|
||||
const_iterator
|
||||
{
|
||||
return &(*t_)[0];
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
cbegin() const noexcept ->
|
||||
const_iterator
|
||||
{
|
||||
return &(*t_)[0];
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
end() noexcept ->
|
||||
iterator
|
||||
{
|
||||
return &(*t_)[t_->size];
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
end() const noexcept ->
|
||||
const_iterator
|
||||
{
|
||||
return &(*t_)[t_->size];
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
cend() const noexcept ->
|
||||
const_iterator
|
||||
{
|
||||
return &(*t_)[t_->size];
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
rbegin() noexcept ->
|
||||
reverse_iterator
|
||||
{
|
||||
return reverse_iterator(end());
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
rbegin() const noexcept ->
|
||||
const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
crbegin() const noexcept ->
|
||||
const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
rend() noexcept ->
|
||||
reverse_iterator
|
||||
{
|
||||
return reverse_iterator(begin());
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
rend() const noexcept ->
|
||||
const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
crend() const noexcept ->
|
||||
const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Capacity
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
std::size_t
|
||||
array::
|
||||
size() const noexcept
|
||||
{
|
||||
return t_->size;
|
||||
}
|
||||
|
||||
constexpr
|
||||
std::size_t
|
||||
array::
|
||||
max_size() noexcept
|
||||
{
|
||||
// max_size depends on the address model
|
||||
using min = std::integral_constant<std::size_t,
|
||||
(std::size_t(-1) - sizeof(table)) / sizeof(value)>;
|
||||
return min::value < BOOST_JSON_MAX_STRUCTURED_SIZE ?
|
||||
min::value : BOOST_JSON_MAX_STRUCTURED_SIZE;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
array::
|
||||
capacity() const noexcept
|
||||
{
|
||||
return t_->capacity;
|
||||
}
|
||||
|
||||
bool
|
||||
array::
|
||||
empty() const noexcept
|
||||
{
|
||||
return t_->size == 0;
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
reserve(
|
||||
std::size_t new_capacity)
|
||||
{
|
||||
// never shrink
|
||||
if(new_capacity <= t_->capacity)
|
||||
return;
|
||||
reserve_impl(new_capacity);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// private
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
template<class InputIt>
|
||||
array::
|
||||
array(
|
||||
InputIt first, InputIt last,
|
||||
storage_ptr sp,
|
||||
std::input_iterator_tag)
|
||||
: sp_(std::move(sp))
|
||||
, t_(&empty_)
|
||||
{
|
||||
revert_construct r(*this);
|
||||
while(first != last)
|
||||
{
|
||||
reserve(size() + 1);
|
||||
::new(end()) value(
|
||||
*first++, sp_);
|
||||
++t_->size;
|
||||
}
|
||||
r.commit();
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
array::
|
||||
array(
|
||||
InputIt first, InputIt last,
|
||||
storage_ptr sp,
|
||||
std::forward_iterator_tag)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
std::size_t n =
|
||||
std::distance(first, last);
|
||||
t_ = table::allocate(n, sp_);
|
||||
t_->size = 0;
|
||||
revert_construct r(*this);
|
||||
while(n--)
|
||||
{
|
||||
::new(end()) value(
|
||||
*first++, sp_);
|
||||
++t_->size;
|
||||
}
|
||||
r.commit();
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
auto
|
||||
array::
|
||||
insert(
|
||||
const_iterator pos,
|
||||
InputIt first, InputIt last,
|
||||
std::input_iterator_tag) ->
|
||||
iterator
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
pos >= begin() && pos <= end());
|
||||
if(first == last)
|
||||
return data() + (pos - data());
|
||||
array temp(first, last, sp_);
|
||||
revert_insert r(
|
||||
pos, temp.size(), *this);
|
||||
relocate(
|
||||
r.p,
|
||||
temp.data(),
|
||||
temp.size());
|
||||
temp.t_->size = 0;
|
||||
return r.commit();
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
auto
|
||||
array::
|
||||
insert(
|
||||
const_iterator pos,
|
||||
InputIt first, InputIt last,
|
||||
std::forward_iterator_tag) ->
|
||||
iterator
|
||||
{
|
||||
std::size_t n =
|
||||
std::distance(first, last);
|
||||
revert_insert r(pos, n, *this);
|
||||
while(n--)
|
||||
{
|
||||
::new(r.p) value(*first++);
|
||||
++r.p;
|
||||
}
|
||||
return r.commit();
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
757
install/boost_1_75_0/include/boost/json/impl/array.ipp
Normal file
757
install/boost_1_75_0/include/boost/json/impl/array.ipp
Normal file
@@ -0,0 +1,757 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_ARRAY_IPP
|
||||
#define BOOST_JSON_IMPL_ARRAY_IPP
|
||||
|
||||
#include <boost/json/array.hpp>
|
||||
#include <boost/json/pilfer.hpp>
|
||||
#include <boost/json/detail/except.hpp>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <new>
|
||||
#include <utility>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
constexpr array::table::table() = default;
|
||||
|
||||
// empty arrays point here
|
||||
BOOST_JSON_REQUIRE_CONST_INIT
|
||||
array::table array::empty_;
|
||||
|
||||
auto
|
||||
array::
|
||||
table::
|
||||
allocate(
|
||||
std::size_t capacity,
|
||||
storage_ptr const& sp) ->
|
||||
table*
|
||||
{
|
||||
BOOST_ASSERT(capacity > 0);
|
||||
if(capacity > array::max_size())
|
||||
detail::throw_length_error(
|
||||
"array too large",
|
||||
BOOST_CURRENT_LOCATION);
|
||||
auto p = reinterpret_cast<
|
||||
table*>(sp->allocate(
|
||||
sizeof(table) +
|
||||
capacity * sizeof(value),
|
||||
alignof(value)));
|
||||
p->capacity = static_cast<
|
||||
std::uint32_t>(capacity);
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
table::
|
||||
deallocate(
|
||||
table* p,
|
||||
storage_ptr const& sp)
|
||||
{
|
||||
if(p->capacity == 0)
|
||||
return;
|
||||
sp->deallocate(p,
|
||||
sizeof(table) +
|
||||
p->capacity * sizeof(value),
|
||||
alignof(value));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
array::
|
||||
revert_insert::
|
||||
revert_insert(
|
||||
const_iterator pos,
|
||||
std::size_t n,
|
||||
array& arr)
|
||||
: arr_(&arr)
|
||||
, i_(pos - arr_->data())
|
||||
, n_(n)
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
pos >= arr_->begin() &&
|
||||
pos <= arr_->end());
|
||||
if( n_ <= arr_->capacity() -
|
||||
arr_->size())
|
||||
{
|
||||
// fast path
|
||||
p = arr_->data() + i_;
|
||||
if(n_ == 0)
|
||||
return;
|
||||
relocate(
|
||||
p + n_,
|
||||
p,
|
||||
arr_->size() - i_);
|
||||
arr_->t_->size = static_cast<
|
||||
std::uint32_t>(
|
||||
arr_->t_->size + n_);
|
||||
return;
|
||||
}
|
||||
if(n_ > max_size() - arr_->size())
|
||||
detail::throw_length_error(
|
||||
"array too large",
|
||||
BOOST_CURRENT_LOCATION);
|
||||
auto t = table::allocate(
|
||||
arr_->growth(arr_->size() + n_),
|
||||
arr_->sp_);
|
||||
t->size = static_cast<std::uint32_t>(
|
||||
arr_->size() + n_);
|
||||
p = &(*t)[0] + i_;
|
||||
relocate(
|
||||
&(*t)[0],
|
||||
arr_->data(),
|
||||
i_);
|
||||
relocate(
|
||||
&(*t)[i_ + n_],
|
||||
arr_->data() + i_,
|
||||
arr_->size() - i_);
|
||||
t = detail::exchange(arr_->t_, t);
|
||||
table::deallocate(t, arr_->sp_);
|
||||
}
|
||||
|
||||
array::
|
||||
revert_insert::
|
||||
~revert_insert()
|
||||
{
|
||||
if(! arr_)
|
||||
return;
|
||||
BOOST_ASSERT(n_ != 0);
|
||||
auto const pos =
|
||||
arr_->data() + i_;
|
||||
arr_->destroy(pos, p);
|
||||
arr_->t_->size = static_cast<
|
||||
std::uint32_t>(
|
||||
arr_->t_->size - n_);
|
||||
relocate(
|
||||
pos,
|
||||
pos + n_,
|
||||
arr_->size() - i_);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
array::
|
||||
destroy(
|
||||
value* first, value* last) noexcept
|
||||
{
|
||||
if(sp_.is_not_shared_and_deallocate_is_trivial())
|
||||
return;
|
||||
while(last-- != first)
|
||||
last->~value();
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
destroy() noexcept
|
||||
{
|
||||
if(sp_.is_not_shared_and_deallocate_is_trivial())
|
||||
return;
|
||||
auto last = end();
|
||||
auto const first = begin();
|
||||
while(last-- != first)
|
||||
last->~value();
|
||||
table::deallocate(t_, sp_);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Special Members
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
array::
|
||||
array(detail::unchecked_array&& ua)
|
||||
: sp_(ua.storage())
|
||||
{
|
||||
BOOST_STATIC_ASSERT(
|
||||
alignof(table) == alignof(value));
|
||||
if(ua.size() == 0)
|
||||
{
|
||||
t_ = &empty_;
|
||||
return;
|
||||
}
|
||||
t_= table::allocate(
|
||||
ua.size(), sp_);
|
||||
t_->size = static_cast<
|
||||
std::uint32_t>(ua.size());
|
||||
ua.relocate(data());
|
||||
}
|
||||
|
||||
array::
|
||||
~array()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
array::
|
||||
array(
|
||||
std::size_t count,
|
||||
value const& v,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
if(count == 0)
|
||||
{
|
||||
t_ = &empty_;
|
||||
return;
|
||||
}
|
||||
t_= table::allocate(
|
||||
count, sp_);
|
||||
t_->size = 0;
|
||||
revert_construct r(*this);
|
||||
while(count--)
|
||||
{
|
||||
::new(end()) value(v, sp_);
|
||||
++t_->size;
|
||||
}
|
||||
r.commit();
|
||||
}
|
||||
|
||||
array::
|
||||
array(
|
||||
std::size_t count,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
if(count == 0)
|
||||
{
|
||||
t_ = &empty_;
|
||||
return;
|
||||
}
|
||||
t_ = table::allocate(
|
||||
count, sp_);
|
||||
t_->size = static_cast<
|
||||
std::uint32_t>(count);
|
||||
auto p = data();
|
||||
do
|
||||
{
|
||||
::new(p++) value(sp_);
|
||||
}
|
||||
while(--count);
|
||||
}
|
||||
|
||||
array::
|
||||
array(array const& other)
|
||||
: array(other, other.sp_)
|
||||
{
|
||||
}
|
||||
|
||||
array::
|
||||
array(
|
||||
array const& other,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
if(other.empty())
|
||||
{
|
||||
t_ = &empty_;
|
||||
return;
|
||||
}
|
||||
t_ = table::allocate(
|
||||
other.size(), sp_);
|
||||
t_->size = 0;
|
||||
revert_construct r(*this);
|
||||
auto src = other.data();
|
||||
auto dest = data();
|
||||
auto const n = other.size();
|
||||
do
|
||||
{
|
||||
::new(dest++) value(
|
||||
*src++, sp_);
|
||||
++t_->size;
|
||||
}
|
||||
while(t_->size < n);
|
||||
r.commit();
|
||||
}
|
||||
|
||||
array::
|
||||
array(
|
||||
array&& other,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
if(*sp_ == *other.sp_)
|
||||
{
|
||||
// same resource
|
||||
t_ = detail::exchange(
|
||||
other.t_, &empty_);
|
||||
return;
|
||||
}
|
||||
else if(other.empty())
|
||||
{
|
||||
t_ = &empty_;
|
||||
return;
|
||||
}
|
||||
// copy
|
||||
t_ = table::allocate(
|
||||
other.size(), sp_);
|
||||
t_->size = 0;
|
||||
revert_construct r(*this);
|
||||
auto src = other.data();
|
||||
auto dest = data();
|
||||
auto const n = other.size();
|
||||
do
|
||||
{
|
||||
::new(dest++) value(
|
||||
*src++, sp_);
|
||||
++t_->size;
|
||||
}
|
||||
while(t_->size < n);
|
||||
r.commit();
|
||||
}
|
||||
|
||||
array::
|
||||
array(
|
||||
std::initializer_list<
|
||||
value_ref> init,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
if(init.size() == 0)
|
||||
{
|
||||
t_ = &empty_;
|
||||
return;
|
||||
}
|
||||
t_ = table::allocate(
|
||||
init.size(), sp_);
|
||||
t_->size = 0;
|
||||
revert_construct r(*this);
|
||||
value_ref::write_array(
|
||||
data(), init, sp_);
|
||||
t_->size = static_cast<
|
||||
std::uint32_t>(init.size());
|
||||
r.commit();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
array&
|
||||
array::
|
||||
operator=(array const& other)
|
||||
{
|
||||
array(other,
|
||||
storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
array&
|
||||
array::
|
||||
operator=(array&& other)
|
||||
{
|
||||
array(std::move(other),
|
||||
storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
array&
|
||||
array::
|
||||
operator=(
|
||||
std::initializer_list<value_ref> init)
|
||||
{
|
||||
array(init,
|
||||
storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Capacity
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
array::
|
||||
shrink_to_fit() noexcept
|
||||
{
|
||||
if(capacity() <= size())
|
||||
return;
|
||||
if(size() == 0)
|
||||
{
|
||||
table::deallocate(t_, sp_);
|
||||
t_ = &empty_;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif
|
||||
auto t = table::allocate(
|
||||
size(), sp_);
|
||||
relocate(
|
||||
&(*t)[0],
|
||||
data(),
|
||||
size());
|
||||
t->size = static_cast<
|
||||
std::uint32_t>(size());
|
||||
t = detail::exchange(
|
||||
t_, t);
|
||||
table::deallocate(t, sp_);
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
// eat the exception
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Modifiers
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
array::
|
||||
clear() noexcept
|
||||
{
|
||||
if(size() == 0)
|
||||
return;
|
||||
destroy(
|
||||
begin(), end());
|
||||
t_->size = 0;
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
insert(
|
||||
const_iterator pos,
|
||||
value const& v) ->
|
||||
iterator
|
||||
{
|
||||
return emplace(pos, v);
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
insert(
|
||||
const_iterator pos,
|
||||
value&& v) ->
|
||||
iterator
|
||||
{
|
||||
return emplace(pos, std::move(v));
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
insert(
|
||||
const_iterator pos,
|
||||
std::size_t count,
|
||||
value const& v) ->
|
||||
iterator
|
||||
{
|
||||
revert_insert r(
|
||||
pos, count, *this);
|
||||
while(count--)
|
||||
{
|
||||
::new(r.p) value(v, sp_);
|
||||
++r.p;
|
||||
}
|
||||
return r.commit();
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
insert(
|
||||
const_iterator pos,
|
||||
std::initializer_list<
|
||||
value_ref> init) ->
|
||||
iterator
|
||||
{
|
||||
revert_insert r(
|
||||
pos, init.size(), *this);
|
||||
value_ref::write_array(
|
||||
r.p, init, sp_);
|
||||
return r.commit();
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
erase(
|
||||
const_iterator pos) noexcept ->
|
||||
iterator
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
pos >= begin() &&
|
||||
pos <= end());
|
||||
auto const p = &(*t_)[0] +
|
||||
(pos - &(*t_)[0]);
|
||||
destroy(p, p + 1);
|
||||
relocate(p, p + 1, 1);
|
||||
--t_->size;
|
||||
return p;
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
erase(
|
||||
const_iterator first,
|
||||
const_iterator last) noexcept ->
|
||||
iterator
|
||||
{
|
||||
std::size_t const n =
|
||||
last - first;
|
||||
auto const p = &(*t_)[0] +
|
||||
(first - &(*t_)[0]);
|
||||
destroy(p, p + n);
|
||||
relocate(p, p + n,
|
||||
t_->size - (last -
|
||||
&(*t_)[0]));
|
||||
t_->size = static_cast<
|
||||
std::uint32_t>(t_->size - n);
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
push_back(value const& v)
|
||||
{
|
||||
emplace_back(v);
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
push_back(value&& v)
|
||||
{
|
||||
emplace_back(std::move(v));
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
pop_back() noexcept
|
||||
{
|
||||
auto const p = &back();
|
||||
destroy(p, p + 1);
|
||||
--t_->size;
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
resize(std::size_t count)
|
||||
{
|
||||
if(count <= t_->size)
|
||||
{
|
||||
// shrink
|
||||
destroy(
|
||||
&(*t_)[0] + count,
|
||||
&(*t_)[0] + t_->size);
|
||||
t_->size = static_cast<
|
||||
std::uint32_t>(count);
|
||||
return;
|
||||
}
|
||||
|
||||
reserve(count);
|
||||
auto p = &(*t_)[t_->size];
|
||||
auto const end = &(*t_)[count];
|
||||
while(p != end)
|
||||
::new(p++) value(sp_);
|
||||
t_->size = static_cast<
|
||||
std::uint32_t>(count);
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
resize(
|
||||
std::size_t count,
|
||||
value const& v)
|
||||
{
|
||||
if(count <= size())
|
||||
{
|
||||
// shrink
|
||||
destroy(
|
||||
data() + count,
|
||||
data() + size());
|
||||
t_->size = static_cast<
|
||||
std::uint32_t>(count);
|
||||
return;
|
||||
}
|
||||
count -= size();
|
||||
revert_insert r(
|
||||
end(), count, *this);
|
||||
while(count--)
|
||||
{
|
||||
::new(r.p) value(v, sp_);
|
||||
++r.p;
|
||||
}
|
||||
r.commit();
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
swap(array& other)
|
||||
{
|
||||
BOOST_ASSERT(this != &other);
|
||||
if(*sp_ == *other.sp_)
|
||||
{
|
||||
t_ = detail::exchange(
|
||||
other.t_, t_);
|
||||
return;
|
||||
}
|
||||
array temp1(
|
||||
std::move(*this),
|
||||
other.storage());
|
||||
array temp2(
|
||||
std::move(other),
|
||||
this->storage());
|
||||
this->~array();
|
||||
::new(this) array(
|
||||
pilfer(temp2));
|
||||
other.~array();
|
||||
::new(&other) array(
|
||||
pilfer(temp1));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Private
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
std::size_t
|
||||
array::
|
||||
growth(
|
||||
std::size_t new_size) const
|
||||
{
|
||||
if(new_size > max_size())
|
||||
detail::throw_length_error(
|
||||
"array too large",
|
||||
BOOST_CURRENT_LOCATION);
|
||||
std::size_t const old = capacity();
|
||||
if(old > max_size() - old / 2)
|
||||
return new_size;
|
||||
std::size_t const g =
|
||||
old + old / 2; // 1.5x
|
||||
if(g < new_size)
|
||||
return new_size;
|
||||
return g;
|
||||
}
|
||||
|
||||
// precondition: new_capacity > capacity()
|
||||
void
|
||||
array::
|
||||
reserve_impl(
|
||||
std::size_t new_capacity)
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
new_capacity > t_->capacity);
|
||||
auto t = table::allocate(
|
||||
growth(new_capacity), sp_);
|
||||
relocate(
|
||||
&(*t)[0],
|
||||
&(*t_)[0],
|
||||
t_->size);
|
||||
t->size = t_->size;
|
||||
t = detail::exchange(t_, t);
|
||||
table::deallocate(t, sp_);
|
||||
}
|
||||
|
||||
// precondition: pv is not aliased
|
||||
value&
|
||||
array::
|
||||
push_back(
|
||||
pilfered<value> pv)
|
||||
{
|
||||
auto const n = t_->size;
|
||||
if(n < t_->capacity)
|
||||
{
|
||||
// fast path
|
||||
auto& v = *::new(
|
||||
&(*t_)[n]) value(pv);
|
||||
++t_->size;
|
||||
return v;
|
||||
}
|
||||
auto const t =
|
||||
detail::exchange(t_,
|
||||
table::allocate(
|
||||
growth(n + 1),
|
||||
sp_));
|
||||
auto& v = *::new(
|
||||
&(*t_)[n]) value(pv);
|
||||
relocate(
|
||||
&(*t_)[0],
|
||||
&(*t)[0],
|
||||
n);
|
||||
t_->size = n + 1;
|
||||
table::deallocate(t, sp_);
|
||||
return v;
|
||||
}
|
||||
|
||||
// precondition: pv is not aliased
|
||||
auto
|
||||
array::
|
||||
insert(
|
||||
const_iterator pos,
|
||||
pilfered<value> pv) ->
|
||||
iterator
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
pos >= begin() &&
|
||||
pos <= end());
|
||||
std::size_t const n =
|
||||
t_->size;
|
||||
std::size_t const i =
|
||||
pos - &(*t_)[0];
|
||||
if(n < t_->capacity)
|
||||
{
|
||||
// fast path
|
||||
auto const p =
|
||||
&(*t_)[i];
|
||||
relocate(
|
||||
p + 1,
|
||||
p,
|
||||
n - i);
|
||||
::new(p) value(pv);
|
||||
++t_->size;
|
||||
return p;
|
||||
}
|
||||
auto t =
|
||||
table::allocate(
|
||||
growth(n + 1), sp_);
|
||||
auto const p = &(*t)[i];
|
||||
::new(p) value(pv);
|
||||
relocate(
|
||||
&(*t)[0],
|
||||
&(*t_)[0],
|
||||
i);
|
||||
relocate(
|
||||
p + 1,
|
||||
&(*t_)[i],
|
||||
n - i);
|
||||
t->size = static_cast<
|
||||
std::uint32_t>(size() + 1);
|
||||
t = detail::exchange(t_, t);
|
||||
table::deallocate(t, sp_);
|
||||
return p;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
bool
|
||||
array::
|
||||
equal(
|
||||
array const& other) const noexcept
|
||||
{
|
||||
if(size() != other.size())
|
||||
return false;
|
||||
for(std::size_t i = 0; i < size(); ++i)
|
||||
if((*this)[i] != other[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
61
install/boost_1_75_0/include/boost/json/impl/error.hpp
Normal file
61
install/boost_1_75_0/include/boost/json/impl/error.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_ERROR_HPP
|
||||
#define BOOST_JSON_IMPL_ERROR_HPP
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#ifndef BOOST_JSON_STANDALONE
|
||||
|
||||
namespace boost {
|
||||
namespace system {
|
||||
template<>
|
||||
struct is_error_code_enum< ::boost::json::error >
|
||||
{
|
||||
static bool const value = true;
|
||||
};
|
||||
template<>
|
||||
struct is_error_condition_enum< ::boost::json::condition >
|
||||
{
|
||||
static bool const value = true;
|
||||
};
|
||||
} // system
|
||||
} // boost
|
||||
|
||||
#else
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct is_error_code_enum< ::boost::json::error >
|
||||
{
|
||||
static bool const value = true;
|
||||
};
|
||||
template<>
|
||||
struct is_error_condition_enum< ::boost::json::condition >
|
||||
{
|
||||
static bool const value = true;
|
||||
};
|
||||
} // std
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
BOOST_JSON_DECL
|
||||
error_code
|
||||
make_error_code(error e);
|
||||
|
||||
BOOST_JSON_DECL
|
||||
error_condition
|
||||
make_error_condition(condition c);
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
123
install/boost_1_75_0/include/boost/json/impl/error.ipp
Normal file
123
install/boost_1_75_0/include/boost/json/impl/error.ipp
Normal file
@@ -0,0 +1,123 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_ERROR_IPP
|
||||
#define BOOST_JSON_IMPL_ERROR_IPP
|
||||
|
||||
#include <boost/json/error.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
error_code
|
||||
make_error_code(error e)
|
||||
{
|
||||
struct codes : error_category
|
||||
{
|
||||
const char*
|
||||
name() const noexcept override
|
||||
{
|
||||
return "boost.json";
|
||||
}
|
||||
|
||||
std::string
|
||||
message(int ev) const override
|
||||
{
|
||||
switch(static_cast<error>(ev))
|
||||
{
|
||||
default:
|
||||
case error::syntax: return "syntax error";
|
||||
case error::extra_data: return "extra data";
|
||||
case error::incomplete: return "incomplete JSON";
|
||||
case error::exponent_overflow: return "exponent overflow";
|
||||
case error::too_deep: return "too deep";
|
||||
case error::illegal_leading_surrogate: return "illegal leading surrogate";
|
||||
case error::illegal_trailing_surrogate: return "illegal trailing surrogate";
|
||||
case error::expected_hex_digit: return "expected hex digit";
|
||||
case error::expected_utf16_escape: return "expected utf16 escape";
|
||||
case error::object_too_large: return "object too large";
|
||||
case error::array_too_large: return "array too large";
|
||||
case error::key_too_large: return "key too large";
|
||||
case error::string_too_large: return "string too large";
|
||||
case error::exception: return "got exception";
|
||||
case error::not_number: return "not a number";
|
||||
case error::not_exact: return "not exact";
|
||||
|
||||
case error::test_failure: return "test failure";
|
||||
}
|
||||
}
|
||||
|
||||
error_condition
|
||||
default_error_condition(
|
||||
int ev) const noexcept override
|
||||
{
|
||||
switch(static_cast<error>(ev))
|
||||
{
|
||||
default:
|
||||
return {ev, *this};
|
||||
|
||||
case error::syntax:
|
||||
case error::extra_data:
|
||||
case error::incomplete:
|
||||
case error::exponent_overflow:
|
||||
case error::too_deep:
|
||||
case error::illegal_leading_surrogate:
|
||||
case error::illegal_trailing_surrogate:
|
||||
case error::expected_hex_digit:
|
||||
case error::expected_utf16_escape:
|
||||
case error::object_too_large:
|
||||
case error::array_too_large:
|
||||
case error::key_too_large:
|
||||
case error::string_too_large:
|
||||
case error::exception:
|
||||
return condition::parse_error;
|
||||
|
||||
case error::not_number:
|
||||
case error::not_exact:
|
||||
return condition::assign_error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static codes const cat{};
|
||||
return error_code{static_cast<
|
||||
std::underlying_type<error>::type>(e), cat};
|
||||
}
|
||||
|
||||
error_condition
|
||||
make_error_condition(condition c)
|
||||
{
|
||||
struct codes : error_category
|
||||
{
|
||||
const char*
|
||||
name() const noexcept override
|
||||
{
|
||||
return "boost.json";
|
||||
}
|
||||
|
||||
std::string
|
||||
message(int cv) const override
|
||||
{
|
||||
switch(static_cast<condition>(cv))
|
||||
{
|
||||
default:
|
||||
case condition::parse_error:
|
||||
return "A JSON parse error occurred";
|
||||
case condition::assign_error:
|
||||
return "An error occurred during assignment";
|
||||
}
|
||||
}
|
||||
};
|
||||
static codes const cat{};
|
||||
return error_condition{static_cast<
|
||||
std::underlying_type<condition>::type>(c), cat};
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
44
install/boost_1_75_0/include/boost/json/impl/kind.ipp
Normal file
44
install/boost_1_75_0/include/boost/json/impl/kind.ipp
Normal file
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_KIND_IPP
|
||||
#define BOOST_JSON_IMPL_KIND_IPP
|
||||
|
||||
#include <boost/json/kind.hpp>
|
||||
#include <ostream>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
string_view
|
||||
to_string(kind k) noexcept
|
||||
{
|
||||
switch(k)
|
||||
{
|
||||
case kind::array: return "array";
|
||||
case kind::object: return "object";
|
||||
case kind::string: return "string";
|
||||
case kind::int64: return "int64";
|
||||
case kind::uint64: return "uint64";
|
||||
case kind::double_: return "double";
|
||||
case kind::bool_: return "bool";
|
||||
default: // satisfy warnings
|
||||
case kind::null: return "null";
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, kind k)
|
||||
{
|
||||
os << to_string(k);
|
||||
return os;
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,171 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
|
||||
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_MONOTONIC_RESOURCE_IPP
|
||||
#define BOOST_JSON_IMPL_MONOTONIC_RESOURCE_IPP
|
||||
|
||||
#include <boost/json/monotonic_resource.hpp>
|
||||
#include <boost/json/detail/align.hpp>
|
||||
#include <boost/json/detail/except.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
struct alignas(detail::max_align_t)
|
||||
monotonic_resource::block : block_base
|
||||
{
|
||||
};
|
||||
|
||||
constexpr
|
||||
std::size_t
|
||||
monotonic_resource::
|
||||
max_size()
|
||||
{
|
||||
return std::size_t(-1) - sizeof(block);
|
||||
}
|
||||
|
||||
// lowest power of 2 greater than or equal to n
|
||||
std::size_t
|
||||
monotonic_resource::
|
||||
round_pow2(
|
||||
std::size_t n) noexcept
|
||||
{
|
||||
if(n & (n - 1))
|
||||
return next_pow2(n);
|
||||
return n;
|
||||
}
|
||||
|
||||
// lowest power of 2 greater than n
|
||||
std::size_t
|
||||
monotonic_resource::
|
||||
next_pow2(
|
||||
std::size_t n) noexcept
|
||||
{
|
||||
std::size_t result = min_size_;
|
||||
while(result <= n)
|
||||
{
|
||||
if(result >= max_size() - result)
|
||||
{
|
||||
// overflow
|
||||
result = max_size();
|
||||
break;
|
||||
}
|
||||
result *= 2;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
monotonic_resource::
|
||||
~monotonic_resource()
|
||||
{
|
||||
release();
|
||||
}
|
||||
|
||||
monotonic_resource::
|
||||
monotonic_resource(
|
||||
std::size_t initial_size,
|
||||
storage_ptr upstream) noexcept
|
||||
: buffer_{
|
||||
nullptr, 0, 0, nullptr}
|
||||
, next_size_(round_pow2(initial_size))
|
||||
, upstream_(std::move(upstream))
|
||||
{
|
||||
}
|
||||
|
||||
monotonic_resource::
|
||||
monotonic_resource(
|
||||
unsigned char* buffer,
|
||||
std::size_t size,
|
||||
storage_ptr upstream) noexcept
|
||||
: buffer_{
|
||||
buffer, size, size, nullptr}
|
||||
, next_size_(next_pow2(size))
|
||||
, upstream_(std::move(upstream))
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
monotonic_resource::
|
||||
release() noexcept
|
||||
{
|
||||
auto p = head_;
|
||||
while(p != &buffer_)
|
||||
{
|
||||
auto next = p->next;
|
||||
upstream_->deallocate(p, p->size);
|
||||
p = next;
|
||||
}
|
||||
buffer_.p = reinterpret_cast<
|
||||
unsigned char*>(buffer_.p) - (
|
||||
buffer_.size - buffer_.avail);
|
||||
buffer_.avail = buffer_.size;
|
||||
head_ = &buffer_;
|
||||
}
|
||||
|
||||
void*
|
||||
monotonic_resource::
|
||||
do_allocate(
|
||||
std::size_t n,
|
||||
std::size_t align)
|
||||
{
|
||||
auto p = detail::align(
|
||||
align, n, head_->p, head_->avail);
|
||||
if(p)
|
||||
{
|
||||
head_->p = reinterpret_cast<
|
||||
unsigned char*>(p) + n;
|
||||
head_->avail -= n;
|
||||
return p;
|
||||
}
|
||||
|
||||
if(next_size_ < n)
|
||||
next_size_ = round_pow2(n);
|
||||
auto b = ::new(upstream_->allocate(
|
||||
sizeof(block) + next_size_)) block;
|
||||
b->p = b + 1;
|
||||
b->avail = next_size_;
|
||||
b->size = next_size_;
|
||||
b->next = head_;
|
||||
head_ = b;
|
||||
next_size_ = next_pow2(next_size_);
|
||||
|
||||
p = detail::align(
|
||||
align, n, head_->p, head_->avail);
|
||||
BOOST_ASSERT(p);
|
||||
head_->p = reinterpret_cast<
|
||||
unsigned char*>(p) + n;
|
||||
head_->avail -= n;
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
monotonic_resource::
|
||||
do_deallocate(
|
||||
void*,
|
||||
std::size_t,
|
||||
std::size_t)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
bool
|
||||
monotonic_resource::
|
||||
do_is_equal(
|
||||
memory_resource const& mr) const noexcept
|
||||
{
|
||||
return this == &mr;
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
101
install/boost_1_75_0/include/boost/json/impl/null_resource.ipp
Normal file
101
install/boost_1_75_0/include/boost/json/impl/null_resource.ipp
Normal file
@@ -0,0 +1,101 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_NULL_RESOURCE_IPP
|
||||
#define BOOST_JSON_IMPL_NULL_RESOURCE_IPP
|
||||
|
||||
#include <boost/json/null_resource.hpp>
|
||||
#include <boost/json/detail/except.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
namespace detail {
|
||||
|
||||
/** A resource which always fails.
|
||||
|
||||
This memory resource always throws the exception
|
||||
`std::bad_alloc` in calls to `allocate`.
|
||||
*/
|
||||
class null_resource final
|
||||
: public memory_resource
|
||||
{
|
||||
public:
|
||||
/// Copy constructor (deleted)
|
||||
null_resource(
|
||||
null_resource const&) = delete;
|
||||
|
||||
/// Copy assignment (deleted)
|
||||
null_resource& operator=(
|
||||
null_resource const&) = delete;
|
||||
|
||||
/** Destructor
|
||||
|
||||
This destroys the resource.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@part Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
~null_resource() noexcept = default;
|
||||
|
||||
/** Constructor
|
||||
|
||||
This constructs the resource.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
/** @{ */
|
||||
null_resource() noexcept = default;
|
||||
|
||||
protected:
|
||||
void*
|
||||
do_allocate(
|
||||
std::size_t,
|
||||
std::size_t) override
|
||||
{
|
||||
detail::throw_bad_alloc(
|
||||
BOOST_CURRENT_LOCATION);
|
||||
}
|
||||
|
||||
void
|
||||
do_deallocate(
|
||||
void*,
|
||||
std::size_t,
|
||||
std::size_t) override
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
bool
|
||||
do_is_equal(
|
||||
memory_resource const& mr
|
||||
) const noexcept override
|
||||
{
|
||||
return this == &mr;
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
|
||||
memory_resource*
|
||||
get_null_resource() noexcept
|
||||
{
|
||||
static detail::null_resource mr;
|
||||
return &mr;
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
530
install/boost_1_75_0/include/boost/json/impl/object.hpp
Normal file
530
install/boost_1_75_0/include/boost/json/impl/object.hpp
Normal file
@@ -0,0 +1,530 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_OBJECT_HPP
|
||||
#define BOOST_JSON_IMPL_OBJECT_HPP
|
||||
|
||||
#include <boost/json/value.hpp>
|
||||
#include <iterator>
|
||||
#include <cmath>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Objects with size less than or equal
|
||||
// to this number will use a linear search
|
||||
// instead of the more expensive hash function.
|
||||
static
|
||||
constexpr
|
||||
std::size_t
|
||||
small_object_size_ = 18;
|
||||
|
||||
BOOST_STATIC_ASSERT(
|
||||
small_object_size_ <
|
||||
BOOST_JSON_MAX_STRUCTURED_SIZE);
|
||||
|
||||
} // detail
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
struct alignas(key_value_pair)
|
||||
object::table
|
||||
{
|
||||
std::uint32_t size = 0;
|
||||
std::uint32_t capacity = 0;
|
||||
std::uintptr_t salt = 0;
|
||||
|
||||
#if defined(_MSC_VER) && BOOST_JSON_ARCH == 32
|
||||
// VFALCO If we make key_value_pair smaller,
|
||||
// then we might want to revisit this
|
||||
// padding.
|
||||
BOOST_STATIC_ASSERT(
|
||||
sizeof(key_value_pair) == 32);
|
||||
char pad[4] = {}; // silence warnings
|
||||
#endif
|
||||
|
||||
constexpr table();
|
||||
|
||||
// returns true if we use a linear
|
||||
// search instead of the hash table.
|
||||
bool is_small() const noexcept
|
||||
{
|
||||
return capacity <=
|
||||
detail::small_object_size_;
|
||||
}
|
||||
|
||||
key_value_pair&
|
||||
operator[](
|
||||
std::size_t pos) noexcept
|
||||
{
|
||||
return reinterpret_cast<
|
||||
key_value_pair*>(
|
||||
this + 1)[pos];
|
||||
}
|
||||
|
||||
// VFALCO This is exported for tests
|
||||
BOOST_JSON_DECL
|
||||
std::size_t
|
||||
digest(string_view key) const noexcept;
|
||||
|
||||
inline
|
||||
index_t&
|
||||
bucket(std::size_t hash) noexcept;
|
||||
|
||||
inline
|
||||
index_t&
|
||||
bucket(string_view key) noexcept;
|
||||
|
||||
inline
|
||||
void
|
||||
clear() noexcept;
|
||||
|
||||
static
|
||||
inline
|
||||
table*
|
||||
allocate(
|
||||
std::size_t capacity,
|
||||
std::uintptr_t salt,
|
||||
storage_ptr const& sp);
|
||||
|
||||
static
|
||||
void
|
||||
deallocate(
|
||||
table* p,
|
||||
storage_ptr const& sp) noexcept
|
||||
{
|
||||
if(p->capacity == 0)
|
||||
return;
|
||||
if(p->is_small())
|
||||
sp->deallocate(p,
|
||||
sizeof(table) + p->capacity * (
|
||||
sizeof(key_value_pair) +
|
||||
sizeof(index_t)));
|
||||
else
|
||||
sp->deallocate(p,
|
||||
sizeof(table) + p->capacity *
|
||||
sizeof(key_value_pair));
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
class object::revert_construct
|
||||
{
|
||||
object* obj_;
|
||||
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
destroy() noexcept;
|
||||
|
||||
public:
|
||||
explicit
|
||||
revert_construct(
|
||||
object& obj) noexcept
|
||||
: obj_(&obj)
|
||||
{
|
||||
}
|
||||
|
||||
~revert_construct()
|
||||
{
|
||||
if(! obj_)
|
||||
return;
|
||||
destroy();
|
||||
}
|
||||
|
||||
void
|
||||
commit() noexcept
|
||||
{
|
||||
obj_ = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
class object::revert_insert
|
||||
{
|
||||
object* obj_;
|
||||
std::size_t size_;
|
||||
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
destroy() noexcept;
|
||||
|
||||
public:
|
||||
explicit
|
||||
revert_insert(
|
||||
object& obj) noexcept
|
||||
: obj_(&obj)
|
||||
, size_(obj_->size())
|
||||
{
|
||||
}
|
||||
|
||||
~revert_insert()
|
||||
{
|
||||
if(! obj_)
|
||||
return;
|
||||
destroy();
|
||||
obj_->t_->size = static_cast<
|
||||
index_t>(size_);
|
||||
}
|
||||
|
||||
void
|
||||
commit() noexcept
|
||||
{
|
||||
obj_ = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Iterators
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
auto
|
||||
object::
|
||||
begin() noexcept ->
|
||||
iterator
|
||||
{
|
||||
return &(*t_)[0];
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
begin() const noexcept ->
|
||||
const_iterator
|
||||
{
|
||||
return &(*t_)[0];
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
cbegin() const noexcept ->
|
||||
const_iterator
|
||||
{
|
||||
return &(*t_)[0];
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
end() noexcept ->
|
||||
iterator
|
||||
{
|
||||
return &(*t_)[t_->size];
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
end() const noexcept ->
|
||||
const_iterator
|
||||
{
|
||||
return &(*t_)[t_->size];
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
cend() const noexcept ->
|
||||
const_iterator
|
||||
{
|
||||
return &(*t_)[t_->size];
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
rbegin() noexcept ->
|
||||
reverse_iterator
|
||||
{
|
||||
return reverse_iterator(end());
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
rbegin() const noexcept ->
|
||||
const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
crbegin() const noexcept ->
|
||||
const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
rend() noexcept ->
|
||||
reverse_iterator
|
||||
{
|
||||
return reverse_iterator(begin());
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
rend() const noexcept ->
|
||||
const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
crend() const noexcept ->
|
||||
const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Capacity
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
bool
|
||||
object::
|
||||
empty() const noexcept
|
||||
{
|
||||
return t_->size == 0;
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
size() const noexcept ->
|
||||
std::size_t
|
||||
{
|
||||
return t_->size;
|
||||
}
|
||||
|
||||
constexpr
|
||||
std::size_t
|
||||
object::
|
||||
max_size() noexcept
|
||||
{
|
||||
// max_size depends on the address model
|
||||
using min = std::integral_constant<std::size_t,
|
||||
(std::size_t(-1) - sizeof(table)) /
|
||||
(sizeof(key_value_pair) + sizeof(index_t))>;
|
||||
return min::value < BOOST_JSON_MAX_STRUCTURED_SIZE ?
|
||||
min::value : BOOST_JSON_MAX_STRUCTURED_SIZE;
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
capacity() const noexcept ->
|
||||
std::size_t
|
||||
{
|
||||
return t_->capacity;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Lookup
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
auto
|
||||
object::
|
||||
at(string_view key) ->
|
||||
value&
|
||||
{
|
||||
auto it = find(key);
|
||||
if(it == end())
|
||||
detail::throw_out_of_range(
|
||||
BOOST_CURRENT_LOCATION);
|
||||
return it->value();
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
at(string_view key) const ->
|
||||
value const&
|
||||
{
|
||||
auto it = find(key);
|
||||
if(it == end())
|
||||
detail::throw_out_of_range(
|
||||
BOOST_CURRENT_LOCATION);
|
||||
return it->value();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
template<class P, class>
|
||||
auto
|
||||
object::
|
||||
insert(P&& p) ->
|
||||
std::pair<iterator, bool>
|
||||
{
|
||||
key_value_pair v(
|
||||
std::forward<P>(p), sp_);
|
||||
return insert_impl(pilfer(v));
|
||||
}
|
||||
|
||||
template<class M>
|
||||
auto
|
||||
object::
|
||||
insert_or_assign(
|
||||
string_view key, M&& m) ->
|
||||
std::pair<iterator, bool>
|
||||
{
|
||||
reserve(size() + 1);
|
||||
auto const result = find_impl(key);
|
||||
if(result.first)
|
||||
{
|
||||
value(std::forward<M>(m),
|
||||
sp_).swap(result.first->value());
|
||||
return { result.first, false };
|
||||
}
|
||||
key_value_pair kv(key,
|
||||
std::forward<M>(m), sp_);
|
||||
return { insert_impl(pilfer(kv),
|
||||
result.second), true };
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
auto
|
||||
object::
|
||||
emplace(
|
||||
string_view key,
|
||||
Arg&& arg) ->
|
||||
std::pair<iterator, bool>
|
||||
{
|
||||
reserve(size() + 1);
|
||||
auto const result = find_impl(key);
|
||||
if(result.first)
|
||||
return { result.first, false };
|
||||
key_value_pair kv(key,
|
||||
std::forward<Arg>(arg), sp_);
|
||||
return { insert_impl(pilfer(kv),
|
||||
result.second), true };
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// (private)
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
object::
|
||||
construct(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
std::size_t min_capacity,
|
||||
std::input_iterator_tag)
|
||||
{
|
||||
reserve(min_capacity);
|
||||
revert_construct r(*this);
|
||||
while(first != last)
|
||||
{
|
||||
insert(*first);
|
||||
++first;
|
||||
}
|
||||
r.commit();
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
object::
|
||||
construct(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
std::size_t min_capacity,
|
||||
std::forward_iterator_tag)
|
||||
{
|
||||
auto n = static_cast<
|
||||
std::size_t>(std::distance(
|
||||
first, last));
|
||||
if( n < min_capacity)
|
||||
n = min_capacity;
|
||||
reserve(n);
|
||||
revert_construct r(*this);
|
||||
while(first != last)
|
||||
{
|
||||
insert(*first);
|
||||
++first;
|
||||
}
|
||||
r.commit();
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
object::
|
||||
insert(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
std::input_iterator_tag)
|
||||
{
|
||||
// Since input iterators cannot be rewound,
|
||||
// we keep inserted elements on an exception.
|
||||
//
|
||||
while(first != last)
|
||||
{
|
||||
insert(*first);
|
||||
++first;
|
||||
}
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
object::
|
||||
insert(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
std::forward_iterator_tag)
|
||||
{
|
||||
auto const n =
|
||||
static_cast<std::size_t>(
|
||||
std::distance(first, last));
|
||||
auto const n0 = size();
|
||||
if(n > max_size() - n0)
|
||||
detail::throw_length_error(
|
||||
"object too large",
|
||||
BOOST_CURRENT_LOCATION);
|
||||
reserve(n0 + n);
|
||||
revert_insert r(*this);
|
||||
while(first != last)
|
||||
{
|
||||
insert(*first);
|
||||
++first;
|
||||
}
|
||||
r.commit();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
namespace detail {
|
||||
|
||||
unchecked_object::
|
||||
~unchecked_object()
|
||||
{
|
||||
if(! data_)
|
||||
return;
|
||||
if(sp_.is_not_shared_and_deallocate_is_trivial())
|
||||
return;
|
||||
value* p = data_;
|
||||
while(size_--)
|
||||
{
|
||||
p[0].~value();
|
||||
p[1].~value();
|
||||
p += 2;
|
||||
}
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
825
install/boost_1_75_0/include/boost/json/impl/object.ipp
Normal file
825
install/boost_1_75_0/include/boost/json/impl/object.ipp
Normal file
@@ -0,0 +1,825 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_OBJECT_IPP
|
||||
#define BOOST_JSON_IMPL_OBJECT_IPP
|
||||
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/detail/digest.hpp>
|
||||
#include <boost/json/detail/except.hpp>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <new>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
constexpr object::table::table() = default;
|
||||
|
||||
// empty objects point here
|
||||
BOOST_JSON_REQUIRE_CONST_INIT
|
||||
object::table object::empty_;
|
||||
|
||||
std::size_t
|
||||
object::table::
|
||||
digest(string_view key) const noexcept
|
||||
{
|
||||
BOOST_ASSERT(salt != 0);
|
||||
return detail::digest(
|
||||
key.data(), key.size(), salt);
|
||||
}
|
||||
|
||||
auto
|
||||
object::table::
|
||||
bucket(std::size_t hash) noexcept ->
|
||||
index_t&
|
||||
{
|
||||
return reinterpret_cast<
|
||||
index_t*>(&(*this)[capacity])[
|
||||
hash % capacity];
|
||||
}
|
||||
|
||||
auto
|
||||
object::table::
|
||||
bucket(string_view key) noexcept ->
|
||||
index_t&
|
||||
{
|
||||
return bucket(digest(key));
|
||||
}
|
||||
|
||||
void
|
||||
object::table::
|
||||
clear() noexcept
|
||||
{
|
||||
BOOST_ASSERT(! is_small());
|
||||
// initialize buckets
|
||||
std::memset(
|
||||
reinterpret_cast<index_t*>(
|
||||
&(*this)[capacity]),
|
||||
0xff, // null_index_
|
||||
capacity * sizeof(index_t));
|
||||
}
|
||||
|
||||
object::table*
|
||||
object::table::
|
||||
allocate(
|
||||
std::size_t capacity,
|
||||
std::uintptr_t salt,
|
||||
storage_ptr const& sp)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(
|
||||
alignof(key_value_pair) >=
|
||||
alignof(index_t));
|
||||
BOOST_ASSERT(capacity > 0);
|
||||
BOOST_ASSERT(capacity <= max_size());
|
||||
table* p;
|
||||
if(capacity <= detail::small_object_size_)
|
||||
{
|
||||
p = reinterpret_cast<
|
||||
table*>(sp->allocate(
|
||||
sizeof(table) + capacity *
|
||||
sizeof(key_value_pair)));
|
||||
p->capacity = static_cast<
|
||||
std::uint32_t>(capacity);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = reinterpret_cast<
|
||||
table*>(sp->allocate(
|
||||
sizeof(table) + capacity * (
|
||||
sizeof(key_value_pair) +
|
||||
sizeof(index_t))));
|
||||
p->capacity = static_cast<
|
||||
std::uint32_t>(capacity);
|
||||
p->clear();
|
||||
}
|
||||
if(salt)
|
||||
{
|
||||
p->salt = salt;
|
||||
}
|
||||
else
|
||||
{
|
||||
// VFALCO This would be better if it
|
||||
// was random, but maybe this
|
||||
// is good enough.
|
||||
p->salt = reinterpret_cast<
|
||||
std::uintptr_t>(p);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
object::
|
||||
revert_construct::
|
||||
destroy() noexcept
|
||||
{
|
||||
obj_->destroy();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
object::
|
||||
revert_insert::
|
||||
destroy() noexcept
|
||||
{
|
||||
obj_->destroy(
|
||||
&(*obj_->t_)[size_],
|
||||
obj_->end());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Construction
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
object::
|
||||
object(detail::unchecked_object&& uo)
|
||||
: sp_(uo.storage())
|
||||
{
|
||||
if(uo.size() == 0)
|
||||
{
|
||||
t_ = &empty_;
|
||||
return;
|
||||
}
|
||||
// should already be checked
|
||||
BOOST_ASSERT(
|
||||
uo.size() <= max_size());
|
||||
t_ = table::allocate(
|
||||
uo.size(), 0, sp_);
|
||||
|
||||
// insert all elements, keeping
|
||||
// the last of any duplicate keys.
|
||||
auto dest = begin();
|
||||
auto src = uo.release();
|
||||
auto const end = src + 2 * uo.size();
|
||||
if(t_->is_small())
|
||||
{
|
||||
t_->size = 0;
|
||||
while(src != end)
|
||||
{
|
||||
access::construct_key_value_pair(
|
||||
dest, pilfer(src[0]), pilfer(src[1]));
|
||||
src += 2;
|
||||
auto result = find_impl(dest->key());
|
||||
if(! result.first)
|
||||
{
|
||||
++dest;
|
||||
++t_->size;
|
||||
continue;
|
||||
}
|
||||
// handle duplicate
|
||||
auto& v = *result.first;
|
||||
// don't bother to check if
|
||||
// storage deallocate is trivial
|
||||
v.~key_value_pair();
|
||||
// trivial relocate
|
||||
std::memcpy(
|
||||
static_cast<void*>(&v),
|
||||
dest, sizeof(v));
|
||||
}
|
||||
return;
|
||||
}
|
||||
while(src != end)
|
||||
{
|
||||
access::construct_key_value_pair(
|
||||
dest, pilfer(src[0]), pilfer(src[1]));
|
||||
src += 2;
|
||||
auto& head = t_->bucket(dest->key());
|
||||
auto i = head;
|
||||
for(;;)
|
||||
{
|
||||
if(i == null_index_)
|
||||
{
|
||||
// end of bucket
|
||||
access::next(
|
||||
*dest) = head;
|
||||
head = static_cast<index_t>(
|
||||
dest - begin());
|
||||
++dest;
|
||||
break;
|
||||
}
|
||||
auto& v = (*t_)[i];
|
||||
if(v.key() != dest->key())
|
||||
{
|
||||
i = access::next(v);
|
||||
continue;
|
||||
}
|
||||
|
||||
// handle duplicate
|
||||
access::next(*dest) =
|
||||
access::next(v);
|
||||
// don't bother to check if
|
||||
// storage deallocate is trivial
|
||||
v.~key_value_pair();
|
||||
// trivial relocate
|
||||
std::memcpy(
|
||||
static_cast<void*>(&v),
|
||||
dest, sizeof(v));
|
||||
break;
|
||||
}
|
||||
}
|
||||
t_->size = static_cast<
|
||||
index_t>(dest - begin());
|
||||
}
|
||||
|
||||
object::
|
||||
~object()
|
||||
{
|
||||
if(sp_.is_not_shared_and_deallocate_is_trivial())
|
||||
return;
|
||||
if(t_->capacity == 0)
|
||||
return;
|
||||
destroy();
|
||||
}
|
||||
|
||||
object::
|
||||
object(
|
||||
std::size_t min_capacity,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
, t_(&empty_)
|
||||
{
|
||||
reserve(min_capacity);
|
||||
}
|
||||
|
||||
object::
|
||||
object(object&& other) noexcept
|
||||
: sp_(other.sp_)
|
||||
, t_(detail::exchange(
|
||||
other.t_, &empty_))
|
||||
{
|
||||
}
|
||||
|
||||
object::
|
||||
object(
|
||||
object&& other,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
if(*sp_ == *other.sp_)
|
||||
{
|
||||
t_ = detail::exchange(
|
||||
other.t_, &empty_);
|
||||
return;
|
||||
}
|
||||
|
||||
t_ = &empty_;
|
||||
object(other, sp_).swap(*this);
|
||||
}
|
||||
|
||||
object::
|
||||
object(
|
||||
object const& other,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
, t_(&empty_)
|
||||
{
|
||||
reserve(other.size());
|
||||
revert_construct r(*this);
|
||||
if(t_->is_small())
|
||||
{
|
||||
for(auto const& v : other)
|
||||
{
|
||||
::new(end())
|
||||
key_value_pair(v, sp_);
|
||||
++t_->size;
|
||||
}
|
||||
r.commit();
|
||||
return;
|
||||
}
|
||||
for(auto const& v : other)
|
||||
{
|
||||
// skip duplicate checking
|
||||
auto& head =
|
||||
t_->bucket(v.key());
|
||||
auto pv = ::new(end())
|
||||
key_value_pair(v, sp_);
|
||||
access::next(*pv) = head;
|
||||
head = t_->size;
|
||||
++t_->size;
|
||||
}
|
||||
r.commit();
|
||||
}
|
||||
|
||||
object::
|
||||
object(
|
||||
std::initializer_list<std::pair<
|
||||
string_view, value_ref>> init,
|
||||
std::size_t min_capacity,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
, t_(&empty_)
|
||||
{
|
||||
if( min_capacity < init.size())
|
||||
min_capacity = init.size();
|
||||
reserve(min_capacity);
|
||||
revert_construct r(*this);
|
||||
insert(init);
|
||||
r.commit();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Assignment
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
object&
|
||||
object::
|
||||
operator=(object const& other)
|
||||
{
|
||||
object tmp(other, sp_);
|
||||
this->~object();
|
||||
::new(this) object(pilfer(tmp));
|
||||
return *this;
|
||||
}
|
||||
|
||||
object&
|
||||
object::
|
||||
operator=(object&& other)
|
||||
{
|
||||
object tmp(std::move(other), sp_);
|
||||
this->~object();
|
||||
::new(this) object(pilfer(tmp));
|
||||
return *this;
|
||||
}
|
||||
|
||||
object&
|
||||
object::
|
||||
operator=(
|
||||
std::initializer_list<std::pair<
|
||||
string_view, value_ref>> init)
|
||||
{
|
||||
object tmp(init, sp_);
|
||||
this->~object();
|
||||
::new(this) object(pilfer(tmp));
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Modifiers
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
object::
|
||||
clear() noexcept
|
||||
{
|
||||
if(empty())
|
||||
return;
|
||||
if(! sp_.is_not_shared_and_deallocate_is_trivial())
|
||||
destroy(begin(), end());
|
||||
if(! t_->is_small())
|
||||
t_->clear();
|
||||
t_->size = 0;
|
||||
}
|
||||
|
||||
void
|
||||
object::
|
||||
insert(
|
||||
std::initializer_list<std::pair<
|
||||
string_view, value_ref>> init)
|
||||
{
|
||||
auto const n0 = size();
|
||||
if(init.size() > max_size() - n0)
|
||||
detail::throw_length_error(
|
||||
"object too large",
|
||||
BOOST_CURRENT_LOCATION);
|
||||
reserve(n0 + init.size());
|
||||
revert_insert r(*this);
|
||||
if(t_->is_small())
|
||||
{
|
||||
for(auto& iv : init)
|
||||
{
|
||||
auto result =
|
||||
find_impl(iv.first);
|
||||
if(result.first)
|
||||
{
|
||||
// ignore duplicate
|
||||
continue;
|
||||
}
|
||||
::new(end()) key_value_pair(
|
||||
iv.first,
|
||||
iv.second.make_value(sp_));
|
||||
++t_->size;
|
||||
}
|
||||
r.commit();
|
||||
return;
|
||||
}
|
||||
for(auto& iv : init)
|
||||
{
|
||||
auto& head = t_->bucket(iv.first);
|
||||
auto i = head;
|
||||
for(;;)
|
||||
{
|
||||
if(i == null_index_)
|
||||
{
|
||||
// VFALCO value_ref should construct
|
||||
// a key_value_pair using placement
|
||||
auto& v = *::new(end())
|
||||
key_value_pair(
|
||||
iv.first,
|
||||
iv.second.make_value(sp_));
|
||||
access::next(v) = head;
|
||||
head = static_cast<index_t>(
|
||||
t_->size);
|
||||
++t_->size;
|
||||
break;
|
||||
}
|
||||
auto& v = (*t_)[i];
|
||||
if(v.key() == iv.first)
|
||||
{
|
||||
// ignore duplicate
|
||||
break;
|
||||
}
|
||||
i = access::next(v);
|
||||
}
|
||||
}
|
||||
r.commit();
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
erase(const_iterator pos) noexcept ->
|
||||
iterator
|
||||
{
|
||||
auto p = begin() + (pos - begin());
|
||||
if(t_->is_small())
|
||||
{
|
||||
p->~value_type();
|
||||
--t_->size;
|
||||
auto const pb = end();
|
||||
if(p != end())
|
||||
{
|
||||
// the casts silence warnings
|
||||
std::memcpy(
|
||||
static_cast<void*>(p),
|
||||
static_cast<void const*>(pb),
|
||||
sizeof(*p));
|
||||
}
|
||||
return p;
|
||||
}
|
||||
remove(t_->bucket(p->key()), *p);
|
||||
p->~value_type();
|
||||
--t_->size;
|
||||
auto const pb = end();
|
||||
if(p != end())
|
||||
{
|
||||
auto& head = t_->bucket(pb->key());
|
||||
remove(head, *pb);
|
||||
// the casts silence warnings
|
||||
std::memcpy(
|
||||
static_cast<void*>(p),
|
||||
static_cast<void const*>(pb),
|
||||
sizeof(*p));
|
||||
access::next(*p) = head;
|
||||
head = static_cast<
|
||||
index_t>(p - begin());
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
erase(string_view key) noexcept ->
|
||||
std::size_t
|
||||
{
|
||||
auto it = find(key);
|
||||
if(it == end())
|
||||
return 0;
|
||||
erase(it);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
object::
|
||||
swap(object& other)
|
||||
{
|
||||
if(*sp_ == *other.sp_)
|
||||
{
|
||||
t_ = detail::exchange(
|
||||
other.t_, t_);
|
||||
return;
|
||||
}
|
||||
object temp1(
|
||||
std::move(*this),
|
||||
other.storage());
|
||||
object temp2(
|
||||
std::move(other),
|
||||
this->storage());
|
||||
other.~object();
|
||||
::new(&other) object(pilfer(temp1));
|
||||
this->~object();
|
||||
::new(this) object(pilfer(temp2));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Lookup
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
auto
|
||||
object::
|
||||
operator[](string_view key) ->
|
||||
value&
|
||||
{
|
||||
auto const result =
|
||||
emplace(key, nullptr);
|
||||
return result.first->value();
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
count(string_view key) const noexcept ->
|
||||
std::size_t
|
||||
{
|
||||
if(find(key) == end())
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
find(string_view key) noexcept ->
|
||||
iterator
|
||||
{
|
||||
if(empty())
|
||||
return end();
|
||||
auto const p =
|
||||
find_impl(key).first;
|
||||
if(p)
|
||||
return p;
|
||||
return end();
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
find(string_view key) const noexcept ->
|
||||
const_iterator
|
||||
{
|
||||
if(empty())
|
||||
return end();
|
||||
auto const p =
|
||||
find_impl(key).first;
|
||||
if(p)
|
||||
return p;
|
||||
return end();
|
||||
}
|
||||
|
||||
bool
|
||||
object::
|
||||
contains(
|
||||
string_view key) const noexcept
|
||||
{
|
||||
if(empty())
|
||||
return false;
|
||||
return find_impl(
|
||||
key).first != nullptr;
|
||||
}
|
||||
|
||||
value const*
|
||||
object::
|
||||
if_contains(
|
||||
string_view key) const noexcept
|
||||
{
|
||||
auto const it = find(key);
|
||||
if(it != end())
|
||||
return &it->value();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
value*
|
||||
object::
|
||||
if_contains(
|
||||
string_view key) noexcept
|
||||
{
|
||||
auto const it = find(key);
|
||||
if(it != end())
|
||||
return &it->value();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// (private)
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
auto
|
||||
object::
|
||||
find_impl(
|
||||
string_view key) const noexcept ->
|
||||
std::pair<
|
||||
key_value_pair*,
|
||||
std::size_t>
|
||||
{
|
||||
BOOST_ASSERT(t_->capacity > 0);
|
||||
if(t_->is_small())
|
||||
{
|
||||
auto it = &(*t_)[0];
|
||||
auto const last =
|
||||
&(*t_)[t_->size];
|
||||
for(;it != last; ++it)
|
||||
if(key == it->key())
|
||||
return { it, 0 };
|
||||
return { nullptr, 0 };
|
||||
}
|
||||
std::pair<
|
||||
key_value_pair*,
|
||||
std::size_t> result;
|
||||
result.second = t_->digest(key);
|
||||
auto i = t_->bucket(
|
||||
result.second);
|
||||
while(i != null_index_)
|
||||
{
|
||||
auto& v = (*t_)[i];
|
||||
if(v.key() == key)
|
||||
{
|
||||
result.first = &v;
|
||||
return result;
|
||||
}
|
||||
i = access::next(v);
|
||||
}
|
||||
result.first = nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
insert_impl(
|
||||
pilfered<key_value_pair> p) ->
|
||||
std::pair<iterator, bool>
|
||||
{
|
||||
// caller is responsible
|
||||
// for preventing aliasing.
|
||||
reserve(size() + 1);
|
||||
auto const result =
|
||||
find_impl(p.get().key());
|
||||
if(result.first)
|
||||
return { result.first, false };
|
||||
return { insert_impl(
|
||||
p, result.second), true };
|
||||
}
|
||||
|
||||
key_value_pair*
|
||||
object::
|
||||
insert_impl(
|
||||
pilfered<key_value_pair> p,
|
||||
std::size_t hash)
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
capacity() > size());
|
||||
if(t_->is_small())
|
||||
{
|
||||
auto const pv = ::new(end())
|
||||
key_value_pair(p);
|
||||
++t_->size;
|
||||
return pv;
|
||||
}
|
||||
auto& head =
|
||||
t_->bucket(hash);
|
||||
auto const pv = ::new(end())
|
||||
key_value_pair(p);
|
||||
access::next(*pv) = head;
|
||||
head = t_->size;
|
||||
++t_->size;
|
||||
return pv;
|
||||
}
|
||||
|
||||
// rehash to at least `n` buckets
|
||||
void
|
||||
object::
|
||||
rehash(std::size_t new_capacity)
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
new_capacity > t_->capacity);
|
||||
auto t = table::allocate(
|
||||
growth(new_capacity),
|
||||
t_->salt, sp_);
|
||||
if(! empty())
|
||||
std::memcpy(
|
||||
static_cast<
|
||||
void*>(&(*t)[0]),
|
||||
begin(),
|
||||
size() * sizeof(
|
||||
key_value_pair));
|
||||
t->size = t_->size;
|
||||
table::deallocate(t_, sp_);
|
||||
t_ = t;
|
||||
|
||||
if(! t_->is_small())
|
||||
{
|
||||
// rebuild hash table,
|
||||
// without dup checks
|
||||
auto p = end();
|
||||
index_t i = t_->size;
|
||||
while(i-- > 0)
|
||||
{
|
||||
--p;
|
||||
auto& head =
|
||||
t_->bucket(p->key());
|
||||
access::next(*p) = head;
|
||||
head = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
object::
|
||||
equal(object const& other) const noexcept
|
||||
{
|
||||
if(size() != other.size())
|
||||
return false;
|
||||
auto const end_ = other.end();
|
||||
for(auto e : *this)
|
||||
{
|
||||
auto it = other.find(e.key());
|
||||
if(it == end_)
|
||||
return false;
|
||||
if(it->value() != e.value())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
object::
|
||||
growth(
|
||||
std::size_t new_size) const
|
||||
{
|
||||
if(new_size > max_size())
|
||||
detail::throw_length_error(
|
||||
"object too large",
|
||||
BOOST_CURRENT_LOCATION);
|
||||
std::size_t const old = capacity();
|
||||
if(old > max_size() - old / 2)
|
||||
return new_size;
|
||||
std::size_t const g =
|
||||
old + old / 2; // 1.5x
|
||||
if(g < new_size)
|
||||
return new_size;
|
||||
return g;
|
||||
}
|
||||
|
||||
void
|
||||
object::
|
||||
remove(
|
||||
index_t& head,
|
||||
key_value_pair& v) noexcept
|
||||
{
|
||||
BOOST_ASSERT(! t_->is_small());
|
||||
auto const i = static_cast<
|
||||
index_t>(&v - begin());
|
||||
if(head == i)
|
||||
{
|
||||
head = access::next(v);
|
||||
return;
|
||||
}
|
||||
auto* pn =
|
||||
&access::next((*t_)[head]);
|
||||
while(*pn != i)
|
||||
pn = &access::next((*t_)[*pn]);
|
||||
*pn = access::next(v);
|
||||
}
|
||||
|
||||
void
|
||||
object::
|
||||
destroy() noexcept
|
||||
{
|
||||
BOOST_ASSERT(t_->capacity > 0);
|
||||
BOOST_ASSERT(! sp_.is_not_shared_and_deallocate_is_trivial());
|
||||
destroy(begin(), end());
|
||||
table::deallocate(t_, sp_);
|
||||
}
|
||||
|
||||
void
|
||||
object::
|
||||
destroy(
|
||||
key_value_pair* first,
|
||||
key_value_pair* last) noexcept
|
||||
{
|
||||
BOOST_ASSERT(! sp_.is_not_shared_and_deallocate_is_trivial());
|
||||
while(last != first)
|
||||
(--last)->~key_value_pair();
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
54
install/boost_1_75_0/include/boost/json/impl/parse.ipp
Normal file
54
install/boost_1_75_0/include/boost/json/impl/parse.ipp
Normal file
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
|
||||
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_PARSE_IPP
|
||||
#define BOOST_JSON_IMPL_PARSE_IPP
|
||||
|
||||
#include <boost/json/parse.hpp>
|
||||
#include <boost/json/parser.hpp>
|
||||
#include <boost/json/detail/except.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
value
|
||||
parse(
|
||||
string_view s,
|
||||
error_code& ec,
|
||||
storage_ptr sp,
|
||||
const parse_options& opt)
|
||||
{
|
||||
unsigned char temp[
|
||||
BOOST_JSON_STACK_BUFFER_SIZE];
|
||||
parser p(storage_ptr(), opt, temp);
|
||||
p.reset(std::move(sp));
|
||||
p.write(s, ec);
|
||||
if(ec)
|
||||
return nullptr;
|
||||
return p.release();
|
||||
}
|
||||
|
||||
value
|
||||
parse(
|
||||
string_view s,
|
||||
storage_ptr sp,
|
||||
const parse_options& opt)
|
||||
{
|
||||
error_code ec;
|
||||
auto jv = parse(
|
||||
s, ec, std::move(sp), opt);
|
||||
if(ec)
|
||||
detail::throw_system_error(ec,
|
||||
BOOST_CURRENT_LOCATION);
|
||||
return jv;
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
136
install/boost_1_75_0/include/boost/json/impl/parser.ipp
Normal file
136
install/boost_1_75_0/include/boost/json/impl/parser.ipp
Normal file
@@ -0,0 +1,136 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_PARSER_IPP
|
||||
#define BOOST_JSON_IMPL_PARSER_IPP
|
||||
|
||||
#include <boost/json/parser.hpp>
|
||||
#include <boost/json/basic_parser_impl.hpp>
|
||||
#include <boost/json/error.hpp>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
parser::
|
||||
parser(
|
||||
storage_ptr sp,
|
||||
parse_options const& opt,
|
||||
unsigned char* buffer,
|
||||
std::size_t size) noexcept
|
||||
: p_(
|
||||
opt,
|
||||
std::move(sp),
|
||||
buffer,
|
||||
size)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
parser::
|
||||
parser(
|
||||
storage_ptr sp,
|
||||
parse_options const& opt) noexcept
|
||||
: p_(
|
||||
opt,
|
||||
std::move(sp),
|
||||
nullptr,
|
||||
0)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void
|
||||
parser::
|
||||
reset(storage_ptr sp) noexcept
|
||||
{
|
||||
p_.reset();
|
||||
p_.handler().st.reset(sp);
|
||||
}
|
||||
|
||||
std::size_t
|
||||
parser::
|
||||
write_some(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec)
|
||||
{
|
||||
auto const n = p_.write_some(
|
||||
false, data, size, ec);
|
||||
BOOST_ASSERT(ec || p_.done());
|
||||
return n;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
parser::
|
||||
write_some(
|
||||
char const* data,
|
||||
std::size_t size)
|
||||
{
|
||||
error_code ec;
|
||||
auto const n = write_some(
|
||||
data, size, ec);
|
||||
if(ec)
|
||||
detail::throw_system_error(ec,
|
||||
BOOST_CURRENT_LOCATION);
|
||||
return n;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
parser::
|
||||
write(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec)
|
||||
{
|
||||
auto const n = write_some(
|
||||
data, size, ec);
|
||||
if(! ec && n < size)
|
||||
{
|
||||
ec = error::extra_data;
|
||||
p_.fail(ec);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
parser::
|
||||
write(
|
||||
char const* data,
|
||||
std::size_t size)
|
||||
{
|
||||
error_code ec;
|
||||
auto const n = write(
|
||||
data, size, ec);
|
||||
if(ec)
|
||||
detail::throw_system_error(ec,
|
||||
BOOST_CURRENT_LOCATION);
|
||||
return n;
|
||||
}
|
||||
|
||||
value
|
||||
parser::
|
||||
release()
|
||||
{
|
||||
if( ! p_.done())
|
||||
{
|
||||
// prevent undefined behavior
|
||||
if(! p_.last_error())
|
||||
p_.fail(error::incomplete);
|
||||
detail::throw_system_error(
|
||||
p_.last_error(),
|
||||
BOOST_CURRENT_LOCATION);
|
||||
}
|
||||
return p_.handler().st.release();
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
191
install/boost_1_75_0/include/boost/json/impl/serialize.ipp
Normal file
191
install/boost_1_75_0/include/boost/json/impl/serialize.ipp
Normal file
@@ -0,0 +1,191 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_SERIALIZE_IPP
|
||||
#define BOOST_JSON_IMPL_SERIALIZE_IPP
|
||||
|
||||
#include <boost/json/serialize.hpp>
|
||||
#include <boost/json/serializer.hpp>
|
||||
#include <ostream>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
static
|
||||
void
|
||||
serialize_impl(
|
||||
std::string& s,
|
||||
serializer& sr)
|
||||
{
|
||||
// serialize to a small buffer to avoid
|
||||
// the first few allocations in std::string
|
||||
char buf[BOOST_JSON_STACK_BUFFER_SIZE];
|
||||
string_view sv;
|
||||
sv = sr.read(buf);
|
||||
if(sr.done())
|
||||
{
|
||||
// fast path
|
||||
s.append(
|
||||
sv.data(), sv.size());
|
||||
return;
|
||||
}
|
||||
std::size_t len = sv.size();
|
||||
s.reserve(len * 2);
|
||||
s.resize(s.capacity());
|
||||
BOOST_ASSERT(
|
||||
s.size() >= len * 2);
|
||||
std::memcpy(&s[0],
|
||||
sv.data(), sv.size());
|
||||
for(;;)
|
||||
{
|
||||
sv = sr.read(
|
||||
&s[0] + len,
|
||||
s.size() - len);
|
||||
len += sv.size();
|
||||
if(sr.done())
|
||||
break;
|
||||
s.resize(
|
||||
s.capacity() + 1);
|
||||
}
|
||||
s.resize(len);
|
||||
}
|
||||
|
||||
std::string
|
||||
serialize(
|
||||
value const& jv)
|
||||
{
|
||||
std::string s;
|
||||
serializer sr;
|
||||
sr.reset(&jv);
|
||||
serialize_impl(s, sr);
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string
|
||||
serialize(
|
||||
array const& arr)
|
||||
{
|
||||
std::string s;
|
||||
serializer sr;
|
||||
sr.reset(&arr);
|
||||
serialize_impl(s, sr);
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string
|
||||
serialize(
|
||||
object const& obj)
|
||||
{
|
||||
std::string s;
|
||||
serializer sr;
|
||||
sr.reset(&obj);
|
||||
serialize_impl(s, sr);
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string
|
||||
serialize(
|
||||
string const& str)
|
||||
{
|
||||
std::string s;
|
||||
serializer sr;
|
||||
sr.reset(&str);
|
||||
serialize_impl(s, sr);
|
||||
return s;
|
||||
}
|
||||
|
||||
// this is here for key_value_pair::key()
|
||||
std::string
|
||||
serialize(
|
||||
string_view sv)
|
||||
{
|
||||
std::string s;
|
||||
serializer sr;
|
||||
sr.reset(sv);
|
||||
serialize_impl(s, sr);
|
||||
return s;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
//[example_operator_lt__lt_
|
||||
// Serialize a value into an output stream
|
||||
|
||||
std::ostream&
|
||||
operator<<( std::ostream& os, value const& jv )
|
||||
{
|
||||
// Create a serializer
|
||||
serializer sr;
|
||||
|
||||
// Set the serializer up for our value
|
||||
sr.reset( &jv );
|
||||
|
||||
// Loop until all output is produced.
|
||||
while( ! sr.done() )
|
||||
{
|
||||
// Use a local buffer to avoid allocation.
|
||||
char buf[ BOOST_JSON_STACK_BUFFER_SIZE ];
|
||||
|
||||
// Fill our buffer with serialized characters and write it to the output stream.
|
||||
os << sr.read( buf );
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
//]
|
||||
|
||||
static
|
||||
void
|
||||
to_ostream(
|
||||
std::ostream& os,
|
||||
serializer& sr)
|
||||
{
|
||||
while(! sr.done())
|
||||
{
|
||||
char buf[BOOST_JSON_STACK_BUFFER_SIZE];
|
||||
auto s = sr.read(buf);
|
||||
os.write(s.data(), s.size());
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(
|
||||
std::ostream& os,
|
||||
array const& arr)
|
||||
{
|
||||
serializer sr;
|
||||
sr.reset(&arr);
|
||||
to_ostream(os, sr);
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(
|
||||
std::ostream& os,
|
||||
object const& obj)
|
||||
{
|
||||
serializer sr;
|
||||
sr.reset(&obj);
|
||||
to_ostream(os, sr);
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(
|
||||
std::ostream& os,
|
||||
string const& str)
|
||||
{
|
||||
serializer sr;
|
||||
sr.reset(&str);
|
||||
to_ostream(os, sr);
|
||||
return os;
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
822
install/boost_1_75_0/include/boost/json/impl/serializer.ipp
Normal file
822
install/boost_1_75_0/include/boost/json/impl/serializer.ipp
Normal file
@@ -0,0 +1,822 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_SERIALIZER_IPP
|
||||
#define BOOST_JSON_IMPL_SERIALIZER_IPP
|
||||
|
||||
#include <boost/json/serializer.hpp>
|
||||
#include <boost/json/detail/format.hpp>
|
||||
#include <boost/json/detail/sse2.hpp>
|
||||
#include <ostream>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
enum class serializer::state : char
|
||||
{
|
||||
nul1, nul2, nul3, nul4,
|
||||
tru1, tru2, tru3, tru4,
|
||||
fal1, fal2, fal3, fal4, fal5,
|
||||
str1, str2, str3, str4, esc1,
|
||||
utf1, utf2, utf3, utf4, utf5,
|
||||
num,
|
||||
arr1, arr2, arr3, arr4,
|
||||
obj1, obj2, obj3, obj4, obj5, obj6
|
||||
};
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
serializer::
|
||||
~serializer() noexcept = default;
|
||||
|
||||
bool
|
||||
serializer::
|
||||
suspend(state st)
|
||||
{
|
||||
st_.push(st);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
serializer::
|
||||
suspend(
|
||||
state st,
|
||||
array::const_iterator it,
|
||||
array const* pa)
|
||||
{
|
||||
st_.push(pa);
|
||||
st_.push(it);
|
||||
st_.push(st);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
serializer::
|
||||
suspend(
|
||||
state st,
|
||||
object::const_iterator it,
|
||||
object const* po)
|
||||
{
|
||||
st_.push(po);
|
||||
st_.push(it);
|
||||
st_.push(st);
|
||||
return false;
|
||||
}
|
||||
|
||||
template<bool StackEmpty>
|
||||
bool
|
||||
serializer::
|
||||
write_null(stream& ss0)
|
||||
{
|
||||
local_stream ss(ss0);
|
||||
if(! StackEmpty && ! st_.empty())
|
||||
{
|
||||
state st;
|
||||
st_.pop(st);
|
||||
switch(st)
|
||||
{
|
||||
default:
|
||||
case state::nul1: goto do_nul1;
|
||||
case state::nul2: goto do_nul2;
|
||||
case state::nul3: goto do_nul3;
|
||||
case state::nul4: goto do_nul4;
|
||||
}
|
||||
}
|
||||
do_nul1:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('n');
|
||||
else
|
||||
return suspend(state::nul1);
|
||||
do_nul2:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('u');
|
||||
else
|
||||
return suspend(state::nul2);
|
||||
do_nul3:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('l');
|
||||
else
|
||||
return suspend(state::nul3);
|
||||
do_nul4:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('l');
|
||||
else
|
||||
return suspend(state::nul4);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<bool StackEmpty>
|
||||
bool
|
||||
serializer::
|
||||
write_true(stream& ss0)
|
||||
{
|
||||
local_stream ss(ss0);
|
||||
if(! StackEmpty && ! st_.empty())
|
||||
{
|
||||
state st;
|
||||
st_.pop(st);
|
||||
switch(st)
|
||||
{
|
||||
default:
|
||||
case state::tru1: goto do_tru1;
|
||||
case state::tru2: goto do_tru2;
|
||||
case state::tru3: goto do_tru3;
|
||||
case state::tru4: goto do_tru4;
|
||||
}
|
||||
}
|
||||
do_tru1:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('t');
|
||||
else
|
||||
return suspend(state::tru1);
|
||||
do_tru2:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('r');
|
||||
else
|
||||
return suspend(state::tru2);
|
||||
do_tru3:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('u');
|
||||
else
|
||||
return suspend(state::tru3);
|
||||
do_tru4:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('e');
|
||||
else
|
||||
return suspend(state::tru4);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<bool StackEmpty>
|
||||
bool
|
||||
serializer::
|
||||
write_false(stream& ss0)
|
||||
{
|
||||
local_stream ss(ss0);
|
||||
if(! StackEmpty && ! st_.empty())
|
||||
{
|
||||
state st;
|
||||
st_.pop(st);
|
||||
switch(st)
|
||||
{
|
||||
default:
|
||||
case state::fal1: goto do_fal1;
|
||||
case state::fal2: goto do_fal2;
|
||||
case state::fal3: goto do_fal3;
|
||||
case state::fal4: goto do_fal4;
|
||||
case state::fal5: goto do_fal5;
|
||||
}
|
||||
}
|
||||
do_fal1:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('f');
|
||||
else
|
||||
return suspend(state::fal1);
|
||||
do_fal2:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('a');
|
||||
else
|
||||
return suspend(state::fal2);
|
||||
do_fal3:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('l');
|
||||
else
|
||||
return suspend(state::fal3);
|
||||
do_fal4:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('s');
|
||||
else
|
||||
return suspend(state::fal4);
|
||||
do_fal5:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('e');
|
||||
else
|
||||
return suspend(state::fal5);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<bool StackEmpty>
|
||||
bool
|
||||
serializer::
|
||||
write_string(stream& ss0)
|
||||
{
|
||||
local_stream ss(ss0);
|
||||
local_const_stream cs(cs0_);
|
||||
if(! StackEmpty && ! st_.empty())
|
||||
{
|
||||
state st;
|
||||
st_.pop(st);
|
||||
switch(st)
|
||||
{
|
||||
default:
|
||||
case state::str1: goto do_str1;
|
||||
case state::str2: goto do_str2;
|
||||
case state::str3: goto do_str3;
|
||||
case state::str4: goto do_str4;
|
||||
case state::esc1: goto do_esc1;
|
||||
case state::utf1: goto do_utf1;
|
||||
case state::utf2: goto do_utf2;
|
||||
case state::utf3: goto do_utf3;
|
||||
case state::utf4: goto do_utf4;
|
||||
case state::utf5: goto do_utf5;
|
||||
}
|
||||
}
|
||||
static constexpr char hex[] = "0123456789abcdef";
|
||||
static constexpr char esc[] =
|
||||
"uuuuuuuubtnufruuuuuuuuuuuuuuuuuu"
|
||||
"\0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
|
||||
|
||||
// opening quote
|
||||
do_str1:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('\x22'); // '"'
|
||||
else
|
||||
return suspend(state::str1);
|
||||
|
||||
// fast loop,
|
||||
// copy unescaped
|
||||
do_str2:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
{
|
||||
std::size_t n = cs.remain();
|
||||
if(BOOST_JSON_LIKELY(n > 0))
|
||||
{
|
||||
if(ss.remain() > n)
|
||||
n = detail::count_unescaped(
|
||||
cs.data(), n);
|
||||
else
|
||||
n = detail::count_unescaped(
|
||||
cs.data(), ss.remain());
|
||||
if(n > 0)
|
||||
{
|
||||
ss.append(cs.data(), n);
|
||||
cs.skip(n);
|
||||
if(! ss)
|
||||
return suspend(state::str2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ss.append('\x22'); // '"'
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return suspend(state::str2);
|
||||
}
|
||||
|
||||
// slow loop,
|
||||
// handle escapes
|
||||
do_str3:
|
||||
while(BOOST_JSON_LIKELY(ss))
|
||||
{
|
||||
if(BOOST_JSON_LIKELY(cs))
|
||||
{
|
||||
auto const ch = *cs;
|
||||
auto const c = esc[static_cast<
|
||||
unsigned char>(ch)];
|
||||
++cs;
|
||||
if(! c)
|
||||
{
|
||||
ss.append(ch);
|
||||
}
|
||||
else if(c != 'u')
|
||||
{
|
||||
ss.append('\\');
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
{
|
||||
ss.append(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
buf_[0] = c;
|
||||
return suspend(
|
||||
state::esc1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(BOOST_JSON_LIKELY(
|
||||
ss.remain() >= 6))
|
||||
{
|
||||
ss.append("\\u00", 4);
|
||||
ss.append(hex[static_cast<
|
||||
unsigned char>(ch) >> 4]);
|
||||
ss.append(hex[static_cast<
|
||||
unsigned char>(ch) & 15]);
|
||||
}
|
||||
else
|
||||
{
|
||||
ss.append('\\');
|
||||
buf_[0] = hex[static_cast<
|
||||
unsigned char>(ch) >> 4];
|
||||
buf_[1] = hex[static_cast<
|
||||
unsigned char>(ch) & 15];
|
||||
goto do_utf1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ss.append('\x22'); // '"'
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return suspend(state::str3);
|
||||
|
||||
do_str4:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('\x22'); // '"'
|
||||
else
|
||||
return suspend(state::str4);
|
||||
|
||||
do_esc1:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append(buf_[0]);
|
||||
else
|
||||
return suspend(state::esc1);
|
||||
goto do_str3;
|
||||
|
||||
do_utf1:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('u');
|
||||
else
|
||||
return suspend(state::utf1);
|
||||
do_utf2:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('0');
|
||||
else
|
||||
return suspend(state::utf2);
|
||||
do_utf3:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('0');
|
||||
else
|
||||
return suspend(state::utf3);
|
||||
do_utf4:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append(buf_[0]);
|
||||
else
|
||||
return suspend(state::utf4);
|
||||
do_utf5:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append(buf_[1]);
|
||||
else
|
||||
return suspend(state::utf5);
|
||||
goto do_str3;
|
||||
}
|
||||
|
||||
template<bool StackEmpty>
|
||||
bool
|
||||
serializer::
|
||||
write_number(stream& ss0)
|
||||
{
|
||||
local_stream ss(ss0);
|
||||
if(StackEmpty || st_.empty())
|
||||
{
|
||||
switch(jv_->kind())
|
||||
{
|
||||
default:
|
||||
case kind::int64:
|
||||
if(BOOST_JSON_LIKELY(
|
||||
ss.remain() >=
|
||||
detail::max_number_chars))
|
||||
{
|
||||
ss.advance(detail::format_int64(
|
||||
ss.data(), jv_->get_int64()));
|
||||
return true;
|
||||
}
|
||||
cs0_ = { buf_, detail::format_int64(
|
||||
buf_, jv_->get_int64()) };
|
||||
break;
|
||||
|
||||
case kind::uint64:
|
||||
if(BOOST_JSON_LIKELY(
|
||||
ss.remain() >=
|
||||
detail::max_number_chars))
|
||||
{
|
||||
ss.advance(detail::format_uint64(
|
||||
ss.data(), jv_->get_uint64()));
|
||||
return true;
|
||||
}
|
||||
cs0_ = { buf_, detail::format_uint64(
|
||||
buf_, jv_->get_uint64()) };
|
||||
break;
|
||||
|
||||
case kind::double_:
|
||||
if(BOOST_JSON_LIKELY(
|
||||
ss.remain() >=
|
||||
detail::max_number_chars))
|
||||
{
|
||||
ss.advance(detail::format_double(
|
||||
ss.data(), jv_->get_double()));
|
||||
return true;
|
||||
}
|
||||
cs0_ = { buf_, detail::format_double(
|
||||
buf_, jv_->get_double()) };
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
state st;
|
||||
st_.pop(st);
|
||||
BOOST_ASSERT(
|
||||
st == state::num);
|
||||
}
|
||||
auto const n = ss.remain();
|
||||
if(n < cs0_.remain())
|
||||
{
|
||||
ss.append(cs0_.data(), n);
|
||||
cs0_.skip(n);
|
||||
return suspend(state::num);
|
||||
}
|
||||
ss.append(
|
||||
cs0_.data(), cs0_.remain());
|
||||
return true;
|
||||
}
|
||||
|
||||
template<bool StackEmpty>
|
||||
bool
|
||||
serializer::
|
||||
write_array(stream& ss0)
|
||||
{
|
||||
array const* pa;
|
||||
local_stream ss(ss0);
|
||||
array::const_iterator it;
|
||||
array::const_iterator end;
|
||||
if(StackEmpty || st_.empty())
|
||||
{
|
||||
pa = pa_;
|
||||
it = pa->begin();
|
||||
end = pa->end();
|
||||
}
|
||||
else
|
||||
{
|
||||
state st;
|
||||
st_.pop(st);
|
||||
st_.pop(it);
|
||||
st_.pop(pa);
|
||||
end = pa->end();
|
||||
switch(st)
|
||||
{
|
||||
default:
|
||||
case state::arr1: goto do_arr1;
|
||||
case state::arr2: goto do_arr2;
|
||||
case state::arr3: goto do_arr3;
|
||||
case state::arr4: goto do_arr4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
do_arr1:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('[');
|
||||
else
|
||||
return suspend(
|
||||
state::arr1, it, pa);
|
||||
if(it == end)
|
||||
goto do_arr4;
|
||||
for(;;)
|
||||
{
|
||||
do_arr2:
|
||||
jv_ = &*it;
|
||||
if(! write_value<StackEmpty>(ss))
|
||||
return suspend(
|
||||
state::arr2, it, pa);
|
||||
if(BOOST_JSON_UNLIKELY(
|
||||
++it == end))
|
||||
break;
|
||||
do_arr3:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append(',');
|
||||
else
|
||||
return suspend(
|
||||
state::arr3, it, pa);
|
||||
}
|
||||
do_arr4:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append(']');
|
||||
else
|
||||
return suspend(
|
||||
state::arr4, it, pa);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<bool StackEmpty>
|
||||
bool
|
||||
serializer::
|
||||
write_object(stream& ss0)
|
||||
{
|
||||
object const* po;
|
||||
local_stream ss(ss0);
|
||||
object::const_iterator it;
|
||||
object::const_iterator end;
|
||||
if(StackEmpty || st_.empty())
|
||||
{
|
||||
po = po_;
|
||||
it = po->begin();
|
||||
end = po->end();
|
||||
}
|
||||
else
|
||||
{
|
||||
state st;
|
||||
st_.pop(st);
|
||||
st_.pop(it);
|
||||
st_.pop(po);
|
||||
end = po->end();
|
||||
switch(st)
|
||||
{
|
||||
default:
|
||||
case state::obj1: goto do_obj1;
|
||||
case state::obj2: goto do_obj2;
|
||||
case state::obj3: goto do_obj3;
|
||||
case state::obj4: goto do_obj4;
|
||||
case state::obj5: goto do_obj5;
|
||||
case state::obj6: goto do_obj6;
|
||||
break;
|
||||
}
|
||||
}
|
||||
do_obj1:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('{');
|
||||
else
|
||||
return suspend(
|
||||
state::obj1, it, po);
|
||||
if(BOOST_JSON_UNLIKELY(
|
||||
it == end))
|
||||
goto do_obj6;
|
||||
for(;;)
|
||||
{
|
||||
cs0_ = {
|
||||
it->key().data(),
|
||||
it->key().size() };
|
||||
do_obj2:
|
||||
if(BOOST_JSON_UNLIKELY(
|
||||
! write_string<StackEmpty>(ss)))
|
||||
return suspend(
|
||||
state::obj2, it, po);
|
||||
do_obj3:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append(':');
|
||||
else
|
||||
return suspend(
|
||||
state::obj3, it, po);
|
||||
do_obj4:
|
||||
jv_ = &it->value();
|
||||
if(BOOST_JSON_UNLIKELY(
|
||||
! write_value<StackEmpty>(ss)))
|
||||
return suspend(
|
||||
state::obj4, it, po);
|
||||
++it;
|
||||
if(BOOST_JSON_UNLIKELY(it == end))
|
||||
break;
|
||||
do_obj5:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append(',');
|
||||
else
|
||||
return suspend(
|
||||
state::obj5, it, po);
|
||||
}
|
||||
do_obj6:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
{
|
||||
ss.append('}');
|
||||
return true;
|
||||
}
|
||||
return suspend(
|
||||
state::obj6, it, po);
|
||||
}
|
||||
|
||||
template<bool StackEmpty>
|
||||
bool
|
||||
serializer::
|
||||
write_value(stream& ss)
|
||||
{
|
||||
if(StackEmpty || st_.empty())
|
||||
{
|
||||
auto const& jv(*jv_);
|
||||
switch(jv.kind())
|
||||
{
|
||||
default:
|
||||
case kind::object:
|
||||
po_ = &jv.get_object();
|
||||
return write_object<true>(ss);
|
||||
|
||||
case kind::array:
|
||||
pa_ = &jv.get_array();
|
||||
return write_array<true>(ss);
|
||||
|
||||
case kind::string:
|
||||
{
|
||||
auto const& js = jv.get_string();
|
||||
cs0_ = { js.data(), js.size() };
|
||||
return write_string<true>(ss);
|
||||
}
|
||||
|
||||
case kind::int64:
|
||||
case kind::uint64:
|
||||
case kind::double_:
|
||||
return write_number<true>(ss);
|
||||
|
||||
case kind::bool_:
|
||||
if(jv.get_bool())
|
||||
{
|
||||
if(BOOST_JSON_LIKELY(
|
||||
ss.remain() >= 4))
|
||||
{
|
||||
ss.append("true", 4);
|
||||
return true;
|
||||
}
|
||||
return write_true<true>(ss);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(BOOST_JSON_LIKELY(
|
||||
ss.remain() >= 5))
|
||||
{
|
||||
ss.append("false", 5);
|
||||
return true;
|
||||
}
|
||||
return write_false<true>(ss);
|
||||
}
|
||||
|
||||
case kind::null:
|
||||
if(BOOST_JSON_LIKELY(
|
||||
ss.remain() >= 4))
|
||||
{
|
||||
ss.append("null", 4);
|
||||
return true;
|
||||
}
|
||||
return write_null<true>(ss);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
state st;
|
||||
st_.peek(st);
|
||||
switch(st)
|
||||
{
|
||||
default:
|
||||
case state::nul1: case state::nul2:
|
||||
case state::nul3: case state::nul4:
|
||||
return write_null<StackEmpty>(ss);
|
||||
|
||||
case state::tru1: case state::tru2:
|
||||
case state::tru3: case state::tru4:
|
||||
return write_true<StackEmpty>(ss);
|
||||
|
||||
case state::fal1: case state::fal2:
|
||||
case state::fal3: case state::fal4:
|
||||
case state::fal5:
|
||||
return write_false<StackEmpty>(ss);
|
||||
|
||||
case state::str1: case state::str2:
|
||||
case state::str3: case state::str4:
|
||||
case state::esc1:
|
||||
case state::utf1: case state::utf2:
|
||||
case state::utf3: case state::utf4:
|
||||
case state::utf5:
|
||||
return write_string<StackEmpty>(ss);
|
||||
|
||||
case state::num:
|
||||
return write_number<StackEmpty>(ss);
|
||||
|
||||
case state::arr1: case state::arr2:
|
||||
case state::arr3: case state::arr4:
|
||||
return write_array<StackEmpty>(ss);
|
||||
|
||||
case state::obj1: case state::obj2:
|
||||
case state::obj3: case state::obj4:
|
||||
case state::obj5: case state::obj6:
|
||||
return write_object<StackEmpty>(ss);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string_view
|
||||
serializer::
|
||||
read_some(
|
||||
char* dest, std::size_t size)
|
||||
{
|
||||
// If this goes off it means you forgot
|
||||
// to call reset() before seriailzing a
|
||||
// new value, or you never checked done()
|
||||
// to see if you should stop.
|
||||
BOOST_ASSERT(! done_);
|
||||
|
||||
stream ss(dest, size);
|
||||
if(st_.empty())
|
||||
(this->*fn0_)(ss);
|
||||
else
|
||||
(this->*fn1_)(ss);
|
||||
if(st_.empty())
|
||||
{
|
||||
done_ = true;
|
||||
jv_ = nullptr;
|
||||
}
|
||||
return string_view(
|
||||
dest, ss.used(dest));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
serializer::
|
||||
serializer() noexcept
|
||||
{
|
||||
// ensure room for \uXXXX escape plus one
|
||||
BOOST_STATIC_ASSERT(
|
||||
sizeof(serializer::buf_) >= 7);
|
||||
}
|
||||
|
||||
void
|
||||
serializer::
|
||||
reset(value const* p) noexcept
|
||||
{
|
||||
pv_ = p;
|
||||
fn0_ = &serializer::write_value<true>;
|
||||
fn1_ = &serializer::write_value<false>;
|
||||
|
||||
jv_ = p;
|
||||
st_.clear();
|
||||
done_ = false;
|
||||
}
|
||||
|
||||
void
|
||||
serializer::
|
||||
reset(array const* p) noexcept
|
||||
{
|
||||
pa_ = p;
|
||||
fn0_ = &serializer::write_array<true>;
|
||||
fn1_ = &serializer::write_array<false>;
|
||||
st_.clear();
|
||||
done_ = false;
|
||||
}
|
||||
|
||||
void
|
||||
serializer::
|
||||
reset(object const* p) noexcept
|
||||
{
|
||||
po_ = p;
|
||||
fn0_ = &serializer::write_object<true>;
|
||||
fn1_ = &serializer::write_object<false>;
|
||||
st_.clear();
|
||||
done_ = false;
|
||||
}
|
||||
|
||||
void
|
||||
serializer::
|
||||
reset(string const* p) noexcept
|
||||
{
|
||||
cs0_ = { p->data(), p->size() };
|
||||
fn0_ = &serializer::write_string<true>;
|
||||
fn1_ = &serializer::write_string<false>;
|
||||
st_.clear();
|
||||
done_ = false;
|
||||
}
|
||||
|
||||
void
|
||||
serializer::
|
||||
reset(string_view sv) noexcept
|
||||
{
|
||||
cs0_ = { sv.data(), sv.size() };
|
||||
fn0_ = &serializer::write_string<true>;
|
||||
fn1_ = &serializer::write_string<false>;
|
||||
st_.clear();
|
||||
done_ = false;
|
||||
}
|
||||
|
||||
string_view
|
||||
serializer::
|
||||
read(char* dest, std::size_t size)
|
||||
{
|
||||
if(! jv_)
|
||||
{
|
||||
static value const null;
|
||||
jv_ = &null;
|
||||
}
|
||||
return read_some(dest, size);
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,78 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_STATIC_RESOURCE_IPP
|
||||
#define BOOST_JSON_IMPL_STATIC_RESOURCE_IPP
|
||||
|
||||
#include <boost/json/static_resource.hpp>
|
||||
#include <boost/json/detail/align.hpp>
|
||||
#include <boost/json/detail/except.hpp>
|
||||
#include <memory>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
static_resource::
|
||||
~static_resource() noexcept = default;
|
||||
|
||||
static_resource::
|
||||
static_resource(
|
||||
unsigned char* buffer,
|
||||
std::size_t size) noexcept
|
||||
: p_(buffer)
|
||||
, n_(size)
|
||||
, size_(size)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
static_resource::
|
||||
release() noexcept
|
||||
{
|
||||
p_ = reinterpret_cast<
|
||||
char*>(p_) - (size_ - n_);
|
||||
n_ = size_;
|
||||
}
|
||||
|
||||
void*
|
||||
static_resource::
|
||||
do_allocate(
|
||||
std::size_t n,
|
||||
std::size_t align)
|
||||
{
|
||||
auto p = detail::align(
|
||||
align, n, p_, n_);
|
||||
if(! p)
|
||||
detail::throw_bad_alloc(
|
||||
BOOST_CURRENT_LOCATION);
|
||||
p_ = reinterpret_cast<char*>(p) + n;
|
||||
n_ -= n;
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
static_resource::
|
||||
do_deallocate(
|
||||
void*,
|
||||
std::size_t,
|
||||
std::size_t)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
bool
|
||||
static_resource::
|
||||
do_is_equal(
|
||||
memory_resource const& mr) const noexcept
|
||||
{
|
||||
return this == &mr;
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
148
install/boost_1_75_0/include/boost/json/impl/stream_parser.ipp
Normal file
148
install/boost_1_75_0/include/boost/json/impl/stream_parser.ipp
Normal file
@@ -0,0 +1,148 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_STREAM_PARSER_IPP
|
||||
#define BOOST_JSON_IMPL_STREAM_PARSER_IPP
|
||||
|
||||
#include <boost/json/stream_parser.hpp>
|
||||
#include <boost/json/basic_parser_impl.hpp>
|
||||
#include <boost/json/error.hpp>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
stream_parser::
|
||||
stream_parser(
|
||||
storage_ptr sp,
|
||||
parse_options const& opt,
|
||||
unsigned char* buffer,
|
||||
std::size_t size) noexcept
|
||||
: p_(
|
||||
opt,
|
||||
std::move(sp),
|
||||
buffer,
|
||||
size)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
stream_parser::
|
||||
stream_parser(
|
||||
storage_ptr sp,
|
||||
parse_options const& opt) noexcept
|
||||
: p_(
|
||||
opt,
|
||||
std::move(sp),
|
||||
nullptr,
|
||||
0)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void
|
||||
stream_parser::
|
||||
reset(storage_ptr sp) noexcept
|
||||
{
|
||||
p_.reset();
|
||||
p_.handler().st.reset(sp);
|
||||
}
|
||||
|
||||
std::size_t
|
||||
stream_parser::
|
||||
write_some(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec)
|
||||
{
|
||||
return p_.write_some(
|
||||
true, data, size, ec);
|
||||
}
|
||||
|
||||
std::size_t
|
||||
stream_parser::
|
||||
write_some(
|
||||
char const* data,
|
||||
std::size_t size)
|
||||
{
|
||||
error_code ec;
|
||||
auto const n = write_some(
|
||||
data, size, ec);
|
||||
if(ec)
|
||||
detail::throw_system_error(ec,
|
||||
BOOST_CURRENT_LOCATION);
|
||||
return n;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
stream_parser::
|
||||
write(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec)
|
||||
{
|
||||
auto const n = write_some(
|
||||
data, size, ec);
|
||||
if(! ec && n < size)
|
||||
{
|
||||
ec = error::extra_data;
|
||||
p_.fail(ec);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
stream_parser::
|
||||
write(
|
||||
char const* data,
|
||||
std::size_t size)
|
||||
{
|
||||
error_code ec;
|
||||
auto const n = write(
|
||||
data, size, ec);
|
||||
if(ec)
|
||||
detail::throw_system_error(ec,
|
||||
BOOST_CURRENT_LOCATION);
|
||||
return n;
|
||||
}
|
||||
|
||||
void
|
||||
stream_parser::
|
||||
finish(error_code& ec)
|
||||
{
|
||||
p_.write_some(false, nullptr, 0, ec);
|
||||
}
|
||||
|
||||
void
|
||||
stream_parser::
|
||||
finish()
|
||||
{
|
||||
error_code ec;
|
||||
finish(ec);
|
||||
if(ec)
|
||||
detail::throw_system_error(ec,
|
||||
BOOST_CURRENT_LOCATION);
|
||||
}
|
||||
|
||||
value
|
||||
stream_parser::
|
||||
release()
|
||||
{
|
||||
if(! p_.done())
|
||||
{
|
||||
// prevent undefined behavior
|
||||
finish();
|
||||
}
|
||||
return p_.handler().st.release();
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
236
install/boost_1_75_0/include/boost/json/impl/string.hpp
Normal file
236
install/boost_1_75_0/include/boost/json/impl/string.hpp
Normal file
@@ -0,0 +1,236 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_STRING_HPP
|
||||
#define BOOST_JSON_IMPL_STRING_HPP
|
||||
|
||||
#include <utility>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
string::
|
||||
string(
|
||||
detail::key_t const&,
|
||||
string_view s,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
, impl_(detail::key_t{},
|
||||
s, sp_)
|
||||
{
|
||||
}
|
||||
|
||||
string::
|
||||
string(
|
||||
detail::key_t const&,
|
||||
string_view s1,
|
||||
string_view s2,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
, impl_(detail::key_t{},
|
||||
s1, s2, sp_)
|
||||
{
|
||||
}
|
||||
|
||||
template<class InputIt, class>
|
||||
string::
|
||||
string(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
, impl_(first, last, sp_,
|
||||
iter_cat<InputIt>{})
|
||||
{
|
||||
}
|
||||
|
||||
template<class InputIt, class>
|
||||
string&
|
||||
string::
|
||||
assign(
|
||||
InputIt first,
|
||||
InputIt last)
|
||||
{
|
||||
assign(first, last,
|
||||
iter_cat<InputIt>{});
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class InputIt, class>
|
||||
string&
|
||||
string::
|
||||
append(InputIt first, InputIt last)
|
||||
{
|
||||
append(first, last,
|
||||
iter_cat<InputIt>{});
|
||||
return *this;
|
||||
}
|
||||
|
||||
// KRYSTIAN TODO: this can be done without copies when
|
||||
// reallocation is not needed, when the iterator is a
|
||||
// FowardIterator or better, as we can use std::distance
|
||||
template<class InputIt, class>
|
||||
auto
|
||||
string::
|
||||
insert(
|
||||
size_type pos,
|
||||
InputIt first,
|
||||
InputIt last) ->
|
||||
string&
|
||||
{
|
||||
struct cleanup
|
||||
{
|
||||
detail::string_impl& s;
|
||||
storage_ptr const& sp;
|
||||
|
||||
~cleanup()
|
||||
{
|
||||
s.destroy(sp);
|
||||
}
|
||||
};
|
||||
|
||||
// We use the default storage because
|
||||
// the allocation is immediately freed.
|
||||
storage_ptr dsp;
|
||||
detail::string_impl tmp(
|
||||
first, last, dsp,
|
||||
iter_cat<InputIt>{});
|
||||
cleanup c{tmp, dsp};
|
||||
std::memcpy(
|
||||
impl_.insert_unchecked(pos, tmp.size(), sp_),
|
||||
tmp.data(),
|
||||
tmp.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// KRYSTIAN TODO: this can be done without copies when
|
||||
// reallocation is not needed, when the iterator is a
|
||||
// FowardIterator or better, as we can use std::distance
|
||||
template<class InputIt, class>
|
||||
auto
|
||||
string::
|
||||
replace(
|
||||
const_iterator first,
|
||||
const_iterator last,
|
||||
InputIt first2,
|
||||
InputIt last2) ->
|
||||
string&
|
||||
{
|
||||
struct cleanup
|
||||
{
|
||||
detail::string_impl& s;
|
||||
storage_ptr const& sp;
|
||||
|
||||
~cleanup()
|
||||
{
|
||||
s.destroy(sp);
|
||||
}
|
||||
};
|
||||
|
||||
// We use the default storage because
|
||||
// the allocation is immediately freed.
|
||||
storage_ptr dsp;
|
||||
detail::string_impl tmp(
|
||||
first2, last2, dsp,
|
||||
iter_cat<InputIt>{});
|
||||
cleanup c{tmp, dsp};
|
||||
std::memcpy(
|
||||
impl_.replace_unchecked(
|
||||
first - begin(),
|
||||
last - first,
|
||||
tmp.size(),
|
||||
sp_),
|
||||
tmp.data(),
|
||||
tmp.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
string::
|
||||
assign(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
std::random_access_iterator_tag)
|
||||
{
|
||||
auto dest = impl_.assign(static_cast<
|
||||
size_type>(last - first), sp_);
|
||||
while(first != last)
|
||||
*dest++ = *first++;
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
string::
|
||||
assign(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
std::input_iterator_tag)
|
||||
{
|
||||
if(first == last)
|
||||
{
|
||||
impl_.term(0);
|
||||
return;
|
||||
}
|
||||
detail::string_impl tmp(
|
||||
first, last, sp_,
|
||||
std::input_iterator_tag{});
|
||||
impl_.destroy(sp_);
|
||||
impl_ = tmp;
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
string::
|
||||
append(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
std::random_access_iterator_tag)
|
||||
{
|
||||
auto const n = static_cast<
|
||||
size_type>(last - first);
|
||||
std::copy(first, last,
|
||||
impl_.append(n, sp_));
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
string::
|
||||
append(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
std::input_iterator_tag)
|
||||
{
|
||||
struct cleanup
|
||||
{
|
||||
detail::string_impl& s;
|
||||
storage_ptr const& sp;
|
||||
|
||||
~cleanup()
|
||||
{
|
||||
s.destroy(sp);
|
||||
}
|
||||
};
|
||||
|
||||
// We use the default storage because
|
||||
// the allocation is immediately freed.
|
||||
storage_ptr dsp;
|
||||
detail::string_impl tmp(
|
||||
first, last, dsp,
|
||||
std::input_iterator_tag{});
|
||||
cleanup c{tmp, dsp};
|
||||
std::memcpy(
|
||||
impl_.append(tmp.size(), sp_),
|
||||
tmp.data(), tmp.size());
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
416
install/boost_1_75_0/include/boost/json/impl/string.ipp
Normal file
416
install/boost_1_75_0/include/boost/json/impl/string.ipp
Normal file
@@ -0,0 +1,416 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_STRING_IPP
|
||||
#define BOOST_JSON_IMPL_STRING_IPP
|
||||
|
||||
#include <boost/json/detail/except.hpp>
|
||||
#include <algorithm>
|
||||
#include <new>
|
||||
#include <ostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Construction
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
string::
|
||||
string(
|
||||
std::size_t count,
|
||||
char ch,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
assign(count, ch);
|
||||
}
|
||||
|
||||
string::
|
||||
string(
|
||||
char const* s,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
assign(s);
|
||||
}
|
||||
|
||||
string::
|
||||
string(
|
||||
char const* s,
|
||||
std::size_t count,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
assign(s, count);
|
||||
}
|
||||
|
||||
string::
|
||||
string(string const& other)
|
||||
: sp_(other.sp_)
|
||||
{
|
||||
assign(other);
|
||||
}
|
||||
|
||||
string::
|
||||
string(
|
||||
string const& other,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
assign(other);
|
||||
}
|
||||
|
||||
string::
|
||||
string(
|
||||
string&& other,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
assign(std::move(other));
|
||||
}
|
||||
|
||||
string::
|
||||
string(
|
||||
string_view s,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
assign(s);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Assignment
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
string&
|
||||
string::
|
||||
operator=(string const& other)
|
||||
{
|
||||
return assign(other);
|
||||
}
|
||||
|
||||
string&
|
||||
string::
|
||||
operator=(string&& other)
|
||||
{
|
||||
return assign(std::move(other));
|
||||
}
|
||||
|
||||
string&
|
||||
string::
|
||||
operator=(char const* s)
|
||||
{
|
||||
return assign(s);
|
||||
}
|
||||
|
||||
string&
|
||||
string::
|
||||
operator=(string_view s)
|
||||
{
|
||||
return assign(s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
string&
|
||||
string::
|
||||
assign(
|
||||
size_type count,
|
||||
char ch)
|
||||
{
|
||||
std::char_traits<char>::assign(
|
||||
impl_.assign(count, sp_),
|
||||
count,
|
||||
ch);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string&
|
||||
string::
|
||||
assign(
|
||||
string const& other)
|
||||
{
|
||||
if(this == &other)
|
||||
return *this;
|
||||
return assign(
|
||||
other.data(),
|
||||
other.size());
|
||||
}
|
||||
|
||||
string&
|
||||
string::
|
||||
assign(string&& other)
|
||||
{
|
||||
if(*sp_ == *other.sp_)
|
||||
{
|
||||
impl_.destroy(sp_);
|
||||
impl_ = other.impl_;
|
||||
::new(&other.impl_) detail::string_impl();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// copy
|
||||
return assign(other);
|
||||
}
|
||||
|
||||
string&
|
||||
string::
|
||||
assign(
|
||||
char const* s,
|
||||
size_type count)
|
||||
{
|
||||
std::char_traits<char>::copy(
|
||||
impl_.assign(count, sp_),
|
||||
s, count);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string&
|
||||
string::
|
||||
assign(
|
||||
char const* s)
|
||||
{
|
||||
return assign(s, std::char_traits<
|
||||
char>::length(s));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Capacity
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
string::
|
||||
shrink_to_fit()
|
||||
{
|
||||
impl_.shrink_to_fit(sp_);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Operations
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
string::
|
||||
clear() noexcept
|
||||
{
|
||||
impl_.term(0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
string::
|
||||
push_back(char ch)
|
||||
{
|
||||
*impl_.append(1, sp_) = ch;
|
||||
}
|
||||
|
||||
void
|
||||
string::
|
||||
pop_back()
|
||||
{
|
||||
back() = 0;
|
||||
impl_.size(impl_.size() - 1);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
string&
|
||||
string::
|
||||
append(size_type count, char ch)
|
||||
{
|
||||
std::char_traits<char>::assign(
|
||||
impl_.append(count, sp_),
|
||||
count, ch);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string&
|
||||
string::
|
||||
append(string_view sv)
|
||||
{
|
||||
std::char_traits<char>::copy(
|
||||
impl_.append(sv.size(), sp_),
|
||||
sv.data(), sv.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
string&
|
||||
string::
|
||||
insert(
|
||||
size_type pos,
|
||||
string_view sv)
|
||||
{
|
||||
impl_.insert(pos, sv.data(), sv.size(), sp_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string&
|
||||
string::
|
||||
insert(
|
||||
std::size_t pos,
|
||||
std::size_t count,
|
||||
char ch)
|
||||
{
|
||||
std::char_traits<char>::assign(
|
||||
impl_.insert_unchecked(pos, count, sp_),
|
||||
count, ch);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
string&
|
||||
string::
|
||||
replace(
|
||||
std::size_t pos,
|
||||
std::size_t count,
|
||||
string_view sv)
|
||||
{
|
||||
impl_.replace(pos, count, sv.data(), sv.size(), sp_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string&
|
||||
string::
|
||||
replace(
|
||||
std::size_t pos,
|
||||
std::size_t count,
|
||||
std::size_t count2,
|
||||
char ch)
|
||||
{
|
||||
std::char_traits<char>::assign(
|
||||
impl_.replace_unchecked(pos, count, count2, sp_),
|
||||
count2, ch);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
string&
|
||||
string::
|
||||
erase(
|
||||
size_type pos,
|
||||
size_type count)
|
||||
{
|
||||
if(pos > impl_.size())
|
||||
detail::throw_out_of_range(
|
||||
BOOST_CURRENT_LOCATION);
|
||||
if( count > impl_.size() - pos)
|
||||
count = impl_.size() - pos;
|
||||
std::char_traits<char>::move(
|
||||
impl_.data() + pos,
|
||||
impl_.data() + pos + count,
|
||||
impl_.size() - pos - count + 1);
|
||||
impl_.term(impl_.size() - count);
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto
|
||||
string::
|
||||
erase(const_iterator pos) ->
|
||||
iterator
|
||||
{
|
||||
return erase(pos, pos+1);
|
||||
}
|
||||
|
||||
auto
|
||||
string::
|
||||
erase(
|
||||
const_iterator first,
|
||||
const_iterator last) ->
|
||||
iterator
|
||||
{
|
||||
auto const pos = first - begin();
|
||||
auto const count = last - first;
|
||||
erase(pos, count);
|
||||
return data() + pos;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
string::
|
||||
resize(size_type count, char ch)
|
||||
{
|
||||
if(count <= impl_.size())
|
||||
{
|
||||
impl_.term(count);
|
||||
return;
|
||||
}
|
||||
|
||||
reserve(count);
|
||||
std::char_traits<char>::assign(
|
||||
impl_.end(),
|
||||
count - impl_.size(),
|
||||
ch);
|
||||
grow(count - size());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
string::
|
||||
swap(string& other)
|
||||
{
|
||||
BOOST_ASSERT(this != &other);
|
||||
if(*sp_ == *other.sp_)
|
||||
{
|
||||
std::swap(impl_, other.impl_);
|
||||
return;
|
||||
}
|
||||
string temp1(
|
||||
std::move(*this), other.sp_);
|
||||
string temp2(
|
||||
std::move(other), sp_);
|
||||
this->~string();
|
||||
::new(this) string(pilfer(temp2));
|
||||
other.~string();
|
||||
::new(&other) string(pilfer(temp1));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
string::
|
||||
reserve_impl(size_type new_cap)
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
new_cap >= impl_.capacity());
|
||||
if(new_cap > impl_.capacity())
|
||||
{
|
||||
// grow
|
||||
new_cap = detail::string_impl::growth(
|
||||
new_cap, impl_.capacity());
|
||||
detail::string_impl tmp(new_cap, sp_);
|
||||
std::char_traits<char>::copy(tmp.data(),
|
||||
impl_.data(), impl_.size() + 1);
|
||||
tmp.size(impl_.size());
|
||||
impl_.destroy(sp_);
|
||||
impl_ = tmp;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
497
install/boost_1_75_0/include/boost/json/impl/value.ipp
Normal file
497
install/boost_1_75_0/include/boost/json/impl/value.ipp
Normal file
@@ -0,0 +1,497 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_VALUE_IPP
|
||||
#define BOOST_JSON_IMPL_VALUE_IPP
|
||||
|
||||
#include <boost/json/value.hpp>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <new>
|
||||
#include <utility>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
value::
|
||||
~value()
|
||||
{
|
||||
switch(kind())
|
||||
{
|
||||
case json::kind::null:
|
||||
case json::kind::bool_:
|
||||
case json::kind::int64:
|
||||
case json::kind::uint64:
|
||||
case json::kind::double_:
|
||||
sca_.~scalar();
|
||||
break;
|
||||
|
||||
case json::kind::string:
|
||||
str_.~string();
|
||||
break;
|
||||
|
||||
case json::kind::array:
|
||||
arr_.~array();
|
||||
break;
|
||||
|
||||
case json::kind::object:
|
||||
obj_.~object();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
value::
|
||||
value(
|
||||
value const& other,
|
||||
storage_ptr sp)
|
||||
{
|
||||
switch(other.kind())
|
||||
{
|
||||
case json::kind::null:
|
||||
::new(&sca_) scalar(
|
||||
std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::bool_:
|
||||
::new(&sca_) scalar(
|
||||
other.sca_.b,
|
||||
std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::int64:
|
||||
::new(&sca_) scalar(
|
||||
other.sca_.i,
|
||||
std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::uint64:
|
||||
::new(&sca_) scalar(
|
||||
other.sca_.u,
|
||||
std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::double_:
|
||||
::new(&sca_) scalar(
|
||||
other.sca_.d,
|
||||
std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::string:
|
||||
::new(&str_) string(
|
||||
other.str_,
|
||||
std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::array:
|
||||
::new(&arr_) array(
|
||||
other.arr_,
|
||||
std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::object:
|
||||
::new(&obj_) object(
|
||||
other.obj_,
|
||||
std::move(sp));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
value::
|
||||
value(value&& other) noexcept
|
||||
{
|
||||
relocate(this, other);
|
||||
::new(&other.sca_) scalar(sp_);
|
||||
}
|
||||
|
||||
value::
|
||||
value(
|
||||
value&& other,
|
||||
storage_ptr sp)
|
||||
{
|
||||
switch(other.kind())
|
||||
{
|
||||
case json::kind::null:
|
||||
::new(&sca_) scalar(
|
||||
std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::bool_:
|
||||
::new(&sca_) scalar(
|
||||
other.sca_.b, std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::int64:
|
||||
::new(&sca_) scalar(
|
||||
other.sca_.i, std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::uint64:
|
||||
::new(&sca_) scalar(
|
||||
other.sca_.u, std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::double_:
|
||||
::new(&sca_) scalar(
|
||||
other.sca_.d, std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::string:
|
||||
::new(&str_) string(
|
||||
std::move(other.str_),
|
||||
std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::array:
|
||||
::new(&arr_) array(
|
||||
std::move(other.arr_),
|
||||
std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::object:
|
||||
::new(&obj_) object(
|
||||
std::move(other.obj_),
|
||||
std::move(sp));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Conversion
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
value::
|
||||
value(
|
||||
std::initializer_list<value_ref> init,
|
||||
storage_ptr sp)
|
||||
{
|
||||
if(value_ref::maybe_object(init))
|
||||
::new(&obj_) object(
|
||||
value_ref::make_object(
|
||||
init, std::move(sp)));
|
||||
else
|
||||
::new(&arr_) array(
|
||||
value_ref::make_array(
|
||||
init, std::move(sp)));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Assignment
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
value&
|
||||
value::
|
||||
operator=(value const& other)
|
||||
{
|
||||
value(other,
|
||||
storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
value&
|
||||
value::
|
||||
operator=(value&& other)
|
||||
{
|
||||
value(std::move(other),
|
||||
storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
value&
|
||||
value::
|
||||
operator=(
|
||||
std::initializer_list<value_ref> init)
|
||||
{
|
||||
value(init,
|
||||
storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
value&
|
||||
value::
|
||||
operator=(string_view s)
|
||||
{
|
||||
value(s, storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
value&
|
||||
value::
|
||||
operator=(char const* s)
|
||||
{
|
||||
value(s, storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
value&
|
||||
value::
|
||||
operator=(string const& str)
|
||||
{
|
||||
value(str, storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
value&
|
||||
value::
|
||||
operator=(string&& str)
|
||||
{
|
||||
value(std::move(str),
|
||||
storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
value&
|
||||
value::
|
||||
operator=(array const& arr)
|
||||
{
|
||||
value(arr, storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
value&
|
||||
value::
|
||||
operator=(array&& arr)
|
||||
{
|
||||
value(std::move(arr),
|
||||
storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
value&
|
||||
value::
|
||||
operator=(object const& obj)
|
||||
{
|
||||
value(obj, storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
value&
|
||||
value::
|
||||
operator=(object&& obj)
|
||||
{
|
||||
value(std::move(obj),
|
||||
storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Modifiers
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
string&
|
||||
value::
|
||||
emplace_string() noexcept
|
||||
{
|
||||
return *::new(&str_) string(destroy());
|
||||
}
|
||||
|
||||
array&
|
||||
value::
|
||||
emplace_array() noexcept
|
||||
{
|
||||
return *::new(&arr_) array(destroy());
|
||||
}
|
||||
|
||||
object&
|
||||
value::
|
||||
emplace_object() noexcept
|
||||
{
|
||||
return *::new(&obj_) object(destroy());
|
||||
}
|
||||
|
||||
void
|
||||
value::
|
||||
swap(value& other)
|
||||
{
|
||||
if(*storage() == *other.storage())
|
||||
{
|
||||
// fast path
|
||||
union U
|
||||
{
|
||||
value tmp;
|
||||
U(){}
|
||||
~U(){}
|
||||
};
|
||||
U u;
|
||||
relocate(&u.tmp, *this);
|
||||
relocate(this, other);
|
||||
relocate(&other, u.tmp);
|
||||
return;
|
||||
}
|
||||
|
||||
// copy
|
||||
value temp1(
|
||||
std::move(*this),
|
||||
other.storage());
|
||||
value temp2(
|
||||
std::move(other),
|
||||
this->storage());
|
||||
other.~value();
|
||||
::new(&other) value(pilfer(temp1));
|
||||
this->~value();
|
||||
::new(this) value(pilfer(temp2));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// private
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
storage_ptr
|
||||
value::
|
||||
destroy() noexcept
|
||||
{
|
||||
switch(kind())
|
||||
{
|
||||
case json::kind::null:
|
||||
case json::kind::bool_:
|
||||
case json::kind::int64:
|
||||
case json::kind::uint64:
|
||||
case json::kind::double_:
|
||||
break;
|
||||
|
||||
case json::kind::string:
|
||||
{
|
||||
auto sp = str_.storage();
|
||||
str_.~string();
|
||||
return sp;
|
||||
}
|
||||
|
||||
case json::kind::array:
|
||||
{
|
||||
auto sp = arr_.storage();
|
||||
arr_.~array();
|
||||
return sp;
|
||||
}
|
||||
|
||||
case json::kind::object:
|
||||
{
|
||||
auto sp = obj_.storage();
|
||||
obj_.~object();
|
||||
return sp;
|
||||
}
|
||||
|
||||
}
|
||||
return std::move(sp_);
|
||||
}
|
||||
|
||||
bool
|
||||
value::
|
||||
equal(value const& other) const noexcept
|
||||
{
|
||||
switch(kind())
|
||||
{
|
||||
default: // unreachable()?
|
||||
case json::kind::null:
|
||||
return other.kind() == json::kind::null;
|
||||
|
||||
case json::kind::bool_:
|
||||
return
|
||||
other.kind() == json::kind::bool_ &&
|
||||
get_bool() == other.get_bool();
|
||||
|
||||
case json::kind::int64:
|
||||
switch(other.kind())
|
||||
{
|
||||
case json::kind::int64:
|
||||
return get_int64() == other.get_int64();
|
||||
case json::kind::uint64:
|
||||
if(get_int64() < 0)
|
||||
return false;
|
||||
return static_cast<std::uint64_t>(
|
||||
get_int64()) == other.get_uint64();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
case json::kind::uint64:
|
||||
switch(other.kind())
|
||||
{
|
||||
case json::kind::uint64:
|
||||
return get_uint64() == other.get_uint64();
|
||||
case json::kind::int64:
|
||||
if(other.get_int64() < 0)
|
||||
return false;
|
||||
return static_cast<std::uint64_t>(
|
||||
other.get_int64()) == get_uint64();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
case json::kind::double_:
|
||||
return
|
||||
other.kind() == json::kind::double_ &&
|
||||
get_double() == other.get_double();
|
||||
|
||||
case json::kind::string:
|
||||
return
|
||||
other.kind() == json::kind::string &&
|
||||
get_string() == other.get_string();
|
||||
|
||||
case json::kind::array:
|
||||
return
|
||||
other.kind() == json::kind::array &&
|
||||
get_array() == other.get_array();
|
||||
|
||||
case json::kind::object:
|
||||
return
|
||||
other.kind() == json::kind::object &&
|
||||
get_object() == other.get_object();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// key_value_pair
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
// empty keys point here
|
||||
BOOST_JSON_REQUIRE_CONST_INIT
|
||||
char const
|
||||
key_value_pair::empty_[1] = { 0 };
|
||||
|
||||
key_value_pair::
|
||||
key_value_pair(
|
||||
pilfered<json::value> key,
|
||||
pilfered<json::value> value) noexcept
|
||||
: value_(value)
|
||||
{
|
||||
std::size_t len;
|
||||
key_ = access::release_key(key.get(), len);
|
||||
len_ = static_cast<std::uint32_t>(len);
|
||||
}
|
||||
|
||||
key_value_pair::
|
||||
key_value_pair(
|
||||
key_value_pair const& other,
|
||||
storage_ptr sp)
|
||||
: value_(other.value_, std::move(sp))
|
||||
{
|
||||
auto p = reinterpret_cast<
|
||||
char*>(value_.storage()->
|
||||
allocate(other.len_ + 1,
|
||||
alignof(char)));
|
||||
std::memcpy(
|
||||
p, other.key_, other.len_);
|
||||
len_ = other.len_;
|
||||
p[len_] = 0;
|
||||
key_ = p;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
58
install/boost_1_75_0/include/boost/json/impl/value_ref.hpp
Normal file
58
install/boost_1_75_0/include/boost/json/impl/value_ref.hpp
Normal file
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_VALUE_REF_HPP
|
||||
#define BOOST_JSON_IMPL_VALUE_REF_HPP
|
||||
|
||||
#include <boost/json/value_from.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
template<class T>
|
||||
value
|
||||
value_ref::
|
||||
from_builtin(
|
||||
void const* p,
|
||||
storage_ptr sp) noexcept
|
||||
{
|
||||
return value(
|
||||
*reinterpret_cast<
|
||||
T const*>(p),
|
||||
std::move(sp));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
value
|
||||
value_ref::
|
||||
from_const(
|
||||
void const* p,
|
||||
storage_ptr sp)
|
||||
{
|
||||
return value_from(
|
||||
*reinterpret_cast<
|
||||
T const*>(p),
|
||||
std::move(sp));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
value
|
||||
value_ref::
|
||||
from_rvalue(
|
||||
void* p,
|
||||
storage_ptr sp)
|
||||
{
|
||||
return value_from(
|
||||
std::move(
|
||||
*reinterpret_cast<T*>(p)),
|
||||
std::move(sp));
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
187
install/boost_1_75_0/include/boost/json/impl/value_ref.ipp
Normal file
187
install/boost_1_75_0/include/boost/json/impl/value_ref.ipp
Normal file
@@ -0,0 +1,187 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_VALUE_REF_IPP
|
||||
#define BOOST_JSON_IMPL_VALUE_REF_IPP
|
||||
|
||||
#include <boost/json/value_ref.hpp>
|
||||
#include <boost/json/array.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
value_ref::
|
||||
operator
|
||||
value() const
|
||||
{
|
||||
return make_value({});
|
||||
}
|
||||
|
||||
value
|
||||
value_ref::
|
||||
from_init_list(
|
||||
void const* p,
|
||||
storage_ptr sp)
|
||||
{
|
||||
return make_value(
|
||||
*reinterpret_cast<
|
||||
init_list const*>(p),
|
||||
std::move(sp));
|
||||
}
|
||||
|
||||
bool
|
||||
value_ref::
|
||||
is_key_value_pair() const noexcept
|
||||
{
|
||||
if(what_ != what::ini)
|
||||
return false;
|
||||
if(arg_.init_list_.size() != 2)
|
||||
return false;
|
||||
auto const& e =
|
||||
*arg_.init_list_.begin();
|
||||
if( e.what_ != what::str &&
|
||||
e.what_ != what::strfunc)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
value_ref::
|
||||
maybe_object(
|
||||
std::initializer_list<
|
||||
value_ref> init) noexcept
|
||||
{
|
||||
for(auto const& e : init)
|
||||
if(! e.is_key_value_pair())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
string_view
|
||||
value_ref::
|
||||
get_string() const noexcept
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
what_ == what::str ||
|
||||
what_ == what::strfunc);
|
||||
if (what_ == what::strfunc)
|
||||
return *static_cast<const string*>(f_.p);
|
||||
return arg_.str_;
|
||||
}
|
||||
|
||||
value
|
||||
value_ref::
|
||||
make_value(
|
||||
storage_ptr sp) const
|
||||
{
|
||||
switch(what_)
|
||||
{
|
||||
default:
|
||||
case what::str:
|
||||
return string(
|
||||
arg_.str_,
|
||||
std::move(sp));
|
||||
|
||||
case what::ini:
|
||||
return make_value(
|
||||
arg_.init_list_,
|
||||
std::move(sp));
|
||||
|
||||
case what::func:
|
||||
return f_.f(f_.p,
|
||||
std::move(sp));
|
||||
|
||||
case what::strfunc:
|
||||
return f_.f(f_.p,
|
||||
std::move(sp));
|
||||
|
||||
case what::cfunc:
|
||||
return cf_.f(cf_.p,
|
||||
std::move(sp));
|
||||
}
|
||||
}
|
||||
|
||||
value
|
||||
value_ref::
|
||||
make_value(
|
||||
std::initializer_list<
|
||||
value_ref> init,
|
||||
storage_ptr sp)
|
||||
{
|
||||
if(maybe_object(init))
|
||||
return make_object(
|
||||
init, std::move(sp));
|
||||
return make_array(
|
||||
init, std::move(sp));
|
||||
}
|
||||
|
||||
object
|
||||
value_ref::
|
||||
make_object(
|
||||
std::initializer_list<value_ref> init,
|
||||
storage_ptr sp)
|
||||
{
|
||||
object obj(std::move(sp));
|
||||
obj.reserve(init.size());
|
||||
for(auto const& e : init)
|
||||
obj.emplace(
|
||||
e.arg_.init_list_.begin()[0].get_string(),
|
||||
e.arg_.init_list_.begin()[1].make_value(
|
||||
obj.storage()));
|
||||
return obj;
|
||||
}
|
||||
|
||||
array
|
||||
value_ref::
|
||||
make_array(
|
||||
std::initializer_list<
|
||||
value_ref> init,
|
||||
storage_ptr sp)
|
||||
{
|
||||
array arr(std::move(sp));
|
||||
arr.reserve(init.size());
|
||||
for(auto const& e : init)
|
||||
arr.emplace_back(
|
||||
e.make_value(
|
||||
arr.storage()));
|
||||
return arr;
|
||||
}
|
||||
|
||||
void
|
||||
value_ref::
|
||||
write_array(
|
||||
value* dest,
|
||||
std::initializer_list<
|
||||
value_ref> init,
|
||||
storage_ptr const& sp)
|
||||
{
|
||||
struct undo
|
||||
{
|
||||
value* const base;
|
||||
value* pos;
|
||||
~undo()
|
||||
{
|
||||
if(pos)
|
||||
while(pos > base)
|
||||
(--pos)->~value();
|
||||
}
|
||||
};
|
||||
undo u{dest, dest};
|
||||
for(auto const& e : init)
|
||||
{
|
||||
::new(u.pos) value(
|
||||
e.make_value(sp));
|
||||
++u.pos;
|
||||
}
|
||||
u.pos = nullptr;
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
472
install/boost_1_75_0/include/boost/json/impl/value_stack.ipp
Normal file
472
install/boost_1_75_0/include/boost/json/impl/value_stack.ipp
Normal file
@@ -0,0 +1,472 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_VALUE_STACK_IPP
|
||||
#define BOOST_JSON_IMPL_VALUE_STACK_IPP
|
||||
|
||||
#include <boost/json/value_stack.hpp>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
//--------------------------------------
|
||||
|
||||
value_stack::
|
||||
stack::
|
||||
~stack()
|
||||
{
|
||||
clear();
|
||||
if( begin_ != temp_ &&
|
||||
begin_ != nullptr)
|
||||
sp_->deallocate(
|
||||
begin_,
|
||||
(end_ - begin_) *
|
||||
sizeof(value));
|
||||
}
|
||||
|
||||
value_stack::
|
||||
stack::
|
||||
stack(
|
||||
storage_ptr sp,
|
||||
void* temp,
|
||||
std::size_t size) noexcept
|
||||
: sp_(std::move(sp))
|
||||
, temp_(temp)
|
||||
{
|
||||
if(size >= min_size_ *
|
||||
sizeof(value))
|
||||
{
|
||||
begin_ = reinterpret_cast<
|
||||
value*>(temp);
|
||||
top_ = begin_;
|
||||
end_ = begin_ +
|
||||
size / sizeof(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
begin_ = nullptr;
|
||||
top_ = nullptr;
|
||||
end_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
value_stack::
|
||||
stack::
|
||||
run_dtors(bool b) noexcept
|
||||
{
|
||||
run_dtors_ = b;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
value_stack::
|
||||
stack::
|
||||
size() const noexcept
|
||||
{
|
||||
return top_ - begin_;
|
||||
}
|
||||
|
||||
bool
|
||||
value_stack::
|
||||
stack::
|
||||
has_chars()
|
||||
{
|
||||
return chars_ != 0;
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
|
||||
// destroy the values but
|
||||
// not the stack allocation.
|
||||
void
|
||||
value_stack::
|
||||
stack::
|
||||
clear() noexcept
|
||||
{
|
||||
if(top_ != begin_)
|
||||
{
|
||||
if(run_dtors_)
|
||||
for(auto it = top_;
|
||||
it-- != begin_;)
|
||||
it->~value();
|
||||
top_ = begin_;
|
||||
}
|
||||
chars_ = 0;
|
||||
}
|
||||
|
||||
void
|
||||
value_stack::
|
||||
stack::
|
||||
maybe_grow()
|
||||
{
|
||||
if(top_ >= end_)
|
||||
grow_one();
|
||||
}
|
||||
|
||||
// make room for at least one more value
|
||||
void
|
||||
value_stack::
|
||||
stack::
|
||||
grow_one()
|
||||
{
|
||||
BOOST_ASSERT(chars_ == 0);
|
||||
std::size_t const capacity =
|
||||
end_ - begin_;
|
||||
std::size_t new_cap = min_size_;
|
||||
// VFALCO check overflow here
|
||||
while(new_cap < capacity + 1)
|
||||
new_cap <<= 1;
|
||||
auto const begin =
|
||||
reinterpret_cast<value*>(
|
||||
sp_->allocate(
|
||||
new_cap * sizeof(value)));
|
||||
if(begin_)
|
||||
{
|
||||
std::memcpy(
|
||||
reinterpret_cast<char*>(begin),
|
||||
reinterpret_cast<char*>(begin_),
|
||||
size() * sizeof(value));
|
||||
if(begin_ != temp_)
|
||||
sp_->deallocate(begin_,
|
||||
capacity * sizeof(value));
|
||||
}
|
||||
// book-keeping
|
||||
top_ = begin + (top_ - begin_);
|
||||
end_ = begin + new_cap;
|
||||
begin_ = begin;
|
||||
}
|
||||
|
||||
// make room for nchars additional characters.
|
||||
void
|
||||
value_stack::
|
||||
stack::
|
||||
grow(std::size_t nchars)
|
||||
{
|
||||
// needed capacity in values
|
||||
std::size_t const needed =
|
||||
size() +
|
||||
1 +
|
||||
((chars_ + nchars +
|
||||
sizeof(value) - 1) /
|
||||
sizeof(value));
|
||||
std::size_t const capacity =
|
||||
end_ - begin_;
|
||||
BOOST_ASSERT(
|
||||
needed > capacity);
|
||||
std::size_t new_cap = min_size_;
|
||||
// VFALCO check overflow here
|
||||
while(new_cap < needed)
|
||||
new_cap <<= 1;
|
||||
auto const begin =
|
||||
reinterpret_cast<value*>(
|
||||
sp_->allocate(
|
||||
new_cap * sizeof(value)));
|
||||
if(begin_)
|
||||
{
|
||||
std::size_t amount =
|
||||
size() * sizeof(value);
|
||||
if(chars_ > 0)
|
||||
amount += sizeof(value) + chars_;
|
||||
std::memcpy(
|
||||
reinterpret_cast<char*>(begin),
|
||||
reinterpret_cast<char*>(begin_),
|
||||
amount);
|
||||
if(begin_ != temp_)
|
||||
sp_->deallocate(begin_,
|
||||
capacity * sizeof(value));
|
||||
}
|
||||
// book-keeping
|
||||
top_ = begin + (top_ - begin_);
|
||||
end_ = begin + new_cap;
|
||||
begin_ = begin;
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
|
||||
void
|
||||
value_stack::
|
||||
stack::
|
||||
append(string_view s)
|
||||
{
|
||||
std::size_t const bytes_avail =
|
||||
reinterpret_cast<
|
||||
char const*>(end_) -
|
||||
reinterpret_cast<
|
||||
char const*>(top_);
|
||||
// make sure there is room for
|
||||
// pushing one more value without
|
||||
// clobbering the string.
|
||||
if(sizeof(value) + chars_ +
|
||||
s.size() > bytes_avail)
|
||||
grow(s.size());
|
||||
|
||||
// copy the new piece
|
||||
std::memcpy(
|
||||
reinterpret_cast<char*>(
|
||||
top_ + 1) + chars_,
|
||||
s.data(), s.size());
|
||||
chars_ += s.size();
|
||||
|
||||
// ensure a pushed value cannot
|
||||
// clobber the released string.
|
||||
BOOST_ASSERT(
|
||||
reinterpret_cast<char*>(
|
||||
top_ + 1) + chars_ <=
|
||||
reinterpret_cast<char*>(
|
||||
end_));
|
||||
}
|
||||
|
||||
string_view
|
||||
value_stack::
|
||||
stack::
|
||||
release_string() noexcept
|
||||
{
|
||||
// ensure a pushed value cannot
|
||||
// clobber the released string.
|
||||
BOOST_ASSERT(
|
||||
reinterpret_cast<char*>(
|
||||
top_ + 1) + chars_ <=
|
||||
reinterpret_cast<char*>(
|
||||
end_));
|
||||
auto const n = chars_;
|
||||
chars_ = 0;
|
||||
return { reinterpret_cast<
|
||||
char const*>(top_ + 1), n };
|
||||
}
|
||||
|
||||
// transfer ownership of the top n
|
||||
// elements of the stack to the caller
|
||||
value*
|
||||
value_stack::
|
||||
stack::
|
||||
release(std::size_t n) noexcept
|
||||
{
|
||||
BOOST_ASSERT(n <= size());
|
||||
BOOST_ASSERT(chars_ == 0);
|
||||
top_ -= n;
|
||||
return top_;
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
value&
|
||||
value_stack::
|
||||
stack::
|
||||
push(Args&&... args)
|
||||
{
|
||||
BOOST_ASSERT(chars_ == 0);
|
||||
if(top_ >= end_)
|
||||
grow_one();
|
||||
value& jv = detail::access::
|
||||
construct_value(top_,
|
||||
std::forward<Args>(args)...);
|
||||
++top_;
|
||||
return jv;
|
||||
}
|
||||
|
||||
template<class Unchecked>
|
||||
void
|
||||
value_stack::
|
||||
stack::
|
||||
exchange(Unchecked&& u)
|
||||
{
|
||||
BOOST_ASSERT(chars_ == 0);
|
||||
union U
|
||||
{
|
||||
value v;
|
||||
U() {}
|
||||
~U() {}
|
||||
} jv;
|
||||
// construct value on the stack
|
||||
// to avoid clobbering top_[0],
|
||||
// which belongs to `u`.
|
||||
detail::access::
|
||||
construct_value(
|
||||
&jv.v, std::move(u));
|
||||
std::memcpy(
|
||||
reinterpret_cast<
|
||||
char*>(top_),
|
||||
&jv.v, sizeof(value));
|
||||
++top_;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
value_stack::
|
||||
~value_stack()
|
||||
{
|
||||
// default dtor is here so the
|
||||
// definition goes in the library
|
||||
// instead of the caller's TU.
|
||||
}
|
||||
|
||||
value_stack::
|
||||
value_stack(
|
||||
storage_ptr sp,
|
||||
unsigned char* temp_buffer,
|
||||
std::size_t temp_size) noexcept
|
||||
: st_(
|
||||
std::move(sp),
|
||||
temp_buffer,
|
||||
temp_size)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
value_stack::
|
||||
reset(storage_ptr sp) noexcept
|
||||
{
|
||||
st_.clear();
|
||||
|
||||
sp_.~storage_ptr();
|
||||
::new(&sp_) storage_ptr(
|
||||
pilfer(sp));
|
||||
|
||||
// `stack` needs this
|
||||
// to clean up correctly
|
||||
st_.run_dtors(
|
||||
! sp_.is_not_shared_and_deallocate_is_trivial());
|
||||
}
|
||||
|
||||
value
|
||||
value_stack::
|
||||
release() noexcept
|
||||
{
|
||||
// This means the caller did not
|
||||
// cause a single top level element
|
||||
// to be produced.
|
||||
BOOST_ASSERT(st_.size() == 1);
|
||||
|
||||
// give up shared ownership
|
||||
sp_ = {};
|
||||
|
||||
return pilfer(*st_.release(1));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
value_stack::
|
||||
push_array(std::size_t n)
|
||||
{
|
||||
// we already have room if n > 0
|
||||
if(BOOST_JSON_UNLIKELY(n == 0))
|
||||
st_.maybe_grow();
|
||||
detail::unchecked_array ua(
|
||||
st_.release(n), n, sp_);
|
||||
st_.exchange(std::move(ua));
|
||||
}
|
||||
|
||||
void
|
||||
value_stack::
|
||||
push_object(std::size_t n)
|
||||
{
|
||||
// we already have room if n > 0
|
||||
if(BOOST_JSON_UNLIKELY(n == 0))
|
||||
st_.maybe_grow();
|
||||
detail::unchecked_object uo(
|
||||
st_.release(n * 2), n, sp_);
|
||||
st_.exchange(std::move(uo));
|
||||
}
|
||||
|
||||
void
|
||||
value_stack::
|
||||
push_chars(
|
||||
string_view s)
|
||||
{
|
||||
st_.append(s);
|
||||
}
|
||||
|
||||
void
|
||||
value_stack::
|
||||
push_key(
|
||||
string_view s)
|
||||
{
|
||||
if(! st_.has_chars())
|
||||
{
|
||||
st_.push(detail::key_t{}, s, sp_);
|
||||
return;
|
||||
}
|
||||
auto part = st_.release_string();
|
||||
st_.push(detail::key_t{}, part, s, sp_);
|
||||
}
|
||||
|
||||
void
|
||||
value_stack::
|
||||
push_string(
|
||||
string_view s)
|
||||
{
|
||||
if(! st_.has_chars())
|
||||
{
|
||||
// fast path
|
||||
st_.push(s, sp_);
|
||||
return;
|
||||
}
|
||||
|
||||
// VFALCO We could add a special
|
||||
// private ctor to string that just
|
||||
// creates uninitialized space,
|
||||
// to reduce member function calls.
|
||||
auto part = st_.release_string();
|
||||
auto& str = st_.push(
|
||||
string_kind, sp_).get_string();
|
||||
str.reserve(
|
||||
part.size() + s.size());
|
||||
std::memcpy(
|
||||
str.data(),
|
||||
part.data(), part.size());
|
||||
std::memcpy(
|
||||
str.data() + part.size(),
|
||||
s.data(), s.size());
|
||||
str.grow(part.size() + s.size());
|
||||
}
|
||||
|
||||
void
|
||||
value_stack::
|
||||
push_int64(
|
||||
int64_t i)
|
||||
{
|
||||
st_.push(i, sp_);
|
||||
}
|
||||
|
||||
void
|
||||
value_stack::
|
||||
push_uint64(
|
||||
uint64_t u)
|
||||
{
|
||||
st_.push(u, sp_);
|
||||
}
|
||||
|
||||
void
|
||||
value_stack::
|
||||
push_double(
|
||||
double d)
|
||||
{
|
||||
st_.push(d, sp_);
|
||||
}
|
||||
|
||||
void
|
||||
value_stack::
|
||||
push_bool(
|
||||
bool b)
|
||||
{
|
||||
st_.push(b, sp_);
|
||||
}
|
||||
|
||||
void
|
||||
value_stack::
|
||||
push_null()
|
||||
{
|
||||
st_.push(nullptr, sp_);
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
59
install/boost_1_75_0/include/boost/json/impl/visit.hpp
Normal file
59
install/boost_1_75_0/include/boost/json/impl/visit.hpp
Normal file
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_VISIT_HPP
|
||||
#define BOOST_JSON_IMPL_VISIT_HPP
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
template<class Visitor>
|
||||
auto
|
||||
visit(
|
||||
Visitor&& v,
|
||||
value& jv) -> decltype(
|
||||
std::declval<Visitor>()(nullptr))
|
||||
{
|
||||
switch(jv.kind())
|
||||
{
|
||||
default: // unreachable()?
|
||||
case kind::null: return std::forward<Visitor>(v)(nullptr);
|
||||
case kind::bool_: return std::forward<Visitor>(v)(jv.get_bool());
|
||||
case kind::int64: return std::forward<Visitor>(v)(jv.get_int64());
|
||||
case kind::uint64: return std::forward<Visitor>(v)(jv.get_uint64());
|
||||
case kind::double_: return std::forward<Visitor>(v)(jv.get_double());
|
||||
case kind::string: return std::forward<Visitor>(v)(jv.get_string());
|
||||
case kind::array: return std::forward<Visitor>(v)(jv.get_array());
|
||||
case kind::object: return std::forward<Visitor>(v)(jv.get_object());
|
||||
}
|
||||
}
|
||||
|
||||
template<class Visitor>
|
||||
auto
|
||||
visit(
|
||||
Visitor&& v,
|
||||
value const& jv) -> decltype(
|
||||
std::declval<Visitor>()(nullptr))
|
||||
{
|
||||
switch (jv.kind())
|
||||
{
|
||||
default: // unreachable()?
|
||||
case kind::null: return std::forward<Visitor>(v)(nullptr);
|
||||
case kind::bool_: return std::forward<Visitor>(v)(jv.get_bool());
|
||||
case kind::int64: return std::forward<Visitor>(v)(jv.get_int64());
|
||||
case kind::uint64: return std::forward<Visitor>(v)(jv.get_uint64());
|
||||
case kind::double_: return std::forward<Visitor>(v)(jv.get_double());
|
||||
case kind::string: return std::forward<Visitor>(v)(jv.get_string());
|
||||
case kind::array: return std::forward<Visitor>(v)(jv.get_array());
|
||||
case kind::object: return std::forward<Visitor>(v)(jv.get_object());
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user