Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

caller provided serializer storage #848

Merged
merged 1 commit into from Jan 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 21 additions & 8 deletions include/boost/json/detail/impl/stack.ipp
Expand Up @@ -19,9 +19,21 @@ namespace detail {
stack::
~stack()
{
if(buf_)
if(base_ != buf_)
sp_->deallocate(
buf_, cap_);
base_, cap_);
}

stack::
stack(
storage_ptr sp,
unsigned char* buf,
std::size_t buf_size) noexcept
: sp_(std::move(sp))
, cap_(buf_size)
, base_(buf)
, buf_(buf)
{
}

void
Expand All @@ -30,15 +42,16 @@ reserve(std::size_t n)
{
if(cap_ >= n)
return;
auto const buf = static_cast<
char*>(sp_->allocate(n));
if(buf_)
auto const base = static_cast<
unsigned char*>(sp_->allocate(n));
if(base_)
{
if(size_ > 0)
std::memcpy(buf, buf_, size_);
sp_->deallocate(buf_, cap_);
std::memcpy(base, base_, size_);
if(base_ != buf_)
sp_->deallocate(base_, cap_);
}
buf_ = buf;
base_ = base;
cap_ = n;
}

Expand Down
18 changes: 13 additions & 5 deletions include/boost/json/detail/stack.hpp
Expand Up @@ -23,12 +23,20 @@ class stack
storage_ptr sp_;
std::size_t cap_ = 0;
std::size_t size_ = 0;
char* buf_ = nullptr;
unsigned char* base_ = nullptr;
unsigned char* buf_ = nullptr;

public:
BOOST_JSON_DECL
~stack();

stack() = default;

stack(
storage_ptr sp,
unsigned char* buf,
std::size_t buf_size) noexcept;

bool
empty() const noexcept
{
Expand Down Expand Up @@ -57,7 +65,7 @@ class stack
//BOOST_ASSERT(cap_ >= size_ + n);
reserve(size_ + n);
std::memcpy(
buf_ + size_, &t, n);
base_ + size_, &t, n);
size_ += n;
}

Expand All @@ -68,7 +76,7 @@ class stack
auto const n = sizeof(T);
BOOST_ASSERT(size_ + n <= cap_);
std::memcpy(
buf_ + size_, &t, n);
base_ + size_, &t, n);
size_ += n;
}

Expand All @@ -79,7 +87,7 @@ class stack
auto const n = sizeof(T);
BOOST_ASSERT(size_ >= n);
std::memcpy(&t,
buf_ + size_ - n, n);
base_ + size_ - n, n);
}

template<class T>
Expand All @@ -90,7 +98,7 @@ class stack
BOOST_ASSERT(size_ >= n);
size_ -= n;
std::memcpy(
&t, buf_ + size_, n);
&t, base_ + size_, n);
}
};

Expand Down
32 changes: 22 additions & 10 deletions include/boost/json/impl/serialize.ipp
Expand Up @@ -65,9 +65,13 @@ std::string
serialize(
value const& jv)
{
std::string s;
serializer sr;
unsigned char buf[256];
serializer sr(
storage_ptr(),
buf,
sizeof(buf));
sr.reset(&jv);
std::string s;
serialize_impl(s, sr);
return s;
}
Expand All @@ -76,8 +80,12 @@ std::string
serialize(
array const& arr)
{
unsigned char buf[256];
serializer sr(
storage_ptr(),
buf,
sizeof(buf));
std::string s;
serializer sr;
sr.reset(&arr);
serialize_impl(s, sr);
return s;
Expand All @@ -87,8 +95,12 @@ std::string
serialize(
object const& obj)
{
unsigned char buf[256];
serializer sr(
storage_ptr(),
buf,
sizeof(buf));
std::string s;
serializer sr;
sr.reset(&obj);
serialize_impl(s, sr);
return s;
Expand All @@ -98,20 +110,20 @@ std::string
serialize(
string const& str)
{
std::string s;
serializer sr;
sr.reset(&str);
serialize_impl(s, sr);
return s;
return serialize( str.subview() );
}

// this is here for key_value_pair::key()
std::string
serialize(
string_view sv)
{
unsigned char buf[256];
serializer sr(
storage_ptr(),
buf,
sizeof(buf));
std::string s;
serializer sr;
sr.reset(sv);
serialize_impl(s, sr);
return s;
Expand Down
12 changes: 12 additions & 0 deletions include/boost/json/impl/serializer.ipp
Expand Up @@ -40,6 +40,18 @@ enum class serializer::state : char
serializer::
~serializer() noexcept = default;

serializer::
serializer(
storage_ptr sp,
unsigned char* buf,
std::size_t buf_size) noexcept
: st_(
std::move(sp),
buf,
buf_size)
{
}

bool
serializer::
suspend(state st)
Expand Down
34 changes: 33 additions & 1 deletion include/boost/json/serializer.hpp
Expand Up @@ -114,7 +114,7 @@ class serializer
BOOST_JSON_DECL
~serializer() noexcept;

/** Default constructor
/** Constructor

This constructs a serializer with no value.
The value may be set later by calling @ref reset.
Expand All @@ -130,6 +130,38 @@ class serializer
BOOST_JSON_DECL
serializer() noexcept;

/** Constructor

This constructs a serializer with no value.
The value may be set later by calling @ref reset.
If serialization is attempted with no value,
the output is as if a null value is serialized.

@par Complexity
Constant.

@par Exception Safety
No-throw guarantee.

@param sp A pointer to the @ref memory_resource
to use when producing partial output.
Shared ownership of the memory resource
is retained until the serializer is
destroyed.

@param buf An optional static buffer to
use for temporary storage when producing
partial output.

@param buf_size The number of bytes of
valid memory pointed to by `buf`.
*/
BOOST_JSON_DECL
serializer(
storage_ptr sp,
unsigned char* buf = nullptr,
std::size_t buf_size = 0) noexcept;

/** Returns `true` if the serialization is complete

This function returns `true` when all of the
Expand Down
50 changes: 49 additions & 1 deletion test/serializer.cpp
Expand Up @@ -10,8 +10,10 @@
// Test that header file is self-contained.
#include <boost/json/serializer.hpp>

#include <boost/json/parse.hpp>
#include <boost/json/serialize.hpp>
#include <boost/json/null_resource.hpp>
#include <boost/json/parse.hpp>
#include <boost/json/parse.hpp>
#include <iostream>

#include "parse-vectors.hpp"
Expand Down Expand Up @@ -368,6 +370,52 @@ class serializer_test
BOOST_TEST(sr.read(buf) == "null");
}

// serializer(storage_ptr)
{
{
serializer sr((storage_ptr()));
char buf[32];
BOOST_TEST(sr.read(buf) == "null");
}
{
serializer sr(get_null_resource());
char buf[1];
BOOST_TEST_THROWS(
sr.read(buf),
std::exception);
}
}

// serializer(storage_ptr, unsigned char*, size_t)
{
{
unsigned char temp[256];
serializer sr(
get_null_resource(),
temp,
sizeof(temp));
char buf[32];
BOOST_TEST(sr.read(&buf[0], 1) == "n");
BOOST_TEST(sr.read(&buf[1], 2) == "ul");
BOOST_TEST(sr.read(&buf[3], 1) == "l");
BOOST_TEST(
std::memcmp(buf, "null", 4) == 0);
}
{
unsigned char temp[1];
serializer sr(
get_null_resource(),
temp,
sizeof(temp));
array ar({1, 2, 3});
sr.reset(&ar);
char buf[32];
BOOST_TEST_THROWS(
sr.read(&buf[0], 1),
std::exception);
}
}

// done()
{
value jv = 1;
Expand Down