Skip to content

Commit

Permalink
Fix alignment issue with heap_string
Browse files Browse the repository at this point in the history
  • Loading branch information
danielaparker committed Oct 12, 2023
1 parent 03a4e38 commit ba2a3c5
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 26 deletions.
4 changes: 2 additions & 2 deletions include/jsoncons/detail/heap_string.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ namespace detail {

pointer p_;
std::size_t length_;
uint16_t offset_;
uint8_t offset_;

~heap_string() noexcept = default;

Expand Down Expand Up @@ -156,7 +156,7 @@ namespace detail {
p[length] = 0;
ps->p_ = std::pointer_traits<typename heap_string_type::pointer>::pointer_to(*p);
ps->length_ = length;
ps->offset_ = (uint16_t)(storage - q);
ps->offset_ = (uint8_t)(storage - q);
return std::pointer_traits<pointer>::pointer_to(*ps);
}

Expand Down
11 changes: 5 additions & 6 deletions include/jsoncons/unicode_traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,20 +299,19 @@ namespace jsoncons { namespace unicode_traits {
{
uint8_t a;
const CharT* srcptr = first+length;
switch (length)
{
switch (length) {
default:
return conv_errc::over_long_utf8_sequence;
case 4:
if (((a = static_cast<uint8_t>(*--srcptr)) < 0x80) || a > 0xBF)
if (((a = (*--srcptr))& 0xC0) != 0x80)
return conv_errc::expected_continuation_byte;
JSONCONS_FALLTHROUGH;
case 3:
if (((a = static_cast<uint8_t>(*--srcptr)) < 0x80) || a > 0xBF)
if (((a = (*--srcptr))& 0xC0) != 0x80)
return conv_errc::expected_continuation_byte;
JSONCONS_FALLTHROUGH;
case 2:
if (((a = static_cast<uint8_t>(*--srcptr)) > 0xBF))
if (((a = (*--srcptr))& 0xC0) != 0x80)
return conv_errc::expected_continuation_byte;

switch (static_cast<uint8_t>(*first))
Expand All @@ -322,7 +321,7 @@ namespace jsoncons { namespace unicode_traits {
case 0xED: if (a > 0x9F) return conv_errc::source_illegal; break;
case 0xF0: if (a < 0x90) return conv_errc::source_illegal; break;
case 0xF4: if (a > 0x8F) return conv_errc::source_illegal; break;
default: if (a < 0x80) return conv_errc::source_illegal; break;
default: if (a < 0x80) return conv_errc::source_illegal;
}

JSONCONS_FALLTHROUGH;
Expand Down
32 changes: 18 additions & 14 deletions include/jsoncons_ext/bson/bson_parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,16 @@ class basic_bson_parser : public ser_context
using temp_allocator_type = TempAllocator;
using char_allocator_type = typename std::allocator_traits<temp_allocator_type>:: template rebind_alloc<char_type>;
using byte_allocator_type = typename std::allocator_traits<temp_allocator_type>:: template rebind_alloc<uint8_t>;
using parse_state_allocator_type = typename std::allocator_traits<temp_allocator_type>:: template rebind_alloc<parse_state>;
using parse_state_allocator_type = typename std::allocator_traits<temp_allocator_type>:: template rebind_alloc<parse_state>;
using string_type = std::basic_string<char,std::char_traits<char>,char_allocator_type>;

Source source_;
bson_decode_options options_;
bool more_;
bool done_;
std::vector<uint8_t,byte_allocator_type> bytes_buffer_;
std::basic_string<char,std::char_traits<char>,char_allocator_type> text_buffer_;
string_type name_buffer_;
string_type text_buffer_;
std::vector<parse_state,parse_state_allocator_type> state_stack_;
public:
template <class Sourceable>
Expand All @@ -71,6 +73,7 @@ class basic_bson_parser : public ser_context
more_(true),
done_(false),
bytes_buffer_(temp_alloc),
name_buffer_(temp_alloc),
text_buffer_(temp_alloc),
state_stack_(temp_alloc)
{
Expand All @@ -87,6 +90,7 @@ class basic_bson_parser : public ser_context
more_ = true;
done_ = false;
bytes_buffer_.clear();
name_buffer_.clear();
text_buffer_.clear();
state_stack_.clear();
state_stack_.emplace_back(parse_mode::root,0,0);
Expand Down Expand Up @@ -293,22 +297,22 @@ class basic_bson_parser : public ser_context

void read_e_name(json_visitor& visitor, jsoncons::bson::bson_container_type type, std::error_code& ec)
{
text_buffer_.clear();
read_cstring(ec);
name_buffer_.clear();
read_cstring(name_buffer_, ec);
if (ec)
{
return;
}
if (type == jsoncons::bson::bson_container_type::document)
{
auto result = unicode_traits::validate(text_buffer_.data(),text_buffer_.size());
auto result = unicode_traits::validate(name_buffer_.data(),name_buffer_.size());
if (JSONCONS_UNLIKELY(result.ec != unicode_traits::conv_errc()))
{
ec = bson_errc::invalid_utf8_text_string;
more_ = false;
return;
}
more_ = visitor.key(jsoncons::basic_string_view<char>(text_buffer_.data(),text_buffer_.length()), *this, ec);
more_ = visitor.key(jsoncons::basic_string_view<char>(name_buffer_.data(),name_buffer_.length()), *this, ec);
}
}

Expand Down Expand Up @@ -337,7 +341,7 @@ class basic_bson_parser : public ser_context
case jsoncons::bson::bson_type::string_type:
{
text_buffer_.clear();
read_string(ec);
read_string(text_buffer_, ec);
if (ec)
{
return;
Expand All @@ -355,7 +359,7 @@ class basic_bson_parser : public ser_context
case jsoncons::bson::bson_type::javascript_type:
{
text_buffer_.clear();
read_string(ec);
read_string(text_buffer_, ec);
if (ec)
{
return;
Expand All @@ -374,13 +378,13 @@ class basic_bson_parser : public ser_context
{
text_buffer_.clear();
text_buffer_.push_back('/');
read_cstring(ec);
read_cstring(text_buffer_, ec);
if (ec)
{
return;
}
text_buffer_.push_back('/');
read_cstring(ec);
read_cstring(text_buffer_, ec);
if (ec)
{
return;
Expand Down Expand Up @@ -579,7 +583,7 @@ class basic_bson_parser : public ser_context
}
}

void read_cstring(std::error_code& ec)
void read_cstring(string_type& buffer, std::error_code& ec)
{
uint8_t c = 0xff;
while (true)
Expand All @@ -596,11 +600,11 @@ class basic_bson_parser : public ser_context
{
break;
}
text_buffer_.push_back(c);
buffer.push_back(c);
}
}

void read_string(std::error_code& ec)
void read_string(string_type& buffer, std::error_code& ec)
{
uint8_t buf[sizeof(int32_t)];
std::size_t n = source_.read(buf, sizeof(int32_t));
Expand All @@ -620,7 +624,7 @@ class basic_bson_parser : public ser_context
}

std::size_t size = static_cast<std::size_t>(len) - static_cast<std::size_t>(1);
n = source_reader<Source>::read(source_, text_buffer_, size);
n = source_reader<Source>::read(source_, buffer, size);
state_stack_.back().pos += n;

if (JSONCONS_UNLIKELY(n != size))
Expand Down
32 changes: 28 additions & 4 deletions test/corelib/src/detail/heap_string_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,40 @@

using namespace jsoncons;

using heap_string_factory_type = jsoncons::detail::heap_string_factory<char, null_type, std::allocator<char>>;
using pointer = typename heap_string_factory_type::pointer;

TEST_CASE("heap_string test")
/* TEST_CASE("heap_string test")
{
using heap_string_factory_type = jsoncons::detail::heap_string_factory<char, null_type, std::allocator<char>>;
using pointer = typename heap_string_factory_type::pointer;
std::string s("String too long for short string");
pointer ptr = heap_string_factory_type::create(s.data(), s.length(), null_type(), std::allocator<char>());
heap_string_factory_type::destroy(ptr);
}*/

#if defined(JSONCONS_HAS_POLYMORPHIC_ALLOCATOR)
#include <memory_resource>

TEST_CASE("heap_string with polymorphic allocator test")
{
using heap_string_factory_type = jsoncons::detail::heap_string_factory<char, null_type, std::pmr::polymorphic_allocator<char>>;
using pointer = typename heap_string_factory_type::pointer;

char buffer[1024] = {}; // a small buffer on the stack
std::pmr::monotonic_buffer_resource pool1{ std::data(buffer), std::size(buffer) };
std::pmr::polymorphic_allocator<char> alloc(&pool1);

std::string s1("Hello World 1");
pointer ptr1 = heap_string_factory_type::create(s1.data(), s1.length(), null_type(), alloc);

std::string s2("Hello World 2");
pointer ptr2 = heap_string_factory_type::create(s2.data(), s2.length(), null_type(), alloc);

heap_string_factory_type::destroy(ptr1);
heap_string_factory_type::destroy(ptr2);
}


#endif

0 comments on commit ba2a3c5

Please sign in to comment.