diff --git a/bench/bench.cpp b/bench/bench.cpp
index 8e785bdf..3c1bc36b 100644
--- a/bench/bench.cpp
+++ b/bench/bench.cpp
@@ -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(;;)
{
diff --git a/doc/qbk/02_8_serializing.qbk b/doc/qbk/02_8_serializing.qbk
index 563ba774..7472b762 100644
--- a/doc/qbk/02_8_serializing.qbk
+++ b/doc/qbk/02_8_serializing.qbk
@@ -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]
diff --git a/doc/qbk/main.qbk b/doc/qbk/main.qbk
index 23d984c9..e01d51a1 100644
--- a/doc/qbk/main.qbk
+++ b/doc/qbk/main.qbk
@@ -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]
diff --git a/doc/qbk/quickref.xml b/doc/qbk/quickref.xml
index 27751286..dcfb312c 100644
--- a/doc/qbk/quickref.xml
+++ b/doc/qbk/quickref.xml
@@ -43,8 +43,8 @@
make_counted_resource
number_cast
parse
+ serialize
swap
- to_string
value_from
value_to
diff --git a/example/pretty.cpp b/example/pretty.cpp
index 01501e6a..47e5c5f3 100644
--- a/example/pretty.cpp
+++ b/example/pretty.cpp
@@ -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;
}
diff --git a/fuzzing/fuzz_parser.cpp b/fuzzing/fuzz_parser.cpp
index 0228ba36..d367668c 100644
--- a/fuzzing/fuzz_parser.cpp
+++ b/fuzzing/fuzz_parser.cpp
@@ -9,7 +9,7 @@
#include
#include
-#include
+#include
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;
}
diff --git a/include/boost/json.hpp b/include/boost/json.hpp
index f4b800f8..42b3a692 100644
--- a/include/boost/json.hpp
+++ b/include/boost/json.hpp
@@ -20,12 +20,12 @@
#include
#include
#include
+#include
#include
#include
#include
#include
#include
-#include
#include
#include
#include
diff --git a/include/boost/json/impl/serialize.ipp b/include/boost/json/impl/serialize.ipp
new file mode 100644
index 00000000..8c187f90
--- /dev/null
+++ b/include/boost/json/impl/serialize.ipp
@@ -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
+#include
+#include
+
+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
diff --git a/include/boost/json/impl/serializer.ipp b/include/boost/json/impl/serializer.ipp
index aa3da8b2..e6eb2380 100644
--- a/include/boost/json/impl/serializer.ipp
+++ b/include/boost/json/impl/serializer.ipp
@@ -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(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(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(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
@@ -612,9 +612,11 @@ write_value(stream& ss)
{
default:
case kind::object:
+ po_ = jv.is_object();
return write_object(ss);
case kind::array:
+ pa_ = jv.is_array();
return write_array(ss);
case kind::string:
@@ -717,9 +719,9 @@ read_some(
stream ss(dest, size);
if(st_.empty())
- write_value(ss);
+ (this->*fn0_)(ss);
else
- write_value(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;
+ fn1_ = &serializer::write_value;
+
+ 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;
+ fn1_ = &serializer::write_array;
+ st_.clear();
+ done_ = false;
+}
+
+void
+serializer::
+reset(object const* p) noexcept
+{
+ po_ = p;
+ fn0_ = &serializer::write_object;
+ fn1_ = &serializer::write_object;
+ st_.clear();
+ done_ = false;
+}
+
+void
+serializer::
+reset(string const* p) noexcept
+{
+ cs0_ = { p->data(), p->size() };
+ fn0_ = &serializer::write_string;
+ fn1_ = &serializer::write_string;
+ st_.clear();
+ done_ = false;
+}
+
+void
+serializer::
+reset(string_view sv) noexcept
+{
+ cs0_ = { sv.data(), sv.size() };
+ fn0_ = &serializer::write_string;
+ fn1_ = &serializer::write_string;
st_.clear();
done_ = false;
}
diff --git a/include/boost/json/impl/string.ipp b/include/boost/json/impl/string.ipp
index 68d9cc93..c8339755 100644
--- a/include/boost/json/impl/string.ipp
+++ b/include/boost/json/impl/string.ipp
@@ -310,14 +310,6 @@ reserve_impl(size_type new_cap)
}
}
-//----------------------------------------------------------
-
-std::ostream&
-operator<<(std::ostream& os, string const& s)
-{
- return os << static_cast(s);
-}
-
BOOST_JSON_NS_END
#endif
diff --git a/include/boost/json/impl/to_string.ipp b/include/boost/json/impl/to_string.ipp
deleted file mode 100644
index 112a653b..00000000
--- a/include/boost/json/impl/to_string.ipp
+++ /dev/null
@@ -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
-#include
-#include
-
-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
diff --git a/include/boost/json/serialize.hpp b/include/boost/json/serialize.hpp
new file mode 100644
index 00000000..0ac1a746
--- /dev/null
+++ b/include/boost/json/serialize.hpp
@@ -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
+#include
+#include
+
+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
diff --git a/include/boost/json/serializer.hpp b/include/boost/json/serializer.hpp
index 99693451..3f8f5ed2 100644
--- a/include/boost/json/serializer.hpp
+++ b/include/boost/json/serializer.hpp
@@ -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;
+ fn_t fn1_ = &serializer::write_null;
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 write_null(stream& ss);
- template bool write_true(stream& ss);
- template bool write_false(stream& ss);
- template bool write_string(stream& ss);
- template bool write_number(stream& ss);
- template bool write_array(stream& ss);
- template bool write_object(stream& ss);
- template 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 write_null (stream& ss);
+ template bool write_true (stream& ss);
+ template bool write_false (stream& ss);
+ template bool write_string (stream& ss);
+ template bool write_number (stream& ss);
+ template bool write_array (stream& ss);
+ template bool write_object (stream& ss);
+ template 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
diff --git a/include/boost/json/src.hpp b/include/boost/json/src.hpp
index 26b7ae28..ea2f39c9 100644
--- a/include/boost/json/src.hpp
+++ b/include/boost/json/src.hpp
@@ -29,10 +29,10 @@ in a translation unit of the program.
#include
#include
#include
+#include
#include
#include
#include
-#include
#include
#include
#include
diff --git a/include/boost/json/string.hpp b/include/boost/json/string.hpp
index 66949fca..ed45aea8 100644
--- a/include/boost/json/string.hpp
+++ b/include/boost/json/string.hpp
@@ -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.
diff --git a/include/boost/json/to_string.hpp b/include/boost/json/to_string.hpp
deleted file mode 100644
index 58f31d70..00000000
--- a/include/boost/json/to_string.hpp
+++ /dev/null
@@ -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
-#include
-#include
-
-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
diff --git a/include/boost/json/value_stack.hpp b/include/boost/json/value_stack.hpp
index 7b4d182d..6c3ffbc4 100644
--- a/include/boost/json/value_stack.hpp
+++ b/include/boost/json/value_stack.hpp
@@ -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
diff --git a/test/Jamfile b/test/Jamfile
index fdc0ea87..04e5db33 100644
--- a/test/Jamfile
+++ b/test/Jamfile
@@ -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
diff --git a/test/monotonic_resource.cpp b/test/monotonic_resource.cpp
index 9a042db7..a808483f 100644
--- a/test/monotonic_resource.cpp
+++ b/test/monotonic_resource.cpp
@@ -12,7 +12,7 @@
#include
#include
-#include
+#include
#include
#include
diff --git a/test/parser.cpp b/test/parser.cpp
index 120cce39..638fd88d 100644
--- a/test/parser.cpp
+++ b/test/parser.cpp
@@ -13,7 +13,7 @@
#include
#include
-#include
+#include
#include
#include
@@ -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) == "[]");
}
//------------------------------------------------------
diff --git a/test/serialize.cpp b/test/serialize.cpp
new file mode 100644
index 00000000..e68a47f7
--- /dev/null
+++ b/test/serialize.cpp
@@ -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
+
+#include
+#include
+#include
+
+#include "test_suite.hpp"
+
+BOOST_JSON_NS_BEGIN
+
+class serialize_test
+{
+public:
+ template
+ 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
diff --git a/test/serializer.cpp b/test/serializer.cpp
index 7b2566f1..064885ae 100644
--- a/test/serializer.cpp
+++ b/test/serializer.cpp
@@ -11,7 +11,7 @@
#include
#include
-#include
+#include
#include
#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
diff --git a/test/snippets.cpp b/test/snippets.cpp
index 5d30583b..1da7fc66 100644
--- a/test/snippets.cpp
+++ b/test/snippets.cpp
@@ -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}" );
//]
}
diff --git a/test/static_resource.cpp b/test/static_resource.cpp
index 8905e3f5..f6b6e370 100644
--- a/test/static_resource.cpp
+++ b/test/static_resource.cpp
@@ -11,7 +11,7 @@
#include
#include
-#include
+#include
#include
#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]");
}
diff --git a/test/string.cpp b/test/string.cpp
index 832edd50..4cb51f1d 100644
--- a/test/string.cpp
+++ b/test/string.cpp
@@ -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
diff --git a/test/test.hpp b/test/test.hpp
index f0dbd4b0..71be135a 100644
--- a/test/test.hpp
+++ b/test/test.hpp
@@ -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;
diff --git a/test/to_string.cpp b/test/to_string.cpp
deleted file mode 100644
index 8db1442f..00000000
--- a/test/to_string.cpp
+++ /dev/null
@@ -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
-
-#include
-
-#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
diff --git a/test/value_from.cpp b/test/value_from.cpp
index e356c4f1..91912823 100644
--- a/test/value_from.cpp
+++ b/test/value_from.cpp
@@ -12,7 +12,7 @@
#include
#include // prevent intellisense bugs
-#include
+#include
#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 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 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));
}
}
diff --git a/test/value_ref.cpp b/test/value_ref.cpp
index 0d1d9daa..3cbab9e7 100644
--- a/test/value_ref.cpp
+++ b/test/value_ref.cpp
@@ -11,7 +11,7 @@
#include
#include
-#include
+#include
#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);
}
diff --git a/test/value_stack.cpp b/test/value_stack.cpp
index cf773028..ee5ef91a 100644
--- a/test/value_stack.cpp
+++ b/test/value_stack.cpp
@@ -10,8 +10,8 @@
// Test that header file is self-contained.
#include
+#include
#include
-#include
#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
}