Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/qbk/quickref.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
<bridgehead renderas="sect3">Functions</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="json.ref.boost__json__make_storage">make_storage</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__swap">swap</link></member>
<member><link linkend="json.ref.boost__json__to_string">to_string</link></member>
Expand Down
1 change: 1 addition & 0 deletions include/boost/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <boost/json/basic_parser.hpp>
#include <boost/json/error.hpp>
#include <boost/json/kind.hpp>
#include <boost/json/number_cast.hpp>
#include <boost/json/object.hpp>
#include <boost/json/parser.hpp>
#include <boost/json/pool.hpp>
Expand Down
5 changes: 5 additions & 0 deletions include/boost/json/detail/buffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class buffer
void
push_back(char ch) noexcept
{
BOOST_ASSERT(size_ <= N - 1);
buf_[size_++] = ch;
}

Expand All @@ -87,13 +88,15 @@ class buffer
auto dest = buf_ + size_;
if(cp < 0x80)
{
BOOST_ASSERT(size_ <= N - 1);
dest[0] = static_cast<char>(cp);
size_ += 1;
return;
}

if(cp < 0x800)
{
BOOST_ASSERT(size_ <= N - 2);
dest[0] = static_cast<char>( (cp >> 6) | 0xc0);
dest[1] = static_cast<char>( (cp & 0x3f) | 0x80);
size_ += 2;
Expand All @@ -102,6 +105,7 @@ class buffer

if(cp < 0x10000)
{
BOOST_ASSERT(size_ <= N - 3);
dest[0] = static_cast<char>( (cp >> 12) | 0xe0);
dest[1] = static_cast<char>(((cp >> 6) & 0x3f) | 0x80);
dest[2] = static_cast<char>( (cp & 0x3f) | 0x80);
Expand All @@ -110,6 +114,7 @@ class buffer
}

{
BOOST_ASSERT(size_ <= N - 4);
dest[0] = static_cast<char>( (cp >> 18) | 0xf0);
dest[1] = static_cast<char>(((cp >> 12) & 0x3f) | 0x80);
dest[2] = static_cast<char>(((cp >> 6) & 0x3f) | 0x80);
Expand Down
8 changes: 4 additions & 4 deletions include/boost/json/detail/format.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,18 @@ int constexpr max_number_chars =
1 + // '-'
5; // unsigned 16-bit exponent

inline
BOOST_JSON_DECL
unsigned
format_uint64(
char* dest,
std::uint64_t value) noexcept;

inline
BOOST_JSON_DECL
unsigned
format_int64(
char* dest, int64_t i) noexcept;

inline
BOOST_JSON_DECL
unsigned
format_double(
char* dest, double d) noexcept;
Expand All @@ -44,7 +44,7 @@ format_double(
} // boost

#ifdef BOOST_JSON_HEADER_ONLY
#include <boost/json/detail/format.ipp>
#include <boost/json/detail/impl/format.ipp>
#endif

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
// Official repository: https://github.com/vinniefalco/json
//

#ifndef BOOST_JSON_DETAIL_FORMAT_IPP
#define BOOST_JSON_DETAIL_FORMAT_IPP
#ifndef BOOST_JSON_DETAIL_IMPL_FORMAT_IPP
#define BOOST_JSON_DETAIL_IMPL_FORMAT_IPP

#include <boost/json/detail/ryu/ryu.hpp>
#include <cstdint>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
// Official repository: https://github.com/vinniefalco/json
//

#ifndef BOOST_JSON_DETAIL_NUMBER_IPP
#define BOOST_JSON_DETAIL_NUMBER_IPP
#ifndef BOOST_JSON_DETAIL_IMPL_NUMBER_IPP
#define BOOST_JSON_DETAIL_IMPL_NUMBER_IPP

#include <boost/json/detail/number.hpp>
#include <boost/json/detail/sse2.hpp>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
// Official repository: https://github.com/vinniefalco/json
//

#ifndef BOOST_JSON_DETAIL_RAW_STACK_IPP
#define BOOST_JSON_DETAIL_RAW_STACK_IPP
#ifndef BOOST_JSON_DETAIL_IMPL_RAW_STACK_IPP
#define BOOST_JSON_DETAIL_IMPL_RAW_STACK_IPP

#include <boost/json/detail/raw_stack.hpp>
#include <boost/json/detail/except.hpp>
Expand All @@ -29,19 +29,23 @@ reserve(std::size_t bytes)
stack_overflow_exception());
if( bytes < min_capacity_)
bytes = min_capacity_;
if( capacity_ >
max_size() - capacity_)
{
bytes = max_size();
}
else

// 2x growth factor
{
// 2x growth factor
auto hint =
(capacity_ * 2) & ~1;
if( bytes < hint)
bytes = hint;
if( capacity_ <=
max_size() - capacity_)
{
auto hint =
(capacity_ * 2) & ~1;
if( bytes < hint)
bytes = hint;
}
else
{
bytes = max_size();
}
}

auto base = reinterpret_cast<
char*>(sp_->allocate(bytes));
if(base_)
Expand Down
5 changes: 4 additions & 1 deletion include/boost/json/detail/number.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <boost/json/config.hpp>
#include <boost/json/error.hpp>
#include <boost/json/kind.hpp>
#include <type_traits>

namespace boost {
namespace json {
Expand All @@ -30,6 +31,8 @@ struct number
json::kind kind;
};

//----------------------------------------------------------

class number_parser
{
enum class state
Expand Down Expand Up @@ -106,7 +109,7 @@ class number_parser
} // boost

#ifdef BOOST_JSON_HEADER_ONLY
#include <boost/json/detail/number.ipp>
#include <boost/json/detail/impl/number.ipp>
#endif

#endif
165 changes: 165 additions & 0 deletions include/boost/json/detail/number_cast.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
//
// Copyright (c) 2019 Vinnie Falco ([email protected])
//
// 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/vinniefalco/json
//

#ifndef BOOST_JSON_DETAIL_NUMBER_CAST_HPP
#define BOOST_JSON_DETAIL_NUMBER_CAST_HPP

#include <boost/json/value.hpp>
#include <limits>
#include <type_traits>

namespace boost {
namespace json {
namespace detail {

template<class T>
using is_signed_integral =
std::integral_constant<bool,
std::is_signed<T>::value &&
! std::is_floating_point<T>::value>;

template<class T>
using is_unsigned_integral =
std::integral_constant<bool,
std::is_unsigned<T>::value &&
! std::is_same<T, bool>::value>;

template<class T>
T
number_cast(
value const& jv,
error_code& ec,
typename std::enable_if<
is_signed_integral<T>::value
>::type* = 0) noexcept
{
T result{};
if(jv.kind() == kind::int64)
{
auto const i = jv.get_int64();
if( i > (std::numeric_limits<T>::max)() ||
i < (std::numeric_limits<T>::min)())
{
ec = error::not_exact;
}
else
{
result = static_cast<T>(i);
}
}
else if(jv.kind() == kind::uint64)
{
auto const u = jv.get_uint64();
if(u > static_cast<std::uint64_t>((
std::numeric_limits<T>::max)()))
{
ec = error::not_exact;
}
else
{
result = static_cast<T>(u);
}
}
else
{
BOOST_ASSERT(jv.kind() == kind::double_);
auto const d = jv.get_double();
if( d > (std::numeric_limits<T>::max)() ||
d < (std::numeric_limits<T>::min)() ||
static_cast<T>(d) != d)
{
ec = error::not_exact;
}
else
{
result = static_cast<T>(d);
}
}
return result;
}

template<class T>
T
number_cast(
value const& jv,
error_code& ec,
typename std::enable_if<
is_unsigned_integral<T>::value
>::type* = 0
) noexcept
{
T result{};
if(jv.kind() == kind::int64)
{
auto const i = jv.get_int64();
if( i < 0 || static_cast<std::uint64_t>(i) >
(std::numeric_limits<T>::max)())
{
ec = error::not_exact;
}
else
{
result = static_cast<T>(i);
}
}
else if(jv.kind() == kind::uint64)
{
auto const u = jv.get_uint64();
if(u > (std::numeric_limits<T>::max)())
{
ec = error::not_exact;
}
else
{
result = static_cast<T>(u);
}
}
else
{
BOOST_ASSERT(jv.kind() == kind::double_);
auto const d = jv.get_double();
if( d < 0 ||
d > (std::numeric_limits<T>::max)() ||
static_cast<T>(d) != d)
{
ec = error::not_exact;
}
else
{
result = static_cast<T>(d);
}
}
return result;
}

template<class T>
T
number_cast(
value const& jv,
error_code&,
typename std::enable_if<
std::is_floating_point<T>::value
>::type* = 0
) noexcept
{
if(jv.kind() == kind::int64)
return static_cast<T>(jv.get_int64());

if(jv.kind() == kind::uint64)
return static_cast<T>(jv.get_uint64());

BOOST_ASSERT(jv.kind() == kind::double_);
return static_cast<T>(jv.get_double());
}

} // detail
} // json
} // boost

#endif
2 changes: 1 addition & 1 deletion include/boost/json/detail/raw_stack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ align_to(raw_stack& rs) noexcept
} // boost

#ifdef BOOST_JSON_HEADER_ONLY
#include <boost/json/detail/raw_stack.ipp>
#include <boost/json/detail/impl/raw_stack.ipp>
#endif

#endif
3 changes: 3 additions & 0 deletions include/boost/json/error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ enum class error
/// integer overflow
integer_overflow,

/// number cast is not exact
not_exact,

/// key not found
key_not_found,

Expand Down
4 changes: 3 additions & 1 deletion include/boost/json/impl/basic_parser.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ write_some(
[this, &temp](error_code& ec)
{
// need 4 chars for largest utf8 code point
if(temp.max_size() - temp.size() >= 4)
if(temp.size() < temp.max_size() - 4)
return true;
if(is_key_)
this->on_key_part(temp, ec);
Expand Down Expand Up @@ -754,6 +754,8 @@ loop_str1:
unsigned long cp =
((u0_ - 0xd800) << 10) +
(u_ - 0xdc00);
if(! maybe_flush(ec))
goto yield;
temp.append_utf8(cp);
u0_ = -1;
st_.pop();
Expand Down
Loading