serializer refactor (API Change):

fix #275

* serialize() replaces to_string()
* serialize.hpp replaces to_string.hpp
* serializer works on all types
* serialize, operator<< work on all types
* reset() takes pointer arguments
* resetting constructor removed
This commit is contained in:
Vinnie Falco 2020-09-07 06:17:25 -07:00
parent 07dcc303b3
commit 591e2dc5a5
30 changed files with 665 additions and 355 deletions

View File

@ -294,7 +294,7 @@ public:
out.reserve(512);
while(repeat--)
{
sr.reset(jv);
sr.reset(&jv);
out.clear();
for(;;)
{
@ -362,7 +362,7 @@ public:
out.reserve(512);
while(repeat--)
{
sr.reset(jv);
sr.reset(&jv);
out.clear();
for(;;)
{

View File

@ -25,7 +25,7 @@ serialization:
[@https://en.cppreference.com/w/cpp/io/basic_ostream `std::ostream`].
]
][
[__to_string__]
[__serialize__]
[
Returns a __string__ representing a serialized __value__.
]
@ -43,7 +43,7 @@ written to standard output streams using the stream operator:
[snippet_serializing_1]
The __to_string__ function converts a __value__ into a __string__:
The __serialize__ function converts a __value__ into a __string__:
[snippet_serializing_2]

View File

@ -67,13 +67,13 @@
[def __polymorphic_allocator__ [link json.ref.boost__json__polymorphic_allocator `polymorphic_allocator`]]
[def __memory_resource__ [link json.ref.boost__json__memory_resource `memory_resource`]]
[def __monotonic_resource__ [link json.ref.boost__json__monotonic_resource `monotonic_resource`]]
[def __serialize__ [link json.ref.boost__json__serialize `serialize`]]
[def __serializer__ [link json.ref.boost__json__serializer `serializer`]]
[def __static_resource__ [link json.ref.boost__json__static_resource `static_resource`]]
[def __storage_ptr__ [link json.ref.boost__json__storage_ptr `storage_ptr`]]
[def __string__ [link json.ref.boost__json__string `string`]]
[def __string_view__ [link json.ref.boost__json__string_view `string_view`]]
[def __system_error__ [link json.ref.boost__json__system_error `system_error`]]
[def __to_string__ [link json.ref.boost__json__to_string `to_string`]]
[def __value__ [link json.ref.boost__json__value `value`]]
[def __value_from__ [link json.ref.boost__json__value_from `value_from`]]
[def __value_stack_ [link json.ref.boost__json__value_stack `value_stack`]]
@ -98,7 +98,7 @@
[import ../../example/pretty.cpp]
[import ../../example/validate.cpp]
[import ../../include/boost/json/impl/to_string.ipp]
[import ../../include/boost/json/impl/serialize.ipp]
[import ../../test/memory_resource.cpp]
[import ../../test/snippets.cpp]

View File

@ -43,8 +43,8 @@
<member><link linkend="json.ref.boost__json__make_counted_resource">make_counted_resource</link></member>
<member><link linkend="json.ref.boost__json__number_cast">number_cast</link></member>
<member><link linkend="json.ref.boost__json__parse">parse</link></member>
<member><link linkend="json.ref.boost__json__serialize">serialize</link></member>
<member><link linkend="json.ref.boost__json__swap">swap</link></member>
<member><link linkend="json.ref.boost__json__to_string">to_string</link></member>
<member><link linkend="json.ref.boost__json__value_from">value_from</link></member>
<member><link linkend="json.ref.boost__json__value_to">value_to</link></member>
</simplelist>

View File

@ -62,7 +62,7 @@ pretty_print( std::ostream& os, json::value const& jv, std::string* indent = nul
auto it = obj.begin();
for(;;)
{
os << *indent << json::to_string(it->key()) << " : ";
os << *indent << json::serialize(it->key()) << " : ";
pretty_print(os, it->value(), indent);
if(++it == obj.end())
break;
@ -100,7 +100,7 @@ pretty_print( std::ostream& os, json::value const& jv, std::string* indent = nul
case json::kind::string:
{
os << json::to_string(jv.get_string());
os << json::serialize(jv.get_string());
break;
}

View File

@ -9,7 +9,7 @@
#include <boost/json/parser.hpp>
#include <boost/json/parse_options.hpp>
#include <boost/json/to_string.hpp>
#include <boost/json/serialize.hpp>
using namespace boost::json;
bool
@ -33,7 +33,7 @@ fuzz_parser(parse_options popt,string_view sv)
{
value jv = p.release( ec );
if(! ec )
return to_string(jv).size()==42;
return serialize(jv).size()==42;
}
return false;
}

View File

@ -20,12 +20,12 @@
#include <boost/json/object.hpp>
#include <boost/json/parse.hpp>
#include <boost/json/parser.hpp>
#include <boost/json/serialize.hpp>
#include <boost/json/serializer.hpp>
#include <boost/json/static_resource.hpp>
#include <boost/json/storage_ptr.hpp>
#include <boost/json/string.hpp>
#include <boost/json/system_error.hpp>
#include <boost/json/to_string.hpp>
#include <boost/json/value.hpp>
#include <boost/json/value_from.hpp>
#include <boost/json/value_to.hpp>

View File

@ -0,0 +1,185 @@
//
// 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/cppalliance/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(
string& s,
serializer& sr)
{
// serialize to a small buffer
// to avoid most reallocations
char buf[16384];
string_view sv;
sv = sr.read(buf);
if(sr.done())
{
// fast path
s.append(sv);
return;
}
s.reserve(sv.size() * 2);
s.append(sv);
do
{
sv = sr.read(
s.data() + s.size(),
s.capacity() - s.size());
s.grow(sv.size());
}
while(! sr.done());
}
string
serialize(
value const& jv,
storage_ptr sp)
{
string s(std::move(sp));
serializer sr;
sr.reset(&jv);
serialize_impl(s, sr);
return s;
}
string
serialize(
array const& arr,
storage_ptr sp)
{
string s(std::move(sp));
serializer sr;
sr.reset(&arr);
serialize_impl(s, sr);
return s;
}
string
serialize(
object const& obj,
storage_ptr sp)
{
string s(std::move(sp));
serializer sr;
sr.reset(&obj);
serialize_impl(s, sr);
return s;
}
string
serialize(
string const& str,
storage_ptr sp)
{
string s(std::move(sp));
serializer sr;
sr.reset(&str);
serialize_impl(s, sr);
return s;
}
string
serialize(
string_view sv,
storage_ptr sp)
{
string s(std::move(sp));
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[ 4000 ];
// 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)
{
char buf[16384];
while(! sr.done())
{
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

View File

@ -49,9 +49,9 @@ serializer::
suspend(
state st,
array::const_iterator it,
value const* jv)
array const* pa)
{
st_.push(jv);
st_.push(pa);
st_.push(it);
st_.push(st);
return false;
@ -62,9 +62,9 @@ serializer::
suspend(
state st,
object::const_iterator it,
value const* jv)
object const* po)
{
st_.push(jv);
st_.push(po);
st_.push(it);
st_.push(st);
return false;
@ -454,23 +454,23 @@ bool
serializer::
write_array(stream& ss0)
{
value const* jv;
array const* pa;
local_stream ss(ss0);
array::const_iterator it;
array::const_iterator end;
if(StackEmpty || st_.empty())
{
jv = jv_;
it = jv->get_array().begin();
end = jv->get_array().end();
pa = pa_;
it = pa->begin();
end = pa->end();
}
else
{
state st;
st_.pop(st);
st_.pop(it);
st_.pop(jv);
end = jv->get_array().end();
st_.pop(pa);
end = pa->end();
switch(st)
{
default:
@ -486,7 +486,7 @@ do_arr1:
ss.append('[');
else
return suspend(
state::arr1, it, jv);
state::arr1, it, pa);
if(it == end)
goto do_arr4;
for(;;)
@ -495,7 +495,7 @@ do_arr2:
jv_ = &*it;
if(! write_value<StackEmpty>(ss))
return suspend(
state::arr2, it, jv);
state::arr2, it, pa);
if(BOOST_JSON_UNLIKELY(
++it == end))
break;
@ -504,14 +504,14 @@ do_arr3:
ss.append(',');
else
return suspend(
state::arr3, it, jv);
state::arr3, it, pa);
}
do_arr4:
if(BOOST_JSON_LIKELY(ss))
ss.append(']');
else
return suspend(
state::arr4, it, jv);
state::arr4, it, pa);
return true;
}
@ -520,23 +520,23 @@ bool
serializer::
write_object(stream& ss0)
{
value const* jv;
object const* po;
local_stream ss(ss0);
object::const_iterator it;
object::const_iterator end;
if(StackEmpty || st_.empty())
{
jv = jv_;
it = jv->get_object().begin();
end = jv->get_object().end();
po = po_;
it = po->begin();
end = po->end();
}
else
{
state st;
st_.pop(st);
st_.pop(it);
st_.pop(jv);
end = jv->get_object().end();
st_.pop(po);
end = po->end();
switch(st)
{
default:
@ -554,7 +554,7 @@ do_obj1:
ss.append('{');
else
return suspend(
state::obj1, it, jv);
state::obj1, it, po);
if(BOOST_JSON_UNLIKELY(
it == end))
goto do_obj6;
@ -567,19 +567,19 @@ do_obj2:
if(BOOST_JSON_UNLIKELY(
! write_string<StackEmpty>(ss)))
return suspend(
state::obj2, it, jv);
state::obj2, it, po);
do_obj3:
if(BOOST_JSON_LIKELY(ss))
ss.append(':');
else
return suspend(
state::obj3, it, jv);
state::obj3, it, po);
do_obj4:
jv_ = &it->value();
if(BOOST_JSON_UNLIKELY(
! write_value<StackEmpty>(ss)))
return suspend(
state::obj4, it, jv);
state::obj4, it, po);
++it;
if(BOOST_JSON_UNLIKELY(it == end))
break;
@ -588,7 +588,7 @@ do_obj5:
ss.append(',');
else
return suspend(
state::obj5, it, jv);
state::obj5, it, po);
}
do_obj6:
if(BOOST_JSON_LIKELY(ss))
@ -597,7 +597,7 @@ do_obj6:
return true;
}
return suspend(
state::obj6, it, jv);
state::obj6, it, po);
}
template<bool StackEmpty>
@ -612,9 +612,11 @@ write_value(stream& ss)
{
default:
case kind::object:
po_ = jv.is_object();
return write_object<true>(ss);
case kind::array:
pa_ = jv.is_array();
return write_array<true>(ss);
case kind::string:
@ -717,9 +719,9 @@ read_some(
stream ss(dest, size);
if(st_.empty())
write_value<true>(ss);
(this->*fn0_)(ss);
else
write_value<false>(ss);
(this->*fn1_)(ss);
if(st_.empty())
{
done_ = true;
@ -739,17 +741,59 @@ serializer() noexcept
sizeof(serializer::buf_) >= 7);
}
void
serializer::
serializer(value const& jv) noexcept
reset(value const* p) noexcept
{
reset(jv);
pv_ = p;
fn0_ = &serializer::write_value<true>;
fn1_ = &serializer::write_value<false>;
jv_ = p;
st_.clear();
done_ = false;
}
void
serializer::
reset(value const& jv) noexcept
reset(array const* p) noexcept
{
jv_ = &jv;
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;
}

View File

@ -310,14 +310,6 @@ reserve_impl(size_type new_cap)
}
}
//----------------------------------------------------------
std::ostream&
operator<<(std::ostream& os, string const& s)
{
return os << static_cast<string_view>(s);
}
BOOST_JSON_NS_END
#endif

View File

@ -1,65 +0,0 @@
//
// 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/cppalliance/json
//
#ifndef BOOST_JSON_IMPL_TO_STRING_IPP
#define BOOST_JSON_IMPL_TO_STRING_IPP
#include <boost/json/to_string.hpp>
#include <boost/json/serializer.hpp>
#include <ostream>
BOOST_JSON_NS_BEGIN
string
to_string(
json::value const& jv)
{
string s;
serializer sr(jv);
while(! sr.done())
{
if(s.size() >= s.capacity())
s.reserve(s.capacity() + 1);
s.grow(static_cast<
string::size_type>(
sr.read(s.data() + s.size(),
s.capacity() - s.size()).size()));
}
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 that is set to output our value.
serializer sr( jv );
// Loop until all output is produced.
while( ! sr.done() )
{
// Use a local buffer.
char buf[4000];
// Try to fill up the local buffer.
auto const bytes_written = sr.read( buf ).size();
// Write the valid portion of the buffer to the output stream.
os.write( buf, bytes_written );
}
return os;
}
//]
BOOST_JSON_NS_END
#endif

View File

@ -0,0 +1,118 @@
//
// 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/cppalliance/json
//
#ifndef BOOST_JSON_SERIALIZE_HPP
#define BOOST_JSON_SERIALIZE_HPP
#include <boost/json/detail/config.hpp>
#include <boost/json/value.hpp>
#include <iosfwd>
BOOST_JSON_NS_BEGIN
/** Return a string representing a serialized element.
This function serializes `t` as JSON and returns
it as a @ref string using the specified memory
resource.
@par Complexity
Constant or linear in the size of `t`.
@par Exception Safety
Strong guarantee.
Calls to `memory_resource::allocate` may throw.
@return The serialized string
@param t The value to serialize
@param sp The memory resource to use for the
returned string. If omitted, the default resource
is used.
*/
/** @{ */
BOOST_JSON_DECL
string
serialize(
value const& t,
storage_ptr sp = {});
BOOST_JSON_DECL
string
serialize(
array const& t,
storage_ptr sp = {});
BOOST_JSON_DECL
string
serialize(
object const& t,
storage_ptr sp = {});
BOOST_JSON_DECL
string
serialize(
string const& t,
storage_ptr sp = {});
BOOST_JSON_DECL
string
serialize(
string_view t,
storage_ptr sp = {});
/** @} */
/** Serialize an element to an output stream.
This function serializes the specified element
as JSON into the output stream.
@return `os`.
@par Complexity
Constant or linear in the size of `t`.
@par Exception Safety
Strong guarantee.
Calls to `memory_resource::allocate` may throw.
@param os The output stream to serialize to.
@param t The value to serialize
*/
/** @{ */
BOOST_JSON_DECL
std::ostream&
operator<<(
std::ostream& os,
value const& t);
BOOST_JSON_DECL
std::ostream&
operator<<(
std::ostream& os,
array const& t);
BOOST_JSON_DECL
std::ostream&
operator<<(
std::ostream& os,
object const& t);
BOOST_JSON_DECL
std::ostream&
operator<<(
std::ostream& os,
string const& t);
/** @} */
BOOST_JSON_NS_END
#endif

View File

@ -20,14 +20,13 @@ BOOST_JSON_NS_BEGIN
/** A serializer for JSON.
This class traverses a @ref value and emits
a JSON text by filling a series of one or more
caller-provided buffers. To use it, declare
a serializer and construct it with a reference
to the value to serialize. Alternatively, call
@ref reset to set the value to serialize.
Then call @ref read over and over while
@ref done returns `false`.
This class traverses an instance of a library
type and emits serialized JSON text by filling
in one or more caller-provided buffers. To use,
declare a variable and call @ref reset with
a pointer to the variable you want to serialize.
Then call @ref read over and over until
@ref done returns `true`.
@par Example
@ -39,10 +38,11 @@ BOOST_JSON_NS_BEGIN
void print( std::ostream& os, value const& jv)
{
serializer sr( jv );
serializer sr;
sr.reset( &jv );
while( ! sr.done() )
{
char buf[4000];
char buf[ 4000 ];
os << sr.read( buf );
}
}
@ -63,6 +63,18 @@ class serializer
using local_const_stream =
detail::local_const_stream;
using fn_t = bool (serializer::*)(stream&);
#ifndef BOOST_JSON_DOCS
union
{
value const* pv_;
array const* pa_;
object const* po_;
};
#endif
fn_t fn0_ = &serializer::write_null<true>;
fn_t fn1_ = &serializer::write_null<false>;
value const* jv_ = nullptr;
detail::stack st_;
const_stream cs0_;
@ -70,18 +82,18 @@ class serializer
bool done_ = false;
inline bool suspend(state st);
inline bool suspend(state st,
array::const_iterator it, value const* jv);
inline bool suspend(state st,
object::const_iterator it, value const* jv);
template<bool StackEmpty> bool write_null(stream& ss);
template<bool StackEmpty> bool write_true(stream& ss);
template<bool StackEmpty> bool write_false(stream& ss);
template<bool StackEmpty> bool write_string(stream& ss);
template<bool StackEmpty> bool write_number(stream& ss);
template<bool StackEmpty> bool write_array(stream& ss);
template<bool StackEmpty> bool write_object(stream& ss);
template<bool StackEmpty> bool write_value(stream& ss);
inline bool suspend(
state st, array::const_iterator it, array const* pa);
inline bool suspend(
state st, object::const_iterator it, object const* po);
template<bool StackEmpty> bool write_null (stream& ss);
template<bool StackEmpty> bool write_true (stream& ss);
template<bool StackEmpty> bool write_false (stream& ss);
template<bool StackEmpty> bool write_string (stream& ss);
template<bool StackEmpty> bool write_number (stream& ss);
template<bool StackEmpty> bool write_array (stream& ss);
template<bool StackEmpty> bool write_object (stream& ss);
template<bool StackEmpty> bool write_value (stream& ss);
inline string_view read_some(char* dest, std::size_t size);
public:
@ -101,29 +113,6 @@ public:
BOOST_JSON_DECL
serializer() noexcept;
/** Constructor
This constructs the serializer and prepares
it to serialize the @ref value `jv` as if
@ref reset was called.
@par Complexity
Constant.
@par Exception Safety
No-throw guarantee.
@param jv The value to serialize. Ownership
is not transferred. The caller is responsible
for ensuring that the lifetime of the value
extends until @ref done returns `true`,
@ref reset is called with a new value, or
the serializer is destroyed.
*/
explicit
BOOST_JSON_DECL
serializer(value const& jv) noexcept;
/** Returns `true` if the serialization is complete
This function returns `true` when all of the
@ -142,23 +131,52 @@ public:
return done_;
}
/** Reset the serializer for a new JSON value
/** Reset the serializer for a new element
This function prepares the serializer to emit
a new serialized JSON based on the specified
value. Any internally allocated memory is
a new serialized JSON representing `*p`.
Any internally allocated memory is
preserved and re-used for the new output.
@param jv The value to serialize. Ownership
is not transferred. The caller is responsible
for ensuring that the lifetime of the value
extends until @ref done returns `true`,
@ref reset is called with a new value, or
the serializer is destroyed.
@param p A pointer to the element to serialize.
Ownership is not transferred; The caller is
responsible for ensuring that the lifetime of
`*p` extends until it is no longer needed.
*/
/** @{ */
BOOST_JSON_DECL
void
reset(value const* p) noexcept;
BOOST_JSON_DECL
void
reset(array const* p) noexcept;
BOOST_JSON_DECL
void
reset(object const* p) noexcept;
BOOST_JSON_DECL
void
reset(string const* p) noexcept;
/** @} */
/** Reset the serializer for a new string
This function prepares the serializer to emit
a new serialized JSON representing the string.
Any internally allocated memory is
preserved and re-used for the new output.
@param sv The characters representing the string.
Ownership is not transferred; The caller is
responsible for ensuring that the lifetime of
the characters reference by `sv` extends
until it is no longer needed.
*/
BOOST_JSON_DECL
void
reset(value const& jv) noexcept;
reset(string_view sv) noexcept;
/** Read the next buffer of serialized JSON

View File

@ -29,10 +29,10 @@ in a translation unit of the program.
#include <boost/json/impl/object.ipp>
#include <boost/json/impl/parse.ipp>
#include <boost/json/impl/parser.ipp>
#include <boost/json/impl/serialize.ipp>
#include <boost/json/impl/serializer.ipp>
#include <boost/json/impl/static_resource.ipp>
#include <boost/json/impl/string.ipp>
#include <boost/json/impl/to_string.ipp>
#include <boost/json/impl/value.ipp>
#include <boost/json/impl/value_stack.ipp>
#include <boost/json/impl/value_ref.ipp>

View File

@ -2769,14 +2769,6 @@ swap(string& lhs, string& rhs)
//----------------------------------------------------------
/** Serialize a @ref string to an output stream
Behaves as a formatted output function.
*/
BOOST_JSON_DECL
std::ostream&
operator<<(std::ostream& os, string const& s);
/** Return true if lhs equals rhs.
A lexicographical comparison is used.

View File

@ -1,63 +0,0 @@
//
// 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/cppalliance/json
//
#ifndef BOOST_JSON_TO_STRING_HPP
#define BOOST_JSON_TO_STRING_HPP
#include <boost/json/detail/config.hpp>
#include <boost/json/value.hpp>
#include <iosfwd>
BOOST_JSON_NS_BEGIN
/** Return a string representing a serialized @ref value.
This function serializes the specified value
and returns it as a @ref string using the
default memory resource.
@par Exception Safety
Strong guarantee.
Calls to `memory_resource::allocate` may throw.
@return The serialized string
@param jv The value to serialize
*/
BOOST_JSON_DECL
string
to_string(
value const& jv);
/** Serialize a @ref value to an output stream.
This function serializes the specified value
into the output stream.
@par Exception Safety
Strong guarantee.
Calls to `memory_resource::allocate` may throw.
@return `os`.
@param os The output stream to serialize to.
@param jv The value to serialize.
*/
BOOST_JSON_DECL
std::ostream&
operator<<(
std::ostream& os,
value const& jv);
BOOST_JSON_NS_END
#endif

View File

@ -102,7 +102,7 @@ BOOST_JSON_NS_BEGIN
// Pop the object from the stack and take ownership.
value jv = st.release();
assert( to_string(jv) == "{\"a\":1,\"b\":null,\"c\":\"hello\"}" );
assert( serialize(jv) == "{\"a\":1,\"b\":null,\"c\":\"hello\"}" );
// At this point we could re-use the stack by calling reset
@ -274,7 +274,7 @@ public:
// Pop the object from the stack and take ownership.
value jv = st.release();
assert( to_string(jv) == "[1,2,3]" );
assert( serialize(jv) == "[1,2,3]" );
// At this point, reset must be called again to use the stack
@ -325,7 +325,7 @@ public:
// Pop the object from the stack and take ownership.
value jv = st.release();
assert( to_string(jv) == "{\"x\",true}" );
assert( serialize(jv) == "{\"x\",true}" );
// At this point, reset must be called again to use the stack

View File

@ -37,6 +37,7 @@ local SOURCES =
parse.cpp
parser.cpp
pilfer.cpp
serialize.cpp
serializer.cpp
snippets.cpp
static_resource.cpp
@ -44,7 +45,6 @@ local SOURCES =
string.cpp
string_view.cpp
system_error.cpp
to_string.cpp
value.cpp
value_from.cpp
value_stack.cpp

View File

@ -12,7 +12,7 @@
#include <boost/json/monotonic_resource.hpp>
#include <boost/json/parse.hpp>
#include <boost/json/to_string.hpp>
#include <boost/json/serialize.hpp>
#include <boost/json/detail/align.hpp>
#include <iostream>

View File

@ -13,7 +13,7 @@
#include <boost/json/monotonic_resource.hpp>
#include <boost/json/parse.hpp>
#include <boost/json/to_string.hpp>
#include <boost/json/serialize.hpp>
#include <sstream>
#include <iostream>
@ -80,7 +80,7 @@ public:
{
auto const s2 =
//to_string_test(jv1); // use this if serializer is broken
to_string(jv1);
serialize(jv1);
auto jv2 =
from_string_test(s2, {}, po);
BOOST_TEST(equal(jv1, jv2));
@ -860,7 +860,7 @@ R"xx({
p.finish(ec);
if(BOOST_TEST(! ec))
{
BOOST_TEST(to_string(p.release(ec)) == out);
BOOST_TEST(serialize(p.release(ec)) == out);
BOOST_TEST(! ec);
}
}
@ -1038,7 +1038,7 @@ R"xx({
auto const jv = parse("[]");
auto const t = T{jv};
BOOST_TEST(to_string(t.jv) == "[]");
BOOST_TEST(serialize(t.jv) == "[]");
}
//------------------------------------------------------

90
test/serialize.cpp Normal file
View File

@ -0,0 +1,90 @@
//
// 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/cppalliance/json
//
// Test that header file is self-contained.
#include <boost/json/serialize.hpp>
#include <boost/json/parse.hpp>
#include <boost/json/static_resource.hpp>
#include <sstream>
#include "test_suite.hpp"
BOOST_JSON_NS_BEGIN
class serialize_test
{
public:
template<class T>
static
std::string
print(T const& t)
{
std::stringstream ss;
ss << t;
return ss.str();
}
void
testSerialize()
{
{
value const jv = { 1, 2, 3 };
BOOST_TEST(serialize(jv) == "[1,2,3]");
BOOST_TEST(print(jv) == "[1,2,3]");
unsigned char buf[100];
static_resource mr(buf);
BOOST_TEST(serialize(
jv, &mr).storage().get() == &mr);
}
{
array const arr = { 1, 2 ,3 };
BOOST_TEST(serialize(arr) == "[1,2,3]");
BOOST_TEST(print(arr) == "[1,2,3]");
unsigned char buf[100];
static_resource mr(buf);
BOOST_TEST(serialize(
arr, &mr).storage().get() == &mr);
}
{
object const obj = { {"k1",1}, {"k2",2} };
BOOST_TEST(serialize(obj) == "{\"k1\":1,\"k2\":2}");
BOOST_TEST(print(obj) == "{\"k1\":1,\"k2\":2}");
unsigned char buf[100];
static_resource mr(buf);
BOOST_TEST(serialize(
obj, &mr).storage().get() == &mr);
}
{
string const str = "123";
BOOST_TEST(serialize(str) == "\"123\"");
BOOST_TEST(print(str) == "\"123\"");
unsigned char buf[100];
static_resource mr(buf);
BOOST_TEST(serialize(
str, &mr).storage().get() == &mr);
}
}
void
testOstream()
{
}
void
run()
{
testSerialize();
testOstream();
}
};
TEST_SUITE(serialize_test, "boost.json.serialize");
BOOST_JSON_NS_END

View File

@ -11,7 +11,7 @@
#include <boost/json/serializer.hpp>
#include <boost/json/parse.hpp>
#include <boost/json/to_string.hpp>
#include <boost/json/serialize.hpp>
#include <iostream>
#include "parse-vectors.hpp"
@ -23,6 +23,23 @@ BOOST_JSON_NS_BEGIN
class serializer_test
{
public:
//------------------------------------------------------
// From the javadoc
void print( std::ostream& os, value const& jv)
{
serializer sr;
sr.reset( &jv );
while( ! sr.done() )
{
char buf[ 4000 ];
os << sr.read( buf );
}
}
//------------------------------------------------------
::test_suite::log_type log;
void
@ -33,7 +50,7 @@ public:
{
{
error_code ec;
auto const s1 = to_string(jv);
auto const s1 = serialize(jv);
auto const jv2 = parse(s1, ec);
if(! BOOST_TEST(equal(jv, jv2)))
{
@ -53,13 +70,14 @@ public:
// large buffer
{
error_code ec;
serializer sr(jv);
serializer sr;
sr.reset(&jv);
string js;
js.reserve(4096);
js.grow(sr.read(
js.data(), js.capacity()).size());
auto const s1 = to_string(jv);
auto const s1 = serialize(jv);
auto const jv2 = parse(s1, ec);
BOOST_TEST(equal(jv, jv2));
}
@ -73,12 +91,12 @@ public:
{
grind_one(s0, jv, name);
auto const s1 =
to_string(jv);
auto const s1 = serialize(jv);
for(std::size_t i = 1;
i < s1.size(); ++i)
{
serializer sr(jv);
serializer sr;
sr.reset(&jv);
string s2;
s2.reserve(s1.size());
s2.grow(sr.read(
@ -339,8 +357,6 @@ public:
void
testMembers()
{
value jv = 1;
// serializer()
{
serializer sr;
@ -349,17 +365,11 @@ public:
BOOST_TEST(sr.read(buf) == "null");
}
// serializer(value)
{
serializer sr(jv);
char buf[32];
BOOST_TEST(sr.read(buf) == "1");
}
// done()
{
serializer sr(jv);
value jv = 1;
serializer sr;
sr.reset(&jv);
BOOST_TEST(! sr.done());
char buf[32];
BOOST_TEST(sr.read(buf) == "1");
@ -368,7 +378,9 @@ public:
// read()
{
serializer sr(jv);
value jv = 1;
serializer sr;
sr.reset(&jv);
char buf[1024];
auto const s = sr.read(buf);
BOOST_TEST(sr.done());
@ -381,6 +393,42 @@ public:
char buf[100];
BOOST_TEST(sr.read(buf, 50) == "null");
}
// reset(value)
{
char buf[100];
serializer sr;
value jv = { 1, 2, 3 };
sr.reset(&jv);
BOOST_TEST(sr.read(buf) == "[1,2,3]");
}
// reset(array)
{
char buf[100];
serializer sr;
array arr = { 1, 2, 3 };
sr.reset(&arr);
BOOST_TEST(sr.read(buf) == "[1,2,3]");
}
// reset(object)
{
char buf[100];
serializer sr;
object obj = { {"k1",1}, {"k2",2} };
sr.reset(&obj);
BOOST_TEST(sr.read(buf) == "{\"k1\":1,\"k2\":2}");
}
// reset(string)
{
char buf[100];
serializer sr;
string str = "123";
sr.reset(&str);
BOOST_TEST(sr.read(buf) == "\"123\"");
}
}
void
@ -486,11 +534,11 @@ public:
{
// no decimal or exponent parsed as integer
BOOST_TEST(parse("-0").as_int64() == 0);
BOOST_TEST(to_string(parse("-0")) == "0");
BOOST_TEST(serialize(parse("-0")) == "0");
BOOST_TEST(parse("-0.0").as_double() == -0);
BOOST_TEST(to_string(parse("0.0")) == "0E0");
BOOST_TEST(serialize(parse("0.0")) == "0E0");
BOOST_TEST(parse("0.0").as_double() == 0);
BOOST_TEST(to_string(parse("-0.0")) == "-0E0");
BOOST_TEST(serialize(parse("-0.0")) == "-0E0");
}
void

View File

@ -257,7 +257,7 @@ usingInitLists()
assert( jv.as_array().size() == 4 );
assert( to_string(jv) == "[true,2,\"hello\",null]" );
assert( serialize(jv) == "[true,2,\"hello\",null]" );
//]
}
@ -271,7 +271,7 @@ usingInitLists()
assert( jv.as_array().back().is_array() );
assert( to_string(jv) == "[true,2,\"hello\",[\"bye\",null,false]]" );
assert( serialize(jv) == "[true,2,\"hello\",[\"bye\",null,false]]" );
//]
}
@ -294,7 +294,7 @@ usingInitLists()
assert( jv1.as_object().size() == 2 );
assert( to_string(jv1) == R"({"hello":42,"world":43})" );
assert( serialize(jv1) == R"({"hello":42,"world":43})" );
// All of the following are arrays
@ -320,7 +320,7 @@ usingInitLists()
assert( ja[0].is_array() && ja[1].is_array());
assert ( to_string(jv) == R"([["hello",42],["world",43]])" );
assert ( serialize(jv) == R"([["hello",42],["world",43]])" );
//]
@ -334,11 +334,11 @@ usingInitLists()
assert( jv.is_object() );
assert( to_string(jv) == "{\"mercury\":36,\"venus\":67,\"earth\":93}" );
assert( serialize(jv) == "{\"mercury\":36,\"venus\":67,\"earth\":93}" );
array ja = { { "mercury", 36 }, { "venus", 67 }, { "earth", 93 } };
assert( to_string(ja) == "[[\"mercury\",36],[\"venus\",67],[\"earth\",93]]" );
assert( serialize(ja) == "[[\"mercury\",36],[\"venus\",67],[\"earth\",93]]" );
//]
@ -368,7 +368,7 @@ usingInitLists()
assert( ! jo2.empty() && jo1.empty() );
assert( to_string(jv) == R"({"clients":{"john":100,"dave":500,"joe":300}})" );
assert( serialize(jv) == R"({"clients":{"john":100,"dave":500,"joe":300}})" );
//]
@ -939,7 +939,7 @@ usingSerializing()
value jv = { 1, 2, 3, 4, 5 };
string s = to_string( jv );
string s = serialize( jv );
//]
}
@ -1070,7 +1070,7 @@ usingExchange()
value jv = value_from( pos );
assert( to_string( jv ) == "{\"x\":4,\"y\":1,\"z\":4}" );
assert( serialize( jv ) == "{\"x\":4,\"y\":1,\"z\":4}" );
//]
}

View File

@ -11,7 +11,7 @@
#include <boost/json/static_resource.hpp>
#include <boost/json/parse.hpp>
#include <boost/json/to_string.hpp>
#include <boost/json/serialize.hpp>
#include <iostream>
#include "test_suite.hpp"
@ -46,7 +46,7 @@ public:
unsigned char buf[1000];
static_resource mr(
&buf[0], sizeof(buf));
BOOST_TEST(to_string(parse(
BOOST_TEST(serialize(parse(
"[1,2,3]", &mr)) == "[1,2,3]");
}
@ -55,7 +55,7 @@ public:
unsigned char buf[10];
static_resource mr(buf);
BOOST_TEST_THROWS(
to_string(parse("[1,2,3]", &mr)),
serialize(parse("[1,2,3]", &mr)),
std::bad_alloc);
}
@ -64,7 +64,7 @@ public:
unsigned char buf[1000];
static_resource mr(
buf, 500);
BOOST_TEST(to_string(parse(
BOOST_TEST(serialize(parse(
"[1,2,3]", &mr)) == "[1,2,3]");
}

View File

@ -2697,11 +2697,6 @@ public:
BOOST_TEST( operator> (s1, s2));
BOOST_TEST( operator> (v1, s2));
BOOST_TEST( operator> (c1, s2));
std::stringstream ss;
string s = "Hello, world";
ss << s;
BOOST_TEST(ss.str() == s);
}
void

View File

@ -883,7 +883,7 @@ to_string_test(
dest.append(jv.get_string());
dest.push_back('\"');
#else
dest.append(to_string(jv));
dest.append(serialize(jv));
#endif
break;

View File

@ -1,44 +0,0 @@
//
// 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/cppalliance/json
//
// Test that header file is self-contained.
#include <boost/json/to_string.hpp>
#include <boost/json/parse.hpp>
#include "test_suite.hpp"
BOOST_JSON_NS_BEGIN
class to_string_test
{
public:
void
testToString()
{
BOOST_TEST(
to_string(parse("[1,2,3]")) == "[1,2,3]");
}
void
testOstream()
{
}
void
run()
{
testToString();
testOstream();
}
};
TEST_SUITE(to_string_test, "boost.json.to_string");
BOOST_JSON_NS_END

View File

@ -12,7 +12,7 @@
#include <boost/json/value_from.hpp>
#include <boost/json/value.hpp> // prevent intellisense bugs
#include <boost/json/to_string.hpp>
#include <boost/json/serialize.hpp>
#include "test_suite.hpp"
@ -88,14 +88,14 @@ check(
auto const jv = value_from(t,
::boost::json::storage_ptr{});
auto const js =
::boost::json::to_string(jv);
::boost::json::serialize(jv);
BOOST_TEST(js == s);
}
{
auto const jv =
::boost::json::value_from(t);
auto const js =
::boost::json::to_string(jv);
::boost::json::serialize(jv);
BOOST_TEST(js == s);
}
}
@ -106,9 +106,9 @@ void
testValueCtor()
{
BOOST_TEST(
::boost::json::to_string(
::boost::json::serialize(
::boost::json::value_from(T{})) ==
::boost::json::to_string(
::boost::json::serialize(
::boost::json::value(T{})));
}
@ -161,21 +161,21 @@ public:
value b{1, 2, 3, 4};
value c = value_from(a);
BOOST_TEST(c.is_array());
BOOST_TEST(to_string(c) == to_string(b));
BOOST_TEST(serialize(c) == serialize(b));
}
{
std::tuple<int, string, int, bool> a{1, "2", 42, true};
value b{1, "2", 42, true};
value c = value_from(a);
BOOST_TEST(c.is_array());
BOOST_TEST(to_string(c) == to_string(b));
BOOST_TEST(serialize(c) == serialize(b));
}
{
std::pair<int, string> a{1, string("2")};
value b{1, "2"};
value c = value_from(a);
BOOST_TEST(c.is_array());
BOOST_TEST(to_string(c) == to_string(b));
BOOST_TEST(serialize(c) == serialize(b));
}
{
// ensures that this isn't parsed as a key value pair
@ -183,14 +183,14 @@ public:
value b{"2", 1};
value c = value_from(a);
BOOST_TEST(c.is_array());
BOOST_TEST(to_string(c) == to_string(b));
BOOST_TEST(serialize(c) == serialize(b));
}
{
key_value_pair a{"2", 1};
value b{"2", 1};
value c = value_from(a);
BOOST_TEST(c.is_array());
BOOST_TEST(to_string(c) == to_string(b));
BOOST_TEST(serialize(c) == serialize(b));
}
}

View File

@ -11,7 +11,7 @@
#include <boost/json/value_ref.hpp>
#include <boost/json/value.hpp>
#include <boost/json/to_string.hpp>
#include <boost/json/serialize.hpp>
#include "test_suite.hpp"
@ -209,7 +209,7 @@ public:
{
auto const jv =
value_ref(init).make_value({});
auto const js = to_string(jv);
auto const js = serialize(jv);
BOOST_TEST(js == s);
}
@ -309,7 +309,7 @@ public:
string_view s)
{
auto const jv = value(object(init));
auto const js = to_string(jv);
auto const js = serialize(jv);
BOOST_TEST(js == s);
}

View File

@ -10,8 +10,8 @@
// Test that header file is self-contained.
#include <boost/json/value_stack.hpp>
#include <boost/json/serialize.hpp>
#include <boost/json/static_resource.hpp>
#include <boost/json/to_string.hpp>
#include "test_suite.hpp"
@ -59,7 +59,7 @@ public:
// Pop the object from the stack and take ownership.
value jv = st.release();
assert( to_string(jv) == "{\"a\":1,\"b\":null,\"c\":\"hello\"}" );
assert( serialize(jv) == "{\"a\":1,\"b\":null,\"c\":\"hello\"}" );
// At this point we could re-use the stack by calling reset
}
@ -83,7 +83,7 @@ public:
// Pop the object from the stack and take ownership.
value jv = st.release();
assert( to_string(jv) == "[1,2,3]" );
assert( serialize(jv) == "[1,2,3]" );
// At this point, reset must be called again to use the stack
}
@ -106,7 +106,7 @@ public:
// Pop the object from the stack and take ownership.
value jv = st.release();
assert( to_string(jv) == "{\"x\":true}" );
assert( serialize(jv) == "{\"x\":true}" );
// At this point, reset must be called again to use the stack
}