mirror of
https://github.com/boostorg/json.git
synced 2025-05-12 06:01:41 +00:00
Fixes
This commit is contained in:
parent
adcebea5a9
commit
a0e46853a8
@ -325,8 +325,13 @@ struct nlohmann_impl : public any_impl
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
serialize(string_view, int) const override
|
serialize(string_view s, int repeat) const override
|
||||||
{
|
{
|
||||||
|
auto jv = nlohmann::json::parse(
|
||||||
|
s.begin(), s.end());
|
||||||
|
while(repeat--)
|
||||||
|
auto s = jv.dump();
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -369,7 +374,7 @@ benchParse(
|
|||||||
std::endl;
|
std::endl;
|
||||||
for(unsigned j = 0; j < vi.size(); ++j)
|
for(unsigned j = 0; j < vi.size(); ++j)
|
||||||
{
|
{
|
||||||
for(unsigned k = 0; k < 10; ++k)
|
for(unsigned k = 0; k < 7; ++k)
|
||||||
{
|
{
|
||||||
auto const when = clock_type::now();
|
auto const when = clock_type::now();
|
||||||
vi[j]->parse(vs[i].text, 250);
|
vi[j]->parse(vs[i].text, 250);
|
||||||
@ -401,14 +406,14 @@ benchSerialize(
|
|||||||
std::endl;
|
std::endl;
|
||||||
for(unsigned j = 0; j < vi.size(); ++j)
|
for(unsigned j = 0; j < vi.size(); ++j)
|
||||||
{
|
{
|
||||||
for(unsigned k = 0; k < 5; ++k)
|
for(unsigned k = 0; k < 7; ++k)
|
||||||
{
|
{
|
||||||
auto const when = clock_type::now();
|
auto const when = clock_type::now();
|
||||||
vi[j]->serialize(vs[i].text, 1000);
|
vi[j]->serialize(vs[i].text, 1000);
|
||||||
auto const ms = std::chrono::duration_cast<
|
auto const ms = std::chrono::duration_cast<
|
||||||
std::chrono::milliseconds>(
|
std::chrono::milliseconds>(
|
||||||
clock_type::now() - when).count();
|
clock_type::now() - when).count();
|
||||||
if(k > 9)
|
if(k > 4)
|
||||||
dout << " " << vi[j]->name() << ": " <<
|
dout << " " << vi[j]->name() << ": " <<
|
||||||
std::to_string(ms) << "ms" <<
|
std::to_string(ms) << "ms" <<
|
||||||
std::endl;
|
std::endl;
|
||||||
@ -442,13 +447,13 @@ main(
|
|||||||
std::vector<std::unique_ptr<any_impl const>> vi;
|
std::vector<std::unique_ptr<any_impl const>> vi;
|
||||||
vi.reserve(10);
|
vi.reserve(10);
|
||||||
//vi.emplace_back(new boost_default_impl);
|
//vi.emplace_back(new boost_default_impl);
|
||||||
vi.emplace_back(new boost_impl);
|
//.emplace_back(new boost_impl);
|
||||||
//vi.emplace_back(new boost_vec_impl);
|
//vi.emplace_back(new boost_vec_impl);
|
||||||
vi.emplace_back(new rapidjson_impl);
|
//vi.emplace_back(new rapidjson_impl);
|
||||||
//vi.emplace_back(new nlohmann_impl);
|
vi.emplace_back(new nlohmann_impl);
|
||||||
|
|
||||||
benchParse(vs, vi);
|
//benchParse(vs, vi);
|
||||||
//benchSerialize(vs, vi);
|
benchSerialize(vs, vi);
|
||||||
}
|
}
|
||||||
catch(system_error const& se)
|
catch(system_error const& se)
|
||||||
{
|
{
|
||||||
|
@ -487,6 +487,7 @@ public:
|
|||||||
std::initializer_list<value> init,
|
std::initializer_list<value> init,
|
||||||
storage_ptr sp = {});
|
storage_ptr sp = {});
|
||||||
|
|
||||||
|
explicit
|
||||||
BOOST_JSON_DECL
|
BOOST_JSON_DECL
|
||||||
array(unchecked_array&& ua);
|
array(unchecked_array&& ua);
|
||||||
|
|
||||||
@ -1594,6 +1595,11 @@ private:
|
|||||||
impl_type& operator=(
|
impl_type& operator=(
|
||||||
impl_type const&) = default;
|
impl_type const&) = default;
|
||||||
|
|
||||||
|
inline
|
||||||
|
impl_type(
|
||||||
|
size_type capacity,
|
||||||
|
storage_ptr const& sp);
|
||||||
|
|
||||||
inline
|
inline
|
||||||
impl_type&
|
impl_type&
|
||||||
operator=(
|
operator=(
|
||||||
@ -1611,12 +1617,6 @@ private:
|
|||||||
void
|
void
|
||||||
swap(impl_type& rhs) noexcept;
|
swap(impl_type& rhs) noexcept;
|
||||||
|
|
||||||
inline
|
|
||||||
void
|
|
||||||
construct(
|
|
||||||
size_type capacity,
|
|
||||||
storage_ptr const& sp);
|
|
||||||
|
|
||||||
BOOST_JSON_DECL
|
BOOST_JSON_DECL
|
||||||
void
|
void
|
||||||
destroy(storage_ptr const& sp) noexcept;
|
destroy(storage_ptr const& sp) noexcept;
|
||||||
@ -1636,7 +1636,7 @@ private:
|
|||||||
array(
|
array(
|
||||||
InputIt first, InputIt last,
|
InputIt first, InputIt last,
|
||||||
storage_ptr sp,
|
storage_ptr sp,
|
||||||
std::random_access_iterator_tag);
|
std::forward_iterator_tag);
|
||||||
|
|
||||||
template<class InputIt>
|
template<class InputIt>
|
||||||
iterator
|
iterator
|
||||||
@ -1650,7 +1650,7 @@ private:
|
|||||||
insert(
|
insert(
|
||||||
const_iterator pos,
|
const_iterator pos,
|
||||||
InputIt first, InputIt last,
|
InputIt first, InputIt last,
|
||||||
std::random_access_iterator_tag);
|
std::forward_iterator_tag);
|
||||||
|
|
||||||
inline
|
inline
|
||||||
void
|
void
|
||||||
@ -1686,7 +1686,7 @@ private:
|
|||||||
class undo_assign;
|
class undo_assign;
|
||||||
class undo_insert;
|
class undo_insert;
|
||||||
|
|
||||||
storage_ptr sp_;
|
storage_ptr sp_; // must come first
|
||||||
impl_type impl_;
|
impl_type impl_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -420,12 +420,13 @@ array::
|
|||||||
array(
|
array(
|
||||||
InputIt first, InputIt last,
|
InputIt first, InputIt last,
|
||||||
storage_ptr sp,
|
storage_ptr sp,
|
||||||
std::random_access_iterator_tag)
|
std::forward_iterator_tag)
|
||||||
: sp_(std::move(sp))
|
: sp_(std::move(sp))
|
||||||
{
|
{
|
||||||
undo_create u(*this);
|
undo_create u(*this);
|
||||||
auto const n = static_cast<
|
auto const n =
|
||||||
unsigned long long>(last - first);
|
static_cast<std::size_t>(
|
||||||
|
std::distance(first, last));
|
||||||
if(n > max_size())
|
if(n > max_size())
|
||||||
BOOST_JSON_THROW(
|
BOOST_JSON_THROW(
|
||||||
std::length_error(
|
std::length_error(
|
||||||
@ -471,11 +472,12 @@ array::
|
|||||||
insert(
|
insert(
|
||||||
const_iterator pos,
|
const_iterator pos,
|
||||||
InputIt first, InputIt last,
|
InputIt first, InputIt last,
|
||||||
std::random_access_iterator_tag) ->
|
std::forward_iterator_tag) ->
|
||||||
iterator
|
iterator
|
||||||
{
|
{
|
||||||
auto const n = static_cast<
|
auto const n =
|
||||||
unsigned long long>(last - first);
|
static_cast<std::size_t>(
|
||||||
|
std::distance(first, last));
|
||||||
if(n > max_size())
|
if(n > max_size())
|
||||||
BOOST_JSON_THROW(
|
BOOST_JSON_THROW(
|
||||||
std::length_error(
|
std::length_error(
|
||||||
|
@ -24,6 +24,25 @@ namespace json {
|
|||||||
|
|
||||||
//----------------------------------------------------------
|
//----------------------------------------------------------
|
||||||
|
|
||||||
|
array::
|
||||||
|
impl_type::
|
||||||
|
impl_type(
|
||||||
|
size_type capacity_,
|
||||||
|
storage_ptr const& sp)
|
||||||
|
{
|
||||||
|
// The choice of minimum capacity
|
||||||
|
// affects the speed of parsing.
|
||||||
|
// if( capacity_ < min_capacity_)
|
||||||
|
// capacity_ = min_capacity_;
|
||||||
|
vec = reinterpret_cast<value*>(
|
||||||
|
sp->allocate(
|
||||||
|
capacity_ * sizeof(value),
|
||||||
|
alignof(value)));
|
||||||
|
size = 0;
|
||||||
|
capacity = capacity_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
array::
|
array::
|
||||||
impl_type::
|
impl_type::
|
||||||
impl_type(impl_type&& other) noexcept
|
impl_type(impl_type&& other) noexcept
|
||||||
@ -76,25 +95,6 @@ destroy(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
array::
|
|
||||||
impl_type::
|
|
||||||
construct(
|
|
||||||
size_type capacity_,
|
|
||||||
storage_ptr const& sp)
|
|
||||||
{
|
|
||||||
// The choice of minimum capacity
|
|
||||||
// affects the speed of parsing.
|
|
||||||
if( capacity_ < min_capacity_)
|
|
||||||
capacity_ = min_capacity_;
|
|
||||||
vec = reinterpret_cast<value*>(
|
|
||||||
sp->allocate(
|
|
||||||
capacity_ * sizeof(value),
|
|
||||||
alignof(value)));
|
|
||||||
size = 0;
|
|
||||||
capacity = capacity_;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------
|
//----------------------------------------------------------
|
||||||
|
|
||||||
array::
|
array::
|
||||||
@ -281,12 +281,10 @@ array(
|
|||||||
array::
|
array::
|
||||||
array(unchecked_array&& ua)
|
array(unchecked_array&& ua)
|
||||||
: sp_(ua.get_storage())
|
: sp_(ua.get_storage())
|
||||||
|
, impl_(ua.size(), sp_) // exact
|
||||||
{
|
{
|
||||||
undo_create u(*this);
|
|
||||||
reserve(ua.size());
|
|
||||||
impl_.size = ua.size();
|
impl_.size = ua.size();
|
||||||
ua.relocate(impl_.vec);
|
ua.relocate(impl_.vec);
|
||||||
u.commit = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------
|
//----------------------------------------------------------
|
||||||
@ -346,13 +344,18 @@ shrink_to_fit() noexcept
|
|||||||
impl_.capacity <= min_capacity_)
|
impl_.capacity <= min_capacity_)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
impl_type impl;
|
|
||||||
#ifndef BOOST_NO_EXCEPTIONS
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
impl.construct(
|
impl_type impl(impl_.size, sp_);
|
||||||
impl_.size, sp_);
|
relocate(
|
||||||
|
impl.vec,
|
||||||
|
impl_.vec, impl_.size);
|
||||||
|
impl.size = impl_.size;
|
||||||
|
impl_.size = 0;
|
||||||
|
impl_.swap(impl);
|
||||||
|
impl.destroy(sp_);
|
||||||
#ifndef BOOST_NO_EXCEPTIONS
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
@ -361,14 +364,6 @@ shrink_to_fit() noexcept
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
relocate(
|
|
||||||
impl.vec,
|
|
||||||
impl_.vec, impl_.size);
|
|
||||||
impl.size = impl_.size;
|
|
||||||
impl_.size = 0;
|
|
||||||
impl_.swap(impl);
|
|
||||||
impl.destroy(sp_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------
|
//----------------------------------------------------------
|
||||||
@ -628,15 +623,16 @@ reserve_impl(size_type capacity)
|
|||||||
else if(capacity < hint)
|
else if(capacity < hint)
|
||||||
capacity = hint;
|
capacity = hint;
|
||||||
}
|
}
|
||||||
impl_type impl;
|
if( capacity < min_capacity_)
|
||||||
impl.construct(capacity, sp_);
|
capacity = min_capacity_;
|
||||||
|
impl_type impl(capacity, sp_);
|
||||||
relocate(
|
relocate(
|
||||||
impl.vec,
|
impl.vec,
|
||||||
impl_.vec, impl_.size);
|
impl_.vec, impl_.size);
|
||||||
impl.size = impl_.size;
|
impl.size = impl_.size;
|
||||||
impl_.size = 0;
|
impl_.size = 0;
|
||||||
impl_.swap(impl);
|
impl_.destroy(sp_);
|
||||||
impl.destroy(sp_);
|
impl_ = impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
#include <boost/json/detail/except.hpp>
|
#include <boost/json/detail/except.hpp>
|
||||||
#include <boost/json/detail/exchange.hpp>
|
#include <boost/json/detail/exchange.hpp>
|
||||||
#include <boost/json/detail/string.hpp>
|
#include <boost/json/detail/string.hpp>
|
||||||
#include <algorithm>
|
#include <iterator>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@ -123,66 +123,35 @@ bucket_end() const noexcept ->
|
|||||||
return bucket_begin() + buckets();
|
return bucket_begin() + buckets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------
|
//----------------------------------------------------------
|
||||||
|
|
||||||
class object::undo_construct
|
struct object::undo_construct
|
||||||
{
|
{
|
||||||
object& self_;
|
object* self;
|
||||||
|
|
||||||
public:
|
|
||||||
bool commit = false;
|
|
||||||
|
|
||||||
~undo_construct()
|
~undo_construct()
|
||||||
{
|
{
|
||||||
if(! commit)
|
if(self)
|
||||||
self_.impl_.destroy(
|
self->impl_.destroy(
|
||||||
self_.sp_);
|
self->sp_);
|
||||||
}
|
|
||||||
|
|
||||||
explicit
|
|
||||||
undo_construct(
|
|
||||||
object& self) noexcept
|
|
||||||
: self_(self)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------
|
//----------------------------------------------------------
|
||||||
|
|
||||||
class object::undo_insert
|
struct object::place_one
|
||||||
{
|
{
|
||||||
object& self_;
|
virtual
|
||||||
|
void
|
||||||
|
operator()(void* dest) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
struct object::place_range
|
||||||
value_type* const first;
|
|
||||||
value_type* last;
|
|
||||||
bool commit = false;
|
|
||||||
|
|
||||||
~undo_insert()
|
|
||||||
{
|
{
|
||||||
if(commit)
|
virtual
|
||||||
{
|
bool
|
||||||
self_.impl_.grow(last - first);
|
operator()(void* dest) = 0;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for(auto it = first; it != last; ++it)
|
|
||||||
self_.impl_.remove(
|
|
||||||
self_.impl_.bucket(it->key()), it);
|
|
||||||
value_type::destroy(
|
|
||||||
first, static_cast<
|
|
||||||
std::size_t>(last - first));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit
|
|
||||||
undo_insert(
|
|
||||||
object& self) noexcept
|
|
||||||
: self_(self)
|
|
||||||
, first(self_.impl_.end())
|
|
||||||
, last(first)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------
|
//----------------------------------------------------------
|
||||||
@ -200,11 +169,11 @@ object(
|
|||||||
storage_ptr sp)
|
storage_ptr sp)
|
||||||
: sp_(std::move(sp))
|
: sp_(std::move(sp))
|
||||||
{
|
{
|
||||||
undo_construct u(*this);
|
undo_construct u{this};
|
||||||
insert_range(
|
insert_range(
|
||||||
first, last,
|
first, last,
|
||||||
min_capacity);
|
min_capacity);
|
||||||
u.commit = true;
|
u.self = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------
|
//----------------------------------------------------------
|
||||||
@ -355,22 +324,30 @@ object::
|
|||||||
insert(P&& p) ->
|
insert(P&& p) ->
|
||||||
std::pair<iterator, bool>
|
std::pair<iterator, bool>
|
||||||
{
|
{
|
||||||
reserve(size() + 1);
|
struct place_impl : place_one
|
||||||
auto& e = *::new(
|
{
|
||||||
impl_.end()) value_type(
|
P&& p;
|
||||||
std::forward<P>(p), sp_);
|
storage_ptr const& sp;
|
||||||
auto const result = find_impl(e.key());
|
|
||||||
if(result.first)
|
place_impl(
|
||||||
|
P&& p_,
|
||||||
|
storage_ptr const& sp_)
|
||||||
|
: p(std::forward<P>(p_))
|
||||||
|
, sp(sp_)
|
||||||
{
|
{
|
||||||
e.~value_type();
|
|
||||||
return { result.first, false };
|
|
||||||
}
|
}
|
||||||
auto& head =
|
|
||||||
impl_.bucket(result.second);
|
void
|
||||||
e.next_ = head;
|
operator()(void* dest) override
|
||||||
head = &e;
|
{
|
||||||
impl_.grow(1);
|
::new(dest) value_type(
|
||||||
return { &e, true };
|
std::forward<P>(p), sp);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
place_impl f(
|
||||||
|
std::forward<P>(p), sp_);
|
||||||
|
return insert_impl(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class M>
|
template<class M>
|
||||||
@ -380,6 +357,30 @@ insert_or_assign(
|
|||||||
key_type key, M&& m) ->
|
key_type key, M&& m) ->
|
||||||
std::pair<iterator, bool>
|
std::pair<iterator, bool>
|
||||||
{
|
{
|
||||||
|
struct place_impl : place_one
|
||||||
|
{
|
||||||
|
key_type key;
|
||||||
|
M&& m;
|
||||||
|
storage_ptr const& sp;
|
||||||
|
|
||||||
|
place_impl(
|
||||||
|
key_type key_,
|
||||||
|
M&& m_,
|
||||||
|
storage_ptr const& sp_)
|
||||||
|
: key(key_)
|
||||||
|
, m(std::forward<M>(m_))
|
||||||
|
, sp(sp_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
operator()(void* dest) override
|
||||||
|
{
|
||||||
|
::new(dest) value_type(key,
|
||||||
|
std::forward<M>(m), sp);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
auto const result = find_impl(key);
|
auto const result = find_impl(key);
|
||||||
if(result.first)
|
if(result.first)
|
||||||
{
|
{
|
||||||
@ -387,16 +388,11 @@ insert_or_assign(
|
|||||||
std::forward<M>(m);
|
std::forward<M>(m);
|
||||||
return { result.first, false };
|
return { result.first, false };
|
||||||
}
|
}
|
||||||
reserve(size() + 1);
|
|
||||||
auto& e = *::new(
|
place_impl f(key,
|
||||||
impl_.end()) value_type(
|
std::forward<M>(m), sp_);
|
||||||
key, std::forward<M>(m), sp_);
|
return { insert_impl(
|
||||||
auto& head =
|
result.second, f), true };
|
||||||
impl_.bucket(result.second);
|
|
||||||
e.next_ = head;
|
|
||||||
head = &e;
|
|
||||||
impl_.grow(1);
|
|
||||||
return { &e, true };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Arg>
|
template<class Arg>
|
||||||
@ -407,17 +403,33 @@ emplace(
|
|||||||
Arg&& arg) ->
|
Arg&& arg) ->
|
||||||
std::pair<iterator, bool>
|
std::pair<iterator, bool>
|
||||||
{
|
{
|
||||||
auto const result = find_impl(key);
|
struct place_impl : place_one
|
||||||
if(result.first)
|
{
|
||||||
return { result.first, false };
|
key_type key;
|
||||||
reserve(size() + 1);
|
Arg&& arg;
|
||||||
auto p = ::new(impl_.end()) value_type(
|
storage_ptr const& sp;
|
||||||
key, std::forward<Arg>(arg), sp_);
|
|
||||||
auto& head = impl_.bucket(result.second);
|
place_impl(
|
||||||
p->next_ = head;
|
key_type key_,
|
||||||
head = p;
|
Arg&& arg_,
|
||||||
impl_.grow(1);
|
storage_ptr const& sp_)
|
||||||
return { p, true };
|
: key(key_)
|
||||||
|
, arg(std::forward<Arg>(arg_))
|
||||||
|
, sp(sp_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
operator()(void* dest) override
|
||||||
|
{
|
||||||
|
::new(dest) value_type(key,
|
||||||
|
std::forward<Arg>(arg), sp);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
place_impl f(key,
|
||||||
|
std::forward<Arg>(arg), sp_);
|
||||||
|
return emplace_impl(key, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------
|
//----------------------------------------------------------
|
||||||
@ -482,33 +494,15 @@ insert_range(
|
|||||||
std::size_t min_capacity,
|
std::size_t min_capacity,
|
||||||
std::input_iterator_tag)
|
std::input_iterator_tag)
|
||||||
{
|
{
|
||||||
|
// Since input iterators cannot be rewound,
|
||||||
|
// we keep inserted elements on an exception.
|
||||||
|
//
|
||||||
reserve(min_capacity);
|
reserve(min_capacity);
|
||||||
undo_insert u(*this);
|
|
||||||
while(first != last)
|
while(first != last)
|
||||||
{
|
{
|
||||||
reserve(size() + 1);
|
insert(*first);
|
||||||
auto& e = *::new(
|
++first;
|
||||||
u.last) value_type(*first++, sp_);
|
|
||||||
auto& head = impl_.bucket(e.key());
|
|
||||||
for(auto it = head;;
|
|
||||||
it = it->next_)
|
|
||||||
{
|
|
||||||
if(it)
|
|
||||||
{
|
|
||||||
if(it->key() != e.key())
|
|
||||||
continue;
|
|
||||||
e.~value_type();
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
e.next_ = head;
|
|
||||||
head = &e;
|
|
||||||
++u.last;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
u.commit = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class InputIt>
|
template<class InputIt>
|
||||||
@ -518,42 +512,44 @@ insert_range(
|
|||||||
InputIt first,
|
InputIt first,
|
||||||
InputIt last,
|
InputIt last,
|
||||||
std::size_t min_capacity,
|
std::size_t min_capacity,
|
||||||
std::random_access_iterator_tag)
|
std::forward_iterator_tag)
|
||||||
{
|
{
|
||||||
auto n = static_cast<
|
struct place_impl : place_range
|
||||||
std::size_t>(last - first);
|
{
|
||||||
|
InputIt it;
|
||||||
|
std::size_t n;
|
||||||
|
storage_ptr const& sp;
|
||||||
|
|
||||||
|
place_impl(
|
||||||
|
InputIt it_,
|
||||||
|
std::size_t n_,
|
||||||
|
storage_ptr const& sp_)
|
||||||
|
: it(it_)
|
||||||
|
, n(n_)
|
||||||
|
, sp(sp_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
operator()(void* dest) override
|
||||||
|
{
|
||||||
|
if(n-- == 0)
|
||||||
|
return false;
|
||||||
|
::new(dest) value_type(*it++, sp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto const n = static_cast<std::size_t>(
|
||||||
|
std::distance(first, last));
|
||||||
auto const n0 = size();
|
auto const n0 = size();
|
||||||
if(n > max_size() - n0)
|
if(n > max_size() - n0)
|
||||||
BOOST_JSON_THROW(
|
BOOST_JSON_THROW(
|
||||||
detail::object_too_large_exception());
|
detail::object_too_large_exception());
|
||||||
if( min_capacity < n0 + n)
|
if( min_capacity < n0 + n)
|
||||||
min_capacity = n0 + n;
|
min_capacity = n0 + n;
|
||||||
reserve(min_capacity);
|
place_impl f(first, n, sp_);
|
||||||
undo_insert u(*this);
|
insert_range_impl(min_capacity, f);
|
||||||
while(n--)
|
|
||||||
{
|
|
||||||
auto& e = *::new(
|
|
||||||
u.last) value_type(*first++, sp_);
|
|
||||||
auto& head = impl_.bucket(e.key());
|
|
||||||
for(auto it = head;;
|
|
||||||
it = it->next_)
|
|
||||||
{
|
|
||||||
if(it)
|
|
||||||
{
|
|
||||||
if(it->key() != e.key())
|
|
||||||
continue;
|
|
||||||
e.~value_type();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
e.next_ = head;
|
|
||||||
head = &e;
|
|
||||||
++u.last;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
u.commit = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // json
|
} // json
|
||||||
|
@ -148,6 +148,52 @@ swap(impl_type& rhs) noexcept
|
|||||||
rhs.tab_ = tmp;
|
rhs.tab_ = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
|
||||||
|
class object::undo_insert
|
||||||
|
{
|
||||||
|
object& self_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::size_t const first;
|
||||||
|
std::size_t last;
|
||||||
|
bool commit = false;
|
||||||
|
|
||||||
|
~undo_insert()
|
||||||
|
{
|
||||||
|
if(commit)
|
||||||
|
{
|
||||||
|
self_.impl_.grow(last - first);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto p0 = self_.impl_.begin() + first;
|
||||||
|
auto p1 = self_.impl_.begin() + last;
|
||||||
|
for(auto it = p0; it != p1; ++it)
|
||||||
|
self_.impl_.remove(
|
||||||
|
self_.impl_.bucket(it->key()), it);
|
||||||
|
value_type::destroy(p0, last - first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit
|
||||||
|
undo_insert(
|
||||||
|
object& self) noexcept
|
||||||
|
: self_(self)
|
||||||
|
, first(
|
||||||
|
self_.impl_.end() -
|
||||||
|
self_.impl_.begin())
|
||||||
|
, last(first)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type*
|
||||||
|
pos() noexcept
|
||||||
|
{
|
||||||
|
return self_.begin() + last;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------
|
//----------------------------------------------------------
|
||||||
//
|
//
|
||||||
// object
|
// object
|
||||||
@ -188,11 +234,11 @@ object(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
undo_construct u(*this);
|
undo_construct u{this};
|
||||||
insert_range(
|
insert_range(
|
||||||
other.begin(),
|
other.begin(),
|
||||||
other.end(), 0);
|
other.end(), 0);
|
||||||
u.commit = true;
|
u.self = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,11 +254,11 @@ object(
|
|||||||
object const& other)
|
object const& other)
|
||||||
: sp_(other.sp_)
|
: sp_(other.sp_)
|
||||||
{
|
{
|
||||||
undo_construct u(*this);
|
undo_construct u{this};
|
||||||
insert_range(
|
insert_range(
|
||||||
other.begin(),
|
other.begin(),
|
||||||
other.end(), 0);
|
other.end(), 0);
|
||||||
u.commit = true;
|
u.self = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
object::
|
object::
|
||||||
@ -221,11 +267,11 @@ object(
|
|||||||
storage_ptr sp)
|
storage_ptr sp)
|
||||||
: sp_(std::move(sp))
|
: sp_(std::move(sp))
|
||||||
{
|
{
|
||||||
undo_construct u(*this);
|
undo_construct u{this};
|
||||||
insert_range(
|
insert_range(
|
||||||
other.begin(),
|
other.begin(),
|
||||||
other.end(), 0);
|
other.end(), 0);
|
||||||
u.commit = true;
|
u.self = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
object::
|
object::
|
||||||
@ -235,12 +281,12 @@ object(
|
|||||||
storage_ptr sp)
|
storage_ptr sp)
|
||||||
: sp_(std::move(sp))
|
: sp_(std::move(sp))
|
||||||
{
|
{
|
||||||
undo_construct u(*this);
|
undo_construct u{this};
|
||||||
insert_range(
|
insert_range(
|
||||||
init.begin(),
|
init.begin(),
|
||||||
init.end(),
|
init.end(),
|
||||||
min_capacity);
|
min_capacity);
|
||||||
u.commit = true;
|
u.self = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
object::
|
object::
|
||||||
@ -565,6 +611,106 @@ rehash(std::size_t new_capacity)
|
|||||||
impl_.rebuild();
|
impl_.rebuild();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto
|
||||||
|
object::
|
||||||
|
emplace_impl(
|
||||||
|
key_type key,
|
||||||
|
place_one& f) ->
|
||||||
|
std::pair<iterator, bool>
|
||||||
|
{
|
||||||
|
auto const result = find_impl(key);
|
||||||
|
if(result.first)
|
||||||
|
return { result.first, false };
|
||||||
|
reserve(size() + 1);
|
||||||
|
auto& e = *impl_.end();
|
||||||
|
f(&e);
|
||||||
|
auto& head =
|
||||||
|
impl_.bucket(result.second);
|
||||||
|
e.next_ = head;
|
||||||
|
head = &e;
|
||||||
|
impl_.grow(1);
|
||||||
|
return { &e, true };
|
||||||
|
}
|
||||||
|
|
||||||
|
auto
|
||||||
|
object::
|
||||||
|
insert_impl(
|
||||||
|
place_one& f) ->
|
||||||
|
std::pair<iterator, bool>
|
||||||
|
{
|
||||||
|
reserve(size() + 1);
|
||||||
|
auto& e = *impl_.end();
|
||||||
|
f(&e);
|
||||||
|
auto const result =
|
||||||
|
find_impl(e.key());
|
||||||
|
if(result.first)
|
||||||
|
{
|
||||||
|
e.~value_type();
|
||||||
|
return { result.first, false };
|
||||||
|
}
|
||||||
|
auto& head =
|
||||||
|
impl_.bucket(result.second);
|
||||||
|
e.next_ = head;
|
||||||
|
head = &e;
|
||||||
|
impl_.grow(1);
|
||||||
|
return { &e, true };
|
||||||
|
}
|
||||||
|
|
||||||
|
auto
|
||||||
|
object::
|
||||||
|
insert_impl(
|
||||||
|
std::size_t hash,
|
||||||
|
place_one& f) ->
|
||||||
|
iterator
|
||||||
|
{
|
||||||
|
reserve(size() + 1);
|
||||||
|
auto& e = *impl_.end();
|
||||||
|
f(&e);
|
||||||
|
auto& head =
|
||||||
|
impl_.bucket(hash);
|
||||||
|
e.next_ = head;
|
||||||
|
head = &e;
|
||||||
|
impl_.grow(1);
|
||||||
|
return &e;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
object::
|
||||||
|
insert_range_impl(
|
||||||
|
std::size_t min_capacity,
|
||||||
|
place_range& f)
|
||||||
|
{
|
||||||
|
reserve(min_capacity);
|
||||||
|
undo_insert u(*this);
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
reserve(size() + 1);
|
||||||
|
auto& e = *u.pos();
|
||||||
|
if(! f(&e))
|
||||||
|
break;
|
||||||
|
auto& head =
|
||||||
|
impl_.bucket(e.key());
|
||||||
|
for(auto it = head;;
|
||||||
|
it = it->next_)
|
||||||
|
{
|
||||||
|
if(it)
|
||||||
|
{
|
||||||
|
if(it->key() != e.key())
|
||||||
|
continue;
|
||||||
|
e.~value_type();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
e.next_ = head;
|
||||||
|
head = &e;
|
||||||
|
++u.last;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
u.commit = true;
|
||||||
|
}
|
||||||
|
|
||||||
} // json
|
} // json
|
||||||
} // boost
|
} // boost
|
||||||
|
|
||||||
|
@ -97,6 +97,7 @@ void
|
|||||||
parser::
|
parser::
|
||||||
on_document_begin(error_code&)
|
on_document_begin(error_code&)
|
||||||
{
|
{
|
||||||
|
lev_ = level{ 0, false };
|
||||||
st_.placeholder(sizeof(value));
|
st_.placeholder(sizeof(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +116,6 @@ void
|
|||||||
parser::
|
parser::
|
||||||
on_object_begin(error_code&)
|
on_object_begin(error_code&)
|
||||||
{
|
{
|
||||||
lev_ = level{ 0, false };
|
|
||||||
st_.push(lev_);
|
st_.push(lev_);
|
||||||
lev_ = level{ 0, true };
|
lev_ = level{ 0, true };
|
||||||
st_.placeholder(sizeof(
|
st_.placeholder(sizeof(
|
||||||
@ -204,6 +204,7 @@ on_key(
|
|||||||
st_.push(s);
|
st_.push(s);
|
||||||
key_ += static_cast<size_type>(
|
key_ += static_cast<size_type>(
|
||||||
s.size());
|
s.size());
|
||||||
|
st_.align();
|
||||||
st_.push(key_);
|
st_.push(key_);
|
||||||
key_ = 0;
|
key_ = 0;
|
||||||
}
|
}
|
||||||
|
@ -136,6 +136,20 @@ from_json(T& t, value const& v)
|
|||||||
|
|
||||||
//----------------------------------------------------------
|
//----------------------------------------------------------
|
||||||
|
|
||||||
|
value::
|
||||||
|
value(unchecked_object&& uo)
|
||||||
|
: obj_(std::move(uo))
|
||||||
|
, kind_(json::kind::object)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
value::
|
||||||
|
value(unchecked_array&& ua)
|
||||||
|
: arr_(std::move(ua))
|
||||||
|
, kind_(json::kind::array)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
template<class Bool, class>
|
template<class Bool, class>
|
||||||
value::
|
value::
|
||||||
value(Bool b, storage_ptr sp) noexcept
|
value(Bool b, storage_ptr sp) noexcept
|
||||||
@ -165,6 +179,7 @@ value_type(
|
|||||||
Args&&... args)
|
Args&&... args)
|
||||||
: value_(std::forward<Args>(args)...)
|
: value_(std::forward<Args>(args)...)
|
||||||
, len_(key.size())
|
, len_(key.size())
|
||||||
|
#if 0
|
||||||
, key_(
|
, key_(
|
||||||
[&]
|
[&]
|
||||||
{
|
{
|
||||||
@ -178,7 +193,16 @@ value_type(
|
|||||||
s[key.size()] = 0;
|
s[key.size()] = 0;
|
||||||
return s;
|
return s;
|
||||||
}())
|
}())
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
|
if(key.size() > detail::max_string_length_)
|
||||||
|
BOOST_JSON_THROW(
|
||||||
|
detail::string_too_large_exception());
|
||||||
|
key_ = reinterpret_cast<
|
||||||
|
char*>(value_.get_storage()->
|
||||||
|
allocate(key.size() + 1));
|
||||||
|
std::memcpy(key_, key.data(), key.size());
|
||||||
|
key_[key.size()] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------
|
//----------------------------------------------------------
|
||||||
|
@ -446,34 +446,6 @@ maybe_object(
|
|||||||
//
|
//
|
||||||
//----------------------------------------------------------
|
//----------------------------------------------------------
|
||||||
|
|
||||||
storage_ptr const&
|
|
||||||
value::
|
|
||||||
get_storage() const noexcept
|
|
||||||
{
|
|
||||||
switch(kind_)
|
|
||||||
{
|
|
||||||
case json::kind::object:
|
|
||||||
return obj_.get_storage();
|
|
||||||
|
|
||||||
case json::kind::array:
|
|
||||||
return arr_.get_storage();
|
|
||||||
|
|
||||||
case json::kind::string:
|
|
||||||
return str_.get_storage();
|
|
||||||
|
|
||||||
case json::kind::int64:
|
|
||||||
case json::kind::uint64:
|
|
||||||
case json::kind::double_:
|
|
||||||
case json::kind::boolean:
|
|
||||||
case json::kind::null:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return sca_.sp;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------
|
|
||||||
|
|
||||||
storage_ptr
|
storage_ptr
|
||||||
value::
|
value::
|
||||||
destroy() noexcept
|
destroy() noexcept
|
||||||
|
@ -225,7 +225,7 @@ private:
|
|||||||
bucket_end() const noexcept;
|
bucket_end() const noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
class undo_construct;
|
struct undo_construct;
|
||||||
class undo_insert;
|
class undo_insert;
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
@ -242,7 +242,7 @@ private:
|
|||||||
return 1.0;
|
return 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
storage_ptr sp_;
|
storage_ptr sp_; // must come first
|
||||||
impl_type impl_;
|
impl_type impl_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -553,6 +553,7 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
|
explicit
|
||||||
BOOST_JSON_DECL
|
BOOST_JSON_DECL
|
||||||
object(unchecked_object&& uo);
|
object(unchecked_object&& uo);
|
||||||
|
|
||||||
@ -1345,12 +1346,8 @@ public:
|
|||||||
contains(key_type key) const noexcept;
|
contains(key_type key) const noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct place
|
struct place_one;
|
||||||
{
|
struct place_range;
|
||||||
virtual
|
|
||||||
void
|
|
||||||
operator()(void* dest) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class It>
|
template<class It>
|
||||||
using iter_cat = typename
|
using iter_cat = typename
|
||||||
@ -1376,15 +1373,39 @@ private:
|
|||||||
digest(key_type key) noexcept;
|
digest(key_type key) noexcept;
|
||||||
|
|
||||||
BOOST_JSON_DECL
|
BOOST_JSON_DECL
|
||||||
std::pair<
|
std::pair<value_type*, std::size_t>
|
||||||
value_type*,
|
|
||||||
std::size_t>
|
|
||||||
find_impl(key_type key) const noexcept;
|
find_impl(key_type key) const noexcept;
|
||||||
|
|
||||||
BOOST_JSON_DECL
|
BOOST_JSON_DECL
|
||||||
void
|
void
|
||||||
rehash(std::size_t new_capacity);
|
rehash(std::size_t new_capacity);
|
||||||
|
|
||||||
|
BOOST_JSON_DECL
|
||||||
|
std::pair<iterator, bool>
|
||||||
|
emplace_impl(
|
||||||
|
key_type key, place_one& f);
|
||||||
|
|
||||||
|
BOOST_JSON_DECL
|
||||||
|
std::pair<iterator, bool>
|
||||||
|
insert_impl(place_one& f);
|
||||||
|
|
||||||
|
BOOST_JSON_DECL
|
||||||
|
iterator
|
||||||
|
insert_impl(
|
||||||
|
std::size_t hash,
|
||||||
|
place_one& f);
|
||||||
|
|
||||||
|
BOOST_JSON_DECL
|
||||||
|
std::pair<iterator, bool>
|
||||||
|
insert_or_assign_impl(
|
||||||
|
key_type key, place_one& f);
|
||||||
|
|
||||||
|
BOOST_JSON_DECL
|
||||||
|
void
|
||||||
|
insert_range_impl(
|
||||||
|
std::size_t min_capacity,
|
||||||
|
place_range& f);
|
||||||
|
|
||||||
template<class InputIt>
|
template<class InputIt>
|
||||||
void
|
void
|
||||||
insert_range(
|
insert_range(
|
||||||
@ -1399,7 +1420,7 @@ private:
|
|||||||
InputIt first,
|
InputIt first,
|
||||||
InputIt last,
|
InputIt last,
|
||||||
std::size_t min_capacity,
|
std::size_t min_capacity,
|
||||||
std::random_access_iterator_tag);
|
std::forward_iterator_tag);
|
||||||
|
|
||||||
template<class InputIt>
|
template<class InputIt>
|
||||||
void
|
void
|
||||||
|
@ -31,8 +31,9 @@ class parser final
|
|||||||
{
|
{
|
||||||
struct level
|
struct level
|
||||||
{
|
{
|
||||||
size_type size;
|
std::int32_t size;
|
||||||
bool obj;
|
bool obj;
|
||||||
|
char pad[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
class stack
|
class stack
|
||||||
@ -97,8 +98,9 @@ class parser final
|
|||||||
object::value_type&
|
object::value_type&
|
||||||
emplace_pair(Arg&& arg)
|
emplace_pair(Arg&& arg)
|
||||||
{
|
{
|
||||||
size_type len;
|
std::size_t len;
|
||||||
pop_impl(len);
|
pop_impl(len);
|
||||||
|
size_ -= alignup(len) - len;
|
||||||
auto key = pop_string(len);
|
auto key = pop_string(len);
|
||||||
auto const n = sizeof(object::value_type);
|
auto const n = sizeof(object::value_type);
|
||||||
// size for n was placeheld
|
// size for n was placeheld
|
||||||
@ -114,7 +116,10 @@ class parser final
|
|||||||
placeholder(
|
placeholder(
|
||||||
std::size_t bytes)
|
std::size_t bytes)
|
||||||
{
|
{
|
||||||
bytes = alignup(bytes);
|
BOOST_JSON_ASSERT(
|
||||||
|
alignup(bytes) == bytes);
|
||||||
|
BOOST_JSON_ASSERT(
|
||||||
|
alignup(size_) == size_);
|
||||||
prepare(bytes);
|
prepare(bytes);
|
||||||
size_ += bytes;
|
size_ += bytes;
|
||||||
}
|
}
|
||||||
@ -123,14 +128,26 @@ class parser final
|
|||||||
unreserve(
|
unreserve(
|
||||||
std::size_t bytes)
|
std::size_t bytes)
|
||||||
{
|
{
|
||||||
bytes = alignup(bytes);
|
BOOST_JSON_ASSERT(
|
||||||
|
alignup(bytes) == bytes);
|
||||||
|
BOOST_JSON_ASSERT(
|
||||||
|
alignup(size_) == size_);
|
||||||
BOOST_JSON_ASSERT(
|
BOOST_JSON_ASSERT(
|
||||||
bytes <= size_);
|
bytes <= size_);
|
||||||
size_ -= bytes;
|
size_ -= bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
push(size_type u)
|
align()
|
||||||
|
{
|
||||||
|
auto const n = alignup(size_);
|
||||||
|
if(n > capacity_)
|
||||||
|
grow(n - size_);
|
||||||
|
size_ = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
push(std::size_t u)
|
||||||
{
|
{
|
||||||
push_impl(u);
|
push_impl(u);
|
||||||
}
|
}
|
||||||
@ -147,7 +164,7 @@ class parser final
|
|||||||
prepare(s.size());
|
prepare(s.size());
|
||||||
std::memcpy(base_ + size_,
|
std::memcpy(base_ + size_,
|
||||||
s.data(), s.size());
|
s.data(), s.size());
|
||||||
size_ += alignup(s.size());
|
size_ += s.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -159,11 +176,16 @@ class parser final
|
|||||||
unchecked_array
|
unchecked_array
|
||||||
pop_array(size_type size) noexcept
|
pop_array(size_type size) noexcept
|
||||||
{
|
{
|
||||||
|
BOOST_JSON_ASSERT(
|
||||||
|
alignup(size_) == size_);
|
||||||
if(size == 0)
|
if(size == 0)
|
||||||
return { nullptr, 0, sp_ };
|
return { nullptr, 0, sp_ };
|
||||||
auto const n = sizeof(value) * size;
|
auto const n =
|
||||||
|
sizeof(value) * size;
|
||||||
|
BOOST_JSON_ASSERT(
|
||||||
|
alignup(n) == n);
|
||||||
BOOST_JSON_ASSERT(n <= size_);
|
BOOST_JSON_ASSERT(n <= size_);
|
||||||
size_ -= alignup(n);
|
size_ -= n;
|
||||||
return { reinterpret_cast<
|
return { reinterpret_cast<
|
||||||
value*>(base_ + size_),
|
value*>(base_ + size_),
|
||||||
size, sp_ };
|
size, sp_ };
|
||||||
@ -172,19 +194,23 @@ class parser final
|
|||||||
unchecked_object
|
unchecked_object
|
||||||
pop_object(size_type size) noexcept
|
pop_object(size_type size) noexcept
|
||||||
{
|
{
|
||||||
|
BOOST_JSON_ASSERT(
|
||||||
|
alignup(size_) == size_);
|
||||||
if(size == 0)
|
if(size == 0)
|
||||||
return { nullptr, 0, sp_ };
|
return { nullptr, 0, sp_ };
|
||||||
auto const n = sizeof(
|
auto const n = sizeof(
|
||||||
object::value_type) * size;
|
object::value_type) * size;
|
||||||
|
BOOST_JSON_ASSERT(
|
||||||
|
alignup(n) == n);
|
||||||
BOOST_JSON_ASSERT(n <= size_);
|
BOOST_JSON_ASSERT(n <= size_);
|
||||||
size_ -= alignup(n);
|
size_ -= n;
|
||||||
return { reinterpret_cast<
|
return { reinterpret_cast<
|
||||||
object::value_type*>(base_ + size_),
|
object::value_type*>(base_ + size_),
|
||||||
size, sp_ };
|
size, sp_ };
|
||||||
}
|
}
|
||||||
|
|
||||||
string_view
|
string_view
|
||||||
pop_string(size_type len) noexcept
|
pop_string(std::size_t len) noexcept
|
||||||
{
|
{
|
||||||
BOOST_JSON_ASSERT(len <= size_);
|
BOOST_JSON_ASSERT(len <= size_);
|
||||||
size_ -= len;
|
size_ -= len;
|
||||||
@ -205,7 +231,6 @@ class parser final
|
|||||||
void
|
void
|
||||||
prepare(std::size_t n)
|
prepare(std::size_t n)
|
||||||
{
|
{
|
||||||
n = alignup(n);
|
|
||||||
if(n > capacity_ - size_)
|
if(n > capacity_ - size_)
|
||||||
grow(n);
|
grow(n);
|
||||||
}
|
}
|
||||||
@ -238,7 +263,11 @@ class parser final
|
|||||||
void
|
void
|
||||||
push_impl(T t)
|
push_impl(T t)
|
||||||
{
|
{
|
||||||
auto const n = alignup(sizeof(T));
|
BOOST_JSON_ASSERT((sizeof(T) %
|
||||||
|
sizeof(max_align_t)) == 0);
|
||||||
|
BOOST_JSON_ASSERT((size_ %
|
||||||
|
sizeof(max_align_t)) == 0);
|
||||||
|
auto const n = sizeof(T);
|
||||||
if(n > capacity_ - size_)
|
if(n > capacity_ - size_)
|
||||||
grow(n);
|
grow(n);
|
||||||
::new(base_ + size_) T(t);
|
::new(base_ + size_) T(t);
|
||||||
@ -249,9 +278,13 @@ class parser final
|
|||||||
void
|
void
|
||||||
pop_impl(T& t) noexcept
|
pop_impl(T& t) noexcept
|
||||||
{
|
{
|
||||||
BOOST_JSON_ASSERT(
|
BOOST_JSON_ASSERT((sizeof(T) %
|
||||||
size_ >= sizeof(T));
|
sizeof(max_align_t)) == 0);
|
||||||
size_ -= alignup(sizeof(T));
|
BOOST_JSON_ASSERT((size_ %
|
||||||
|
sizeof(max_align_t)) == 0);
|
||||||
|
auto const n = sizeof(T);
|
||||||
|
BOOST_JSON_ASSERT(size_ >= n);
|
||||||
|
size_ -= n;
|
||||||
std::memcpy(
|
std::memcpy(
|
||||||
&t, base_ + size_, sizeof(T));
|
&t, base_ + size_, sizeof(T));
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ private:
|
|||||||
union
|
union
|
||||||
{
|
{
|
||||||
char* p;
|
char* p;
|
||||||
char buf[20]; // SBO
|
char buf[4]; // SBO
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -227,7 +227,7 @@ private:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
storage_ptr sp_;
|
storage_ptr sp_; // must come first
|
||||||
impl impl_;
|
impl impl_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -33,6 +33,8 @@ namespace boost {
|
|||||||
namespace json {
|
namespace json {
|
||||||
|
|
||||||
class value;
|
class value;
|
||||||
|
class unchecked_object;
|
||||||
|
class unchecked_array;
|
||||||
|
|
||||||
/** Customization point for assigning to and from class types.
|
/** Customization point for assigning to and from class types.
|
||||||
*/
|
*/
|
||||||
@ -109,7 +111,7 @@ class value
|
|||||||
#ifndef GENERATING_DOCUMENTATION
|
#ifndef GENERATING_DOCUMENTATION
|
||||||
struct scalar
|
struct scalar
|
||||||
{
|
{
|
||||||
storage_ptr sp;
|
storage_ptr sp; // must come first
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
std::uint64_t u;
|
std::uint64_t u;
|
||||||
@ -132,6 +134,7 @@ class value
|
|||||||
// XSL scripts have trouble with private anon unions
|
// XSL scripts have trouble with private anon unions
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
|
storage_ptr sp_; // must come first
|
||||||
object obj_;
|
object obj_;
|
||||||
array arr_;
|
array arr_;
|
||||||
string str_;
|
string str_;
|
||||||
@ -377,6 +380,11 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Construct an array.
|
||||||
|
*/
|
||||||
|
inline
|
||||||
|
value(unchecked_object&& uo);
|
||||||
|
|
||||||
/** Construct an array.
|
/** Construct an array.
|
||||||
*/
|
*/
|
||||||
value(array arr) noexcept
|
value(array arr) noexcept
|
||||||
@ -402,6 +410,11 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Construct an array.
|
||||||
|
*/
|
||||||
|
inline
|
||||||
|
value(unchecked_array&& ua);
|
||||||
|
|
||||||
/** Construct a string.
|
/** Construct a string.
|
||||||
*/
|
*/
|
||||||
value(
|
value(
|
||||||
@ -1055,9 +1068,11 @@ public:
|
|||||||
|
|
||||||
No-throw guarantee.
|
No-throw guarantee.
|
||||||
*/
|
*/
|
||||||
BOOST_JSON_DECL
|
|
||||||
storage_ptr const&
|
storage_ptr const&
|
||||||
get_storage() const noexcept;
|
get_storage() const noexcept
|
||||||
|
{
|
||||||
|
return sp_;
|
||||||
|
}
|
||||||
|
|
||||||
/** Return a pointer to an object, or nullptr.
|
/** Return a pointer to an object, or nullptr.
|
||||||
|
|
||||||
|
@ -92,6 +92,12 @@ struct fail_storage
|
|||||||
|
|
||||||
std::size_t fail_max = 1;
|
std::size_t fail_max = 1;
|
||||||
std::size_t fail = 0;
|
std::size_t fail = 0;
|
||||||
|
std::size_t nalloc = 0;
|
||||||
|
|
||||||
|
~fail_storage()
|
||||||
|
{
|
||||||
|
BEAST_EXPECT(nalloc == 0);
|
||||||
|
}
|
||||||
|
|
||||||
void*
|
void*
|
||||||
allocate(
|
allocate(
|
||||||
@ -104,7 +110,9 @@ struct fail_storage
|
|||||||
fail = 0;
|
fail = 0;
|
||||||
throw test_failure{};
|
throw test_failure{};
|
||||||
}
|
}
|
||||||
return ::operator new(n);
|
auto p = ::operator new(n);
|
||||||
|
++nalloc;
|
||||||
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -113,6 +121,8 @@ struct fail_storage
|
|||||||
std::size_t,
|
std::size_t,
|
||||||
std::size_t) noexcept
|
std::size_t) noexcept
|
||||||
{
|
{
|
||||||
|
if(BEAST_EXPECT(nalloc > 0))
|
||||||
|
--nalloc;
|
||||||
::operator delete(p);
|
::operator delete(p);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user