Merge pull request #122 from d-frey/patch-1

exception-safe object creation, fixes #118
This commit is contained in:
Niels 2015-10-03 12:29:26 +02:00
commit 2550d29ded

View file

@ -584,6 +584,17 @@ class basic_json
private: private:
/// helper for exception-safe object creation
template<typename T, typename... Args>
static T* create( Args&&... args )
{
AllocatorType<T> alloc;
auto deleter = [&](T* object) { alloc.deallocate(object, 1); };
std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
alloc.construct(object.get(), std::forward<Args>(args)...);
return object.release();
}
//////////////////////// ////////////////////////
// JSON value storage // // JSON value storage //
//////////////////////// ////////////////////////
@ -625,25 +636,19 @@ class basic_json
case (value_t::object): case (value_t::object):
{ {
AllocatorType<object_t> alloc; object = create<object_t>();
object = alloc.allocate(1);
alloc.construct(object);
break; break;
} }
case (value_t::array): case (value_t::array):
{ {
AllocatorType<array_t> alloc; array = create<array_t>();
array = alloc.allocate(1);
alloc.construct(array);
break; break;
} }
case (value_t::string): case (value_t::string):
{ {
AllocatorType<string_t> alloc; string = create<string_t>("");
string = alloc.allocate(1);
alloc.construct(string, "");
break; break;
} }
@ -670,25 +675,19 @@ class basic_json
/// constructor for strings /// constructor for strings
json_value(const string_t& value) json_value(const string_t& value)
{ {
AllocatorType<string_t> alloc; string = create<string_t>(value);
string = alloc.allocate(1);
alloc.construct(string, value);
} }
/// constructor for objects /// constructor for objects
json_value(const object_t& value) json_value(const object_t& value)
{ {
AllocatorType<object_t> alloc; object = create<object_t>(value);
object = alloc.allocate(1);
alloc.construct(object, value);
} }
/// constructor for arrays /// constructor for arrays
json_value(const array_t& value) json_value(const array_t& value)
{ {
AllocatorType<array_t> alloc; array = create<array_t>(value);
array = alloc.allocate(1);
alloc.construct(array, value);
} }
}; };
@ -892,11 +891,9 @@ class basic_json
basic_json(const CompatibleObjectType& value) basic_json(const CompatibleObjectType& value)
: m_type(value_t::object) : m_type(value_t::object)
{ {
AllocatorType<object_t> alloc;
m_value.object = alloc.allocate(1);
using std::begin; using std::begin;
using std::end; using std::end;
alloc.construct(m_value.object, begin(value), end(value)); m_value.object = create<object_t>(begin(value), end(value));
} }
/*! /*!
@ -953,11 +950,9 @@ class basic_json
basic_json(const CompatibleArrayType& value) basic_json(const CompatibleArrayType& value)
: m_type(value_t::array) : m_type(value_t::array)
{ {
AllocatorType<array_t> alloc;
m_value.array = alloc.allocate(1);
using std::begin; using std::begin;
using std::end; using std::end;
alloc.construct(m_value.array, begin(value), end(value)); m_value.array = create<array_t>(begin(value), end(value));
} }
/*! /*!
@ -1315,9 +1310,7 @@ class basic_json
{ {
// the initializer list describes an array -> create array // the initializer list describes an array -> create array
m_type = value_t::array; m_type = value_t::array;
AllocatorType<array_t> alloc; m_value.array = create<array_t>(std::move(init));
m_value.array = alloc.allocate(1);
alloc.construct(m_value.array, std::move(init));
} }
} }
@ -1416,9 +1409,7 @@ class basic_json
basic_json(size_type count, const basic_json& value) basic_json(size_type count, const basic_json& value)
: m_type(value_t::array) : m_type(value_t::array)
{ {
AllocatorType<array_t> alloc; m_value.array = create<array_t>(count, value);
m_value.array = alloc.allocate(1);
alloc.construct(m_value.array, count, value);
} }
/*! /*!
@ -1514,17 +1505,13 @@ class basic_json
case value_t::object: case value_t::object:
{ {
AllocatorType<object_t> alloc; m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
m_value.object = alloc.allocate(1);
alloc.construct(m_value.object, first.m_it.object_iterator, last.m_it.object_iterator);
break; break;
} }
case value_t::array: case value_t::array:
{ {
AllocatorType<array_t> alloc; m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
m_value.array = alloc.allocate(1);
alloc.construct(m_value.array, first.m_it.array_iterator, last.m_it.array_iterator);
break; break;
} }
@ -2595,9 +2582,7 @@ class basic_json
if (m_type == value_t::null) if (m_type == value_t::null)
{ {
m_type = value_t::array; m_type = value_t::array;
AllocatorType<array_t> alloc; m_value.array = create<array_t>();
m_value.array = alloc.allocate(1);
alloc.construct(m_value.array);
} }
// [] only works for arrays // [] only works for arrays
@ -2667,9 +2652,7 @@ class basic_json
if (m_type == value_t::null) if (m_type == value_t::null)
{ {
m_type = value_t::object; m_type = value_t::object;
AllocatorType<object_t> alloc; m_value.object = create<object_t>();
m_value.object = alloc.allocate(1);
alloc.construct(m_value.object);
} }
// [] only works for objects // [] only works for objects