feat():initial version
This commit is contained in:
1748
install/boost_1_75_0/include/boost/json/array.hpp
Normal file
1748
install/boost_1_75_0/include/boost/json/array.hpp
Normal file
File diff suppressed because it is too large
Load Diff
715
install/boost_1_75_0/include/boost/json/basic_parser.hpp
Normal file
715
install/boost_1_75_0/include/boost/json/basic_parser.hpp
Normal file
@@ -0,0 +1,715 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
|
||||
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_BASIC_PARSER_HPP
|
||||
#define BOOST_JSON_BASIC_PARSER_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/error.hpp>
|
||||
#include <boost/json/kind.hpp>
|
||||
#include <boost/json/parse_options.hpp>
|
||||
#include <boost/json/detail/stack.hpp>
|
||||
#include <boost/json/detail/stream.hpp>
|
||||
#include <boost/json/detail/utf8.hpp>
|
||||
|
||||
/* VFALCO NOTE
|
||||
|
||||
This file is in the detail namespace because it
|
||||
is not allowed to be included directly by users,
|
||||
who should be including <boost/json/basic_parser.hpp>
|
||||
instead, which provides the member function definitions.
|
||||
|
||||
The source code is arranged this way to keep compile
|
||||
times down.
|
||||
*/
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
/** An incremental SAX parser for serialized JSON.
|
||||
|
||||
This implements a SAX-style parser, invoking a
|
||||
caller-supplied handler with each parsing event.
|
||||
To use, first declare a variable of type
|
||||
`basic_parser<T>` where `T` meets the handler
|
||||
requirements specified below. Then call
|
||||
@ref write_some one or more times with the input,
|
||||
setting `more = false` on the final buffer.
|
||||
The parsing events are realized through member
|
||||
function calls on the handler, which exists
|
||||
as a data member of the parser.
|
||||
\n
|
||||
The parser may dynamically allocate intermediate
|
||||
storage as needed to accommodate the nesting level
|
||||
of the input JSON. On subsequent invocations, the
|
||||
parser can cheaply re-use this memory, improving
|
||||
performance. This storage is freed when the
|
||||
parser is destroyed
|
||||
|
||||
@par Usage
|
||||
|
||||
To get the declaration and function definitions
|
||||
for this class it is necessary to include this
|
||||
file instead:
|
||||
@code
|
||||
#include <boost/json/basic_parser_impl.hpp>
|
||||
@endcode
|
||||
|
||||
Users who wish to parse JSON into the DOM container
|
||||
@ref value will not use this class directly; instead
|
||||
they will create an instance of @ref parser or
|
||||
@ref stream_parser and use that instead. Alternatively,
|
||||
they may call the function @ref parse. This class is
|
||||
designed for users who wish to perform custom actions
|
||||
instead of building a @ref value. For example, to
|
||||
produce a DOM from an external library.
|
||||
\n
|
||||
@note
|
||||
|
||||
By default, only conforming JSON using UTF-8
|
||||
encoding is accepted. However, select non-compliant
|
||||
syntax can be allowed by construction using a
|
||||
@ref parse_options set to desired values.
|
||||
|
||||
@par Handler
|
||||
|
||||
The handler provided must be implemented as an
|
||||
object of class type which defines each of the
|
||||
required event member functions below. The event
|
||||
functions return a `bool` where `true` indicates
|
||||
success, and `false` indicates failure. If the
|
||||
member function returns `false`, it must set
|
||||
the error code to a suitable value. This error
|
||||
code will be returned by the write function to
|
||||
the caller.
|
||||
\n
|
||||
Handlers are required to declare the maximum
|
||||
limits on various elements. If these limits
|
||||
are exceeded during parsing, then parsing
|
||||
fails with an error.
|
||||
\n
|
||||
The following declaration meets the parser's
|
||||
handler requirements:
|
||||
|
||||
@code
|
||||
struct handler
|
||||
{
|
||||
/// The maximum number of elements allowed in an array
|
||||
static constexpr std::size_t max_array_size = -1;
|
||||
|
||||
/// The maximum number of elements allowed in an object
|
||||
static constexpr std::size_t max_object_size = -1;
|
||||
|
||||
/// The maximum number of characters allowed in a string
|
||||
static constexpr std::size_t max_string_size = -1;
|
||||
|
||||
/// The maximum number of characters allowed in a key
|
||||
static constexpr std::size_t max_key_size = -1;
|
||||
|
||||
/// Called once when the JSON parsing begins.
|
||||
///
|
||||
/// @return `true` on success.
|
||||
/// @param ec Set to the error, if any occurred.
|
||||
///
|
||||
bool on_document_begin( error_code& ec );
|
||||
|
||||
/// Called when the JSON parsing is done.
|
||||
///
|
||||
/// @return `true` on success.
|
||||
/// @param ec Set to the error, if any occurred.
|
||||
///
|
||||
bool on_document_end( error_code& ec );
|
||||
|
||||
/// Called when the beginning of an array is encountered.
|
||||
///
|
||||
/// @return `true` on success.
|
||||
/// @param ec Set to the error, if any occurred.
|
||||
///
|
||||
bool on_array_begin( error_code& ec );
|
||||
|
||||
/// Called when the end of the current array is encountered.
|
||||
///
|
||||
/// @return `true` on success.
|
||||
/// @param n The number of elements in the array.
|
||||
/// @param ec Set to the error, if any occurred.
|
||||
///
|
||||
bool on_array_end( std::size_t n, error_code& ec );
|
||||
|
||||
/// Called when the beginning of an object is encountered.
|
||||
///
|
||||
/// @return `true` on success.
|
||||
/// @param ec Set to the error, if any occurred.
|
||||
///
|
||||
bool on_object_begin( error_code& ec );
|
||||
|
||||
/// Called when the end of the current object is encountered.
|
||||
///
|
||||
/// @return `true` on success.
|
||||
/// @param n The number of elements in the object.
|
||||
/// @param ec Set to the error, if any occurred.
|
||||
///
|
||||
bool on_object_end( std::size_t n, error_code& ec );
|
||||
|
||||
/// Called with characters corresponding to part of the current string.
|
||||
///
|
||||
/// @return `true` on success.
|
||||
/// @param s The partial characters
|
||||
/// @param n The total size of the string thus far
|
||||
/// @param ec Set to the error, if any occurred.
|
||||
///
|
||||
bool on_string_part( string_view s, std::size_t n, error_code& ec );
|
||||
|
||||
/// Called with the last characters corresponding to the current string.
|
||||
///
|
||||
/// @return `true` on success.
|
||||
/// @param s The remaining characters
|
||||
/// @param n The total size of the string
|
||||
/// @param ec Set to the error, if any occurred.
|
||||
///
|
||||
bool on_string( string_view s, std::size_t n, error_code& ec );
|
||||
|
||||
/// Called with characters corresponding to part of the current key.
|
||||
///
|
||||
/// @return `true` on success.
|
||||
/// @param s The partial characters
|
||||
/// @param n The total size of the key thus far
|
||||
/// @param ec Set to the error, if any occurred.
|
||||
///
|
||||
bool on_key_part( string_view s, std::size_t n, error_code& ec );
|
||||
|
||||
/// Called with the last characters corresponding to the current key.
|
||||
///
|
||||
/// @return `true` on success.
|
||||
/// @param s The remaining characters
|
||||
/// @param n The total size of the key
|
||||
/// @param ec Set to the error, if any occurred.
|
||||
///
|
||||
bool on_key( string_view s, std::size_t n, error_code& ec );
|
||||
|
||||
/// Called with the characters corresponding to part of the current number.
|
||||
///
|
||||
/// @return `true` on success.
|
||||
/// @param s The partial characters
|
||||
/// @param ec Set to the error, if any occurred.
|
||||
///
|
||||
bool on_number_part( string_view s, error_code& ec );
|
||||
|
||||
/// Called when a signed integer is parsed.
|
||||
///
|
||||
/// @return `true` on success.
|
||||
/// @param i The value
|
||||
/// @param s The remaining characters
|
||||
/// @param ec Set to the error, if any occurred.
|
||||
///
|
||||
bool on_int64( int64_t i, string_view s, error_code& ec );
|
||||
|
||||
/// Called when an unsigend integer is parsed.
|
||||
///
|
||||
/// @return `true` on success.
|
||||
/// @param u The value
|
||||
/// @param s The remaining characters
|
||||
/// @param ec Set to the error, if any occurred.
|
||||
///
|
||||
bool on_uint64( uint64_t u, string_view s, error_code& ec );
|
||||
|
||||
/// Called when a double is parsed.
|
||||
///
|
||||
/// @return `true` on success.
|
||||
/// @param d The value
|
||||
/// @param s The remaining characters
|
||||
/// @param ec Set to the error, if any occurred.
|
||||
///
|
||||
bool on_double( double d, string_view s, error_code& ec );
|
||||
|
||||
/// Called when a boolean is parsed.
|
||||
///
|
||||
/// @return `true` on success.
|
||||
/// @param b The value
|
||||
/// @param s The remaining characters
|
||||
/// @param ec Set to the error, if any occurred.
|
||||
///
|
||||
bool on_bool( bool b, error_code& ec );
|
||||
|
||||
/// Called when a null is parsed.
|
||||
///
|
||||
/// @return `true` on success.
|
||||
/// @param ec Set to the error, if any occurred.
|
||||
///
|
||||
bool on_null( error_code& ec );
|
||||
|
||||
/// Called with characters corresponding to part of the current comment.
|
||||
///
|
||||
/// @return `true` on success.
|
||||
/// @param s The partial characters.
|
||||
/// @param ec Set to the error, if any occurred.
|
||||
///
|
||||
bool on_comment_part( string_view s, error_code& ec );
|
||||
|
||||
/// Called with the last characters corresponding to the current comment.
|
||||
///
|
||||
/// @return `true` on success.
|
||||
/// @param s The remaining characters
|
||||
/// @param ec Set to the error, if any occurred.
|
||||
///
|
||||
bool on_comment( string_view s, error_code& ec );
|
||||
};
|
||||
@endcode
|
||||
|
||||
@see
|
||||
@ref parse,
|
||||
@ref stream_parser.
|
||||
|
||||
@headerfile <boost/json/basic_parser.hpp>
|
||||
*/
|
||||
template<class Handler>
|
||||
class basic_parser
|
||||
{
|
||||
enum class state : char
|
||||
{
|
||||
doc1, doc2, doc3, doc4,
|
||||
com1, com2, com3, com4,
|
||||
nul1, nul2, nul3,
|
||||
tru1, tru2, tru3,
|
||||
fal1, fal2, fal3, fal4,
|
||||
str1, str2, str3, str4,
|
||||
str5, str6, str7, str8,
|
||||
sur1, sur2, sur3,
|
||||
sur4, sur5, sur6,
|
||||
obj1, obj2, obj3, obj4,
|
||||
obj5, obj6, obj7, obj8,
|
||||
obj9, obj10, obj11,
|
||||
arr1, arr2, arr3,
|
||||
arr4, arr5, arr6,
|
||||
num1, num2, num3, num4,
|
||||
num5, num6, num7, num8,
|
||||
exp1, exp2, exp3,
|
||||
val1, val2
|
||||
};
|
||||
|
||||
struct number
|
||||
{
|
||||
uint64_t mant;
|
||||
int bias;
|
||||
int exp;
|
||||
bool frac;
|
||||
bool neg;
|
||||
};
|
||||
|
||||
// optimization: must come first
|
||||
Handler h_;
|
||||
|
||||
number num_;
|
||||
error_code ec_;
|
||||
detail::stack st_;
|
||||
detail::utf8_sequence seq_;
|
||||
unsigned u1_;
|
||||
unsigned u2_;
|
||||
bool more_; // false for final buffer
|
||||
bool done_ = false; // true on complete parse
|
||||
bool clean_ = true; // write_some exited cleanly
|
||||
const char* end_;
|
||||
parse_options opt_;
|
||||
// how many levels deeper the parser can go
|
||||
std::size_t depth_ = opt_.max_depth;
|
||||
|
||||
inline void reserve();
|
||||
inline const char* sentinel();
|
||||
inline bool incomplete(
|
||||
const detail::const_stream_wrapper& cs);
|
||||
|
||||
#ifdef __INTEL_COMPILER
|
||||
#pragma warning push
|
||||
#pragma warning disable 2196
|
||||
#endif
|
||||
|
||||
BOOST_NOINLINE
|
||||
inline
|
||||
const char*
|
||||
suspend_or_fail(state st);
|
||||
|
||||
BOOST_NOINLINE
|
||||
inline
|
||||
const char*
|
||||
suspend_or_fail(
|
||||
state st,
|
||||
std::size_t n);
|
||||
|
||||
BOOST_NOINLINE
|
||||
inline
|
||||
const char*
|
||||
fail(const char* p) noexcept;
|
||||
|
||||
BOOST_NOINLINE
|
||||
inline
|
||||
const char*
|
||||
fail(
|
||||
const char* p,
|
||||
error ev) noexcept;
|
||||
|
||||
BOOST_NOINLINE
|
||||
inline
|
||||
const char*
|
||||
maybe_suspend(
|
||||
const char* p,
|
||||
state st);
|
||||
|
||||
BOOST_NOINLINE
|
||||
inline
|
||||
const char*
|
||||
maybe_suspend(
|
||||
const char* p,
|
||||
state st,
|
||||
std::size_t n);
|
||||
|
||||
BOOST_NOINLINE
|
||||
inline
|
||||
const char*
|
||||
maybe_suspend(
|
||||
const char* p,
|
||||
state st,
|
||||
const number& num);
|
||||
|
||||
BOOST_NOINLINE
|
||||
inline
|
||||
const char*
|
||||
suspend(
|
||||
const char* p,
|
||||
state st);
|
||||
|
||||
BOOST_NOINLINE
|
||||
inline
|
||||
const char*
|
||||
suspend(
|
||||
const char* p,
|
||||
state st,
|
||||
const number& num);
|
||||
|
||||
#ifdef __INTEL_COMPILER
|
||||
#pragma warning pop
|
||||
#endif
|
||||
|
||||
template<bool StackEmpty_/*, bool Terminal_*/>
|
||||
const char* parse_comment(const char* p,
|
||||
std::integral_constant<bool, StackEmpty_> stack_empty,
|
||||
/*std::integral_constant<bool, Terminal_>*/ bool terminal);
|
||||
|
||||
template<bool StackEmpty_>
|
||||
const char* parse_document(const char* p,
|
||||
std::integral_constant<bool, StackEmpty_> stack_empty);
|
||||
|
||||
template<bool StackEmpty_, bool AllowComments_/*,
|
||||
bool AllowTrailing_, bool AllowBadUTF8_*/>
|
||||
const char* parse_value(const char* p,
|
||||
std::integral_constant<bool, StackEmpty_> stack_empty,
|
||||
std::integral_constant<bool, AllowComments_> allow_comments,
|
||||
/*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
|
||||
/*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8);
|
||||
|
||||
template<bool StackEmpty_, bool AllowComments_/*,
|
||||
bool AllowTrailing_, bool AllowBadUTF8_*/>
|
||||
const char* resume_value(const char* p,
|
||||
std::integral_constant<bool, StackEmpty_> stack_empty,
|
||||
std::integral_constant<bool, AllowComments_> allow_comments,
|
||||
/*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
|
||||
/*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8);
|
||||
|
||||
template<bool StackEmpty_, bool AllowComments_/*,
|
||||
bool AllowTrailing_, bool AllowBadUTF8_*/>
|
||||
const char* parse_object(const char* p,
|
||||
std::integral_constant<bool, StackEmpty_> stack_empty,
|
||||
std::integral_constant<bool, AllowComments_> allow_comments,
|
||||
/*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
|
||||
/*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8);
|
||||
|
||||
template<bool StackEmpty_, bool AllowComments_/*,
|
||||
bool AllowTrailing_, bool AllowBadUTF8_*/>
|
||||
const char* parse_array(const char* p,
|
||||
std::integral_constant<bool, StackEmpty_> stack_empty,
|
||||
std::integral_constant<bool, AllowComments_> allow_comments,
|
||||
/*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
|
||||
/*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8);
|
||||
|
||||
template<bool StackEmpty_>
|
||||
const char* parse_null(const char* p,
|
||||
std::integral_constant<bool, StackEmpty_> stack_empty);
|
||||
|
||||
template<bool StackEmpty_>
|
||||
const char* parse_true(const char* p,
|
||||
std::integral_constant<bool, StackEmpty_> stack_empty);
|
||||
|
||||
template<bool StackEmpty_>
|
||||
const char* parse_false(const char* p,
|
||||
std::integral_constant<bool, StackEmpty_> stack_empty);
|
||||
|
||||
template<bool StackEmpty_, bool IsKey_/*,
|
||||
bool AllowBadUTF8_*/>
|
||||
const char* parse_string(const char* p,
|
||||
std::integral_constant<bool, StackEmpty_> stack_empty,
|
||||
std::integral_constant<bool, IsKey_> is_key,
|
||||
/*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8);
|
||||
|
||||
template<bool StackEmpty_, char First_>
|
||||
const char* parse_number(const char* p,
|
||||
std::integral_constant<bool, StackEmpty_> stack_empty,
|
||||
std::integral_constant<char, First_> first);
|
||||
|
||||
template<bool StackEmpty_, bool IsKey_/*,
|
||||
bool AllowBadUTF8_*/>
|
||||
const char* parse_unescaped(const char* p,
|
||||
std::integral_constant<bool, StackEmpty_> stack_empty,
|
||||
std::integral_constant<bool, IsKey_> is_key,
|
||||
/*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8);
|
||||
|
||||
template<bool StackEmpty_/*, bool IsKey_,
|
||||
bool AllowBadUTF8_*/>
|
||||
const char* parse_escaped(
|
||||
const char* p,
|
||||
std::size_t total,
|
||||
std::integral_constant<bool, StackEmpty_> stack_empty,
|
||||
/*std::integral_constant<bool, IsKey_>*/ bool is_key,
|
||||
/*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8);
|
||||
|
||||
// intentionally private
|
||||
std::size_t
|
||||
depth() const noexcept
|
||||
{
|
||||
return opt_.max_depth - depth_;
|
||||
}
|
||||
|
||||
public:
|
||||
/// Copy constructor (deleted)
|
||||
basic_parser(
|
||||
basic_parser const&) = delete;
|
||||
|
||||
/// Copy assignment (deleted)
|
||||
basic_parser& operator=(
|
||||
basic_parser const&) = delete;
|
||||
|
||||
/** Destructor.
|
||||
|
||||
All dynamically allocated internal memory is freed.
|
||||
|
||||
@par Effects
|
||||
@code
|
||||
this->handler().~Handler()
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Same as `~Handler()`.
|
||||
|
||||
@par Exception Safety
|
||||
Same as `~Handler()`.
|
||||
*/
|
||||
~basic_parser() = default;
|
||||
|
||||
/** Constructor.
|
||||
|
||||
This function constructs the parser with
|
||||
the specified options, with any additional
|
||||
arguments forwarded to the handler's constructor.
|
||||
|
||||
@par Complexity
|
||||
Same as `Handler( std::forward< Args >( args )... )`.
|
||||
|
||||
@par Exception Safety
|
||||
Same as `Handler( std::forward< Args >( args )... )`.
|
||||
|
||||
@param opt Configuration settings for the parser.
|
||||
If this structure is default constructed, the
|
||||
parser will accept only standard JSON.
|
||||
|
||||
@param args Optional additional arguments
|
||||
forwarded to the handler's constructor.
|
||||
|
||||
@see parse_options
|
||||
*/
|
||||
template<class... Args>
|
||||
explicit
|
||||
basic_parser(
|
||||
parse_options const& opt,
|
||||
Args&&... args);
|
||||
|
||||
/** Return a reference to the handler.
|
||||
|
||||
This function provides access to the constructed
|
||||
instance of the handler owned by the parser.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
Handler&
|
||||
handler() noexcept
|
||||
{
|
||||
return h_;
|
||||
}
|
||||
|
||||
/** Return a reference to the handler.
|
||||
|
||||
This function provides access to the constructed
|
||||
instance of the handler owned by the parser.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
Handler const&
|
||||
handler() const noexcept
|
||||
{
|
||||
return h_;
|
||||
}
|
||||
|
||||
/** Return the last error.
|
||||
|
||||
This returns the last error code which
|
||||
was generated in the most recent call
|
||||
to @ref write_some.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
error_code
|
||||
last_error() const noexcept
|
||||
{
|
||||
return ec_;
|
||||
}
|
||||
|
||||
/** Return true if a complete JSON has been parsed.
|
||||
|
||||
This function returns `true` when all of these
|
||||
conditions are met:
|
||||
|
||||
@li A complete serialized JSON has been
|
||||
presented to the parser, and
|
||||
|
||||
@li No error or exception has occurred since the
|
||||
parser was constructed, or since the last call
|
||||
to @ref reset,
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
bool
|
||||
done() const noexcept
|
||||
{
|
||||
return done_;
|
||||
}
|
||||
|
||||
/** Reset the state, to parse a new document.
|
||||
|
||||
This function discards the current parsing
|
||||
state, to prepare for parsing a new document.
|
||||
Dynamically allocated temporary memory used
|
||||
by the implementation is not deallocated.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
void
|
||||
reset() noexcept;
|
||||
|
||||
/** Indicate a parsing failure.
|
||||
|
||||
This changes the state of the parser to indicate
|
||||
that the parse has failed. A parser implementation
|
||||
can use this to fail the parser if needed due to
|
||||
external inputs.
|
||||
|
||||
@note
|
||||
|
||||
If `!ec`, the stored error code is unspecified.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param ec The error code to set. If the code does
|
||||
not indicate failure, an implementation-defined
|
||||
error code that indicates failure will be stored
|
||||
instead.
|
||||
*/
|
||||
void
|
||||
fail(error_code ec) noexcept;
|
||||
|
||||
/** Parse some of an input string as JSON, incrementally.
|
||||
|
||||
This function parses the JSON in the specified
|
||||
buffer, calling the handler to emit each SAX
|
||||
parsing event. The parse proceeds from the
|
||||
current state, which is at the beginning of a
|
||||
new JSON or in the middle of the current JSON
|
||||
if any characters were already parsed.
|
||||
\n
|
||||
The characters in the buffer are processed
|
||||
starting from the beginning, until one of the
|
||||
following conditions is met:
|
||||
|
||||
@li All of the characters in the buffer
|
||||
have been parsed, or
|
||||
|
||||
@li Some of the characters in the buffer
|
||||
have been parsed and the JSON is complete, or
|
||||
|
||||
@li A parsing error occurs.
|
||||
|
||||
The supplied buffer does not need to contain the
|
||||
entire JSON. Subsequent calls can provide more
|
||||
serialized data, allowing JSON to be processed
|
||||
incrementally. The end of the serialized JSON
|
||||
can be indicated by passing `more = false`.
|
||||
|
||||
@par Complexity
|
||||
Linear in `size`.
|
||||
|
||||
@par Exception Safety
|
||||
Basic guarantee.
|
||||
Calls to the handler may throw.
|
||||
Upon error or exception, subsequent calls will
|
||||
fail until @ref reset is called to parse a new JSON.
|
||||
|
||||
@return The number of characters successfully
|
||||
parsed, which may be smaller than `size`.
|
||||
|
||||
@param more `true` if there are possibly more
|
||||
buffers in the current JSON, otherwise `false`.
|
||||
|
||||
@param data A pointer to a buffer of `size`
|
||||
characters to parse.
|
||||
|
||||
@param size The number of characters pointed to
|
||||
by `data`.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
std::size_t
|
||||
write_some(
|
||||
bool more,
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec);
|
||||
};
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
2537
install/boost_1_75_0/include/boost/json/basic_parser_impl.hpp
Normal file
2537
install/boost_1_75_0/include/boost/json/basic_parser_impl.hpp
Normal file
File diff suppressed because it is too large
Load Diff
75
install/boost_1_75_0/include/boost/json/detail/align.hpp
Normal file
75
install/boost_1_75_0/include/boost/json/detail/align.hpp
Normal file
@@ -0,0 +1,75 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_ALIGN_HPP
|
||||
#define BOOST_JSON_DETAIL_ALIGN_HPP
|
||||
|
||||
#ifndef BOOST_JSON_STANDALONE
|
||||
#include <boost/align/align.hpp>
|
||||
#else
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#endif
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
#ifndef BOOST_JSON_STANDALONE
|
||||
using boost::alignment::align;
|
||||
|
||||
// VFALCO workaround until Boost.Align has the type
|
||||
|
||||
struct class_type {};
|
||||
enum unscoped_enumeration_type { };
|
||||
enum class scoped_enumeration_type { };
|
||||
|
||||
// [support.types] p5: The type max_align_t is a trivial
|
||||
// standard-layout type whose alignment requirement
|
||||
// is at least as great as that of every scalar type.
|
||||
struct max_align_t
|
||||
{
|
||||
// arithmetic types
|
||||
char a;
|
||||
char16_t b;
|
||||
char32_t c;
|
||||
bool d;
|
||||
short int e;
|
||||
int f;
|
||||
long int g;
|
||||
long long int h;
|
||||
wchar_t i;
|
||||
float j;
|
||||
double k;
|
||||
long double l;
|
||||
// enumeration types
|
||||
unscoped_enumeration_type m;
|
||||
scoped_enumeration_type n;
|
||||
// pointer types
|
||||
void* o;
|
||||
char* p;
|
||||
class_type* q;
|
||||
unscoped_enumeration_type* r;
|
||||
scoped_enumeration_type* s;
|
||||
void(*t)();
|
||||
// pointer to member types
|
||||
char class_type::* u;
|
||||
void (class_type::*v)();
|
||||
// nullptr
|
||||
std::nullptr_t w;
|
||||
};
|
||||
|
||||
#else
|
||||
using std::align;
|
||||
using max_align_t = std::max_align_t;
|
||||
#endif
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
75
install/boost_1_75_0/include/boost/json/detail/array.hpp
Normal file
75
install/boost_1_75_0/include/boost/json/detail/array.hpp
Normal file
@@ -0,0 +1,75 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_ARRAY_HPP
|
||||
#define BOOST_JSON_DETAIL_ARRAY_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/storage_ptr.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
class value;
|
||||
|
||||
namespace detail {
|
||||
|
||||
class unchecked_array
|
||||
{
|
||||
value* data_;
|
||||
std::size_t size_;
|
||||
storage_ptr const& sp_;
|
||||
|
||||
public:
|
||||
inline
|
||||
~unchecked_array();
|
||||
|
||||
unchecked_array(
|
||||
value* data,
|
||||
std::size_t size,
|
||||
storage_ptr const& sp) noexcept
|
||||
: data_(data)
|
||||
, size_(size)
|
||||
, sp_(sp)
|
||||
{
|
||||
}
|
||||
|
||||
unchecked_array(
|
||||
unchecked_array&& other) noexcept
|
||||
: data_(other.data_)
|
||||
, size_(other.size_)
|
||||
, sp_(other.sp_)
|
||||
{
|
||||
other.data_ = nullptr;
|
||||
}
|
||||
|
||||
storage_ptr const&
|
||||
storage() const noexcept
|
||||
{
|
||||
return sp_;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
size() const noexcept
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
relocate(value* dest) noexcept;
|
||||
};
|
||||
|
||||
} // detail
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
// includes are at the bottom of <boost/json/value.hpp>
|
||||
|
||||
#endif
|
||||
144
install/boost_1_75_0/include/boost/json/detail/buffer.hpp
Normal file
144
install/boost_1_75_0/include/boost/json/detail/buffer.hpp
Normal file
@@ -0,0 +1,144 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_BUFFER_HPP
|
||||
#define BOOST_JSON_DETAIL_BUFFER_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/string_view.hpp>
|
||||
#include <cstring>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
// A simple string-like temporary static buffer
|
||||
template<std::size_t N>
|
||||
class buffer
|
||||
{
|
||||
public:
|
||||
using size_type = std::size_t;
|
||||
|
||||
buffer() = default;
|
||||
|
||||
bool
|
||||
empty() const noexcept
|
||||
{
|
||||
return size_ == 0;
|
||||
}
|
||||
|
||||
string_view
|
||||
get() const noexcept
|
||||
{
|
||||
return {buf_, size_};
|
||||
}
|
||||
|
||||
operator string_view() const noexcept
|
||||
{
|
||||
return get();
|
||||
}
|
||||
|
||||
char const*
|
||||
data() const noexcept
|
||||
{
|
||||
return buf_;
|
||||
}
|
||||
|
||||
size_type
|
||||
size() const noexcept
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
size_type
|
||||
capacity() const noexcept
|
||||
{
|
||||
return N - size_;
|
||||
}
|
||||
|
||||
size_type
|
||||
max_size() const noexcept
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
void
|
||||
clear() noexcept
|
||||
{
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
void
|
||||
push_back(char ch) noexcept
|
||||
{
|
||||
BOOST_ASSERT(capacity() > 0);
|
||||
buf_[size_++] = ch;
|
||||
}
|
||||
|
||||
// append an unescaped string
|
||||
void
|
||||
append(
|
||||
char const* s,
|
||||
size_type n)
|
||||
{
|
||||
BOOST_ASSERT(n <= N - size_);
|
||||
std::memcpy(buf_ + size_, s, n);
|
||||
size_ += n;
|
||||
}
|
||||
|
||||
// append valid 32-bit code point as utf8
|
||||
void
|
||||
append_utf8(
|
||||
unsigned long cp) noexcept
|
||||
{
|
||||
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;
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
size_ += 3;
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
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);
|
||||
dest[3] = static_cast<char>( (cp & 0x3f) | 0x80);
|
||||
size_ += 4;
|
||||
}
|
||||
}
|
||||
private:
|
||||
char buf_[N];
|
||||
size_type size_ = 0;
|
||||
};
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
321
install/boost_1_75_0/include/boost/json/detail/config.hpp
Normal file
321
install/boost_1_75_0/include/boost/json/detail/config.hpp
Normal file
@@ -0,0 +1,321 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_CONFIG_HPP
|
||||
#define BOOST_JSON_DETAIL_CONFIG_HPP
|
||||
|
||||
#ifndef BOOST_JSON_STANDALONE
|
||||
# include <boost/config.hpp>
|
||||
# include <boost/assert.hpp>
|
||||
# include <boost/throw_exception.hpp>
|
||||
#else
|
||||
# include <cassert>
|
||||
#endif
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
// detect 32/64 bit
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
# define BOOST_JSON_ARCH 64
|
||||
#elif UINTPTR_MAX == UINT32_MAX
|
||||
# define BOOST_JSON_ARCH 32
|
||||
#else
|
||||
# error Unknown or unsupported architecture, please open an issue
|
||||
#endif
|
||||
|
||||
// VFALCO Copied from Boost.Config
|
||||
// This is a derivative work.
|
||||
#ifndef BOOST_JSON_NODISCARD
|
||||
# ifdef __has_cpp_attribute
|
||||
// clang-6 accepts [[nodiscard]] with -std=c++14, but warns about it -pedantic
|
||||
# if __has_cpp_attribute(nodiscard) && !(defined(__clang__) && (__cplusplus < 201703L))
|
||||
# define BOOST_JSON_NODISCARD [[nodiscard]]
|
||||
# else
|
||||
# define BOOST_JSON_NODISCARD
|
||||
# endif
|
||||
# else
|
||||
# define BOOST_JSON_NODISCARD
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_JSON_REQUIRE_CONST_INIT
|
||||
# define BOOST_JSON_REQUIRE_CONST_INIT
|
||||
# if __cpp_constinit >= 201907L
|
||||
# undef BOOST_JSON_REQUIRE_CONST_INIT
|
||||
# define BOOST_JSON_REQUIRE_CONST_INIT constinit
|
||||
# elif defined(__clang__) && defined(__has_cpp_attribute)
|
||||
# if __has_cpp_attribute(clang::require_constant_initialization)
|
||||
# undef BOOST_JSON_REQUIRE_CONST_INIT
|
||||
# define BOOST_JSON_REQUIRE_CONST_INIT [[clang::require_constant_initialization]]
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_JSON_NO_DESTROY
|
||||
# if defined(__clang__) && defined(__has_cpp_attribute)
|
||||
# if __has_cpp_attribute(clang::no_destroy)
|
||||
# define BOOST_JSON_NO_DESTROY [[clang::no_destroy]]
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// BOOST_NORETURN ---------------------------------------------//
|
||||
// Macro to use before a function declaration/definition to designate
|
||||
// the function as not returning normally (i.e. with a return statement
|
||||
// or by leaving the function scope, if the function return type is void).
|
||||
#if !defined(BOOST_NORETURN)
|
||||
# if defined(_MSC_VER)
|
||||
# define BOOST_NORETURN __declspec(noreturn)
|
||||
# elif defined(__GNUC__)
|
||||
# define BOOST_NORETURN __attribute__ ((__noreturn__))
|
||||
# elif defined(__has_attribute) && defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x5130)
|
||||
# if __has_attribute(noreturn)
|
||||
# define BOOST_NORETURN [[noreturn]]
|
||||
# endif
|
||||
# elif defined(__has_cpp_attribute)
|
||||
# if __has_cpp_attribute(noreturn)
|
||||
# define BOOST_NORETURN [[noreturn]]
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_ASSERT
|
||||
#define BOOST_ASSERT assert
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_STATIC_ASSERT
|
||||
#define BOOST_STATIC_ASSERT( ... ) static_assert(__VA_ARGS__, #__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_FALLTHROUGH
|
||||
#define BOOST_FALLTHROUGH [[fallthrough]]
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_FORCEINLINE
|
||||
# ifdef _MSC_VER
|
||||
# define BOOST_FORCEINLINE __forceinline
|
||||
# elif defined(__GNUC__) || defined(__clang__)
|
||||
# define BOOST_FORCEINLINE inline __attribute__((always_inline))
|
||||
# else
|
||||
# define BOOST_FORCEINLINE inline
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NOINLINE
|
||||
# ifdef _MSC_VER
|
||||
# define BOOST_NOINLINE __declspec(noinline)
|
||||
# elif defined(__GNUC__) || defined(__clang__)
|
||||
# define BOOST_NOINLINE __attribute__((noinline))
|
||||
# else
|
||||
# define BOOST_NOINLINE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_THROW_EXCEPTION
|
||||
# ifndef BOOST_NO_EXCEPTIONS
|
||||
# define BOOST_THROW_EXCEPTION(x) throw(x)
|
||||
# else
|
||||
# define BOOST_THROW_EXCEPTION(x) do{}while(0)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if ! defined(BOOST_JSON_NO_SSE2) && \
|
||||
! defined(BOOST_JSON_USE_SSE2)
|
||||
# if (defined(_M_IX86) && _M_IX86_FP == 2) || \
|
||||
defined(_M_X64) || defined(__SSE2__)
|
||||
# define BOOST_JSON_USE_SSE2
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_SYMBOL_VISIBLE
|
||||
#define BOOST_SYMBOL_VISIBLE
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_JSON_STANDALONE
|
||||
# define BOOST_JSON_NS_BEGIN \
|
||||
namespace boost { \
|
||||
namespace json { \
|
||||
inline namespace standalone {
|
||||
# define BOOST_JSON_NS_END } } }
|
||||
#elif ! defined(BOOST_JSON_DOCS)
|
||||
# define BOOST_JSON_NS_BEGIN \
|
||||
namespace boost { \
|
||||
namespace json {
|
||||
# define BOOST_JSON_NS_END } }
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_JSON_STANDALONE
|
||||
# if defined(BOOST_JSON_DOCS)
|
||||
# define BOOST_JSON_DECL
|
||||
# else
|
||||
# if (defined(BOOST_JSON_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)) && !defined(BOOST_JSON_STATIC_LINK)
|
||||
# if defined(BOOST_JSON_SOURCE)
|
||||
# define BOOST_JSON_DECL BOOST_SYMBOL_EXPORT
|
||||
# define BOOST_JSON_CLASS_DECL BOOST_SYMBOL_EXPORT
|
||||
# define BOOST_JSON_BUILD_DLL
|
||||
# else
|
||||
# define BOOST_JSON_DECL BOOST_SYMBOL_IMPORT
|
||||
# define BOOST_JSON_CLASS_DECL BOOST_SYMBOL_IMPORT
|
||||
# endif
|
||||
# endif // shared lib
|
||||
# ifndef BOOST_JSON_DECL
|
||||
# define BOOST_JSON_DECL
|
||||
# endif
|
||||
# if !defined(BOOST_JSON_SOURCE) && !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_JSON_NO_LIB)
|
||||
# define BOOST_LIB_NAME boost_json
|
||||
# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_JSON_DYN_LINK)
|
||||
# define BOOST_DYN_LINK
|
||||
# endif
|
||||
# include <boost/config/auto_link.hpp>
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
// For standalone, shared library builds, users must manually
|
||||
// define the macros BOOST_JSON_DECL and BOOST_JSON_CLASS_DECL
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_JSON_DECL
|
||||
#define BOOST_JSON_DECL
|
||||
#endif
|
||||
#ifndef BOOST_JSON_CLASS_DECL
|
||||
#define BOOST_JSON_CLASS_DECL
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_JSON_LIKELY
|
||||
# if defined(__GNUC__) || defined(__clang__)
|
||||
# define BOOST_JSON_LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
# else
|
||||
# define BOOST_JSON_LIKELY(x) x
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_JSON_UNLIKELY
|
||||
# if defined(__GNUC__) || defined(__clang__)
|
||||
# define BOOST_JSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||
# else
|
||||
# define BOOST_JSON_UNLIKELY(x) x
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_JSON_UNREACHABLE
|
||||
# define BOOST_JSON_UNREACHABLE() static_cast<void>(0)
|
||||
# ifdef _MSC_VER
|
||||
# undef BOOST_JSON_UNREACHABLE
|
||||
# define BOOST_JSON_UNREACHABLE() __assume(0)
|
||||
# elif defined(__has_builtin)
|
||||
# if __has_builtin(__builtin_unreachable)
|
||||
# undef BOOST_JSON_UNREACHABLE
|
||||
# define BOOST_JSON_UNREACHABLE() __builtin_unreachable()
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_JSON_ASSUME
|
||||
# define BOOST_JSON_ASSUME(x) (!!(x) ? void() : BOOST_JSON_UNREACHABLE())
|
||||
# ifdef _MSC_VER
|
||||
# undef BOOST_JSON_ASSUME
|
||||
# define BOOST_JSON_ASSUME(x) __assume(!!(x))
|
||||
# elif defined(__has_builtin)
|
||||
# if __has_builtin(__builtin_assume)
|
||||
# undef BOOST_JSON_ASSUME
|
||||
# define BOOST_JSON_ASSUME(x) __builtin_assume(!!(x))
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// older versions of msvc and clang don't always
|
||||
// constant initialize when they are supposed to
|
||||
#ifndef BOOST_JSON_WEAK_CONSTINIT
|
||||
# if defined(_MSC_VER) && ! defined(__clang__) && _MSC_VER < 1920
|
||||
# define BOOST_JSON_WEAK_CONSTINIT
|
||||
# elif defined(__clang__) && __clang_major__ < 4
|
||||
# define BOOST_JSON_WEAK_CONSTINIT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// These macros are private, for tests, do not change
|
||||
// them or else previously built libraries won't match.
|
||||
#ifndef BOOST_JSON_MAX_STRING_SIZE
|
||||
# define BOOST_JSON_NO_MAX_STRING_SIZE
|
||||
# define BOOST_JSON_MAX_STRING_SIZE 0x7ffffffe
|
||||
#endif
|
||||
#ifndef BOOST_JSON_MAX_STRUCTURED_SIZE
|
||||
# define BOOST_JSON_NO_MAX_STRUCTURED_SIZE
|
||||
# define BOOST_JSON_MAX_STRUCTURED_SIZE 0x7ffffffe
|
||||
#endif
|
||||
#ifndef BOOST_JSON_STACK_BUFFER_SIZE
|
||||
# define BOOST_JSON_NO_STACK_BUFFER_SIZE
|
||||
# if defined(__i386__) || defined(__x86_64__) || \
|
||||
defined(_M_IX86) || defined(_M_X64)
|
||||
# define BOOST_JSON_STACK_BUFFER_SIZE 4096
|
||||
# else
|
||||
// If we are not on Intel, then assume we are on
|
||||
// embedded and use a smaller stack size. If this
|
||||
// is not suitable, the user can define the macro
|
||||
// themselves when building the library or including
|
||||
// src.hpp.
|
||||
# define BOOST_JSON_STACK_BUFFER_SIZE 256
|
||||
# endif
|
||||
#endif
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
template<class...>
|
||||
struct make_void
|
||||
{
|
||||
using type =void;
|
||||
};
|
||||
|
||||
template<class... Ts>
|
||||
using void_t = typename
|
||||
make_void<Ts...>::type;
|
||||
|
||||
template<class T>
|
||||
using remove_cvref = typename
|
||||
std::remove_cv<typename
|
||||
std::remove_reference<T>::type>::type;
|
||||
|
||||
template<class T, class U>
|
||||
T exchange(T& t, U u) noexcept
|
||||
{
|
||||
T v = std::move(t);
|
||||
t = std::move(u);
|
||||
return v;
|
||||
}
|
||||
|
||||
/* This is a derivative work, original copyright:
|
||||
|
||||
Copyright Eric Niebler 2013-present
|
||||
|
||||
Use, modification and distribution is subject to 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)
|
||||
|
||||
Project home: https://github.com/ericniebler/range-v3
|
||||
*/
|
||||
template<typename T>
|
||||
struct static_const
|
||||
{
|
||||
static constexpr T value {};
|
||||
};
|
||||
template<typename T>
|
||||
constexpr T static_const<T>::value;
|
||||
|
||||
#define BOOST_JSON_INLINE_VARIABLE(name, type) \
|
||||
namespace { constexpr auto& name = \
|
||||
::boost::json::detail::static_const<type>::value; \
|
||||
} struct _unused_ ## name ## _semicolon_bait_
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,99 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DEFAULT_RESOURCE_HPP
|
||||
#define BOOST_JSON_DEFAULT_RESOURCE_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <new>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4251) // class needs to have dll-interface to be used by clients of class
|
||||
#pragma warning(disable: 4275) // non dll-interface class used as base for dll-interface class
|
||||
#endif
|
||||
|
||||
// A simple memory resource that uses operator new and delete.
|
||||
class
|
||||
BOOST_SYMBOL_VISIBLE
|
||||
BOOST_JSON_CLASS_DECL
|
||||
default_resource final
|
||||
: public memory_resource
|
||||
{
|
||||
union holder;
|
||||
|
||||
#ifndef BOOST_JSON_WEAK_CONSTINIT
|
||||
# ifndef BOOST_JSON_NO_DESTROY
|
||||
static holder instance_;
|
||||
# else
|
||||
BOOST_JSON_NO_DESTROY
|
||||
static default_resource instance_;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
public:
|
||||
static
|
||||
memory_resource*
|
||||
get() noexcept
|
||||
{
|
||||
#ifdef BOOST_JSON_WEAK_CONSTINIT
|
||||
static default_resource instance_;
|
||||
#endif
|
||||
return reinterpret_cast<memory_resource*>(
|
||||
reinterpret_cast<std::uintptr_t*>(
|
||||
&instance_));
|
||||
}
|
||||
|
||||
~default_resource();
|
||||
|
||||
void*
|
||||
do_allocate(
|
||||
std::size_t n,
|
||||
std::size_t) override;
|
||||
|
||||
void
|
||||
do_deallocate(
|
||||
void* p,
|
||||
std::size_t,
|
||||
std::size_t) override;
|
||||
|
||||
bool
|
||||
do_is_equal(
|
||||
memory_resource const& mr) const noexcept override;
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
union default_resource::
|
||||
holder
|
||||
{
|
||||
#ifndef BOOST_JSON_WEAK_CONSTINIT
|
||||
constexpr
|
||||
#endif
|
||||
holder()
|
||||
: mr()
|
||||
{
|
||||
}
|
||||
|
||||
~holder()
|
||||
{
|
||||
}
|
||||
|
||||
default_resource mr;
|
||||
};
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
40
install/boost_1_75_0/include/boost/json/detail/digest.hpp
Normal file
40
install/boost_1_75_0/include/boost/json/detail/digest.hpp
Normal file
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_DIGEST_HPP
|
||||
#define BOOST_JSON_DETAIL_DIGEST_HPP
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
// Calculate salted digest of string
|
||||
inline
|
||||
std::size_t
|
||||
digest(
|
||||
char const* s,
|
||||
std::size_t n,
|
||||
std::size_t salt) noexcept
|
||||
{
|
||||
#if BOOST_JSON_ARCH == 64
|
||||
std::uint64_t const prime = 0x100000001B3ULL;
|
||||
std::uint64_t hash = 0xcbf29ce484222325ULL;
|
||||
#else
|
||||
std::uint32_t const prime = 0x01000193UL;
|
||||
std::uint32_t hash = 0x811C9DC5UL;
|
||||
#endif
|
||||
hash += salt;
|
||||
for(;n--;++s)
|
||||
hash = (*s ^ hash) * prime;
|
||||
return hash;
|
||||
}
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
43
install/boost_1_75_0/include/boost/json/detail/except.hpp
Normal file
43
install/boost_1_75_0/include/boost/json/detail/except.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_EXCEPT_HPP
|
||||
#define BOOST_JSON_DETAIL_EXCEPT_HPP
|
||||
|
||||
#include <boost/json/error.hpp>
|
||||
|
||||
#ifndef BOOST_JSON_STANDALONE
|
||||
#include <boost/version.hpp>
|
||||
#if BOOST_VERSION >= 107300
|
||||
# include <boost/assert/source_location.hpp>
|
||||
#endif
|
||||
#include <boost/exception/diagnostic_information.hpp>
|
||||
#endif
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
// VFALCO we are supporting Boost 1.67 because it is in a lot of distros
|
||||
#if ! defined(BOOST_JSON_STANDALONE) && defined(BOOST_CURRENT_LOCATION)
|
||||
using source_location = boost::source_location;
|
||||
#else
|
||||
# define BOOST_CURRENT_LOCATION {}
|
||||
struct source_location{};
|
||||
#endif
|
||||
|
||||
BOOST_JSON_DECL void BOOST_NORETURN throw_bad_alloc(source_location const& loc);
|
||||
BOOST_JSON_DECL void BOOST_NORETURN throw_invalid_argument(char const* what, source_location const& loc);
|
||||
BOOST_JSON_DECL void BOOST_NORETURN throw_length_error(char const* what, source_location const& loc);
|
||||
BOOST_JSON_DECL void BOOST_NORETURN throw_out_of_range(source_location const& loc);
|
||||
BOOST_JSON_DECL void BOOST_NORETURN throw_system_error(error_code const& ec, source_location const& loc);
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
42
install/boost_1_75_0/include/boost/json/detail/format.hpp
Normal file
42
install/boost_1_75_0/include/boost/json/detail/format.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_FORMAT_HPP
|
||||
#define BOOST_JSON_DETAIL_FORMAT_HPP
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
int constexpr max_number_chars =
|
||||
1 + // '-'
|
||||
19 + // unsigned 64-bit mantissa
|
||||
1 + // 'e'
|
||||
1 + // '-'
|
||||
5; // unsigned 16-bit exponent
|
||||
|
||||
BOOST_JSON_DECL
|
||||
unsigned
|
||||
format_uint64(
|
||||
char* dest,
|
||||
std::uint64_t value) noexcept;
|
||||
|
||||
BOOST_JSON_DECL
|
||||
unsigned
|
||||
format_int64(
|
||||
char* dest, int64_t i) noexcept;
|
||||
|
||||
BOOST_JSON_DECL
|
||||
unsigned
|
||||
format_double(
|
||||
char* dest, double d) noexcept;
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
66
install/boost_1_75_0/include/boost/json/detail/handler.hpp
Normal file
66
install/boost_1_75_0/include/boost/json/detail/handler.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_HANDLER_HPP
|
||||
#define BOOST_JSON_DETAIL_HANDLER_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/string_view.hpp>
|
||||
#include <boost/json/array.hpp>
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/string.hpp>
|
||||
#include <boost/json/value_stack.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
struct handler
|
||||
{
|
||||
static constexpr std::size_t
|
||||
max_object_size = object::max_size();
|
||||
|
||||
static constexpr std::size_t
|
||||
max_array_size = array::max_size();
|
||||
|
||||
static constexpr std::size_t
|
||||
max_key_size = string::max_size();
|
||||
|
||||
static constexpr std::size_t
|
||||
max_string_size = string::max_size();
|
||||
|
||||
value_stack st;
|
||||
|
||||
template<class... Args>
|
||||
explicit
|
||||
handler(Args&&... args);
|
||||
|
||||
inline bool on_document_begin(error_code& ec);
|
||||
inline bool on_document_end(error_code& ec);
|
||||
inline bool on_object_begin(error_code& ec);
|
||||
inline bool on_object_end(std::size_t n, error_code& ec);
|
||||
inline bool on_array_begin(error_code& ec);
|
||||
inline bool on_array_end(std::size_t n, error_code& ec);
|
||||
inline bool on_key_part(string_view s, std::size_t n, error_code& ec);
|
||||
inline bool on_key(string_view s, std::size_t n, error_code& ec);
|
||||
inline bool on_string_part(string_view s, std::size_t n, error_code& ec);
|
||||
inline bool on_string(string_view s, std::size_t n, error_code& ec);
|
||||
inline bool on_number_part(string_view, error_code&);
|
||||
inline bool on_int64(std::int64_t i, string_view, error_code& ec);
|
||||
inline bool on_uint64(std::uint64_t u, string_view, error_code& ec);
|
||||
inline bool on_double(double d, string_view, error_code& ec);
|
||||
inline bool on_bool(bool b, error_code& ec);
|
||||
inline bool on_null(error_code& ec);
|
||||
inline bool on_comment_part(string_view, error_code&);
|
||||
inline bool on_comment(string_view, error_code&);
|
||||
};
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,41 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_IMPL_ARRAY_HPP
|
||||
#define BOOST_JSON_DETAIL_IMPL_ARRAY_HPP
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
unchecked_array::
|
||||
~unchecked_array()
|
||||
{
|
||||
if(! data_ ||
|
||||
sp_.is_not_shared_and_deallocate_is_trivial())
|
||||
return;
|
||||
for(unsigned long i = 0;
|
||||
i < size_; ++i)
|
||||
data_[i].~value();
|
||||
}
|
||||
|
||||
void
|
||||
unchecked_array::
|
||||
relocate(value* dest) noexcept
|
||||
{
|
||||
if(size_ > 0)
|
||||
std::memcpy(
|
||||
static_cast<void*>(dest),
|
||||
data_, size_ * sizeof(value));
|
||||
data_ = nullptr;
|
||||
}
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_IMPL_DEFAULT_RESOURCE_IPP
|
||||
#define BOOST_JSON_DETAIL_IMPL_DEFAULT_RESOURCE_IPP
|
||||
|
||||
#include <boost/json/detail/default_resource.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
#ifndef BOOST_JSON_WEAK_CONSTINIT
|
||||
# ifndef BOOST_JSON_NO_DESTROY
|
||||
BOOST_JSON_REQUIRE_CONST_INIT
|
||||
default_resource::holder
|
||||
default_resource::instance_;
|
||||
# else
|
||||
BOOST_JSON_REQUIRE_CONST_INIT
|
||||
default_resource
|
||||
default_resource::instance_;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// this is here so that ~memory_resource
|
||||
// is emitted in the library instead of
|
||||
// the user's TU.
|
||||
default_resource::
|
||||
~default_resource() = default;
|
||||
|
||||
void*
|
||||
default_resource::
|
||||
do_allocate(
|
||||
std::size_t n,
|
||||
std::size_t)
|
||||
{
|
||||
return ::operator new(n);
|
||||
}
|
||||
|
||||
void
|
||||
default_resource::
|
||||
do_deallocate(
|
||||
void* p,
|
||||
std::size_t,
|
||||
std::size_t)
|
||||
{
|
||||
::operator delete(p);
|
||||
}
|
||||
|
||||
bool
|
||||
default_resource::
|
||||
do_is_equal(
|
||||
memory_resource const& mr) const noexcept
|
||||
{
|
||||
return this == &mr;
|
||||
}
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
126
install/boost_1_75_0/include/boost/json/detail/impl/except.ipp
Normal file
126
install/boost_1_75_0/include/boost/json/detail/impl/except.ipp
Normal file
@@ -0,0 +1,126 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_IMPL_EXCEPT_IPP
|
||||
#define BOOST_JSON_DETAIL_IMPL_EXCEPT_IPP
|
||||
|
||||
#include <boost/json/detail/except.hpp>
|
||||
#ifndef BOOST_JSON_STANDALONE
|
||||
# include <boost/version.hpp>
|
||||
# include <boost/throw_exception.hpp>
|
||||
#elif defined(BOOST_JSON_STANDALONE) && defined(BOOST_NO_EXCEPTIONS)
|
||||
# include <exception>
|
||||
#endif
|
||||
#include <stdexcept>
|
||||
|
||||
#if defined(BOOST_JSON_STANDALONE)
|
||||
namespace boost {
|
||||
|
||||
#if defined(BOOST_NO_EXCEPTIONS)
|
||||
// When exceptions are disabled
|
||||
// in standalone, you must provide
|
||||
// this function.
|
||||
BOOST_NORETURN
|
||||
void
|
||||
throw_exception(std::exception const&);
|
||||
#endif
|
||||
|
||||
} // boost
|
||||
#endif
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
namespace detail {
|
||||
|
||||
#if defined(BOOST_JSON_STANDALONE) && \
|
||||
! defined(BOOST_NO_EXCEPTIONS)
|
||||
// this is in the json namespace to avoid
|
||||
// colliding with boost::throw_exception
|
||||
template<class E>
|
||||
void
|
||||
BOOST_NORETURN
|
||||
throw_exception(E e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
throw_bad_alloc(
|
||||
source_location const& loc)
|
||||
{
|
||||
(void)loc;
|
||||
throw_exception(
|
||||
std::bad_alloc()
|
||||
#if BOOST_VERSION >= 107300
|
||||
, loc
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
throw_length_error(
|
||||
char const* what,
|
||||
source_location const& loc)
|
||||
{
|
||||
(void)loc;
|
||||
throw_exception(
|
||||
std::length_error(what)
|
||||
#if BOOST_VERSION >= 107300
|
||||
, loc
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
throw_invalid_argument(
|
||||
char const* what,
|
||||
source_location const& loc)
|
||||
{
|
||||
(void)loc;
|
||||
throw_exception(
|
||||
std::invalid_argument(what)
|
||||
#if BOOST_VERSION >= 107300
|
||||
, loc
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
throw_out_of_range(
|
||||
source_location const& loc)
|
||||
{
|
||||
(void)loc;
|
||||
throw_exception(
|
||||
std::out_of_range(
|
||||
"out of range")
|
||||
#if BOOST_VERSION >= 107300
|
||||
, loc
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
throw_system_error(
|
||||
error_code const& ec,
|
||||
source_location const& loc)
|
||||
{
|
||||
(void)loc;
|
||||
throw_exception(
|
||||
system_error(ec)
|
||||
#if BOOST_VERSION >= 107300
|
||||
, loc
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
123
install/boost_1_75_0/include/boost/json/detail/impl/format.ipp
Normal file
123
install/boost_1_75_0/include/boost/json/detail/impl/format.ipp
Normal file
@@ -0,0 +1,123 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
|
||||
// Copyright (c) 2020 Peter Dimov (pdimov at gmail dot 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_IMPL_FORMAT_IPP
|
||||
#define BOOST_JSON_DETAIL_IMPL_FORMAT_IPP
|
||||
|
||||
#include <boost/json/detail/ryu/ryu.hpp>
|
||||
#include <cstring>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
/* Reference work:
|
||||
|
||||
https://www.ampl.com/netlib/fp/dtoa.c
|
||||
https://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
|
||||
https://kkimdev.github.io/posts/2018/06/15/IEEE-754-Floating-Point-Type-in-C++.html
|
||||
*/
|
||||
|
||||
inline char const* digits_lut() noexcept
|
||||
{
|
||||
return
|
||||
"00010203040506070809"
|
||||
"10111213141516171819"
|
||||
"20212223242526272829"
|
||||
"30313233343536373839"
|
||||
"40414243444546474849"
|
||||
"50515253545556575859"
|
||||
"60616263646566676869"
|
||||
"70717273747576777879"
|
||||
"80818283848586878889"
|
||||
"90919293949596979899";
|
||||
}
|
||||
|
||||
inline void format_four_digits( char * dest, unsigned v )
|
||||
{
|
||||
std::memcpy( dest + 2, digits_lut() + (v % 100) * 2, 2 );
|
||||
std::memcpy( dest , digits_lut() + (v / 100) * 2, 2 );
|
||||
}
|
||||
|
||||
inline void format_two_digits( char * dest, unsigned v )
|
||||
{
|
||||
std::memcpy( dest, digits_lut() + v * 2, 2 );
|
||||
}
|
||||
|
||||
inline void format_digit( char * dest, unsigned v )
|
||||
{
|
||||
*dest = static_cast<char>( v + '0' );
|
||||
}
|
||||
|
||||
unsigned
|
||||
format_uint64(
|
||||
char* dest,
|
||||
std::uint64_t v) noexcept
|
||||
{
|
||||
if(v < 10)
|
||||
{
|
||||
*dest = static_cast<char>( '0' + v );
|
||||
return 1;
|
||||
}
|
||||
|
||||
char buffer[ 24 ];
|
||||
|
||||
char * p = buffer + 24;
|
||||
|
||||
while( v >= 1000 )
|
||||
{
|
||||
p -= 4;
|
||||
format_four_digits( p, v % 10000 );
|
||||
v /= 10000;
|
||||
}
|
||||
|
||||
if( v >= 10 )
|
||||
{
|
||||
p -= 2;
|
||||
format_two_digits( p, v % 100 );
|
||||
v /= 100;
|
||||
}
|
||||
|
||||
if( v )
|
||||
{
|
||||
p -= 1;
|
||||
format_digit( p, static_cast<unsigned>(v) );
|
||||
}
|
||||
|
||||
unsigned const n = static_cast<unsigned>( buffer + 24 - p );
|
||||
std::memcpy( dest, p, n );
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
unsigned
|
||||
format_int64(
|
||||
char* dest, int64_t i) noexcept
|
||||
{
|
||||
std::uint64_t ui = static_cast<
|
||||
std::uint64_t>(i);
|
||||
if(i >= 0)
|
||||
return format_uint64(dest, ui);
|
||||
*dest++ = '-';
|
||||
ui = ~ui + 1;
|
||||
return 1 + format_uint64(dest, ui);
|
||||
}
|
||||
|
||||
unsigned
|
||||
format_double(
|
||||
char* dest, double d) noexcept
|
||||
{
|
||||
return static_cast<int>(
|
||||
ryu::d2s_buffered_n(d, dest));
|
||||
}
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
202
install/boost_1_75_0/include/boost/json/detail/impl/handler.ipp
Normal file
202
install/boost_1_75_0/include/boost/json/detail/impl/handler.ipp
Normal file
@@ -0,0 +1,202 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_IMPL_HANDLER_HPP
|
||||
#define BOOST_JSON_DETAIL_IMPL_HANDLER_HPP
|
||||
|
||||
#include <boost/json/detail/handler.hpp>
|
||||
#include <utility>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
template<class... Args>
|
||||
handler::
|
||||
handler(Args&&... args)
|
||||
: st(std::forward<Args>(args)...)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
handler::
|
||||
on_document_begin(
|
||||
error_code&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
handler::
|
||||
on_document_end(
|
||||
error_code&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
handler::
|
||||
on_object_begin(
|
||||
error_code&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
handler::
|
||||
on_object_end(
|
||||
std::size_t n,
|
||||
error_code&)
|
||||
{
|
||||
st.push_object(n);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
handler::
|
||||
on_array_begin(
|
||||
error_code&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
handler::
|
||||
on_array_end(
|
||||
std::size_t n,
|
||||
error_code&)
|
||||
{
|
||||
st.push_array(n);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
handler::
|
||||
on_key_part(
|
||||
string_view s,
|
||||
std::size_t,
|
||||
error_code&)
|
||||
{
|
||||
st.push_chars(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
handler::
|
||||
on_key(
|
||||
string_view s,
|
||||
std::size_t,
|
||||
error_code&)
|
||||
{
|
||||
st.push_key(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
handler::
|
||||
on_string_part(
|
||||
string_view s,
|
||||
std::size_t,
|
||||
error_code&)
|
||||
{
|
||||
st.push_chars(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
handler::
|
||||
on_string(
|
||||
string_view s,
|
||||
std::size_t,
|
||||
error_code&)
|
||||
{
|
||||
st.push_string(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
handler::
|
||||
on_number_part(
|
||||
string_view,
|
||||
error_code&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
handler::
|
||||
on_int64(
|
||||
std::int64_t i,
|
||||
string_view,
|
||||
error_code&)
|
||||
{
|
||||
st.push_int64(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
handler::
|
||||
on_uint64(
|
||||
std::uint64_t u,
|
||||
string_view,
|
||||
error_code&)
|
||||
{
|
||||
st.push_uint64(u);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
handler::
|
||||
on_double(
|
||||
double d,
|
||||
string_view,
|
||||
error_code&)
|
||||
{
|
||||
st.push_double(d);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
handler::
|
||||
on_bool(
|
||||
bool b,
|
||||
error_code&)
|
||||
{
|
||||
st.push_bool(b);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
handler::
|
||||
on_null(error_code&)
|
||||
{
|
||||
st.push_null();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
handler::
|
||||
on_comment_part(
|
||||
string_view,
|
||||
error_code&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
handler::
|
||||
on_comment(
|
||||
string_view, error_code&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_IMPL_SHARED_RESOURCE_IPP
|
||||
#define BOOST_JSON_DETAIL_IMPL_SHARED_RESOURCE_IPP
|
||||
|
||||
#include <boost/json/detail/shared_resource.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
// these are here so that ~memory_resource
|
||||
// is emitted in the library instead of
|
||||
// the user's TU.
|
||||
|
||||
shared_resource::
|
||||
shared_resource()
|
||||
{
|
||||
}
|
||||
|
||||
shared_resource::
|
||||
~shared_resource()
|
||||
{
|
||||
}
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_IMPL_STACK_IPP
|
||||
#define BOOST_JSON_DETAIL_IMPL_STACK_IPP
|
||||
|
||||
#include <boost/json/detail/stack.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
stack::
|
||||
~stack()
|
||||
{
|
||||
if(buf_)
|
||||
sp_->deallocate(
|
||||
buf_, cap_);
|
||||
}
|
||||
|
||||
void
|
||||
stack::
|
||||
reserve(std::size_t n)
|
||||
{
|
||||
if(cap_ >= n)
|
||||
return;
|
||||
auto const buf = static_cast<
|
||||
char*>(sp_->allocate(n));
|
||||
if(buf_)
|
||||
{
|
||||
if(size_ > 0)
|
||||
std::memcpy(buf, buf_, size_);
|
||||
sp_->deallocate(buf_, cap_);
|
||||
}
|
||||
buf_ = buf;
|
||||
cap_ = n;
|
||||
}
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,471 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
|
||||
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_IMPL_STRING_IMPL_IPP
|
||||
#define BOOST_JSON_DETAIL_IMPL_STRING_IMPL_IPP
|
||||
|
||||
#include <boost/json/detail/string_impl.hpp>
|
||||
#include <boost/json/detail/except.hpp>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
inline
|
||||
bool
|
||||
ptr_in_range(
|
||||
const char* first,
|
||||
const char* last,
|
||||
const char* ptr) noexcept
|
||||
{
|
||||
return std::less<const char*>()(ptr, last) &&
|
||||
std::greater_equal<const char*>()(ptr, first);
|
||||
}
|
||||
|
||||
string_impl::
|
||||
string_impl() noexcept
|
||||
{
|
||||
s_.k = short_string_;
|
||||
s_.buf[sbo_chars_] =
|
||||
static_cast<char>(
|
||||
sbo_chars_);
|
||||
s_.buf[0] = 0;
|
||||
}
|
||||
|
||||
string_impl::
|
||||
string_impl(
|
||||
std::size_t size,
|
||||
storage_ptr const& sp)
|
||||
{
|
||||
if(size <= sbo_chars_)
|
||||
{
|
||||
s_.k = short_string_;
|
||||
s_.buf[sbo_chars_] =
|
||||
static_cast<char>(
|
||||
sbo_chars_ - size);
|
||||
s_.buf[size] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
s_.k = kind::string;
|
||||
auto const n = growth(
|
||||
size, sbo_chars_ + 1);
|
||||
p_.t = ::new(sp->allocate(
|
||||
sizeof(table) +
|
||||
n + 1,
|
||||
alignof(table))) table{
|
||||
static_cast<
|
||||
std::uint32_t>(size),
|
||||
static_cast<
|
||||
std::uint32_t>(n)};
|
||||
data()[n] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// construct a key, unchecked
|
||||
string_impl::
|
||||
string_impl(
|
||||
key_t,
|
||||
string_view s,
|
||||
storage_ptr const& sp)
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
s.size() <= max_size());
|
||||
k_.k = key_string_;
|
||||
k_.n = static_cast<
|
||||
std::uint32_t>(s.size());
|
||||
k_.s = reinterpret_cast<char*>(
|
||||
sp->allocate(s.size() + 1,
|
||||
alignof(char)));
|
||||
k_.s[s.size()] = 0; // null term
|
||||
std::memcpy(&k_.s[0],
|
||||
s.data(), s.size());
|
||||
}
|
||||
|
||||
// construct a key, unchecked
|
||||
string_impl::
|
||||
string_impl(
|
||||
key_t,
|
||||
string_view s1,
|
||||
string_view s2,
|
||||
storage_ptr const& sp)
|
||||
{
|
||||
auto len = s1.size() + s2.size();
|
||||
BOOST_ASSERT(len <= max_size());
|
||||
k_.k = key_string_;
|
||||
k_.n = static_cast<
|
||||
std::uint32_t>(len);
|
||||
k_.s = reinterpret_cast<char*>(
|
||||
sp->allocate(len + 1,
|
||||
alignof(char)));
|
||||
k_.s[len] = 0; // null term
|
||||
std::memcpy(&k_.s[0],
|
||||
s1.data(), s1.size());
|
||||
std::memcpy(&k_.s[s1.size()],
|
||||
s2.data(), s2.size());
|
||||
}
|
||||
|
||||
std::uint32_t
|
||||
string_impl::
|
||||
growth(
|
||||
std::size_t new_size,
|
||||
std::size_t capacity)
|
||||
{
|
||||
if(new_size > max_size())
|
||||
detail::throw_length_error(
|
||||
"string too large",
|
||||
BOOST_CURRENT_LOCATION);
|
||||
// growth factor 2
|
||||
if( capacity >
|
||||
max_size() - capacity)
|
||||
return static_cast<
|
||||
std::uint32_t>(max_size()); // overflow
|
||||
return static_cast<std::uint32_t>(
|
||||
(std::max)(capacity * 2, new_size));
|
||||
}
|
||||
|
||||
char*
|
||||
string_impl::
|
||||
assign(
|
||||
std::size_t new_size,
|
||||
storage_ptr const& sp)
|
||||
{
|
||||
if(new_size > capacity())
|
||||
{
|
||||
string_impl tmp(growth(
|
||||
new_size,
|
||||
capacity()), sp);
|
||||
destroy(sp);
|
||||
*this = tmp;
|
||||
}
|
||||
term(new_size);
|
||||
return data();
|
||||
}
|
||||
|
||||
char*
|
||||
string_impl::
|
||||
append(
|
||||
std::size_t n,
|
||||
storage_ptr const& sp)
|
||||
{
|
||||
if(n > max_size() - size())
|
||||
detail::throw_length_error(
|
||||
"string too large",
|
||||
BOOST_CURRENT_LOCATION);
|
||||
if(n <= capacity() - size())
|
||||
{
|
||||
term(size() + n);
|
||||
return end() - n;
|
||||
}
|
||||
string_impl tmp(growth(
|
||||
size() + n, capacity()), sp);
|
||||
std::memcpy(
|
||||
tmp.data(), data(), size());
|
||||
tmp.term(size() + n);
|
||||
destroy(sp);
|
||||
*this = tmp;
|
||||
return end() - n;
|
||||
}
|
||||
|
||||
void
|
||||
string_impl::
|
||||
insert(
|
||||
std::size_t pos,
|
||||
const char* s,
|
||||
std::size_t n,
|
||||
storage_ptr const& sp)
|
||||
{
|
||||
const auto curr_size = size();
|
||||
if(pos > curr_size)
|
||||
detail::throw_out_of_range(
|
||||
BOOST_CURRENT_LOCATION);
|
||||
const auto curr_data = data();
|
||||
if(n <= capacity() - curr_size)
|
||||
{
|
||||
const bool inside = detail::ptr_in_range(curr_data, curr_data + curr_size, s);
|
||||
if (!inside || (inside && ((s - curr_data) + n <= pos)))
|
||||
{
|
||||
std::memmove(&curr_data[pos + n], &curr_data[pos], curr_size - pos + 1);
|
||||
std::memcpy(&curr_data[pos], s, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::size_t offset = s - curr_data;
|
||||
std::memmove(&curr_data[pos + n], &curr_data[pos], curr_size - pos + 1);
|
||||
if (offset < pos)
|
||||
{
|
||||
const std::size_t diff = pos - offset;
|
||||
std::memcpy(&curr_data[pos], &curr_data[offset], diff);
|
||||
std::memcpy(&curr_data[pos + diff], &curr_data[pos + n], n - diff);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::memcpy(&curr_data[pos], &curr_data[offset + n], n);
|
||||
}
|
||||
}
|
||||
size(curr_size + n);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(n > max_size() - curr_size)
|
||||
detail::throw_length_error(
|
||||
"string too large",
|
||||
BOOST_CURRENT_LOCATION);
|
||||
string_impl tmp(growth(
|
||||
curr_size + n, capacity()), sp);
|
||||
tmp.size(curr_size + n);
|
||||
std::memcpy(
|
||||
tmp.data(),
|
||||
curr_data,
|
||||
pos);
|
||||
std::memcpy(
|
||||
tmp.data() + pos + n,
|
||||
curr_data + pos,
|
||||
curr_size + 1 - pos);
|
||||
std::memcpy(
|
||||
tmp.data() + pos,
|
||||
s,
|
||||
n);
|
||||
destroy(sp);
|
||||
*this = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
char*
|
||||
string_impl::
|
||||
insert_unchecked(
|
||||
std::size_t pos,
|
||||
std::size_t n,
|
||||
storage_ptr const& sp)
|
||||
{
|
||||
const auto curr_size = size();
|
||||
if(pos > curr_size)
|
||||
detail::throw_out_of_range(
|
||||
BOOST_CURRENT_LOCATION);
|
||||
const auto curr_data = data();
|
||||
if(n <= capacity() - size())
|
||||
{
|
||||
auto const dest =
|
||||
curr_data + pos;
|
||||
std::memmove(
|
||||
dest + n,
|
||||
dest,
|
||||
curr_size + 1 - pos);
|
||||
size(curr_size + n);
|
||||
return dest;
|
||||
}
|
||||
if(n > max_size() - curr_size)
|
||||
detail::throw_length_error(
|
||||
"string too large",
|
||||
BOOST_CURRENT_LOCATION);
|
||||
string_impl tmp(growth(
|
||||
curr_size + n, capacity()), sp);
|
||||
tmp.size(curr_size + n);
|
||||
std::memcpy(
|
||||
tmp.data(),
|
||||
curr_data,
|
||||
pos);
|
||||
std::memcpy(
|
||||
tmp.data() + pos + n,
|
||||
curr_data + pos,
|
||||
curr_size + 1 - pos);
|
||||
destroy(sp);
|
||||
*this = tmp;
|
||||
return data() + pos;
|
||||
}
|
||||
|
||||
void
|
||||
string_impl::
|
||||
replace(
|
||||
std::size_t pos,
|
||||
std::size_t n1,
|
||||
const char* s,
|
||||
std::size_t n2,
|
||||
storage_ptr const& sp)
|
||||
{
|
||||
const auto curr_size = size();
|
||||
if (pos > curr_size)
|
||||
detail::throw_out_of_range(
|
||||
BOOST_CURRENT_LOCATION);
|
||||
const auto curr_data = data();
|
||||
n1 = (std::min)(n1, curr_size - pos);
|
||||
const auto delta = (std::max)(n1, n2) -
|
||||
(std::min)(n1, n2);
|
||||
// if we are shrinking in size or we have enough
|
||||
// capacity, dont reallocate
|
||||
if (n1 > n2 || delta <= capacity() - curr_size)
|
||||
{
|
||||
const bool inside = detail::ptr_in_range(curr_data, curr_data + curr_size, s);
|
||||
// there is nothing to replace; return
|
||||
if (inside && s == curr_data + pos && n1 == n2)
|
||||
return;
|
||||
if (!inside || (inside && ((s - curr_data) + n2 <= pos)))
|
||||
{
|
||||
// source outside
|
||||
std::memmove(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1);
|
||||
std::memcpy(&curr_data[pos], s, n2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// source inside
|
||||
const std::size_t offset = s - curr_data;
|
||||
if (n2 >= n1)
|
||||
{
|
||||
// grow/unchanged
|
||||
const std::size_t diff = offset <= pos + n1 ? (std::min)((pos + n1) - offset, n2) : 0;
|
||||
// shift all right of splice point by n2 - n1 to the right
|
||||
std::memmove(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1);
|
||||
// copy all before splice point
|
||||
std::memmove(&curr_data[pos], &curr_data[offset], diff);
|
||||
// copy all after splice point
|
||||
std::memmove(&curr_data[pos + diff], &curr_data[(offset - n1) + n2 + diff], n2 - diff);
|
||||
}
|
||||
else
|
||||
{
|
||||
// shrink
|
||||
// copy all elements into place
|
||||
std::memmove(&curr_data[pos], &curr_data[offset], n2);
|
||||
// shift all elements after splice point left
|
||||
std::memmove(&curr_data[pos + n2], &curr_data[pos + n1], curr_size - pos - n1 + 1);
|
||||
}
|
||||
}
|
||||
size((curr_size - n1) + n2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (delta > max_size() - curr_size)
|
||||
detail::throw_length_error(
|
||||
"string too large",
|
||||
BOOST_CURRENT_LOCATION);
|
||||
// would exceed capacity, reallocate
|
||||
string_impl tmp(growth(
|
||||
curr_size + delta, capacity()), sp);
|
||||
tmp.size(curr_size + delta);
|
||||
std::memcpy(
|
||||
tmp.data(),
|
||||
curr_data,
|
||||
pos);
|
||||
std::memcpy(
|
||||
tmp.data() + pos + n2,
|
||||
curr_data + pos + n1,
|
||||
curr_size - pos - n1 + 1);
|
||||
std::memcpy(
|
||||
tmp.data() + pos,
|
||||
s,
|
||||
n2);
|
||||
destroy(sp);
|
||||
*this = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
// unlike the replace overload, this function does
|
||||
// not move any characters
|
||||
char*
|
||||
string_impl::
|
||||
replace_unchecked(
|
||||
std::size_t pos,
|
||||
std::size_t n1,
|
||||
std::size_t n2,
|
||||
storage_ptr const& sp)
|
||||
{
|
||||
const auto curr_size = size();
|
||||
if(pos > curr_size)
|
||||
detail::throw_out_of_range(
|
||||
BOOST_CURRENT_LOCATION);
|
||||
const auto curr_data = data();
|
||||
const auto delta = (std::max)(n1, n2) -
|
||||
(std::min)(n1, n2);
|
||||
// if the size doesn't change, we don't need to
|
||||
// do anything
|
||||
if (!delta)
|
||||
return curr_data + pos;
|
||||
// if we are shrinking in size or we have enough
|
||||
// capacity, dont reallocate
|
||||
if(n1 > n2 || delta <= capacity() - curr_size)
|
||||
{
|
||||
auto const replace_pos = curr_data + pos;
|
||||
std::memmove(
|
||||
replace_pos + n2,
|
||||
replace_pos + n1,
|
||||
curr_size - pos - n1 + 1);
|
||||
size((curr_size - n1) + n2);
|
||||
return replace_pos;
|
||||
}
|
||||
if(delta > max_size() - curr_size)
|
||||
detail::throw_length_error(
|
||||
"string too large",
|
||||
BOOST_CURRENT_LOCATION);
|
||||
// would exceed capacity, reallocate
|
||||
string_impl tmp(growth(
|
||||
curr_size + delta, capacity()), sp);
|
||||
tmp.size(curr_size + delta);
|
||||
std::memcpy(
|
||||
tmp.data(),
|
||||
curr_data,
|
||||
pos);
|
||||
std::memcpy(
|
||||
tmp.data() + pos + n2,
|
||||
curr_data + pos + n1,
|
||||
curr_size - pos - n1 + 1);
|
||||
destroy(sp);
|
||||
*this = tmp;
|
||||
return data() + pos;
|
||||
}
|
||||
|
||||
void
|
||||
string_impl::
|
||||
shrink_to_fit(
|
||||
storage_ptr const& sp) noexcept
|
||||
{
|
||||
if(s_.k == short_string_)
|
||||
return;
|
||||
auto const t = p_.t;
|
||||
if(t->size <= sbo_chars_)
|
||||
{
|
||||
s_.k = short_string_;
|
||||
std::memcpy(
|
||||
s_.buf, data(), t->size);
|
||||
s_.buf[sbo_chars_] =
|
||||
static_cast<char>(
|
||||
sbo_chars_ - t->size);
|
||||
s_.buf[t->size] = 0;
|
||||
sp->deallocate(t,
|
||||
sizeof(table) +
|
||||
t->capacity + 1,
|
||||
alignof(table));
|
||||
return;
|
||||
}
|
||||
if(t->size >= t->capacity)
|
||||
return;
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif
|
||||
string_impl tmp(t->size, sp);
|
||||
std::memcpy(
|
||||
tmp.data(),
|
||||
data(),
|
||||
size());
|
||||
destroy(sp);
|
||||
*this = tmp;
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
}
|
||||
catch(std::exception const&)
|
||||
{
|
||||
// eat the exception
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
79
install/boost_1_75_0/include/boost/json/detail/object.hpp
Normal file
79
install/boost_1_75_0/include/boost/json/detail/object.hpp
Normal file
@@ -0,0 +1,79 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_OBJECT_HPP
|
||||
#define BOOST_JSON_DETAIL_OBJECT_HPP
|
||||
|
||||
#include <boost/json/storage_ptr.hpp>
|
||||
#include <cstdlib>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
class value;
|
||||
class key_value_pair;
|
||||
|
||||
namespace detail {
|
||||
|
||||
class unchecked_object
|
||||
{
|
||||
// each element is two values,
|
||||
// first one is a string key,
|
||||
// second one is the value.
|
||||
value* data_;
|
||||
std::size_t size_;
|
||||
storage_ptr const& sp_;
|
||||
|
||||
public:
|
||||
inline
|
||||
~unchecked_object();
|
||||
|
||||
unchecked_object(
|
||||
value* data,
|
||||
std::size_t size, // # of kv-pairs
|
||||
storage_ptr const& sp) noexcept
|
||||
: data_(data)
|
||||
, size_(size)
|
||||
, sp_(sp)
|
||||
{
|
||||
}
|
||||
|
||||
unchecked_object(
|
||||
unchecked_object&& other) noexcept
|
||||
: data_(other.data_)
|
||||
, size_(other.size_)
|
||||
, sp_(other.sp_)
|
||||
{
|
||||
other.data_ = nullptr;
|
||||
}
|
||||
|
||||
storage_ptr const&
|
||||
storage() const noexcept
|
||||
{
|
||||
return sp_;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
size() const noexcept
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
value*
|
||||
release() noexcept
|
||||
{
|
||||
auto const data = data_;
|
||||
data_ = nullptr;
|
||||
return data;
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,118 @@
|
||||
// Copyright 2018 Ulf Adams
|
||||
//
|
||||
// The contents of this file may be used under the terms of the Apache License,
|
||||
// Version 2.0.
|
||||
//
|
||||
// (See accompanying file LICENSE-Apache or copy at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0)
|
||||
//
|
||||
// Alternatively, the contents of this file may be used under the terms of
|
||||
// the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE-Boost or copy at
|
||||
// https://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, this software
|
||||
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied.
|
||||
|
||||
/*
|
||||
This is a derivative work
|
||||
*/
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_RYU_DETAIL_COMMON_HPP
|
||||
#define BOOST_JSON_DETAIL_RYU_DETAIL_COMMON_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <string.h>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
namespace ryu {
|
||||
namespace detail {
|
||||
|
||||
constexpr int DOUBLE_MANTISSA_BITS = 52;
|
||||
constexpr int DOUBLE_EXPONENT_BITS = 11;
|
||||
constexpr int DOUBLE_BIAS = 1023;
|
||||
|
||||
#if defined(_M_IX86) || defined(_M_ARM)
|
||||
#define BOOST_JSON_RYU_32_BIT_PLATFORM
|
||||
#endif
|
||||
|
||||
inline uint32_t decimalLength9(const uint32_t v) {
|
||||
// Function precondition: v is not a 10-digit number.
|
||||
// (f2s: 9 digits are sufficient for round-tripping.)
|
||||
// (d2fixed: We print 9-digit blocks.)
|
||||
BOOST_ASSERT(v < 1000000000);
|
||||
if (v >= 100000000) { return 9; }
|
||||
if (v >= 10000000) { return 8; }
|
||||
if (v >= 1000000) { return 7; }
|
||||
if (v >= 100000) { return 6; }
|
||||
if (v >= 10000) { return 5; }
|
||||
if (v >= 1000) { return 4; }
|
||||
if (v >= 100) { return 3; }
|
||||
if (v >= 10) { return 2; }
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Returns e == 0 ? 1 : ceil(log_2(5^e)).
|
||||
inline int32_t pow5bits(const int32_t e) {
|
||||
// This approximation works up to the point that the multiplication overflows at e = 3529.
|
||||
// If the multiplication were done in 64 bits, it would fail at 5^4004 which is just greater
|
||||
// than 2^9297.
|
||||
BOOST_ASSERT(e >= 0);
|
||||
BOOST_ASSERT(e <= 3528);
|
||||
return (int32_t) (((((uint32_t) e) * 1217359) >> 19) + 1);
|
||||
}
|
||||
|
||||
// Returns floor(log_10(2^e)).
|
||||
inline uint32_t log10Pow2(const int32_t e) {
|
||||
// The first value this approximation fails for is 2^1651 which is just greater than 10^297.
|
||||
BOOST_ASSERT(e >= 0);
|
||||
BOOST_ASSERT(e <= 1650);
|
||||
return (((uint32_t) e) * 78913) >> 18;
|
||||
}
|
||||
|
||||
// Returns floor(log_10(5^e)).
|
||||
inline uint32_t log10Pow5(const int32_t e) {
|
||||
// The first value this approximation fails for is 5^2621 which is just greater than 10^1832.
|
||||
BOOST_ASSERT(e >= 0);
|
||||
BOOST_ASSERT(e <= 2620);
|
||||
return (((uint32_t) e) * 732923) >> 20;
|
||||
}
|
||||
|
||||
inline int copy_special_str(char * const result, const bool sign, const bool exponent, const bool mantissa) {
|
||||
if (mantissa) {
|
||||
memcpy(result, "NaN", 3);
|
||||
return 3;
|
||||
}
|
||||
if (sign) {
|
||||
result[0] = '-';
|
||||
}
|
||||
if (exponent) {
|
||||
memcpy(result + sign, "Infinity", 8);
|
||||
return sign + 8;
|
||||
}
|
||||
memcpy(result + sign, "0E0", 3);
|
||||
return sign + 3;
|
||||
}
|
||||
|
||||
inline uint32_t float_to_bits(const float f) {
|
||||
uint32_t bits = 0;
|
||||
memcpy(&bits, &f, sizeof(float));
|
||||
return bits;
|
||||
}
|
||||
|
||||
inline uint64_t double_to_bits(const double d) {
|
||||
uint64_t bits = 0;
|
||||
memcpy(&bits, &d, sizeof(double));
|
||||
return bits;
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // ryu
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,262 @@
|
||||
// Copyright 2018 Ulf Adams
|
||||
//
|
||||
// The contents of this file may be used under the terms of the Apache License,
|
||||
// Version 2.0.
|
||||
//
|
||||
// (See accompanying file LICENSE-Apache or copy at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0)
|
||||
//
|
||||
// Alternatively, the contents of this file may be used under the terms of
|
||||
// the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE-Boost or copy at
|
||||
// https://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, this software
|
||||
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied.
|
||||
|
||||
/*
|
||||
This is a derivative work
|
||||
*/
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_RYU_DETAIL_D2S_HPP
|
||||
#define BOOST_JSON_DETAIL_RYU_DETAIL_D2S_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/detail/ryu/detail/common.hpp>
|
||||
|
||||
// Only include the full table if we're not optimizing for size.
|
||||
#if !defined(BOOST_JSON_RYU_OPTIMIZE_SIZE)
|
||||
#include <boost/json/detail/ryu/detail/d2s_full_table.hpp>
|
||||
#endif
|
||||
#if defined(BOOST_JSON_RYU_HAS_UINT128)
|
||||
typedef __uint128_t uint128_t;
|
||||
#else
|
||||
#include <boost/json/detail/ryu/detail/d2s_intrinsics.hpp>
|
||||
#endif
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
namespace ryu {
|
||||
namespace detail {
|
||||
|
||||
constexpr int DOUBLE_POW5_INV_BITCOUNT = 122;
|
||||
constexpr int DOUBLE_POW5_BITCOUNT = 121;
|
||||
|
||||
#if defined(BOOST_JSON_RYU_OPTIMIZE_SIZE)
|
||||
|
||||
constexpr int POW5_TABLE_SIZE = 26;
|
||||
|
||||
inline
|
||||
std::uint64_t const
|
||||
(&DOUBLE_POW5_TABLE() noexcept)[POW5_TABLE_SIZE]
|
||||
{
|
||||
static constexpr std::uint64_t arr[26] = {
|
||||
1ull, 5ull, 25ull, 125ull, 625ull, 3125ull, 15625ull, 78125ull, 390625ull,
|
||||
1953125ull, 9765625ull, 48828125ull, 244140625ull, 1220703125ull, 6103515625ull,
|
||||
30517578125ull, 152587890625ull, 762939453125ull, 3814697265625ull,
|
||||
19073486328125ull, 95367431640625ull, 476837158203125ull,
|
||||
2384185791015625ull, 11920928955078125ull, 59604644775390625ull,
|
||||
298023223876953125ull //, 1490116119384765625ull
|
||||
};
|
||||
return arr;
|
||||
}
|
||||
|
||||
inline
|
||||
std::uint64_t const
|
||||
(&DOUBLE_POW5_SPLIT2() noexcept)[13][2]
|
||||
{
|
||||
static constexpr std::uint64_t arr[13][2] = {
|
||||
{ 0u, 72057594037927936u },
|
||||
{ 10376293541461622784u, 93132257461547851u },
|
||||
{ 15052517733678820785u, 120370621524202240u },
|
||||
{ 6258995034005762182u, 77787690973264271u },
|
||||
{ 14893927168346708332u, 100538234169297439u },
|
||||
{ 4272820386026678563u, 129942622070561240u },
|
||||
{ 7330497575943398595u, 83973451344588609u },
|
||||
{ 18377130505971182927u, 108533142064701048u },
|
||||
{ 10038208235822497557u, 140275798336537794u },
|
||||
{ 7017903361312433648u, 90651109995611182u },
|
||||
{ 6366496589810271835u, 117163813585596168u },
|
||||
{ 9264989777501460624u, 75715339914673581u },
|
||||
{ 17074144231291089770u, 97859783203563123u }};
|
||||
return arr;
|
||||
}
|
||||
|
||||
// Unfortunately, the results are sometimes off by one. We use an additional
|
||||
// lookup table to store those cases and adjust the result.
|
||||
inline
|
||||
std::uint32_t const
|
||||
(&POW5_OFFSETS() noexcept)[13]
|
||||
{
|
||||
static constexpr std::uint32_t arr[13] = {
|
||||
0x00000000, 0x00000000, 0x00000000, 0x033c55be, 0x03db77d8, 0x0265ffb2,
|
||||
0x00000800, 0x01a8ff56, 0x00000000, 0x0037a200, 0x00004000, 0x03fffffc,
|
||||
0x00003ffe};
|
||||
return arr;
|
||||
}
|
||||
|
||||
inline
|
||||
std::uint64_t const
|
||||
(&DOUBLE_POW5_INV_SPLIT2() noexcept)[13][2]
|
||||
{
|
||||
static constexpr std::uint64_t arr[13][2] = {
|
||||
{ 1u, 288230376151711744u },
|
||||
{ 7661987648932456967u, 223007451985306231u },
|
||||
{ 12652048002903177473u, 172543658669764094u },
|
||||
{ 5522544058086115566u, 266998379490113760u },
|
||||
{ 3181575136763469022u, 206579990246952687u },
|
||||
{ 4551508647133041040u, 159833525776178802u },
|
||||
{ 1116074521063664381u, 247330401473104534u },
|
||||
{ 17400360011128145022u, 191362629322552438u },
|
||||
{ 9297997190148906106u, 148059663038321393u },
|
||||
{ 11720143854957885429u, 229111231347799689u },
|
||||
{ 15401709288678291155u, 177266229209635622u },
|
||||
{ 3003071137298187333u, 274306203439684434u },
|
||||
{ 17516772882021341108u, 212234145163966538u }};
|
||||
return arr;
|
||||
}
|
||||
|
||||
inline
|
||||
std::uint32_t const
|
||||
(&POW5_INV_OFFSETS() noexcept)[20]
|
||||
{
|
||||
static constexpr std::uint32_t arr[20] = {
|
||||
0x51505404, 0x55054514, 0x45555545, 0x05511411, 0x00505010, 0x00000004,
|
||||
0x00000000, 0x00000000, 0x55555040, 0x00505051, 0x00050040, 0x55554000,
|
||||
0x51659559, 0x00001000, 0x15000010, 0x55455555, 0x41404051, 0x00001010,
|
||||
0x00000014, 0x00000000};
|
||||
return arr;
|
||||
}
|
||||
|
||||
#if defined(BOOST_JSON_RYU_HAS_UINT128)
|
||||
|
||||
// Computes 5^i in the form required by Ryu, and stores it in the given pointer.
|
||||
inline
|
||||
void
|
||||
double_computePow5(
|
||||
const std::uint32_t i,
|
||||
std::uint64_t* const result)
|
||||
{
|
||||
const std::uint32_t base = i / POW5_TABLE_SIZE;
|
||||
const std::uint32_t base2 = base * POW5_TABLE_SIZE;
|
||||
const std::uint32_t offset = i - base2;
|
||||
const std::uint64_t* const mul = DOUBLE_POW5_SPLIT2()[base];
|
||||
if (offset == 0)
|
||||
{
|
||||
result[0] = mul[0];
|
||||
result[1] = mul[1];
|
||||
return;
|
||||
}
|
||||
const std::uint64_t m = DOUBLE_POW5_TABLE()[offset];
|
||||
const uint128_t b0 = ((uint128_t)m) * mul[0];
|
||||
const uint128_t b2 = ((uint128_t)m) * mul[1];
|
||||
const std::uint32_t delta = pow5bits(i) - pow5bits(base2);
|
||||
const uint128_t shiftedSum = (b0 >> delta) + (b2 << (64 - delta)) + ((POW5_OFFSETS()[base] >> offset) & 1);
|
||||
result[0] = (std::uint64_t)shiftedSum;
|
||||
result[1] = (std::uint64_t)(shiftedSum >> 64);
|
||||
}
|
||||
|
||||
// Computes 5^-i in the form required by Ryu, and stores it in the given pointer.
|
||||
inline
|
||||
void
|
||||
double_computeInvPow5(
|
||||
const std::uint32_t i,
|
||||
std::uint64_t* const result)
|
||||
{
|
||||
const std::uint32_t base = (i + POW5_TABLE_SIZE - 1) / POW5_TABLE_SIZE;
|
||||
const std::uint32_t base2 = base * POW5_TABLE_SIZE;
|
||||
const std::uint32_t offset = base2 - i;
|
||||
const std::uint64_t* const mul = DOUBLE_POW5_INV_SPLIT2()[base]; // 1/5^base2
|
||||
if (offset == 0)
|
||||
{
|
||||
result[0] = mul[0];
|
||||
result[1] = mul[1];
|
||||
return;
|
||||
}
|
||||
const std::uint64_t m = DOUBLE_POW5_TABLE()[offset]; // 5^offset
|
||||
const uint128_t b0 = ((uint128_t)m) * (mul[0] - 1);
|
||||
const uint128_t b2 = ((uint128_t)m) * mul[1]; // 1/5^base2 * 5^offset = 1/5^(base2-offset) = 1/5^i
|
||||
const std::uint32_t delta = pow5bits(base2) - pow5bits(i);
|
||||
const uint128_t shiftedSum =
|
||||
((b0 >> delta) + (b2 << (64 - delta))) + 1 + ((POW5_INV_OFFSETS()[i / 16] >> ((i % 16) << 1)) & 3);
|
||||
result[0] = (std::uint64_t)shiftedSum;
|
||||
result[1] = (std::uint64_t)(shiftedSum >> 64);
|
||||
}
|
||||
|
||||
#else // defined(BOOST_JSON_RYU_HAS_UINT128)
|
||||
|
||||
// Computes 5^i in the form required by Ryu, and stores it in the given pointer.
|
||||
inline
|
||||
void
|
||||
double_computePow5(
|
||||
const std::uint32_t i,
|
||||
std::uint64_t* const result)
|
||||
{
|
||||
const std::uint32_t base = i / POW5_TABLE_SIZE;
|
||||
const std::uint32_t base2 = base * POW5_TABLE_SIZE;
|
||||
const std::uint32_t offset = i - base2;
|
||||
const std::uint64_t* const mul = DOUBLE_POW5_SPLIT2()[base];
|
||||
if (offset == 0)
|
||||
{
|
||||
result[0] = mul[0];
|
||||
result[1] = mul[1];
|
||||
return;
|
||||
}
|
||||
std::uint64_t const m = DOUBLE_POW5_TABLE()[offset];
|
||||
std::uint64_t high1;
|
||||
std::uint64_t const low1 = umul128(m, mul[1], &high1);
|
||||
std::uint64_t high0;
|
||||
std::uint64_t const low0 = umul128(m, mul[0], &high0);
|
||||
std::uint64_t const sum = high0 + low1;
|
||||
if (sum < high0)
|
||||
++high1; // overflow into high1
|
||||
// high1 | sum | low0
|
||||
std::uint32_t const delta = pow5bits(i) - pow5bits(base2);
|
||||
result[0] = shiftright128(low0, sum, delta) + ((POW5_OFFSETS()[base] >> offset) & 1);
|
||||
result[1] = shiftright128(sum, high1, delta);
|
||||
}
|
||||
|
||||
// Computes 5^-i in the form required by Ryu, and stores it in the given pointer.
|
||||
inline
|
||||
void
|
||||
double_computeInvPow5(
|
||||
const std::uint32_t i,
|
||||
std::uint64_t* const result)
|
||||
{
|
||||
const std::uint32_t base = (i + POW5_TABLE_SIZE - 1) / POW5_TABLE_SIZE;
|
||||
const std::uint32_t base2 = base * POW5_TABLE_SIZE;
|
||||
const std::uint32_t offset = base2 - i;
|
||||
const std::uint64_t* const mul = DOUBLE_POW5_INV_SPLIT2()[base]; // 1/5^base2
|
||||
if (offset == 0)
|
||||
{
|
||||
result[0] = mul[0];
|
||||
result[1] = mul[1];
|
||||
return;
|
||||
}
|
||||
std::uint64_t const m = DOUBLE_POW5_TABLE()[offset];
|
||||
std::uint64_t high1;
|
||||
std::uint64_t const low1 = umul128(m, mul[1], &high1);
|
||||
std::uint64_t high0;
|
||||
std::uint64_t const low0 = umul128(m, mul[0] - 1, &high0);
|
||||
std::uint64_t const sum = high0 + low1;
|
||||
if (sum < high0)
|
||||
++high1; // overflow into high1
|
||||
// high1 | sum | low0
|
||||
std::uint32_t const delta = pow5bits(base2) - pow5bits(i);
|
||||
result[0] = shiftright128(low0, sum, delta) + 1 + ((POW5_INV_OFFSETS()[i / 16] >> ((i % 16) << 1)) & 3);
|
||||
result[1] = shiftright128(sum, high1, delta);
|
||||
}
|
||||
|
||||
#endif // defined(BOOST_JSON_RYU_HAS_UINT128)
|
||||
|
||||
#endif // defined(BOOST_JSON_RYU_OPTIMIZE_SIZE)
|
||||
|
||||
} // detail
|
||||
} // ryu
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,363 @@
|
||||
// Copyright 2018 Ulf Adams
|
||||
//
|
||||
// The contents of this file may be used under the terms of the Apache License,
|
||||
// Version 2.0.
|
||||
//
|
||||
// (See accompanying file LICENSE-Apache or copy at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0)
|
||||
//
|
||||
// Alternatively, the contents of this file may be used under the terms of
|
||||
// the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE-Boost or copy at
|
||||
// https://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, this software
|
||||
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied.
|
||||
|
||||
/*
|
||||
This is a derivative work
|
||||
*/
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_RYU_DETAIL_D2S_FULL_TABLE_HPP
|
||||
#define BOOST_JSON_DETAIL_RYU_DETAIL_D2S_FULL_TABLE_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
namespace ryu {
|
||||
|
||||
// These tables are generated by PrintDoubleLookupTable.
|
||||
inline
|
||||
std::uint64_t const
|
||||
(&DOUBLE_POW5_INV_SPLIT() noexcept)[292][2]
|
||||
{
|
||||
static constexpr std::uint64_t arr[292][2] = {
|
||||
{ 1u, 288230376151711744u }, { 3689348814741910324u, 230584300921369395u },
|
||||
{ 2951479051793528259u, 184467440737095516u }, { 17118578500402463900u, 147573952589676412u },
|
||||
{ 12632330341676300947u, 236118324143482260u }, { 10105864273341040758u, 188894659314785808u },
|
||||
{ 15463389048156653253u, 151115727451828646u }, { 17362724847566824558u, 241785163922925834u },
|
||||
{ 17579528692795369969u, 193428131138340667u }, { 6684925324752475329u, 154742504910672534u },
|
||||
{ 18074578149087781173u, 247588007857076054u }, { 18149011334012135262u, 198070406285660843u },
|
||||
{ 3451162622983977240u, 158456325028528675u }, { 5521860196774363583u, 253530120045645880u },
|
||||
{ 4417488157419490867u, 202824096036516704u }, { 7223339340677503017u, 162259276829213363u },
|
||||
{ 7867994130342094503u, 259614842926741381u }, { 2605046489531765280u, 207691874341393105u },
|
||||
{ 2084037191625412224u, 166153499473114484u }, { 10713157136084480204u, 265845599156983174u },
|
||||
{ 12259874523609494487u, 212676479325586539u }, { 13497248433629505913u, 170141183460469231u },
|
||||
{ 14216899864323388813u, 272225893536750770u }, { 11373519891458711051u, 217780714829400616u },
|
||||
{ 5409467098425058518u, 174224571863520493u }, { 4965798542738183305u, 278759314981632789u },
|
||||
{ 7661987648932456967u, 223007451985306231u }, { 2440241304404055250u, 178405961588244985u },
|
||||
{ 3904386087046488400u, 285449538541191976u }, { 17880904128604832013u, 228359630832953580u },
|
||||
{ 14304723302883865611u, 182687704666362864u }, { 15133127457049002812u, 146150163733090291u },
|
||||
{ 16834306301794583852u, 233840261972944466u }, { 9778096226693756759u, 187072209578355573u },
|
||||
{ 15201174610838826053u, 149657767662684458u }, { 2185786488890659746u, 239452428260295134u },
|
||||
{ 5437978005854438120u, 191561942608236107u }, { 15418428848909281466u, 153249554086588885u },
|
||||
{ 6222742084545298729u, 245199286538542217u }, { 16046240111861969953u, 196159429230833773u },
|
||||
{ 1768945645263844993u, 156927543384667019u }, { 10209010661905972635u, 251084069415467230u },
|
||||
{ 8167208529524778108u, 200867255532373784u }, { 10223115638361732810u, 160693804425899027u },
|
||||
{ 1599589762411131202u, 257110087081438444u }, { 4969020624670815285u, 205688069665150755u },
|
||||
{ 3975216499736652228u, 164550455732120604u }, { 13739044029062464211u, 263280729171392966u },
|
||||
{ 7301886408508061046u, 210624583337114373u }, { 13220206756290269483u, 168499666669691498u },
|
||||
{ 17462981995322520850u, 269599466671506397u }, { 6591687966774196033u, 215679573337205118u },
|
||||
{ 12652048002903177473u, 172543658669764094u }, { 9175230360419352987u, 276069853871622551u },
|
||||
{ 3650835473593572067u, 220855883097298041u }, { 17678063637842498946u, 176684706477838432u },
|
||||
{ 13527506561580357021u, 282695530364541492u }, { 3443307619780464970u, 226156424291633194u },
|
||||
{ 6443994910566282300u, 180925139433306555u }, { 5155195928453025840u, 144740111546645244u },
|
||||
{ 15627011115008661990u, 231584178474632390u }, { 12501608892006929592u, 185267342779705912u },
|
||||
{ 2622589484121723027u, 148213874223764730u }, { 4196143174594756843u, 237142198758023568u },
|
||||
{ 10735612169159626121u, 189713759006418854u }, { 12277838550069611220u, 151771007205135083u },
|
||||
{ 15955192865369467629u, 242833611528216133u }, { 1696107848069843133u, 194266889222572907u },
|
||||
{ 12424932722681605476u, 155413511378058325u }, { 1433148282581017146u, 248661618204893321u },
|
||||
{ 15903913885032455010u, 198929294563914656u }, { 9033782293284053685u, 159143435651131725u },
|
||||
{ 14454051669254485895u, 254629497041810760u }, { 11563241335403588716u, 203703597633448608u },
|
||||
{ 16629290697806691620u, 162962878106758886u }, { 781423413297334329u, 260740604970814219u },
|
||||
{ 4314487545379777786u, 208592483976651375u }, { 3451590036303822229u, 166873987181321100u },
|
||||
{ 5522544058086115566u, 266998379490113760u }, { 4418035246468892453u, 213598703592091008u },
|
||||
{ 10913125826658934609u, 170878962873672806u }, { 10082303693170474728u, 273406340597876490u },
|
||||
{ 8065842954536379782u, 218725072478301192u }, { 17520720807854834795u, 174980057982640953u },
|
||||
{ 5897060404116273733u, 279968092772225526u }, { 1028299508551108663u, 223974474217780421u },
|
||||
{ 15580034865808528224u, 179179579374224336u }, { 17549358155809824511u, 286687326998758938u },
|
||||
{ 2971440080422128639u, 229349861599007151u }, { 17134547323305344204u, 183479889279205720u },
|
||||
{ 13707637858644275364u, 146783911423364576u }, { 14553522944347019935u, 234854258277383322u },
|
||||
{ 4264120725993795302u, 187883406621906658u }, { 10789994210278856888u, 150306725297525326u },
|
||||
{ 9885293106962350374u, 240490760476040522u }, { 529536856086059653u, 192392608380832418u },
|
||||
{ 7802327114352668369u, 153914086704665934u }, { 1415676938738538420u, 246262538727465495u },
|
||||
{ 1132541550990830736u, 197010030981972396u }, { 15663428499760305882u, 157608024785577916u },
|
||||
{ 17682787970132668764u, 252172839656924666u }, { 10456881561364224688u, 201738271725539733u },
|
||||
{ 15744202878575200397u, 161390617380431786u }, { 17812026976236499989u, 258224987808690858u },
|
||||
{ 3181575136763469022u, 206579990246952687u }, { 13613306553636506187u, 165263992197562149u },
|
||||
{ 10713244041592678929u, 264422387516099439u }, { 12259944048016053467u, 211537910012879551u },
|
||||
{ 6118606423670932450u, 169230328010303641u }, { 2411072648389671274u, 270768524816485826u },
|
||||
{ 16686253377679378312u, 216614819853188660u }, { 13349002702143502650u, 173291855882550928u },
|
||||
{ 17669055508687693916u, 277266969412081485u }, { 14135244406950155133u, 221813575529665188u },
|
||||
{ 240149081334393137u, 177450860423732151u }, { 11452284974360759988u, 283921376677971441u },
|
||||
{ 5472479164746697667u, 227137101342377153u }, { 11756680961281178780u, 181709681073901722u },
|
||||
{ 2026647139541122378u, 145367744859121378u }, { 18000030682233437097u, 232588391774594204u },
|
||||
{ 18089373360528660001u, 186070713419675363u }, { 3403452244197197031u, 148856570735740291u },
|
||||
{ 16513570034941246220u, 238170513177184465u }, { 13210856027952996976u, 190536410541747572u },
|
||||
{ 3189987192878576934u, 152429128433398058u }, { 1414630693863812771u, 243886605493436893u },
|
||||
{ 8510402184574870864u, 195109284394749514u }, { 10497670562401807014u, 156087427515799611u },
|
||||
{ 9417575270359070576u, 249739884025279378u }, { 14912757845771077107u, 199791907220223502u },
|
||||
{ 4551508647133041040u, 159833525776178802u }, { 10971762650154775986u, 255733641241886083u },
|
||||
{ 16156107749607641435u, 204586912993508866u }, { 9235537384944202825u, 163669530394807093u },
|
||||
{ 11087511001168814197u, 261871248631691349u }, { 12559357615676961681u, 209496998905353079u },
|
||||
{ 13736834907283479668u, 167597599124282463u }, { 18289587036911657145u, 268156158598851941u },
|
||||
{ 10942320814787415393u, 214524926879081553u }, { 16132554281313752961u, 171619941503265242u },
|
||||
{ 11054691591134363444u, 274591906405224388u }, { 16222450902391311402u, 219673525124179510u },
|
||||
{ 12977960721913049122u, 175738820099343608u }, { 17075388340318968271u, 281182112158949773u },
|
||||
{ 2592264228029443648u, 224945689727159819u }, { 5763160197165465241u, 179956551781727855u },
|
||||
{ 9221056315464744386u, 287930482850764568u }, { 14755542681855616155u, 230344386280611654u },
|
||||
{ 15493782960226403247u, 184275509024489323u }, { 1326979923955391628u, 147420407219591459u },
|
||||
{ 9501865507812447252u, 235872651551346334u }, { 11290841220991868125u, 188698121241077067u },
|
||||
{ 1653975347309673853u, 150958496992861654u }, { 10025058185179298811u, 241533595188578646u },
|
||||
{ 4330697733401528726u, 193226876150862917u }, { 14532604630946953951u, 154581500920690333u },
|
||||
{ 1116074521063664381u, 247330401473104534u }, { 4582208431592841828u, 197864321178483627u },
|
||||
{ 14733813189500004432u, 158291456942786901u }, { 16195403473716186445u, 253266331108459042u },
|
||||
{ 5577625149489128510u, 202613064886767234u }, { 8151448934333213131u, 162090451909413787u },
|
||||
{ 16731667109675051333u, 259344723055062059u }, { 17074682502481951390u, 207475778444049647u },
|
||||
{ 6281048372501740465u, 165980622755239718u }, { 6360328581260874421u, 265568996408383549u },
|
||||
{ 8777611679750609860u, 212455197126706839u }, { 10711438158542398211u, 169964157701365471u },
|
||||
{ 9759603424184016492u, 271942652322184754u }, { 11497031554089123517u, 217554121857747803u },
|
||||
{ 16576322872755119460u, 174043297486198242u }, { 11764721337440549842u, 278469275977917188u },
|
||||
{ 16790474699436260520u, 222775420782333750u }, { 13432379759549008416u, 178220336625867000u },
|
||||
{ 3045063541568861850u, 285152538601387201u }, { 17193446092222730773u, 228122030881109760u },
|
||||
{ 13754756873778184618u, 182497624704887808u }, { 18382503128506368341u, 145998099763910246u },
|
||||
{ 3586563302416817083u, 233596959622256395u }, { 2869250641933453667u, 186877567697805116u },
|
||||
{ 17052795772514404226u, 149502054158244092u }, { 12527077977055405469u, 239203286653190548u },
|
||||
{ 17400360011128145022u, 191362629322552438u }, { 2852241564676785048u, 153090103458041951u },
|
||||
{ 15631632947708587046u, 244944165532867121u }, { 8815957543424959314u, 195955332426293697u },
|
||||
{ 18120812478965698421u, 156764265941034957u }, { 14235904707377476180u, 250822825505655932u },
|
||||
{ 4010026136418160298u, 200658260404524746u }, { 17965416168102169531u, 160526608323619796u },
|
||||
{ 2919224165770098987u, 256842573317791675u }, { 2335379332616079190u, 205474058654233340u },
|
||||
{ 1868303466092863352u, 164379246923386672u }, { 6678634360490491686u, 263006795077418675u },
|
||||
{ 5342907488392393349u, 210405436061934940u }, { 4274325990713914679u, 168324348849547952u },
|
||||
{ 10528270399884173809u, 269318958159276723u }, { 15801313949391159694u, 215455166527421378u },
|
||||
{ 1573004715287196786u, 172364133221937103u }, { 17274202803427156150u, 275782613155099364u },
|
||||
{ 17508711057483635243u, 220626090524079491u }, { 10317620031244997871u, 176500872419263593u },
|
||||
{ 12818843235250086271u, 282401395870821749u }, { 13944423402941979340u, 225921116696657399u },
|
||||
{ 14844887537095493795u, 180736893357325919u }, { 15565258844418305359u, 144589514685860735u },
|
||||
{ 6457670077359736959u, 231343223497377177u }, { 16234182506113520537u, 185074578797901741u },
|
||||
{ 9297997190148906106u, 148059663038321393u }, { 11187446689496339446u, 236895460861314229u },
|
||||
{ 12639306166338981880u, 189516368689051383u }, { 17490142562555006151u, 151613094951241106u },
|
||||
{ 2158786396894637579u, 242580951921985771u }, { 16484424376483351356u, 194064761537588616u },
|
||||
{ 9498190686444770762u, 155251809230070893u }, { 11507756283569722895u, 248402894768113429u },
|
||||
{ 12895553841597688639u, 198722315814490743u }, { 17695140702761971558u, 158977852651592594u },
|
||||
{ 17244178680193423523u, 254364564242548151u }, { 10105994129412828495u, 203491651394038521u },
|
||||
{ 4395446488788352473u, 162793321115230817u }, { 10722063196803274280u, 260469313784369307u },
|
||||
{ 1198952927958798777u, 208375451027495446u }, { 15716557601334680315u, 166700360821996356u },
|
||||
{ 17767794532651667857u, 266720577315194170u }, { 14214235626121334286u, 213376461852155336u },
|
||||
{ 7682039686155157106u, 170701169481724269u }, { 1223217053622520399u, 273121871170758831u },
|
||||
{ 15735968901865657612u, 218497496936607064u }, { 16278123936234436413u, 174797997549285651u },
|
||||
{ 219556594781725998u, 279676796078857043u }, { 7554342905309201445u, 223741436863085634u },
|
||||
{ 9732823138989271479u, 178993149490468507u }, { 815121763415193074u, 286389039184749612u },
|
||||
{ 11720143854957885429u, 229111231347799689u }, { 13065463898708218666u, 183288985078239751u },
|
||||
{ 6763022304224664610u, 146631188062591801u }, { 3442138057275642729u, 234609900900146882u },
|
||||
{ 13821756890046245153u, 187687920720117505u }, { 11057405512036996122u, 150150336576094004u },
|
||||
{ 6623802375033462826u, 240240538521750407u }, { 16367088344252501231u, 192192430817400325u },
|
||||
{ 13093670675402000985u, 153753944653920260u }, { 2503129006933649959u, 246006311446272417u },
|
||||
{ 13070549649772650937u, 196805049157017933u }, { 17835137349301941396u, 157444039325614346u },
|
||||
{ 2710778055689733971u, 251910462920982955u }, { 2168622444551787177u, 201528370336786364u },
|
||||
{ 5424246770383340065u, 161222696269429091u }, { 1300097203129523457u, 257956314031086546u },
|
||||
{ 15797473021471260058u, 206365051224869236u }, { 8948629602435097724u, 165092040979895389u },
|
||||
{ 3249760919670425388u, 264147265567832623u }, { 9978506365220160957u, 211317812454266098u },
|
||||
{ 15361502721659949412u, 169054249963412878u }, { 2442311466204457120u, 270486799941460606u },
|
||||
{ 16711244431931206989u, 216389439953168484u }, { 17058344360286875914u, 173111551962534787u },
|
||||
{ 12535955717491360170u, 276978483140055660u }, { 10028764573993088136u, 221582786512044528u },
|
||||
{ 15401709288678291155u, 177266229209635622u }, { 9885339602917624555u, 283625966735416996u },
|
||||
{ 4218922867592189321u, 226900773388333597u }, { 14443184738299482427u, 181520618710666877u },
|
||||
{ 4175850161155765295u, 145216494968533502u }, { 10370709072591134795u, 232346391949653603u },
|
||||
{ 15675264887556728482u, 185877113559722882u }, { 5161514280561562140u, 148701690847778306u },
|
||||
{ 879725219414678777u, 237922705356445290u }, { 703780175531743021u, 190338164285156232u },
|
||||
{ 11631070584651125387u, 152270531428124985u }, { 162968861732249003u, 243632850284999977u },
|
||||
{ 11198421533611530172u, 194906280227999981u }, { 5269388412147313814u, 155925024182399985u },
|
||||
{ 8431021459435702103u, 249480038691839976u }, { 3055468352806651359u, 199584030953471981u },
|
||||
{ 17201769941212962380u, 159667224762777584u }, { 16454785461715008838u, 255467559620444135u },
|
||||
{ 13163828369372007071u, 204374047696355308u }, { 17909760324981426303u, 163499238157084246u },
|
||||
{ 2830174816776909822u, 261598781051334795u }, { 2264139853421527858u, 209279024841067836u },
|
||||
{ 16568707141704863579u, 167423219872854268u }, { 4373838538276319787u, 267877151796566830u },
|
||||
{ 3499070830621055830u, 214301721437253464u }, { 6488605479238754987u, 171441377149802771u },
|
||||
{ 3003071137298187333u, 274306203439684434u }, { 6091805724580460189u, 219444962751747547u },
|
||||
{ 15941491023890099121u, 175555970201398037u }, { 10748990379256517301u, 280889552322236860u },
|
||||
{ 8599192303405213841u, 224711641857789488u }, { 14258051472207991719u, 179769313486231590u }};
|
||||
return arr;
|
||||
}
|
||||
|
||||
inline
|
||||
std::uint64_t const
|
||||
(&DOUBLE_POW5_SPLIT() noexcept)[326][2]
|
||||
{
|
||||
static constexpr std::uint64_t arr[326][2] = {
|
||||
{ 0u, 72057594037927936u }, { 0u, 90071992547409920u },
|
||||
{ 0u, 112589990684262400u }, { 0u, 140737488355328000u },
|
||||
{ 0u, 87960930222080000u }, { 0u, 109951162777600000u },
|
||||
{ 0u, 137438953472000000u }, { 0u, 85899345920000000u },
|
||||
{ 0u, 107374182400000000u }, { 0u, 134217728000000000u },
|
||||
{ 0u, 83886080000000000u }, { 0u, 104857600000000000u },
|
||||
{ 0u, 131072000000000000u }, { 0u, 81920000000000000u },
|
||||
{ 0u, 102400000000000000u }, { 0u, 128000000000000000u },
|
||||
{ 0u, 80000000000000000u }, { 0u, 100000000000000000u },
|
||||
{ 0u, 125000000000000000u }, { 0u, 78125000000000000u },
|
||||
{ 0u, 97656250000000000u }, { 0u, 122070312500000000u },
|
||||
{ 0u, 76293945312500000u }, { 0u, 95367431640625000u },
|
||||
{ 0u, 119209289550781250u }, { 4611686018427387904u, 74505805969238281u },
|
||||
{ 10376293541461622784u, 93132257461547851u }, { 8358680908399640576u, 116415321826934814u },
|
||||
{ 612489549322387456u, 72759576141834259u }, { 14600669991935148032u, 90949470177292823u },
|
||||
{ 13639151471491547136u, 113686837721616029u }, { 3213881284082270208u, 142108547152020037u },
|
||||
{ 4314518811765112832u, 88817841970012523u }, { 781462496279003136u, 111022302462515654u },
|
||||
{ 10200200157203529728u, 138777878078144567u }, { 13292654125893287936u, 86736173798840354u },
|
||||
{ 7392445620511834112u, 108420217248550443u }, { 4628871007212404736u, 135525271560688054u },
|
||||
{ 16728102434789916672u, 84703294725430033u }, { 7075069988205232128u, 105879118406787542u },
|
||||
{ 18067209522111315968u, 132348898008484427u }, { 8986162942105878528u, 82718061255302767u },
|
||||
{ 6621017659204960256u, 103397576569128459u }, { 3664586055578812416u, 129246970711410574u },
|
||||
{ 16125424340018921472u, 80779356694631608u }, { 1710036351314100224u, 100974195868289511u },
|
||||
{ 15972603494424788992u, 126217744835361888u }, { 9982877184015493120u, 78886090522101180u },
|
||||
{ 12478596480019366400u, 98607613152626475u }, { 10986559581596820096u, 123259516440783094u },
|
||||
{ 2254913720070624656u, 77037197775489434u }, { 12042014186943056628u, 96296497219361792u },
|
||||
{ 15052517733678820785u, 120370621524202240u }, { 9407823583549262990u, 75231638452626400u },
|
||||
{ 11759779479436578738u, 94039548065783000u }, { 14699724349295723422u, 117549435082228750u },
|
||||
{ 4575641699882439235u, 73468396926392969u }, { 10331238143280436948u, 91835496157991211u },
|
||||
{ 8302361660673158281u, 114794370197489014u }, { 1154580038986672043u, 143492962746861268u },
|
||||
{ 9944984561221445835u, 89683101716788292u }, { 12431230701526807293u, 112103877145985365u },
|
||||
{ 1703980321626345405u, 140129846432481707u }, { 17205888765512323542u, 87581154020301066u },
|
||||
{ 12283988920035628619u, 109476442525376333u }, { 1519928094762372062u, 136845553156720417u },
|
||||
{ 12479170105294952299u, 85528470722950260u }, { 15598962631618690374u, 106910588403687825u },
|
||||
{ 5663645234241199255u, 133638235504609782u }, { 17374836326682913246u, 83523897190381113u },
|
||||
{ 7883487353071477846u, 104404871487976392u }, { 9854359191339347308u, 130506089359970490u },
|
||||
{ 10770660513014479971u, 81566305849981556u }, { 13463325641268099964u, 101957882312476945u },
|
||||
{ 2994098996302961243u, 127447352890596182u }, { 15706369927971514489u, 79654595556622613u },
|
||||
{ 5797904354682229399u, 99568244445778267u }, { 2635694424925398845u, 124460305557222834u },
|
||||
{ 6258995034005762182u, 77787690973264271u }, { 3212057774079814824u, 97234613716580339u },
|
||||
{ 17850130272881932242u, 121543267145725423u }, { 18073860448192289507u, 75964541966078389u },
|
||||
{ 8757267504958198172u, 94955677457597987u }, { 6334898362770359811u, 118694596821997484u },
|
||||
{ 13182683513586250689u, 74184123013748427u }, { 11866668373555425458u, 92730153767185534u },
|
||||
{ 5609963430089506015u, 115912692208981918u }, { 17341285199088104971u, 72445432630613698u },
|
||||
{ 12453234462005355406u, 90556790788267123u }, { 10954857059079306353u, 113195988485333904u },
|
||||
{ 13693571323849132942u, 141494985606667380u }, { 17781854114260483896u, 88434366004167112u },
|
||||
{ 3780573569116053255u, 110542957505208891u }, { 114030942967678664u, 138178696881511114u },
|
||||
{ 4682955357782187069u, 86361685550944446u }, { 15077066234082509644u, 107952106938680557u },
|
||||
{ 5011274737320973344u, 134940133673350697u }, { 14661261756894078100u, 84337583545844185u },
|
||||
{ 4491519140835433913u, 105421979432305232u }, { 5614398926044292391u, 131777474290381540u },
|
||||
{ 12732371365632458552u, 82360921431488462u }, { 6692092170185797382u, 102951151789360578u },
|
||||
{ 17588487249587022536u, 128688939736700722u }, { 15604490549419276989u, 80430587335437951u },
|
||||
{ 14893927168346708332u, 100538234169297439u }, { 14005722942005997511u, 125672792711621799u },
|
||||
{ 15671105866394830300u, 78545495444763624u }, { 1142138259283986260u, 98181869305954531u },
|
||||
{ 15262730879387146537u, 122727336632443163u }, { 7233363790403272633u, 76704585395276977u },
|
||||
{ 13653390756431478696u, 95880731744096221u }, { 3231680390257184658u, 119850914680120277u },
|
||||
{ 4325643253124434363u, 74906821675075173u }, { 10018740084832930858u, 93633527093843966u },
|
||||
{ 3300053069186387764u, 117041908867304958u }, { 15897591223523656064u, 73151193042065598u },
|
||||
{ 10648616992549794273u, 91438991302581998u }, { 4087399203832467033u, 114298739128227498u },
|
||||
{ 14332621041645359599u, 142873423910284372u }, { 18181260187883125557u, 89295889943927732u },
|
||||
{ 4279831161144355331u, 111619862429909666u }, { 14573160988285219972u, 139524828037387082u },
|
||||
{ 13719911636105650386u, 87203017523366926u }, { 7926517508277287175u, 109003771904208658u },
|
||||
{ 684774848491833161u, 136254714880260823u }, { 7345513307948477581u, 85159196800163014u },
|
||||
{ 18405263671790372785u, 106448996000203767u }, { 18394893571310578077u, 133061245000254709u },
|
||||
{ 13802651491282805250u, 83163278125159193u }, { 3418256308821342851u, 103954097656448992u },
|
||||
{ 4272820386026678563u, 129942622070561240u }, { 2670512741266674102u, 81214138794100775u },
|
||||
{ 17173198981865506339u, 101517673492625968u }, { 3019754653622331308u, 126897091865782461u },
|
||||
{ 4193189667727651020u, 79310682416114038u }, { 14464859121514339583u, 99138353020142547u },
|
||||
{ 13469387883465536574u, 123922941275178184u }, { 8418367427165960359u, 77451838296986365u },
|
||||
{ 15134645302384838353u, 96814797871232956u }, { 471562554271496325u, 121018497339041196u },
|
||||
{ 9518098633274461011u, 75636560836900747u }, { 7285937273165688360u, 94545701046125934u },
|
||||
{ 18330793628311886258u, 118182126307657417u }, { 4539216990053847055u, 73863828942285886u },
|
||||
{ 14897393274422084627u, 92329786177857357u }, { 4786683537745442072u, 115412232722321697u },
|
||||
{ 14520892257159371055u, 72132645451451060u }, { 18151115321449213818u, 90165806814313825u },
|
||||
{ 8853836096529353561u, 112707258517892282u }, { 1843923083806916143u, 140884073147365353u },
|
||||
{ 12681666973447792349u, 88052545717103345u }, { 2017025661527576725u, 110065682146379182u },
|
||||
{ 11744654113764246714u, 137582102682973977u }, { 422879793461572340u, 85988814176858736u },
|
||||
{ 528599741826965425u, 107486017721073420u }, { 660749677283706782u, 134357522151341775u },
|
||||
{ 7330497575943398595u, 83973451344588609u }, { 13774807988356636147u, 104966814180735761u },
|
||||
{ 3383451930163631472u, 131208517725919702u }, { 15949715511634433382u, 82005323578699813u },
|
||||
{ 6102086334260878016u, 102506654473374767u }, { 3015921899398709616u, 128133318091718459u },
|
||||
{ 18025852251620051174u, 80083323807324036u }, { 4085571240815512351u, 100104154759155046u },
|
||||
{ 14330336087874166247u, 125130193448943807u }, { 15873989082562435760u, 78206370905589879u },
|
||||
{ 15230800334775656796u, 97757963631987349u }, { 5203442363187407284u, 122197454539984187u },
|
||||
{ 946308467778435600u, 76373409087490117u }, { 5794571603150432404u, 95466761359362646u },
|
||||
{ 16466586540792816313u, 119333451699203307u }, { 7985773578781816244u, 74583407312002067u },
|
||||
{ 5370530955049882401u, 93229259140002584u }, { 6713163693812353001u, 116536573925003230u },
|
||||
{ 18030785363914884337u, 72835358703127018u }, { 13315109668038829614u, 91044198378908773u },
|
||||
{ 2808829029766373305u, 113805247973635967u }, { 17346094342490130344u, 142256559967044958u },
|
||||
{ 6229622945628943561u, 88910349979403099u }, { 3175342663608791547u, 111137937474253874u },
|
||||
{ 13192550366365765242u, 138922421842817342u }, { 3633657960551215372u, 86826513651760839u },
|
||||
{ 18377130505971182927u, 108533142064701048u }, { 4524669058754427043u, 135666427580876311u },
|
||||
{ 9745447189362598758u, 84791517238047694u }, { 2958436949848472639u, 105989396547559618u },
|
||||
{ 12921418224165366607u, 132486745684449522u }, { 12687572408530742033u, 82804216052780951u },
|
||||
{ 11247779492236039638u, 103505270065976189u }, { 224666310012885835u, 129381587582470237u },
|
||||
{ 2446259452971747599u, 80863492239043898u }, { 12281196353069460307u, 101079365298804872u },
|
||||
{ 15351495441336825384u, 126349206623506090u }, { 14206370669262903769u, 78968254139691306u },
|
||||
{ 8534591299723853903u, 98710317674614133u }, { 15279925143082205283u, 123387897093267666u },
|
||||
{ 14161639232853766206u, 77117435683292291u }, { 13090363022639819853u, 96396794604115364u },
|
||||
{ 16362953778299774816u, 120495993255144205u }, { 12532689120651053212u, 75309995784465128u },
|
||||
{ 15665861400813816515u, 94137494730581410u }, { 10358954714162494836u, 117671868413226763u },
|
||||
{ 4168503687137865320u, 73544917758266727u }, { 598943590494943747u, 91931147197833409u },
|
||||
{ 5360365506546067587u, 114913933997291761u }, { 11312142901609972388u, 143642417496614701u },
|
||||
{ 9375932322719926695u, 89776510935384188u }, { 11719915403399908368u, 112220638669230235u },
|
||||
{ 10038208235822497557u, 140275798336537794u }, { 10885566165816448877u, 87672373960336121u },
|
||||
{ 18218643725697949000u, 109590467450420151u }, { 18161618638695048346u, 136988084313025189u },
|
||||
{ 13656854658398099168u, 85617552695640743u }, { 12459382304570236056u, 107021940869550929u },
|
||||
{ 1739169825430631358u, 133777426086938662u }, { 14922039196176308311u, 83610891304336663u },
|
||||
{ 14040862976792997485u, 104513614130420829u }, { 3716020665709083144u, 130642017663026037u },
|
||||
{ 4628355925281870917u, 81651261039391273u }, { 10397130925029726550u, 102064076299239091u },
|
||||
{ 8384727637859770284u, 127580095374048864u }, { 5240454773662356427u, 79737559608780540u },
|
||||
{ 6550568467077945534u, 99671949510975675u }, { 3576524565420044014u, 124589936888719594u },
|
||||
{ 6847013871814915412u, 77868710555449746u }, { 17782139376623420074u, 97335888194312182u },
|
||||
{ 13004302183924499284u, 121669860242890228u }, { 17351060901807587860u, 76043662651806392u },
|
||||
{ 3242082053549933210u, 95054578314757991u }, { 17887660622219580224u, 118818222893447488u },
|
||||
{ 11179787888887237640u, 74261389308404680u }, { 13974734861109047050u, 92826736635505850u },
|
||||
{ 8245046539531533005u, 116033420794382313u }, { 16682369133275677888u, 72520887996488945u },
|
||||
{ 7017903361312433648u, 90651109995611182u }, { 17995751238495317868u, 113313887494513977u },
|
||||
{ 8659630992836983623u, 141642359368142472u }, { 5412269370523114764u, 88526474605089045u },
|
||||
{ 11377022731581281359u, 110658093256361306u }, { 4997906377621825891u, 138322616570451633u },
|
||||
{ 14652906532082110942u, 86451635356532270u }, { 9092761128247862869u, 108064544195665338u },
|
||||
{ 2142579373455052779u, 135080680244581673u }, { 12868327154477877747u, 84425425152863545u },
|
||||
{ 2250350887815183471u, 105531781441079432u }, { 2812938609768979339u, 131914726801349290u },
|
||||
{ 6369772649532999991u, 82446704250843306u }, { 17185587848771025797u, 103058380313554132u },
|
||||
{ 3035240737254230630u, 128822975391942666u }, { 6508711479211282048u, 80514359619964166u },
|
||||
{ 17359261385868878368u, 100642949524955207u }, { 17087390713908710056u, 125803686906194009u },
|
||||
{ 3762090168551861929u, 78627304316371256u }, { 4702612710689827411u, 98284130395464070u },
|
||||
{ 15101637925217060072u, 122855162994330087u }, { 16356052730901744401u, 76784476871456304u },
|
||||
{ 1998321839917628885u, 95980596089320381u }, { 7109588318324424010u, 119975745111650476u },
|
||||
{ 13666864735807540814u, 74984840694781547u }, { 12471894901332038114u, 93731050868476934u },
|
||||
{ 6366496589810271835u, 117163813585596168u }, { 3979060368631419896u, 73227383490997605u },
|
||||
{ 9585511479216662775u, 91534229363747006u }, { 2758517312166052660u, 114417786704683758u },
|
||||
{ 12671518677062341634u, 143022233380854697u }, { 1002170145522881665u, 89388895863034186u },
|
||||
{ 10476084718758377889u, 111736119828792732u }, { 13095105898447972362u, 139670149785990915u },
|
||||
{ 5878598177316288774u, 87293843616244322u }, { 16571619758500136775u, 109117304520305402u },
|
||||
{ 11491152661270395161u, 136396630650381753u }, { 264441385652915120u, 85247894156488596u },
|
||||
{ 330551732066143900u, 106559867695610745u }, { 5024875683510067779u, 133199834619513431u },
|
||||
{ 10058076329834874218u, 83249896637195894u }, { 3349223375438816964u, 104062370796494868u },
|
||||
{ 4186529219298521205u, 130077963495618585u }, { 14145795808130045513u, 81298727184761615u },
|
||||
{ 13070558741735168987u, 101623408980952019u }, { 11726512408741573330u, 127029261226190024u },
|
||||
{ 7329070255463483331u, 79393288266368765u }, { 13773023837756742068u, 99241610332960956u },
|
||||
{ 17216279797195927585u, 124052012916201195u }, { 8454331864033760789u, 77532508072625747u },
|
||||
{ 5956228811614813082u, 96915635090782184u }, { 7445286014518516353u, 121144543863477730u },
|
||||
{ 9264989777501460624u, 75715339914673581u }, { 16192923240304213684u, 94644174893341976u },
|
||||
{ 1794409976670715490u, 118305218616677471u }, { 8039035263060279037u, 73940761635423419u },
|
||||
{ 5437108060397960892u, 92425952044279274u }, { 16019757112352226923u, 115532440055349092u },
|
||||
{ 788976158365366019u, 72207775034593183u }, { 14821278253238871236u, 90259718793241478u },
|
||||
{ 9303225779693813237u, 112824648491551848u }, { 11629032224617266546u, 141030810614439810u },
|
||||
{ 11879831158813179495u, 88144256634024881u }, { 1014730893234310657u, 110180320792531102u },
|
||||
{ 10491785653397664129u, 137725400990663877u }, { 8863209042587234033u, 86078375619164923u },
|
||||
{ 6467325284806654637u, 107597969523956154u }, { 17307528642863094104u, 134497461904945192u },
|
||||
{ 10817205401789433815u, 84060913690590745u }, { 18133192770664180173u, 105076142113238431u },
|
||||
{ 18054804944902837312u, 131345177641548039u }, { 18201782118205355176u, 82090736025967524u },
|
||||
{ 4305483574047142354u, 102613420032459406u }, { 14605226504413703751u, 128266775040574257u },
|
||||
{ 2210737537617482988u, 80166734400358911u }, { 16598479977304017447u, 100208418000448638u },
|
||||
{ 11524727934775246001u, 125260522500560798u }, { 2591268940807140847u, 78287826562850499u },
|
||||
{ 17074144231291089770u, 97859783203563123u }, { 16730994270686474309u, 122324729004453904u },
|
||||
{ 10456871419179046443u, 76452955627783690u }, { 3847717237119032246u, 95566194534729613u },
|
||||
{ 9421332564826178211u, 119457743168412016u }, { 5888332853016361382u, 74661089480257510u },
|
||||
{ 16583788103125227536u, 93326361850321887u }, { 16118049110479146516u, 116657952312902359u },
|
||||
{ 16991309721690548428u, 72911220195563974u }, { 12015765115258409727u, 91139025244454968u },
|
||||
{ 15019706394073012159u, 113923781555568710u }, { 9551260955736489391u, 142404726944460888u },
|
||||
{ 5969538097335305869u, 89002954340288055u }, { 2850236603241744433u, 111253692925360069u }};
|
||||
return arr;
|
||||
}
|
||||
|
||||
} // ryu
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,229 @@
|
||||
// Copyright 2018 Ulf Adams
|
||||
//
|
||||
// The contents of this file may be used under the terms of the Apache License,
|
||||
// Version 2.0.
|
||||
//
|
||||
// (See accompanying file LICENSE-Apache or copy at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0)
|
||||
//
|
||||
// Alternatively, the contents of this file may be used under the terms of
|
||||
// the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE-Boost or copy at
|
||||
// https://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, this software
|
||||
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied.
|
||||
|
||||
/*
|
||||
This is a derivative work
|
||||
*/
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_RYU_DETAIL_D2S_INTRINSICS_HPP
|
||||
#define BOOST_JSON_DETAIL_RYU_DETAIL_D2S_INTRINSICS_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
|
||||
// This sets BOOST_JSON_RYU_32_BIT_PLATFORM as a side effect if applicable.
|
||||
#include <boost/json/detail/ryu/detail/common.hpp>
|
||||
|
||||
#if defined(BOOST_JSON_RYU_HAS_64_BIT_INTRINSICS)
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
namespace ryu {
|
||||
namespace detail {
|
||||
|
||||
#if defined(BOOST_JSON_RYU_HAS_64_BIT_INTRINSICS)
|
||||
|
||||
inline uint64_t umul128(const uint64_t a, const uint64_t b, uint64_t* const productHi) {
|
||||
return _umul128(a, b, productHi);
|
||||
}
|
||||
|
||||
inline uint64_t shiftright128(const uint64_t lo, const uint64_t hi, const uint32_t dist) {
|
||||
// For the __shiftright128 intrinsic, the shift value is always
|
||||
// modulo 64.
|
||||
// In the current implementation of the double-precision version
|
||||
// of Ryu, the shift value is always < 64. (In the case
|
||||
// RYU_OPTIMIZE_SIZE == 0, the shift value is in the range [49, 58].
|
||||
// Otherwise in the range [2, 59].)
|
||||
// Check this here in case a future change requires larger shift
|
||||
// values. In this case this function needs to be adjusted.
|
||||
BOOST_ASSERT(dist < 64);
|
||||
return __shiftright128(lo, hi, (unsigned char) dist);
|
||||
}
|
||||
|
||||
#else // defined(HAS_64_BIT_INTRINSICS)
|
||||
|
||||
inline uint64_t umul128(const uint64_t a, const uint64_t b, uint64_t* const productHi) {
|
||||
// The casts here help MSVC to avoid calls to the __allmul library function.
|
||||
const uint32_t aLo = (uint32_t)a;
|
||||
const uint32_t aHi = (uint32_t)(a >> 32);
|
||||
const uint32_t bLo = (uint32_t)b;
|
||||
const uint32_t bHi = (uint32_t)(b >> 32);
|
||||
|
||||
const uint64_t b00 = (uint64_t)aLo * bLo;
|
||||
const uint64_t b01 = (uint64_t)aLo * bHi;
|
||||
const uint64_t b10 = (uint64_t)aHi * bLo;
|
||||
const uint64_t b11 = (uint64_t)aHi * bHi;
|
||||
|
||||
const uint32_t b00Lo = (uint32_t)b00;
|
||||
const uint32_t b00Hi = (uint32_t)(b00 >> 32);
|
||||
|
||||
const uint64_t mid1 = b10 + b00Hi;
|
||||
const uint32_t mid1Lo = (uint32_t)(mid1);
|
||||
const uint32_t mid1Hi = (uint32_t)(mid1 >> 32);
|
||||
|
||||
const uint64_t mid2 = b01 + mid1Lo;
|
||||
const uint32_t mid2Lo = (uint32_t)(mid2);
|
||||
const uint32_t mid2Hi = (uint32_t)(mid2 >> 32);
|
||||
|
||||
const uint64_t pHi = b11 + mid1Hi + mid2Hi;
|
||||
const uint64_t pLo = ((uint64_t)mid2Lo << 32) | b00Lo;
|
||||
|
||||
*productHi = pHi;
|
||||
return pLo;
|
||||
}
|
||||
|
||||
inline uint64_t shiftright128(const uint64_t lo, const uint64_t hi, const uint32_t dist) {
|
||||
// We don't need to handle the case dist >= 64 here (see above).
|
||||
BOOST_ASSERT(dist < 64);
|
||||
#if defined(RYU_OPTIMIZE_SIZE) || !defined(RYU_32_BIT_PLATFORM)
|
||||
BOOST_ASSERT(dist > 0);
|
||||
return (hi << (64 - dist)) | (lo >> dist);
|
||||
#else
|
||||
// Avoid a 64-bit shift by taking advantage of the range of shift values.
|
||||
BOOST_ASSERT(dist >= 32);
|
||||
return (hi << (64 - dist)) | ((uint32_t)(lo >> 32) >> (dist - 32));
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // defined(HAS_64_BIT_INTRINSICS)
|
||||
|
||||
#ifdef RYU_32_BIT_PLATFORM
|
||||
|
||||
// Returns the high 64 bits of the 128-bit product of a and b.
|
||||
inline uint64_t umulh(const uint64_t a, const uint64_t b) {
|
||||
// Reuse the umul128 implementation.
|
||||
// Optimizers will likely eliminate the instructions used to compute the
|
||||
// low part of the product.
|
||||
uint64_t hi;
|
||||
umul128(a, b, &hi);
|
||||
return hi;
|
||||
}
|
||||
|
||||
// On 32-bit platforms, compilers typically generate calls to library
|
||||
// functions for 64-bit divisions, even if the divisor is a constant.
|
||||
//
|
||||
// E.g.:
|
||||
// https://bugs.llvm.org/show_bug.cgi?id=37932
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=17958
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37443
|
||||
//
|
||||
// The functions here perform division-by-constant using multiplications
|
||||
// in the same way as 64-bit compilers would do.
|
||||
//
|
||||
// NB:
|
||||
// The multipliers and shift values are the ones generated by clang x64
|
||||
// for expressions like x/5, x/10, etc.
|
||||
|
||||
inline uint64_t div5(const uint64_t x) {
|
||||
return umulh(x, 0xCCCCCCCCCCCCCCCDu) >> 2;
|
||||
}
|
||||
|
||||
inline uint64_t div10(const uint64_t x) {
|
||||
return umulh(x, 0xCCCCCCCCCCCCCCCDu) >> 3;
|
||||
}
|
||||
|
||||
inline uint64_t div100(const uint64_t x) {
|
||||
return umulh(x >> 2, 0x28F5C28F5C28F5C3u) >> 2;
|
||||
}
|
||||
|
||||
inline uint64_t div1e8(const uint64_t x) {
|
||||
return umulh(x, 0xABCC77118461CEFDu) >> 26;
|
||||
}
|
||||
|
||||
inline uint64_t div1e9(const uint64_t x) {
|
||||
return umulh(x >> 9, 0x44B82FA09B5A53u) >> 11;
|
||||
}
|
||||
|
||||
inline uint32_t mod1e9(const uint64_t x) {
|
||||
// Avoid 64-bit math as much as possible.
|
||||
// Returning (uint32_t) (x - 1000000000 * div1e9(x)) would
|
||||
// perform 32x64-bit multiplication and 64-bit subtraction.
|
||||
// x and 1000000000 * div1e9(x) are guaranteed to differ by
|
||||
// less than 10^9, so their highest 32 bits must be identical,
|
||||
// so we can truncate both sides to uint32_t before subtracting.
|
||||
// We can also simplify (uint32_t) (1000000000 * div1e9(x)).
|
||||
// We can truncate before multiplying instead of after, as multiplying
|
||||
// the highest 32 bits of div1e9(x) can't affect the lowest 32 bits.
|
||||
return ((uint32_t) x) - 1000000000 * ((uint32_t) div1e9(x));
|
||||
}
|
||||
|
||||
#else // RYU_32_BIT_PLATFORM
|
||||
|
||||
inline uint64_t div5(const uint64_t x) {
|
||||
return x / 5;
|
||||
}
|
||||
|
||||
inline uint64_t div10(const uint64_t x) {
|
||||
return x / 10;
|
||||
}
|
||||
|
||||
inline uint64_t div100(const uint64_t x) {
|
||||
return x / 100;
|
||||
}
|
||||
|
||||
inline uint64_t div1e8(const uint64_t x) {
|
||||
return x / 100000000;
|
||||
}
|
||||
|
||||
inline uint64_t div1e9(const uint64_t x) {
|
||||
return x / 1000000000;
|
||||
}
|
||||
|
||||
inline uint32_t mod1e9(const uint64_t x) {
|
||||
return (uint32_t) (x - 1000000000 * div1e9(x));
|
||||
}
|
||||
|
||||
#endif // RYU_32_BIT_PLATFORM
|
||||
|
||||
inline uint32_t pow5Factor(uint64_t value) {
|
||||
uint32_t count = 0;
|
||||
for (;;) {
|
||||
BOOST_ASSERT(value != 0);
|
||||
const uint64_t q = div5(value);
|
||||
const uint32_t r = ((uint32_t) value) - 5 * ((uint32_t) q);
|
||||
if (r != 0) {
|
||||
break;
|
||||
}
|
||||
value = q;
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// Returns true if value is divisible by 5^p.
|
||||
inline bool multipleOfPowerOf5(const uint64_t value, const uint32_t p) {
|
||||
// I tried a case distinction on p, but there was no performance difference.
|
||||
return pow5Factor(value) >= p;
|
||||
}
|
||||
|
||||
// Returns true if value is divisible by 2^p.
|
||||
inline bool multipleOfPowerOf2(const uint64_t value, const uint32_t p) {
|
||||
BOOST_ASSERT(value != 0);
|
||||
// return __builtin_ctzll(value) >= p;
|
||||
return (value & ((1ull << p) - 1)) == 0;
|
||||
}
|
||||
|
||||
|
||||
} // detail
|
||||
} // ryu
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright 2018 Ulf Adams
|
||||
//
|
||||
// The contents of this file may be used under the terms of the Apache License,
|
||||
// Version 2.0.
|
||||
//
|
||||
// (See accompanying file LICENSE-Apache or copy at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0)
|
||||
//
|
||||
// Alternatively, the contents of this file may be used under the terms of
|
||||
// the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE-Boost or copy at
|
||||
// https://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, this software
|
||||
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied.
|
||||
|
||||
/*
|
||||
This is a derivative work
|
||||
*/
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_RYU_DETAIL_DIGIT_TABLE_HPP
|
||||
#define BOOST_JSON_DETAIL_RYU_DETAIL_DIGIT_TABLE_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
namespace ryu {
|
||||
namespace detail {
|
||||
|
||||
// A table of all two-digit numbers. This is used to speed up decimal digit
|
||||
// generation by copying pairs of digits into the final output.
|
||||
inline
|
||||
char const
|
||||
(&DIGIT_TABLE() noexcept)[200]
|
||||
{
|
||||
static constexpr char arr[200] = {
|
||||
'0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9',
|
||||
'1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9',
|
||||
'2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9',
|
||||
'3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9',
|
||||
'4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9',
|
||||
'5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9',
|
||||
'6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9',
|
||||
'7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9',
|
||||
'8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9',
|
||||
'9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9' };
|
||||
return arr;
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // ryu
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
743
install/boost_1_75_0/include/boost/json/detail/ryu/impl/d2s.ipp
Normal file
743
install/boost_1_75_0/include/boost/json/detail/ryu/impl/d2s.ipp
Normal file
@@ -0,0 +1,743 @@
|
||||
// Copyright 2018 Ulf Adams
|
||||
//
|
||||
// The contents of this file may be used under the terms of the Apache License,
|
||||
// Version 2.0.
|
||||
//
|
||||
// (See accompanying file LICENSE-Apache or copy at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0)
|
||||
//
|
||||
// Alternatively, the contents of this file may be used under the terms of
|
||||
// the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE-Boost or copy at
|
||||
// https://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, this software
|
||||
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied.
|
||||
|
||||
// Runtime compiler options:
|
||||
// -DRYU_DEBUG Generate verbose debugging output to stdout.
|
||||
//
|
||||
// -DRYU_ONLY_64_BIT_OPS Avoid using uint128_t or 64-bit intrinsics. Slower,
|
||||
// depending on your compiler.
|
||||
//
|
||||
// -DRYU_OPTIMIZE_SIZE Use smaller lookup tables. Instead of storing every
|
||||
// required power of 5, only store every 26th entry, and compute
|
||||
// intermediate values with a multiplication. This reduces the lookup table
|
||||
// size by about 10x (only one case, and only double) at the cost of some
|
||||
// performance. Currently requires MSVC intrinsics.
|
||||
|
||||
/*
|
||||
This is a derivative work
|
||||
*/
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_RYU_IMPL_D2S_IPP
|
||||
#define BOOST_JSON_DETAIL_RYU_IMPL_D2S_IPP
|
||||
|
||||
#include <boost/json/detail/ryu/ryu.hpp>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef RYU_DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
// ABSL avoids uint128_t on Win32 even if __SIZEOF_INT128__ is defined.
|
||||
// Let's do the same for now.
|
||||
#if defined(__SIZEOF_INT128__) && !defined(_MSC_VER) && !defined(RYU_ONLY_64_BIT_OPS)
|
||||
#define BOOST_JSON_RYU_HAS_UINT128
|
||||
#elif defined(_MSC_VER) && !defined(RYU_ONLY_64_BIT_OPS) && defined(_M_X64)
|
||||
#define BOOST_JSON_RYU_HAS_64_BIT_INTRINSICS
|
||||
#endif
|
||||
|
||||
#include <boost/json/detail/ryu/detail/common.hpp>
|
||||
#include <boost/json/detail/ryu/detail/digit_table.hpp>
|
||||
#include <boost/json/detail/ryu/detail/d2s.hpp>
|
||||
#include <boost/json/detail/ryu/detail/d2s_intrinsics.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
namespace ryu {
|
||||
namespace detail {
|
||||
|
||||
// We need a 64x128-bit multiplication and a subsequent 128-bit shift.
|
||||
// Multiplication:
|
||||
// The 64-bit factor is variable and passed in, the 128-bit factor comes
|
||||
// from a lookup table. We know that the 64-bit factor only has 55
|
||||
// significant bits (i.e., the 9 topmost bits are zeros). The 128-bit
|
||||
// factor only has 124 significant bits (i.e., the 4 topmost bits are
|
||||
// zeros).
|
||||
// Shift:
|
||||
// In principle, the multiplication result requires 55 + 124 = 179 bits to
|
||||
// represent. However, we then shift this value to the right by j, which is
|
||||
// at least j >= 115, so the result is guaranteed to fit into 179 - 115 = 64
|
||||
// bits. This means that we only need the topmost 64 significant bits of
|
||||
// the 64x128-bit multiplication.
|
||||
//
|
||||
// There are several ways to do this:
|
||||
// 1. Best case: the compiler exposes a 128-bit type.
|
||||
// We perform two 64x64-bit multiplications, add the higher 64 bits of the
|
||||
// lower result to the higher result, and shift by j - 64 bits.
|
||||
//
|
||||
// We explicitly cast from 64-bit to 128-bit, so the compiler can tell
|
||||
// that these are only 64-bit inputs, and can map these to the best
|
||||
// possible sequence of assembly instructions.
|
||||
// x64 machines happen to have matching assembly instructions for
|
||||
// 64x64-bit multiplications and 128-bit shifts.
|
||||
//
|
||||
// 2. Second best case: the compiler exposes intrinsics for the x64 assembly
|
||||
// instructions mentioned in 1.
|
||||
//
|
||||
// 3. We only have 64x64 bit instructions that return the lower 64 bits of
|
||||
// the result, i.e., we have to use plain C.
|
||||
// Our inputs are less than the full width, so we have three options:
|
||||
// a. Ignore this fact and just implement the intrinsics manually.
|
||||
// b. Split both into 31-bit pieces, which guarantees no internal overflow,
|
||||
// but requires extra work upfront (unless we change the lookup table).
|
||||
// c. Split only the first factor into 31-bit pieces, which also guarantees
|
||||
// no internal overflow, but requires extra work since the intermediate
|
||||
// results are not perfectly aligned.
|
||||
#if defined(BOOST_JSON_RYU_HAS_UINT128)
|
||||
|
||||
// Best case: use 128-bit type.
|
||||
inline
|
||||
std::uint64_t
|
||||
mulShift(
|
||||
const std::uint64_t m,
|
||||
const std::uint64_t* const mul,
|
||||
const std::int32_t j) noexcept
|
||||
{
|
||||
const uint128_t b0 = ((uint128_t) m) * mul[0];
|
||||
const uint128_t b2 = ((uint128_t) m) * mul[1];
|
||||
return (std::uint64_t) (((b0 >> 64) + b2) >> (j - 64));
|
||||
}
|
||||
|
||||
inline
|
||||
uint64_t
|
||||
mulShiftAll(
|
||||
const std::uint64_t m,
|
||||
const std::uint64_t* const mul,
|
||||
std::int32_t const j,
|
||||
std::uint64_t* const vp,
|
||||
std::uint64_t* const vm,
|
||||
const std::uint32_t mmShift) noexcept
|
||||
{
|
||||
// m <<= 2;
|
||||
// uint128_t b0 = ((uint128_t) m) * mul[0]; // 0
|
||||
// uint128_t b2 = ((uint128_t) m) * mul[1]; // 64
|
||||
//
|
||||
// uint128_t hi = (b0 >> 64) + b2;
|
||||
// uint128_t lo = b0 & 0xffffffffffffffffull;
|
||||
// uint128_t factor = (((uint128_t) mul[1]) << 64) + mul[0];
|
||||
// uint128_t vpLo = lo + (factor << 1);
|
||||
// *vp = (std::uint64_t) ((hi + (vpLo >> 64)) >> (j - 64));
|
||||
// uint128_t vmLo = lo - (factor << mmShift);
|
||||
// *vm = (std::uint64_t) ((hi + (vmLo >> 64) - (((uint128_t) 1ull) << 64)) >> (j - 64));
|
||||
// return (std::uint64_t) (hi >> (j - 64));
|
||||
*vp = mulShift(4 * m + 2, mul, j);
|
||||
*vm = mulShift(4 * m - 1 - mmShift, mul, j);
|
||||
return mulShift(4 * m, mul, j);
|
||||
}
|
||||
|
||||
#elif defined(BOOST_JSON_RYU_HAS_64_BIT_INTRINSICS)
|
||||
|
||||
inline
|
||||
std::uint64_t
|
||||
mulShift(
|
||||
const std::uint64_t m,
|
||||
const std::uint64_t* const mul,
|
||||
const std::int32_t j) noexcept
|
||||
{
|
||||
// m is maximum 55 bits
|
||||
std::uint64_t high1; // 128
|
||||
std::uint64_t const low1 = umul128(m, mul[1], &high1); // 64
|
||||
std::uint64_t high0; // 64
|
||||
umul128(m, mul[0], &high0); // 0
|
||||
std::uint64_t const sum = high0 + low1;
|
||||
if (sum < high0)
|
||||
++high1; // overflow into high1
|
||||
return shiftright128(sum, high1, j - 64);
|
||||
}
|
||||
|
||||
inline
|
||||
std::uint64_t
|
||||
mulShiftAll(
|
||||
const std::uint64_t m,
|
||||
const std::uint64_t* const mul,
|
||||
const std::int32_t j,
|
||||
std::uint64_t* const vp,
|
||||
std::uint64_t* const vm,
|
||||
const std::uint32_t mmShift) noexcept
|
||||
{
|
||||
*vp = mulShift(4 * m + 2, mul, j);
|
||||
*vm = mulShift(4 * m - 1 - mmShift, mul, j);
|
||||
return mulShift(4 * m, mul, j);
|
||||
}
|
||||
|
||||
#else // !defined(BOOST_JSON_RYU_HAS_UINT128) && !defined(BOOST_JSON_RYU_HAS_64_BIT_INTRINSICS)
|
||||
|
||||
inline
|
||||
std::uint64_t
|
||||
mulShiftAll(
|
||||
std::uint64_t m,
|
||||
const std::uint64_t* const mul,
|
||||
const std::int32_t j,
|
||||
std::uint64_t* const vp,
|
||||
std::uint64_t* const vm,
|
||||
const std::uint32_t mmShift)
|
||||
{
|
||||
m <<= 1;
|
||||
// m is maximum 55 bits
|
||||
std::uint64_t tmp;
|
||||
std::uint64_t const lo = umul128(m, mul[0], &tmp);
|
||||
std::uint64_t hi;
|
||||
std::uint64_t const mid = tmp + umul128(m, mul[1], &hi);
|
||||
hi += mid < tmp; // overflow into hi
|
||||
|
||||
const std::uint64_t lo2 = lo + mul[0];
|
||||
const std::uint64_t mid2 = mid + mul[1] + (lo2 < lo);
|
||||
const std::uint64_t hi2 = hi + (mid2 < mid);
|
||||
*vp = shiftright128(mid2, hi2, (std::uint32_t)(j - 64 - 1));
|
||||
|
||||
if (mmShift == 1)
|
||||
{
|
||||
const std::uint64_t lo3 = lo - mul[0];
|
||||
const std::uint64_t mid3 = mid - mul[1] - (lo3 > lo);
|
||||
const std::uint64_t hi3 = hi - (mid3 > mid);
|
||||
*vm = shiftright128(mid3, hi3, (std::uint32_t)(j - 64 - 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::uint64_t lo3 = lo + lo;
|
||||
const std::uint64_t mid3 = mid + mid + (lo3 < lo);
|
||||
const std::uint64_t hi3 = hi + hi + (mid3 < mid);
|
||||
const std::uint64_t lo4 = lo3 - mul[0];
|
||||
const std::uint64_t mid4 = mid3 - mul[1] - (lo4 > lo3);
|
||||
const std::uint64_t hi4 = hi3 - (mid4 > mid3);
|
||||
*vm = shiftright128(mid4, hi4, (std::uint32_t)(j - 64));
|
||||
}
|
||||
|
||||
return shiftright128(mid, hi, (std::uint32_t)(j - 64 - 1));
|
||||
}
|
||||
|
||||
#endif // BOOST_JSON_RYU_HAS_64_BIT_INTRINSICS
|
||||
|
||||
inline
|
||||
std::uint32_t
|
||||
decimalLength17(
|
||||
const std::uint64_t v)
|
||||
{
|
||||
// This is slightly faster than a loop.
|
||||
// The average output length is 16.38 digits, so we check high-to-low.
|
||||
// Function precondition: v is not an 18, 19, or 20-digit number.
|
||||
// (17 digits are sufficient for round-tripping.)
|
||||
BOOST_ASSERT(v < 100000000000000000L);
|
||||
if (v >= 10000000000000000L) { return 17; }
|
||||
if (v >= 1000000000000000L) { return 16; }
|
||||
if (v >= 100000000000000L) { return 15; }
|
||||
if (v >= 10000000000000L) { return 14; }
|
||||
if (v >= 1000000000000L) { return 13; }
|
||||
if (v >= 100000000000L) { return 12; }
|
||||
if (v >= 10000000000L) { return 11; }
|
||||
if (v >= 1000000000L) { return 10; }
|
||||
if (v >= 100000000L) { return 9; }
|
||||
if (v >= 10000000L) { return 8; }
|
||||
if (v >= 1000000L) { return 7; }
|
||||
if (v >= 100000L) { return 6; }
|
||||
if (v >= 10000L) { return 5; }
|
||||
if (v >= 1000L) { return 4; }
|
||||
if (v >= 100L) { return 3; }
|
||||
if (v >= 10L) { return 2; }
|
||||
return 1;
|
||||
}
|
||||
|
||||
// A floating decimal representing m * 10^e.
|
||||
struct floating_decimal_64
|
||||
{
|
||||
std::uint64_t mantissa;
|
||||
// Decimal exponent's range is -324 to 308
|
||||
// inclusive, and can fit in a short if needed.
|
||||
std::int32_t exponent;
|
||||
};
|
||||
|
||||
inline
|
||||
floating_decimal_64
|
||||
d2d(
|
||||
const std::uint64_t ieeeMantissa,
|
||||
const std::uint32_t ieeeExponent)
|
||||
{
|
||||
std::int32_t e2;
|
||||
std::uint64_t m2;
|
||||
if (ieeeExponent == 0)
|
||||
{
|
||||
// We subtract 2 so that the bounds computation has 2 additional bits.
|
||||
e2 = 1 - DOUBLE_BIAS - DOUBLE_MANTISSA_BITS - 2;
|
||||
m2 = ieeeMantissa;
|
||||
}
|
||||
else
|
||||
{
|
||||
e2 = (std::int32_t)ieeeExponent - DOUBLE_BIAS - DOUBLE_MANTISSA_BITS - 2;
|
||||
m2 = (1ull << DOUBLE_MANTISSA_BITS) | ieeeMantissa;
|
||||
}
|
||||
const bool even = (m2 & 1) == 0;
|
||||
const bool acceptBounds = even;
|
||||
|
||||
#ifdef RYU_DEBUG
|
||||
printf("-> %" PRIu64 " * 2^%d\n", m2, e2 + 2);
|
||||
#endif
|
||||
|
||||
// Step 2: Determine the interval of valid decimal representations.
|
||||
const std::uint64_t mv = 4 * m2;
|
||||
// Implicit bool -> int conversion. True is 1, false is 0.
|
||||
const std::uint32_t mmShift = ieeeMantissa != 0 || ieeeExponent <= 1;
|
||||
// We would compute mp and mm like this:
|
||||
// uint64_t mp = 4 * m2 + 2;
|
||||
// uint64_t mm = mv - 1 - mmShift;
|
||||
|
||||
// Step 3: Convert to a decimal power base using 128-bit arithmetic.
|
||||
std::uint64_t vr, vp, vm;
|
||||
std::int32_t e10;
|
||||
bool vmIsTrailingZeros = false;
|
||||
bool vrIsTrailingZeros = false;
|
||||
if (e2 >= 0) {
|
||||
// I tried special-casing q == 0, but there was no effect on performance.
|
||||
// This expression is slightly faster than max(0, log10Pow2(e2) - 1).
|
||||
const std::uint32_t q = log10Pow2(e2) - (e2 > 3);
|
||||
e10 = (std::int32_t)q;
|
||||
const std::int32_t k = DOUBLE_POW5_INV_BITCOUNT + pow5bits((int32_t)q) - 1;
|
||||
const std::int32_t i = -e2 + (std::int32_t)q + k;
|
||||
#if defined(BOOST_JSON_RYU_OPTIMIZE_SIZE)
|
||||
uint64_t pow5[2];
|
||||
double_computeInvPow5(q, pow5);
|
||||
vr = mulShiftAll(m2, pow5, i, &vp, &vm, mmShift);
|
||||
#else
|
||||
vr = mulShiftAll(m2, DOUBLE_POW5_INV_SPLIT()[q], i, &vp, &vm, mmShift);
|
||||
#endif
|
||||
#ifdef RYU_DEBUG
|
||||
printf("%" PRIu64 " * 2^%d / 10^%u\n", mv, e2, q);
|
||||
printf("V+=%" PRIu64 "\nV =%" PRIu64 "\nV-=%" PRIu64 "\n", vp, vr, vm);
|
||||
#endif
|
||||
if (q <= 21)
|
||||
{
|
||||
// This should use q <= 22, but I think 21 is also safe. Smaller values
|
||||
// may still be safe, but it's more difficult to reason about them.
|
||||
// Only one of mp, mv, and mm can be a multiple of 5, if any.
|
||||
const std::uint32_t mvMod5 = ((std::uint32_t)mv) - 5 * ((std::uint32_t)div5(mv));
|
||||
if (mvMod5 == 0)
|
||||
{
|
||||
vrIsTrailingZeros = multipleOfPowerOf5(mv, q);
|
||||
}
|
||||
else if (acceptBounds)
|
||||
{
|
||||
// Same as min(e2 + (~mm & 1), pow5Factor(mm)) >= q
|
||||
// <=> e2 + (~mm & 1) >= q && pow5Factor(mm) >= q
|
||||
// <=> true && pow5Factor(mm) >= q, since e2 >= q.
|
||||
vmIsTrailingZeros = multipleOfPowerOf5(mv - 1 - mmShift, q);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Same as min(e2 + 1, pow5Factor(mp)) >= q.
|
||||
vp -= multipleOfPowerOf5(mv + 2, q);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This expression is slightly faster than max(0, log10Pow5(-e2) - 1).
|
||||
const std::uint32_t q = log10Pow5(-e2) - (-e2 > 1);
|
||||
e10 = (std::int32_t)q + e2;
|
||||
const std::int32_t i = -e2 - (std::int32_t)q;
|
||||
const std::int32_t k = pow5bits(i) - DOUBLE_POW5_BITCOUNT;
|
||||
const std::int32_t j = (std::int32_t)q - k;
|
||||
#if defined(BOOST_JSON_RYU_OPTIMIZE_SIZE)
|
||||
std::uint64_t pow5[2];
|
||||
double_computePow5(i, pow5);
|
||||
vr = mulShiftAll(m2, pow5, j, &vp, &vm, mmShift);
|
||||
#else
|
||||
vr = mulShiftAll(m2, DOUBLE_POW5_SPLIT()[i], j, &vp, &vm, mmShift);
|
||||
#endif
|
||||
#ifdef RYU_DEBUG
|
||||
printf("%" PRIu64 " * 5^%d / 10^%u\n", mv, -e2, q);
|
||||
printf("%u %d %d %d\n", q, i, k, j);
|
||||
printf("V+=%" PRIu64 "\nV =%" PRIu64 "\nV-=%" PRIu64 "\n", vp, vr, vm);
|
||||
#endif
|
||||
if (q <= 1)
|
||||
{
|
||||
// {vr,vp,vm} is trailing zeros if {mv,mp,mm} has at least q trailing 0 bits.
|
||||
// mv = 4 * m2, so it always has at least two trailing 0 bits.
|
||||
vrIsTrailingZeros = true;
|
||||
if (acceptBounds)
|
||||
{
|
||||
// mm = mv - 1 - mmShift, so it has 1 trailing 0 bit iff mmShift == 1.
|
||||
vmIsTrailingZeros = mmShift == 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// mp = mv + 2, so it always has at least one trailing 0 bit.
|
||||
--vp;
|
||||
}
|
||||
}
|
||||
else if (q < 63)
|
||||
{
|
||||
// TODO(ulfjack): Use a tighter bound here.
|
||||
// We want to know if the full product has at least q trailing zeros.
|
||||
// We need to compute min(p2(mv), p5(mv) - e2) >= q
|
||||
// <=> p2(mv) >= q && p5(mv) - e2 >= q
|
||||
// <=> p2(mv) >= q (because -e2 >= q)
|
||||
vrIsTrailingZeros = multipleOfPowerOf2(mv, q);
|
||||
#ifdef RYU_DEBUG
|
||||
printf("vr is trailing zeros=%s\n", vrIsTrailingZeros ? "true" : "false");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef RYU_DEBUG
|
||||
printf("e10=%d\n", e10);
|
||||
printf("V+=%" PRIu64 "\nV =%" PRIu64 "\nV-=%" PRIu64 "\n", vp, vr, vm);
|
||||
printf("vm is trailing zeros=%s\n", vmIsTrailingZeros ? "true" : "false");
|
||||
printf("vr is trailing zeros=%s\n", vrIsTrailingZeros ? "true" : "false");
|
||||
#endif
|
||||
|
||||
// Step 4: Find the shortest decimal representation in the interval of valid representations.
|
||||
std::int32_t removed = 0;
|
||||
std::uint8_t lastRemovedDigit = 0;
|
||||
std::uint64_t output;
|
||||
// On average, we remove ~2 digits.
|
||||
if (vmIsTrailingZeros || vrIsTrailingZeros)
|
||||
{
|
||||
// General case, which happens rarely (~0.7%).
|
||||
for (;;)
|
||||
{
|
||||
const std::uint64_t vpDiv10 = div10(vp);
|
||||
const std::uint64_t vmDiv10 = div10(vm);
|
||||
if (vpDiv10 <= vmDiv10)
|
||||
break;
|
||||
const std::uint32_t vmMod10 = ((std::uint32_t)vm) - 10 * ((std::uint32_t)vmDiv10);
|
||||
const std::uint64_t vrDiv10 = div10(vr);
|
||||
const std::uint32_t vrMod10 = ((std::uint32_t)vr) - 10 * ((std::uint32_t)vrDiv10);
|
||||
vmIsTrailingZeros &= vmMod10 == 0;
|
||||
vrIsTrailingZeros &= lastRemovedDigit == 0;
|
||||
lastRemovedDigit = (uint8_t)vrMod10;
|
||||
vr = vrDiv10;
|
||||
vp = vpDiv10;
|
||||
vm = vmDiv10;
|
||||
++removed;
|
||||
}
|
||||
#ifdef RYU_DEBUG
|
||||
printf("V+=%" PRIu64 "\nV =%" PRIu64 "\nV-=%" PRIu64 "\n", vp, vr, vm);
|
||||
printf("d-10=%s\n", vmIsTrailingZeros ? "true" : "false");
|
||||
#endif
|
||||
if (vmIsTrailingZeros)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
const std::uint64_t vmDiv10 = div10(vm);
|
||||
const std::uint32_t vmMod10 = ((std::uint32_t)vm) - 10 * ((std::uint32_t)vmDiv10);
|
||||
if (vmMod10 != 0)
|
||||
break;
|
||||
const std::uint64_t vpDiv10 = div10(vp);
|
||||
const std::uint64_t vrDiv10 = div10(vr);
|
||||
const std::uint32_t vrMod10 = ((std::uint32_t)vr) - 10 * ((std::uint32_t)vrDiv10);
|
||||
vrIsTrailingZeros &= lastRemovedDigit == 0;
|
||||
lastRemovedDigit = (uint8_t)vrMod10;
|
||||
vr = vrDiv10;
|
||||
vp = vpDiv10;
|
||||
vm = vmDiv10;
|
||||
++removed;
|
||||
}
|
||||
}
|
||||
#ifdef RYU_DEBUG
|
||||
printf("%" PRIu64 " %d\n", vr, lastRemovedDigit);
|
||||
printf("vr is trailing zeros=%s\n", vrIsTrailingZeros ? "true" : "false");
|
||||
#endif
|
||||
if (vrIsTrailingZeros && lastRemovedDigit == 5 && vr % 2 == 0)
|
||||
{
|
||||
// Round even if the exact number is .....50..0.
|
||||
lastRemovedDigit = 4;
|
||||
}
|
||||
// We need to take vr + 1 if vr is outside bounds or we need to round up.
|
||||
output = vr + ((vr == vm && (!acceptBounds || !vmIsTrailingZeros)) || lastRemovedDigit >= 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Specialized for the common case (~99.3%). Percentages below are relative to this.
|
||||
bool roundUp = false;
|
||||
const std::uint64_t vpDiv100 = div100(vp);
|
||||
const std::uint64_t vmDiv100 = div100(vm);
|
||||
if (vpDiv100 > vmDiv100)
|
||||
{
|
||||
// Optimization: remove two digits at a time (~86.2%).
|
||||
const std::uint64_t vrDiv100 = div100(vr);
|
||||
const std::uint32_t vrMod100 = ((std::uint32_t)vr) - 100 * ((std::uint32_t)vrDiv100);
|
||||
roundUp = vrMod100 >= 50;
|
||||
vr = vrDiv100;
|
||||
vp = vpDiv100;
|
||||
vm = vmDiv100;
|
||||
removed += 2;
|
||||
}
|
||||
// Loop iterations below (approximately), without optimization above:
|
||||
// 0: 0.03%, 1: 13.8%, 2: 70.6%, 3: 14.0%, 4: 1.40%, 5: 0.14%, 6+: 0.02%
|
||||
// Loop iterations below (approximately), with optimization above:
|
||||
// 0: 70.6%, 1: 27.8%, 2: 1.40%, 3: 0.14%, 4+: 0.02%
|
||||
for (;;)
|
||||
{
|
||||
const std::uint64_t vpDiv10 = div10(vp);
|
||||
const std::uint64_t vmDiv10 = div10(vm);
|
||||
if (vpDiv10 <= vmDiv10)
|
||||
break;
|
||||
const std::uint64_t vrDiv10 = div10(vr);
|
||||
const std::uint32_t vrMod10 = ((std::uint32_t)vr) - 10 * ((std::uint32_t)vrDiv10);
|
||||
roundUp = vrMod10 >= 5;
|
||||
vr = vrDiv10;
|
||||
vp = vpDiv10;
|
||||
vm = vmDiv10;
|
||||
++removed;
|
||||
}
|
||||
#ifdef RYU_DEBUG
|
||||
printf("%" PRIu64 " roundUp=%s\n", vr, roundUp ? "true" : "false");
|
||||
printf("vr is trailing zeros=%s\n", vrIsTrailingZeros ? "true" : "false");
|
||||
#endif
|
||||
// We need to take vr + 1 if vr is outside bounds or we need to round up.
|
||||
output = vr + (vr == vm || roundUp);
|
||||
}
|
||||
const std::int32_t exp = e10 + removed;
|
||||
|
||||
#ifdef RYU_DEBUG
|
||||
printf("V+=%" PRIu64 "\nV =%" PRIu64 "\nV-=%" PRIu64 "\n", vp, vr, vm);
|
||||
printf("O=%" PRIu64 "\n", output);
|
||||
printf("EXP=%d\n", exp);
|
||||
#endif
|
||||
|
||||
floating_decimal_64 fd;
|
||||
fd.exponent = exp;
|
||||
fd.mantissa = output;
|
||||
return fd;
|
||||
}
|
||||
|
||||
inline
|
||||
int
|
||||
to_chars(
|
||||
const floating_decimal_64 v,
|
||||
const bool sign,
|
||||
char* const result)
|
||||
{
|
||||
// Step 5: Print the decimal representation.
|
||||
int index = 0;
|
||||
if (sign)
|
||||
result[index++] = '-';
|
||||
|
||||
std::uint64_t output = v.mantissa;
|
||||
std::uint32_t const olength = decimalLength17(output);
|
||||
|
||||
#ifdef RYU_DEBUG
|
||||
printf("DIGITS=%" PRIu64 "\n", v.mantissa);
|
||||
printf("OLEN=%u\n", olength);
|
||||
printf("EXP=%u\n", v.exponent + olength);
|
||||
#endif
|
||||
|
||||
// Print the decimal digits.
|
||||
// The following code is equivalent to:
|
||||
// for (uint32_t i = 0; i < olength - 1; ++i) {
|
||||
// const uint32_t c = output % 10; output /= 10;
|
||||
// result[index + olength - i] = (char) ('0' + c);
|
||||
// }
|
||||
// result[index] = '0' + output % 10;
|
||||
|
||||
std::uint32_t i = 0;
|
||||
// We prefer 32-bit operations, even on 64-bit platforms.
|
||||
// We have at most 17 digits, and uint32_t can store 9 digits.
|
||||
// If output doesn't fit into uint32_t, we cut off 8 digits,
|
||||
// so the rest will fit into uint32_t.
|
||||
if ((output >> 32) != 0)
|
||||
{
|
||||
// Expensive 64-bit division.
|
||||
std::uint64_t const q = div1e8(output);
|
||||
std::uint32_t output2 = ((std::uint32_t)output) - 100000000 * ((std::uint32_t)q);
|
||||
output = q;
|
||||
|
||||
const std::uint32_t c = output2 % 10000;
|
||||
output2 /= 10000;
|
||||
const std::uint32_t d = output2 % 10000;
|
||||
const std::uint32_t c0 = (c % 100) << 1;
|
||||
const std::uint32_t c1 = (c / 100) << 1;
|
||||
const std::uint32_t d0 = (d % 100) << 1;
|
||||
const std::uint32_t d1 = (d / 100) << 1;
|
||||
std::memcpy(result + index + olength - i - 1, DIGIT_TABLE() + c0, 2);
|
||||
std::memcpy(result + index + olength - i - 3, DIGIT_TABLE() + c1, 2);
|
||||
std::memcpy(result + index + olength - i - 5, DIGIT_TABLE() + d0, 2);
|
||||
std::memcpy(result + index + olength - i - 7, DIGIT_TABLE() + d1, 2);
|
||||
i += 8;
|
||||
}
|
||||
uint32_t output2 = (std::uint32_t)output;
|
||||
while (output2 >= 10000)
|
||||
{
|
||||
#ifdef __clang__ // https://bugs.llvm.org/show_bug.cgi?id=38217
|
||||
const uint32_t c = output2 - 10000 * (output2 / 10000);
|
||||
#else
|
||||
const uint32_t c = output2 % 10000;
|
||||
#endif
|
||||
output2 /= 10000;
|
||||
const uint32_t c0 = (c % 100) << 1;
|
||||
const uint32_t c1 = (c / 100) << 1;
|
||||
memcpy(result + index + olength - i - 1, DIGIT_TABLE() + c0, 2);
|
||||
memcpy(result + index + olength - i - 3, DIGIT_TABLE() + c1, 2);
|
||||
i += 4;
|
||||
}
|
||||
if (output2 >= 100) {
|
||||
const uint32_t c = (output2 % 100) << 1;
|
||||
output2 /= 100;
|
||||
memcpy(result + index + olength - i - 1, DIGIT_TABLE() + c, 2);
|
||||
i += 2;
|
||||
}
|
||||
if (output2 >= 10) {
|
||||
const uint32_t c = output2 << 1;
|
||||
// We can't use memcpy here: the decimal dot goes between these two digits.
|
||||
result[index + olength - i] = DIGIT_TABLE()[c + 1];
|
||||
result[index] = DIGIT_TABLE()[c];
|
||||
}
|
||||
else {
|
||||
result[index] = (char)('0' + output2);
|
||||
}
|
||||
|
||||
// Print decimal point if needed.
|
||||
if (olength > 1) {
|
||||
result[index + 1] = '.';
|
||||
index += olength + 1;
|
||||
}
|
||||
else {
|
||||
++index;
|
||||
}
|
||||
|
||||
// Print the exponent.
|
||||
result[index++] = 'E';
|
||||
int32_t exp = v.exponent + (int32_t)olength - 1;
|
||||
if (exp < 0) {
|
||||
result[index++] = '-';
|
||||
exp = -exp;
|
||||
}
|
||||
|
||||
if (exp >= 100) {
|
||||
const int32_t c = exp % 10;
|
||||
memcpy(result + index, DIGIT_TABLE() + 2 * (exp / 10), 2);
|
||||
result[index + 2] = (char)('0' + c);
|
||||
index += 3;
|
||||
}
|
||||
else if (exp >= 10) {
|
||||
memcpy(result + index, DIGIT_TABLE() + 2 * exp, 2);
|
||||
index += 2;
|
||||
}
|
||||
else {
|
||||
result[index++] = (char)('0' + exp);
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
static inline bool d2d_small_int(const uint64_t ieeeMantissa, const uint32_t ieeeExponent,
|
||||
floating_decimal_64* const v) {
|
||||
const uint64_t m2 = (1ull << DOUBLE_MANTISSA_BITS) | ieeeMantissa;
|
||||
const int32_t e2 = (int32_t) ieeeExponent - DOUBLE_BIAS - DOUBLE_MANTISSA_BITS;
|
||||
|
||||
if (e2 > 0) {
|
||||
// f = m2 * 2^e2 >= 2^53 is an integer.
|
||||
// Ignore this case for now.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e2 < -52) {
|
||||
// f < 1.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Since 2^52 <= m2 < 2^53 and 0 <= -e2 <= 52: 1 <= f = m2 / 2^-e2 < 2^53.
|
||||
// Test if the lower -e2 bits of the significand are 0, i.e. whether the fraction is 0.
|
||||
const uint64_t mask = (1ull << -e2) - 1;
|
||||
const uint64_t fraction = m2 & mask;
|
||||
if (fraction != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// f is an integer in the range [1, 2^53).
|
||||
// Note: mantissa might contain trailing (decimal) 0's.
|
||||
// Note: since 2^53 < 10^16, there is no need to adjust decimalLength17().
|
||||
v->mantissa = m2 >> -e2;
|
||||
v->exponent = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
int
|
||||
d2s_buffered_n(
|
||||
double f,
|
||||
char* result) noexcept
|
||||
{
|
||||
using namespace detail;
|
||||
// Step 1: Decode the floating-point number, and unify normalized and subnormal cases.
|
||||
std::uint64_t const bits = double_to_bits(f);
|
||||
|
||||
#ifdef RYU_DEBUG
|
||||
printf("IN=");
|
||||
for (std::int32_t bit = 63; bit >= 0; --bit) {
|
||||
printf("%d", (int)((bits >> bit) & 1));
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
// Decode bits into sign, mantissa, and exponent.
|
||||
const bool ieeeSign = ((bits >> (DOUBLE_MANTISSA_BITS + DOUBLE_EXPONENT_BITS)) & 1) != 0;
|
||||
const std::uint64_t ieeeMantissa = bits & ((1ull << DOUBLE_MANTISSA_BITS) - 1);
|
||||
const std::uint32_t ieeeExponent = (std::uint32_t)((bits >> DOUBLE_MANTISSA_BITS) & ((1u << DOUBLE_EXPONENT_BITS) - 1));
|
||||
// Case distinction; exit early for the easy cases.
|
||||
if (ieeeExponent == ((1u << DOUBLE_EXPONENT_BITS) - 1u) || (ieeeExponent == 0 && ieeeMantissa == 0)) {
|
||||
return copy_special_str(result, ieeeSign, ieeeExponent != 0, ieeeMantissa != 0);
|
||||
}
|
||||
|
||||
floating_decimal_64 v;
|
||||
const bool isSmallInt = d2d_small_int(ieeeMantissa, ieeeExponent, &v);
|
||||
if (isSmallInt) {
|
||||
// For small integers in the range [1, 2^53), v.mantissa might contain trailing (decimal) zeros.
|
||||
// For scientific notation we need to move these zeros into the exponent.
|
||||
// (This is not needed for fixed-point notation, so it might be beneficial to trim
|
||||
// trailing zeros in to_chars only if needed - once fixed-point notation output is implemented.)
|
||||
for (;;) {
|
||||
std::uint64_t const q = div10(v.mantissa);
|
||||
std::uint32_t const r = ((std::uint32_t) v.mantissa) - 10 * ((std::uint32_t) q);
|
||||
if (r != 0)
|
||||
break;
|
||||
v.mantissa = q;
|
||||
++v.exponent;
|
||||
}
|
||||
}
|
||||
else {
|
||||
v = d2d(ieeeMantissa, ieeeExponent);
|
||||
}
|
||||
|
||||
return to_chars(v, ieeeSign, result);
|
||||
}
|
||||
|
||||
void
|
||||
d2s_buffered(
|
||||
double f,
|
||||
char* result) noexcept
|
||||
{
|
||||
const int index = d2s_buffered_n(f, result);
|
||||
|
||||
// Terminate the string.
|
||||
result[index] = '\0';
|
||||
}
|
||||
|
||||
char*
|
||||
d2s(double f) noexcept
|
||||
{
|
||||
static thread_local char result[25];
|
||||
d2s_buffered(f, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // ryu
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
46
install/boost_1_75_0/include/boost/json/detail/ryu/ryu.hpp
Normal file
46
install/boost_1_75_0/include/boost/json/detail/ryu/ryu.hpp
Normal file
@@ -0,0 +1,46 @@
|
||||
// Copyright 2018 Ulf Adams
|
||||
//
|
||||
// The contents of this file may be used under the terms of the Apache License,
|
||||
// Version 2.0.
|
||||
//
|
||||
// (See accompanying file LICENSE-Apache or copy at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0)
|
||||
//
|
||||
// Alternatively, the contents of this file may be used under the terms of
|
||||
// the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE-Boost or copy at
|
||||
// https://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, this software
|
||||
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied.
|
||||
|
||||
/*
|
||||
This is a derivative work
|
||||
*/
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_RYU_HPP
|
||||
#define BOOST_JSON_DETAIL_RYU_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
namespace ryu {
|
||||
|
||||
BOOST_JSON_DECL
|
||||
int d2s_buffered_n(double f, char* result) noexcept;
|
||||
|
||||
BOOST_JSON_DECL
|
||||
void d2s_buffered(double f, char* result) noexcept;
|
||||
|
||||
BOOST_JSON_DECL
|
||||
char* d2s(double f) noexcept;
|
||||
|
||||
} // ryu
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,85 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_SHARED_RESOURCE_HPP
|
||||
#define BOOST_JSON_DETAIL_SHARED_RESOURCE_HPP
|
||||
|
||||
#include <boost/json/memory_resource.hpp>
|
||||
#include <atomic>
|
||||
#include <utility>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4275) // non dll-interface class used as base for dll-interface class
|
||||
#endif
|
||||
|
||||
struct BOOST_SYMBOL_VISIBLE
|
||||
shared_resource
|
||||
: memory_resource
|
||||
{
|
||||
BOOST_JSON_DECL
|
||||
shared_resource();
|
||||
|
||||
BOOST_JSON_DECL
|
||||
~shared_resource();
|
||||
|
||||
std::atomic<std::size_t> refs{ 1 };
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class shared_resource_impl final
|
||||
: public shared_resource
|
||||
{
|
||||
T t;
|
||||
|
||||
public:
|
||||
template<class... Args>
|
||||
shared_resource_impl(
|
||||
Args&&... args)
|
||||
: t(std::forward<Args>(args)...)
|
||||
{
|
||||
}
|
||||
|
||||
void*
|
||||
do_allocate(
|
||||
std::size_t n,
|
||||
std::size_t align) override
|
||||
{
|
||||
return t.allocate(n, align);
|
||||
}
|
||||
|
||||
void
|
||||
do_deallocate(
|
||||
void* p,
|
||||
std::size_t n,
|
||||
std::size_t align) override
|
||||
{
|
||||
return t.deallocate(p, n, align);
|
||||
}
|
||||
|
||||
bool
|
||||
do_is_equal(
|
||||
memory_resource const&) const noexcept override
|
||||
{
|
||||
// VFALCO Is always false ok?
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
547
install/boost_1_75_0/include/boost/json/detail/sse2.hpp
Normal file
547
install/boost_1_75_0/include/boost/json/detail/sse2.hpp
Normal file
@@ -0,0 +1,547 @@
|
||||
//
|
||||
// Copyright (c) 2019 Peter Dimov (pdimov at gmail dot com),
|
||||
// Vinnie Falco (vinnie.falco@gmail.com)
|
||||
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_SSE2_HPP
|
||||
#define BOOST_JSON_DETAIL_SSE2_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/detail/utf8.hpp>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#ifdef BOOST_JSON_USE_SSE2
|
||||
# include <emmintrin.h>
|
||||
# include <xmmintrin.h>
|
||||
# ifdef _MSC_VER
|
||||
# include <intrin.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
#ifdef BOOST_JSON_USE_SSE2
|
||||
|
||||
template<bool AllowBadUTF8>
|
||||
inline
|
||||
const char*
|
||||
count_valid(
|
||||
char const* p,
|
||||
const char* end) noexcept
|
||||
{
|
||||
__m128i const q1 = _mm_set1_epi8( '\x22' ); // '"'
|
||||
__m128i const q2 = _mm_set1_epi8( '\\' ); // '\\'
|
||||
__m128i const q3 = _mm_set1_epi8( 0x1F );
|
||||
|
||||
while(end - p >= 16)
|
||||
{
|
||||
__m128i v1 = _mm_loadu_si128( (__m128i const*)p );
|
||||
__m128i v2 = _mm_cmpeq_epi8( v1, q1 ); // quote
|
||||
__m128i v3 = _mm_cmpeq_epi8( v1, q2 ); // backslash
|
||||
__m128i v4 = _mm_or_si128( v2, v3 ); // combine quotes and backslash
|
||||
__m128i v5 = _mm_min_epu8( v1, q3 );
|
||||
__m128i v6 = _mm_cmpeq_epi8( v5, v1 ); // controls
|
||||
__m128i v7 = _mm_or_si128( v4, v6 ); // combine with control
|
||||
|
||||
int w = _mm_movemask_epi8( v7 );
|
||||
|
||||
if( w != 0 )
|
||||
{
|
||||
int m;
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
m = __builtin_ffs( w ) - 1;
|
||||
#else
|
||||
unsigned long index;
|
||||
_BitScanForward( &index, w );
|
||||
m = index;
|
||||
#endif
|
||||
return p + m;
|
||||
}
|
||||
|
||||
p += 16;
|
||||
}
|
||||
|
||||
while(p != end)
|
||||
{
|
||||
const unsigned char c = *p;
|
||||
if(c == '\x22' || c == '\\' || c < 0x20)
|
||||
break;
|
||||
++p;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline
|
||||
const char*
|
||||
count_valid<false>(
|
||||
char const* p,
|
||||
const char* end) noexcept
|
||||
{
|
||||
__m128i const q1 = _mm_set1_epi8( '\x22' ); // '"'
|
||||
__m128i const q2 = _mm_set1_epi8( '\\' );
|
||||
__m128i const q3 = _mm_set1_epi8( 0x20 );
|
||||
|
||||
while(end - p >= 16)
|
||||
{
|
||||
__m128i v1 = _mm_loadu_si128( (__m128i const*)p );
|
||||
|
||||
__m128i v2 = _mm_cmpeq_epi8( v1, q1 );
|
||||
__m128i v3 = _mm_cmpeq_epi8( v1, q2 );
|
||||
__m128i v4 = _mm_cmplt_epi8( v1, q3 );
|
||||
|
||||
__m128i v5 = _mm_or_si128( v2, v3 );
|
||||
__m128i v6 = _mm_or_si128( v5, v4 );
|
||||
|
||||
int w = _mm_movemask_epi8( v6 );
|
||||
|
||||
if( w != 0 )
|
||||
{
|
||||
int m;
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
m = __builtin_ffs( w ) - 1;
|
||||
#else
|
||||
unsigned long index;
|
||||
_BitScanForward( &index, w );
|
||||
m = index;
|
||||
#endif
|
||||
p += m;
|
||||
break;
|
||||
}
|
||||
|
||||
p += 16;
|
||||
}
|
||||
|
||||
while(p != end)
|
||||
{
|
||||
const unsigned char c = *p;
|
||||
if(c == '\x22' || c == '\\' || c < 0x20)
|
||||
break;
|
||||
if(c < 0x80)
|
||||
{
|
||||
++p;
|
||||
continue;
|
||||
}
|
||||
// validate utf-8
|
||||
uint16_t first = classify_utf8(c & 0x7F);
|
||||
uint8_t len = first & 0xFF;
|
||||
if(BOOST_JSON_UNLIKELY(end - p < len))
|
||||
break;
|
||||
if(BOOST_JSON_UNLIKELY(! is_valid_utf8(p, first)))
|
||||
break;
|
||||
p += len;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template<bool AllowBadUTF8>
|
||||
char const*
|
||||
count_valid(
|
||||
char const* p,
|
||||
char const* end) noexcept
|
||||
{
|
||||
while(p != end)
|
||||
{
|
||||
const unsigned char c = *p;
|
||||
if(c == '\x22' || c == '\\' || c < 0x20)
|
||||
break;
|
||||
++p;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline
|
||||
char const*
|
||||
count_valid<false>(
|
||||
char const* p,
|
||||
char const* end) noexcept
|
||||
{
|
||||
while(p != end)
|
||||
{
|
||||
const unsigned char c = *p;
|
||||
if(c == '\x22' || c == '\\' || c < 0x20)
|
||||
break;
|
||||
if(c < 0x80)
|
||||
{
|
||||
++p;
|
||||
continue;
|
||||
}
|
||||
// validate utf-8
|
||||
uint16_t first = classify_utf8(c & 0x7F);
|
||||
uint8_t len = first & 0xFF;
|
||||
if(BOOST_JSON_UNLIKELY(end - p < len))
|
||||
break;
|
||||
if(BOOST_JSON_UNLIKELY(! is_valid_utf8(p, first)))
|
||||
break;
|
||||
p += len;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// KRYSTIAN NOTE: does not stop to validate
|
||||
// count_unescaped
|
||||
|
||||
#ifdef BOOST_JSON_USE_SSE2
|
||||
|
||||
inline
|
||||
size_t
|
||||
count_unescaped(
|
||||
char const* s,
|
||||
size_t n) noexcept
|
||||
{
|
||||
|
||||
__m128i const q1 = _mm_set1_epi8( '\x22' ); // '"'
|
||||
__m128i const q2 = _mm_set1_epi8( '\\' ); // '\\'
|
||||
__m128i const q3 = _mm_set1_epi8( 0x1F );
|
||||
|
||||
char const * s0 = s;
|
||||
|
||||
while( n >= 16 )
|
||||
{
|
||||
__m128i v1 = _mm_loadu_si128( (__m128i const*)s );
|
||||
__m128i v2 = _mm_cmpeq_epi8( v1, q1 ); // quote
|
||||
__m128i v3 = _mm_cmpeq_epi8( v1, q2 ); // backslash
|
||||
__m128i v4 = _mm_or_si128( v2, v3 ); // combine quotes and backslash
|
||||
__m128i v5 = _mm_min_epu8( v1, q3 );
|
||||
__m128i v6 = _mm_cmpeq_epi8( v5, v1 ); // controls
|
||||
__m128i v7 = _mm_or_si128( v4, v6 ); // combine with control
|
||||
|
||||
int w = _mm_movemask_epi8( v7 );
|
||||
|
||||
if( w != 0 )
|
||||
{
|
||||
int m;
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
m = __builtin_ffs( w ) - 1;
|
||||
#else
|
||||
unsigned long index;
|
||||
_BitScanForward( &index, w );
|
||||
m = index;
|
||||
#endif
|
||||
|
||||
s += m;
|
||||
break;
|
||||
}
|
||||
|
||||
s += 16;
|
||||
n -= 16;
|
||||
}
|
||||
|
||||
return s - s0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline
|
||||
std::size_t
|
||||
count_unescaped(
|
||||
char const*,
|
||||
std::size_t) noexcept
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// count_digits
|
||||
|
||||
#ifdef BOOST_JSON_USE_SSE2
|
||||
|
||||
// assumes p..p+15 are valid
|
||||
inline int count_digits( char const* p ) noexcept
|
||||
{
|
||||
__m128i v1 = _mm_loadu_si128( (__m128i const*)p );
|
||||
v1 = _mm_add_epi8(v1, _mm_set1_epi8(70));
|
||||
v1 = _mm_cmplt_epi8(v1, _mm_set1_epi8(118));
|
||||
|
||||
int m = _mm_movemask_epi8(v1);
|
||||
|
||||
int n;
|
||||
|
||||
if( m == 0 )
|
||||
{
|
||||
n = 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
n = __builtin_ffs( m ) - 1;
|
||||
#else
|
||||
unsigned long index;
|
||||
_BitScanForward( &index, m );
|
||||
n = static_cast<int>(index);
|
||||
#endif
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// assumes p..p+15 are valid
|
||||
inline int count_digits( char const* p ) noexcept
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
for( ; n < 16; ++n )
|
||||
{
|
||||
unsigned char const d = *p++ - '0';
|
||||
if(d > 9) break;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// parse_unsigned
|
||||
|
||||
inline uint64_t parse_unsigned( uint64_t r, char const * p, std::size_t n ) noexcept
|
||||
{
|
||||
while( n >= 4 )
|
||||
{
|
||||
// faster on on clang for x86,
|
||||
// slower on gcc
|
||||
#ifdef __clang__
|
||||
r = r * 10 + p[0] - '0';
|
||||
r = r * 10 + p[1] - '0';
|
||||
r = r * 10 + p[2] - '0';
|
||||
r = r * 10 + p[3] - '0';
|
||||
#else
|
||||
uint32_t v;
|
||||
std::memcpy( &v, p, 4 );
|
||||
|
||||
v -= 0x30303030;
|
||||
|
||||
unsigned w0 = v & 0xFF;
|
||||
unsigned w1 = (v >> 8) & 0xFF;
|
||||
unsigned w2 = (v >> 16) & 0xFF;
|
||||
unsigned w3 = (v >> 24);
|
||||
|
||||
#ifdef BOOST_JSON_BIG_ENDIAN
|
||||
r = (((r * 10 + w3) * 10 + w2) * 10 + w1) * 10 + w0;
|
||||
#else
|
||||
r = (((r * 10 + w0) * 10 + w1) * 10 + w2) * 10 + w3;
|
||||
#endif
|
||||
#endif
|
||||
p += 4;
|
||||
n -= 4;
|
||||
}
|
||||
|
||||
switch( n )
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
r = r * 10 + p[0] - '0';
|
||||
break;
|
||||
case 2:
|
||||
r = r * 10 + p[0] - '0';
|
||||
r = r * 10 + p[1] - '0';
|
||||
break;
|
||||
case 3:
|
||||
r = r * 10 + p[0] - '0';
|
||||
r = r * 10 + p[1] - '0';
|
||||
r = r * 10 + p[2] - '0';
|
||||
break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
// KRYSTIAN: this function is unused
|
||||
// count_leading
|
||||
|
||||
/*
|
||||
#ifdef BOOST_JSON_USE_SSE2
|
||||
|
||||
// assumes p..p+15
|
||||
inline std::size_t count_leading( char const * p, char ch ) noexcept
|
||||
{
|
||||
__m128i const q1 = _mm_set1_epi8( ch );
|
||||
|
||||
__m128i v = _mm_loadu_si128( (__m128i const*)p );
|
||||
|
||||
__m128i w = _mm_cmpeq_epi8( v, q1 );
|
||||
|
||||
int m = _mm_movemask_epi8( w ) ^ 0xFFFF;
|
||||
|
||||
std::size_t n;
|
||||
|
||||
if( m == 0 )
|
||||
{
|
||||
n = 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
n = __builtin_ffs( m ) - 1;
|
||||
#else
|
||||
unsigned long index;
|
||||
_BitScanForward( &index, m );
|
||||
n = index;
|
||||
#endif
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// assumes p..p+15
|
||||
inline std::size_t count_leading( char const * p, char ch ) noexcept
|
||||
{
|
||||
std::size_t n = 0;
|
||||
|
||||
for( ; n < 16 && *p == ch; ++p, ++n );
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
#endif
|
||||
*/
|
||||
|
||||
// count_whitespace
|
||||
|
||||
#ifdef BOOST_JSON_USE_SSE2
|
||||
|
||||
inline const char* count_whitespace( char const* p, const char* end ) noexcept
|
||||
{
|
||||
if( p == end )
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
if( static_cast<unsigned char>( *p ) > 0x20 )
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
__m128i const q1 = _mm_set1_epi8( ' ' );
|
||||
__m128i const q2 = _mm_set1_epi8( '\n' );
|
||||
__m128i const q3 = _mm_set1_epi8( 4 ); // '\t' | 4 == '\r'
|
||||
__m128i const q4 = _mm_set1_epi8( '\r' );
|
||||
|
||||
while( end - p >= 16 )
|
||||
{
|
||||
__m128i v0 = _mm_loadu_si128( (__m128i const*)p );
|
||||
|
||||
__m128i w0 = _mm_or_si128(
|
||||
_mm_cmpeq_epi8( v0, q1 ),
|
||||
_mm_cmpeq_epi8( v0, q2 ));
|
||||
__m128i v1 = _mm_or_si128( v0, q3 );
|
||||
__m128i w1 = _mm_cmpeq_epi8( v1, q4 );
|
||||
__m128i w2 = _mm_or_si128( w0, w1 );
|
||||
|
||||
int m = _mm_movemask_epi8( w2 ) ^ 0xFFFF;
|
||||
|
||||
if( m != 0 )
|
||||
{
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
std::size_t c = __builtin_ffs( m ) - 1;
|
||||
#else
|
||||
unsigned long index;
|
||||
_BitScanForward( &index, m );
|
||||
std::size_t c = index;
|
||||
#endif
|
||||
|
||||
p += c;
|
||||
return p;
|
||||
}
|
||||
|
||||
p += 16;
|
||||
}
|
||||
|
||||
while( p != end )
|
||||
{
|
||||
if( *p != ' ' && *p != '\t' && *p != '\r' && *p != '\n' )
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
++p;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
// slightly faster on msvc-14.2, slightly slower on clang-win
|
||||
|
||||
inline std::size_t count_whitespace( char const * p, std::size_t n ) noexcept
|
||||
{
|
||||
char const * p0 = p;
|
||||
|
||||
while( n > 0 )
|
||||
{
|
||||
char ch = *p;
|
||||
|
||||
if( ch == '\n' || ch == '\r' )
|
||||
{
|
||||
++p;
|
||||
--n;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( ch != ' ' && ch != '\t' )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
++p;
|
||||
--n;
|
||||
|
||||
while( n >= 16 )
|
||||
{
|
||||
std::size_t n2 = count_leading( p, ch );
|
||||
|
||||
p += n2;
|
||||
n -= n2;
|
||||
|
||||
if( n2 < 16 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return p - p0;
|
||||
}
|
||||
*/
|
||||
|
||||
#else
|
||||
|
||||
inline const char* count_whitespace( char const* p, const char* end ) noexcept
|
||||
{
|
||||
|
||||
for(; p != end; ++p)
|
||||
{
|
||||
char const c = *p;
|
||||
if( c != ' ' && c != '\n' && c != '\r' && c != '\t' ) break;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
99
install/boost_1_75_0/include/boost/json/detail/stack.hpp
Normal file
99
install/boost_1_75_0/include/boost/json/detail/stack.hpp
Normal file
@@ -0,0 +1,99 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_STACK_HPP
|
||||
#define BOOST_JSON_DETAIL_STACK_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/storage_ptr.hpp>
|
||||
#include <cstring>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
class stack
|
||||
{
|
||||
storage_ptr sp_;
|
||||
std::size_t cap_ = 0;
|
||||
std::size_t size_ = 0;
|
||||
char* buf_ = nullptr;
|
||||
|
||||
public:
|
||||
BOOST_JSON_DECL
|
||||
~stack();
|
||||
|
||||
bool
|
||||
empty() const noexcept
|
||||
{
|
||||
return size_ == 0;
|
||||
}
|
||||
|
||||
void
|
||||
clear() noexcept
|
||||
{
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
reserve(std::size_t n);
|
||||
|
||||
template<class T>
|
||||
void
|
||||
push(T const& t)
|
||||
{
|
||||
auto const n = sizeof(T);
|
||||
// If this assert goes off, it
|
||||
// means the calling code did not
|
||||
// reserve enough to prevent a
|
||||
// reallocation.
|
||||
//BOOST_ASSERT(cap_ >= size_ + n);
|
||||
reserve(size_ + n);
|
||||
std::memcpy(
|
||||
buf_ + size_, &t, n);
|
||||
size_ += n;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
push_unchecked(T const& t)
|
||||
{
|
||||
auto const n = sizeof(T);
|
||||
BOOST_ASSERT(size_ + n <= cap_);
|
||||
std::memcpy(
|
||||
buf_ + size_, &t, n);
|
||||
size_ += n;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
peek(T& t)
|
||||
{
|
||||
auto const n = sizeof(T);
|
||||
BOOST_ASSERT(size_ >= n);
|
||||
std::memcpy(&t,
|
||||
buf_ + size_ - n, n);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
pop(T& t)
|
||||
{
|
||||
auto const n = sizeof(T);
|
||||
BOOST_ASSERT(size_ >= n);
|
||||
size_ -= n;
|
||||
std::memcpy(
|
||||
&t, buf_ + size_, n);
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
350
install/boost_1_75_0/include/boost/json/detail/stream.hpp
Normal file
350
install/boost_1_75_0/include/boost/json/detail/stream.hpp
Normal file
@@ -0,0 +1,350 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_STREAM_HPP
|
||||
#define BOOST_JSON_DETAIL_STREAM_HPP
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
class const_stream
|
||||
{
|
||||
friend class local_const_stream;
|
||||
|
||||
char const* p_;
|
||||
char const* end_;
|
||||
|
||||
public:
|
||||
const_stream() = default;
|
||||
const_stream(
|
||||
const_stream const&) = default;
|
||||
|
||||
const_stream(
|
||||
char const* data,
|
||||
std::size_t size) noexcept
|
||||
: p_(data)
|
||||
, end_(data + size)
|
||||
{
|
||||
}
|
||||
|
||||
size_t
|
||||
used(char const* begin) const noexcept
|
||||
{
|
||||
return static_cast<
|
||||
size_t>(p_ - begin);
|
||||
}
|
||||
|
||||
size_t
|
||||
remain() const noexcept
|
||||
{
|
||||
return end_ - p_;
|
||||
}
|
||||
|
||||
char const*
|
||||
data() const noexcept
|
||||
{
|
||||
return p_;
|
||||
}
|
||||
|
||||
operator bool() const noexcept
|
||||
{
|
||||
return p_ < end_;
|
||||
}
|
||||
|
||||
// unchecked
|
||||
char
|
||||
operator*() const noexcept
|
||||
{
|
||||
BOOST_ASSERT(p_ < end_);
|
||||
return *p_;
|
||||
}
|
||||
|
||||
// unchecked
|
||||
const_stream&
|
||||
operator++() noexcept
|
||||
{
|
||||
BOOST_ASSERT(p_ < end_);
|
||||
++p_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
skip(std::size_t n) noexcept
|
||||
{
|
||||
BOOST_ASSERT(n <= remain());
|
||||
p_ += n;
|
||||
}
|
||||
|
||||
void
|
||||
skip_to(const char* p) noexcept
|
||||
{
|
||||
BOOST_ASSERT(p <= end_ && p >= p_);
|
||||
p_ = p;
|
||||
}
|
||||
};
|
||||
|
||||
class local_const_stream
|
||||
: public const_stream
|
||||
{
|
||||
const_stream& src_;
|
||||
|
||||
public:
|
||||
explicit
|
||||
local_const_stream(
|
||||
const_stream& src) noexcept
|
||||
: const_stream(src)
|
||||
, src_(src)
|
||||
{
|
||||
}
|
||||
|
||||
~local_const_stream()
|
||||
{
|
||||
src_.p_ = p_;
|
||||
}
|
||||
|
||||
void
|
||||
clip(std::size_t n) noexcept
|
||||
{
|
||||
if(static_cast<std::size_t>(
|
||||
src_.end_ - p_) > n)
|
||||
end_ = p_ + n;
|
||||
else
|
||||
end_ = src_.end_;
|
||||
}
|
||||
};
|
||||
|
||||
class const_stream_wrapper
|
||||
{
|
||||
const char*& p_;
|
||||
const char* const end_;
|
||||
|
||||
friend class clipped_const_stream;
|
||||
public:
|
||||
const_stream_wrapper(
|
||||
const char*& p,
|
||||
const char* end)
|
||||
: p_(p)
|
||||
, end_(end)
|
||||
{
|
||||
}
|
||||
|
||||
void operator++() noexcept
|
||||
{
|
||||
++p_;
|
||||
}
|
||||
|
||||
void operator+=(std::size_t n) noexcept
|
||||
{
|
||||
p_ += n;
|
||||
}
|
||||
|
||||
void operator=(const char* p) noexcept
|
||||
{
|
||||
p_ = p;
|
||||
}
|
||||
|
||||
char operator*() const noexcept
|
||||
{
|
||||
return *p_;
|
||||
}
|
||||
|
||||
operator bool() const noexcept
|
||||
{
|
||||
return p_ < end_;
|
||||
}
|
||||
|
||||
const char* begin() const noexcept
|
||||
{
|
||||
return p_;
|
||||
}
|
||||
|
||||
const char* end() const noexcept
|
||||
{
|
||||
return end_;
|
||||
}
|
||||
|
||||
std::size_t remain() const noexcept
|
||||
{
|
||||
return end_ - p_;
|
||||
}
|
||||
|
||||
std::size_t remain(const char* p) const noexcept
|
||||
{
|
||||
return end_ - p;
|
||||
}
|
||||
|
||||
std::size_t used(const char* p) const noexcept
|
||||
{
|
||||
return p_ - p;
|
||||
}
|
||||
};
|
||||
|
||||
class clipped_const_stream
|
||||
: public const_stream_wrapper
|
||||
{
|
||||
const char* clip_;
|
||||
|
||||
public:
|
||||
clipped_const_stream(
|
||||
const char*& p,
|
||||
const char* end)
|
||||
: const_stream_wrapper(p, end)
|
||||
, clip_(end)
|
||||
{
|
||||
}
|
||||
|
||||
void operator=(const char* p)
|
||||
{
|
||||
p_ = p;
|
||||
}
|
||||
|
||||
const char* end() const noexcept
|
||||
{
|
||||
return clip_;
|
||||
}
|
||||
|
||||
operator bool() const noexcept
|
||||
{
|
||||
return p_ < clip_;
|
||||
}
|
||||
|
||||
std::size_t remain() const noexcept
|
||||
{
|
||||
return clip_ - p_;
|
||||
}
|
||||
|
||||
std::size_t remain(const char* p) const noexcept
|
||||
{
|
||||
return clip_ - p;
|
||||
}
|
||||
|
||||
void
|
||||
clip(std::size_t n) noexcept
|
||||
{
|
||||
if(static_cast<std::size_t>(
|
||||
end_ - p_) > n)
|
||||
clip_ = p_ + n;
|
||||
else
|
||||
clip_ = end_;
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------------
|
||||
|
||||
class stream
|
||||
{
|
||||
friend class local_stream;
|
||||
|
||||
char* p_;
|
||||
char* end_;
|
||||
|
||||
public:
|
||||
stream(
|
||||
stream const&) = default;
|
||||
|
||||
stream(
|
||||
char* data,
|
||||
std::size_t size) noexcept
|
||||
: p_(data)
|
||||
, end_(data + size)
|
||||
{
|
||||
}
|
||||
|
||||
size_t
|
||||
used(char* begin) const noexcept
|
||||
{
|
||||
return static_cast<
|
||||
size_t>(p_ - begin);
|
||||
}
|
||||
|
||||
size_t
|
||||
remain() const noexcept
|
||||
{
|
||||
return end_ - p_;
|
||||
}
|
||||
|
||||
char*
|
||||
data() noexcept
|
||||
{
|
||||
return p_;
|
||||
}
|
||||
|
||||
operator bool() const noexcept
|
||||
{
|
||||
return p_ < end_;
|
||||
}
|
||||
|
||||
// unchecked
|
||||
char&
|
||||
operator*() noexcept
|
||||
{
|
||||
BOOST_ASSERT(p_ < end_);
|
||||
return *p_;
|
||||
}
|
||||
|
||||
// unchecked
|
||||
stream&
|
||||
operator++() noexcept
|
||||
{
|
||||
BOOST_ASSERT(p_ < end_);
|
||||
++p_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// unchecked
|
||||
void
|
||||
append(
|
||||
char const* src,
|
||||
std::size_t n) noexcept
|
||||
{
|
||||
BOOST_ASSERT(remain() >= n);
|
||||
std::memcpy(p_, src, n);
|
||||
p_ += n;
|
||||
}
|
||||
|
||||
// unchecked
|
||||
void
|
||||
append(char c) noexcept
|
||||
{
|
||||
BOOST_ASSERT(p_ < end_);
|
||||
*p_++ = c;
|
||||
}
|
||||
|
||||
void
|
||||
advance(std::size_t n) noexcept
|
||||
{
|
||||
BOOST_ASSERT(remain() >= n);
|
||||
p_ += n;
|
||||
}
|
||||
};
|
||||
|
||||
class local_stream
|
||||
: public stream
|
||||
{
|
||||
stream& src_;
|
||||
|
||||
public:
|
||||
explicit
|
||||
local_stream(
|
||||
stream& src)
|
||||
: stream(src)
|
||||
, src_(src)
|
||||
{
|
||||
}
|
||||
|
||||
~local_stream()
|
||||
{
|
||||
src_.p_ = p_;
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
357
install/boost_1_75_0/include/boost/json/detail/string_impl.hpp
Normal file
357
install/boost_1_75_0/include/boost/json/detail/string_impl.hpp
Normal file
@@ -0,0 +1,357 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
|
||||
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_STRING_IMPL_HPP
|
||||
#define BOOST_JSON_DETAIL_STRING_IMPL_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/kind.hpp>
|
||||
#include <boost/json/storage_ptr.hpp>
|
||||
#include <boost/json/detail/value.hpp>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
class value;
|
||||
|
||||
namespace detail {
|
||||
|
||||
class string_impl
|
||||
{
|
||||
struct table
|
||||
{
|
||||
std::uint32_t size;
|
||||
std::uint32_t capacity;
|
||||
};
|
||||
|
||||
#if BOOST_JSON_ARCH == 64
|
||||
static constexpr std::size_t sbo_chars_ = 14;
|
||||
#elif BOOST_JSON_ARCH == 32
|
||||
static constexpr std::size_t sbo_chars_ = 10;
|
||||
#else
|
||||
# error Unknown architecture
|
||||
#endif
|
||||
|
||||
static
|
||||
constexpr
|
||||
kind
|
||||
short_string_ =
|
||||
static_cast<kind>(
|
||||
((unsigned char)
|
||||
kind::string) | 0x80);
|
||||
|
||||
static
|
||||
constexpr
|
||||
kind
|
||||
key_string_ =
|
||||
static_cast<kind>(
|
||||
((unsigned char)
|
||||
kind::string) | 0x40);
|
||||
|
||||
struct sbo
|
||||
{
|
||||
kind k; // must come first
|
||||
char buf[sbo_chars_ + 1];
|
||||
};
|
||||
|
||||
struct pointer
|
||||
{
|
||||
kind k; // must come first
|
||||
table* t;
|
||||
};
|
||||
|
||||
struct key
|
||||
{
|
||||
kind k; // must come first
|
||||
std::uint32_t n;
|
||||
char* s;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
sbo s_;
|
||||
pointer p_;
|
||||
key k_;
|
||||
};
|
||||
|
||||
#if BOOST_JSON_ARCH == 64
|
||||
BOOST_STATIC_ASSERT(sizeof(sbo) <= 16);
|
||||
BOOST_STATIC_ASSERT(sizeof(pointer) <= 16);
|
||||
BOOST_STATIC_ASSERT(sizeof(key) <= 16);
|
||||
#elif BOOST_JSON_ARCH == 32
|
||||
BOOST_STATIC_ASSERT(sizeof(sbo) <= 24);
|
||||
BOOST_STATIC_ASSERT(sizeof(pointer) <= 24);
|
||||
BOOST_STATIC_ASSERT(sizeof(key) <= 24);
|
||||
#endif
|
||||
|
||||
public:
|
||||
static
|
||||
constexpr
|
||||
std::size_t
|
||||
max_size() noexcept
|
||||
{
|
||||
// max_size depends on the address model
|
||||
using min = std::integral_constant<std::size_t,
|
||||
std::size_t(-1) - sizeof(table)>;
|
||||
return min::value < BOOST_JSON_MAX_STRING_SIZE ?
|
||||
min::value : BOOST_JSON_MAX_STRING_SIZE;
|
||||
}
|
||||
|
||||
BOOST_JSON_DECL
|
||||
string_impl() noexcept;
|
||||
|
||||
BOOST_JSON_DECL
|
||||
string_impl(
|
||||
std::size_t new_size,
|
||||
storage_ptr const& sp);
|
||||
|
||||
BOOST_JSON_DECL
|
||||
string_impl(
|
||||
key_t,
|
||||
string_view s,
|
||||
storage_ptr const& sp);
|
||||
|
||||
BOOST_JSON_DECL
|
||||
string_impl(
|
||||
key_t,
|
||||
string_view s1,
|
||||
string_view s2,
|
||||
storage_ptr const& sp);
|
||||
|
||||
BOOST_JSON_DECL
|
||||
string_impl(
|
||||
char** dest,
|
||||
std::size_t len,
|
||||
storage_ptr const& sp);
|
||||
|
||||
template<class InputIt>
|
||||
string_impl(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
storage_ptr const& sp,
|
||||
std::random_access_iterator_tag)
|
||||
: string_impl(last - first, sp)
|
||||
{
|
||||
std::copy(first, last, data());
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
string_impl(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
storage_ptr const& sp,
|
||||
std::input_iterator_tag)
|
||||
: string_impl(0, sp)
|
||||
{
|
||||
struct undo
|
||||
{
|
||||
string_impl* s;
|
||||
storage_ptr const& sp;
|
||||
|
||||
~undo()
|
||||
{
|
||||
if(s)
|
||||
s->destroy(sp);
|
||||
}
|
||||
};
|
||||
|
||||
undo u{this, sp};
|
||||
auto dest = data();
|
||||
while(first != last)
|
||||
{
|
||||
if(size() < capacity())
|
||||
size(size() + 1);
|
||||
else
|
||||
dest = append(1, sp);
|
||||
*dest++ = *first++;
|
||||
}
|
||||
term(size());
|
||||
u.s = nullptr;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
size() const noexcept
|
||||
{
|
||||
return s_.k == kind::string ?
|
||||
p_.t->size :
|
||||
sbo_chars_ -
|
||||
s_.buf[sbo_chars_];
|
||||
}
|
||||
|
||||
std::size_t
|
||||
capacity() const noexcept
|
||||
{
|
||||
return s_.k == kind::string ?
|
||||
p_.t->capacity :
|
||||
sbo_chars_;
|
||||
}
|
||||
|
||||
void
|
||||
size(std::size_t n)
|
||||
{
|
||||
if(s_.k == kind::string)
|
||||
p_.t->size = static_cast<
|
||||
std::uint32_t>(n);
|
||||
else
|
||||
s_.buf[sbo_chars_] =
|
||||
static_cast<char>(
|
||||
sbo_chars_ - n);
|
||||
}
|
||||
|
||||
BOOST_JSON_DECL
|
||||
static
|
||||
std::uint32_t
|
||||
growth(
|
||||
std::size_t new_size,
|
||||
std::size_t capacity);
|
||||
|
||||
char const*
|
||||
release_key(
|
||||
std::size_t& n) noexcept
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
k_.k == key_string_);
|
||||
n = k_.n;
|
||||
auto const s = k_.s;
|
||||
// prevent deallocate
|
||||
k_.k = short_string_;
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
destroy(
|
||||
storage_ptr const& sp) noexcept
|
||||
{
|
||||
if(s_.k == kind::string)
|
||||
{
|
||||
sp->deallocate(p_.t,
|
||||
sizeof(table) +
|
||||
p_.t->capacity + 1,
|
||||
alignof(table));
|
||||
}
|
||||
else if(s_.k != key_string_)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
s_.k == key_string_);
|
||||
// VFALCO unfortunately the key string
|
||||
// kind increases the cost of the destructor.
|
||||
// This function should be skipped when using
|
||||
// monotonic_resource.
|
||||
sp->deallocate(k_.s, k_.n + 1);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_JSON_DECL
|
||||
char*
|
||||
assign(
|
||||
std::size_t new_size,
|
||||
storage_ptr const& sp);
|
||||
|
||||
BOOST_JSON_DECL
|
||||
char*
|
||||
append(
|
||||
std::size_t n,
|
||||
storage_ptr const& sp);
|
||||
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
insert(
|
||||
std::size_t pos,
|
||||
const char* s,
|
||||
std::size_t n,
|
||||
storage_ptr const& sp);
|
||||
|
||||
BOOST_JSON_DECL
|
||||
char*
|
||||
insert_unchecked(
|
||||
std::size_t pos,
|
||||
std::size_t n,
|
||||
storage_ptr const& sp);
|
||||
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
replace(
|
||||
std::size_t pos,
|
||||
std::size_t n1,
|
||||
const char* s,
|
||||
std::size_t n2,
|
||||
storage_ptr const& sp);
|
||||
|
||||
BOOST_JSON_DECL
|
||||
char*
|
||||
replace_unchecked(
|
||||
std::size_t pos,
|
||||
std::size_t n1,
|
||||
std::size_t n2,
|
||||
storage_ptr const& sp);
|
||||
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
shrink_to_fit(
|
||||
storage_ptr const& sp) noexcept;
|
||||
|
||||
void
|
||||
term(std::size_t n) noexcept
|
||||
{
|
||||
if(s_.k == short_string_)
|
||||
{
|
||||
s_.buf[sbo_chars_] =
|
||||
static_cast<char>(
|
||||
sbo_chars_ - n);
|
||||
s_.buf[n] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
p_.t->size = static_cast<
|
||||
std::uint32_t>(n);
|
||||
data()[n] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
char*
|
||||
data() noexcept
|
||||
{
|
||||
if(s_.k == short_string_)
|
||||
return s_.buf;
|
||||
return reinterpret_cast<
|
||||
char*>(p_.t + 1);
|
||||
}
|
||||
|
||||
char const*
|
||||
data() const noexcept
|
||||
{
|
||||
if(s_.k == short_string_)
|
||||
return s_.buf;
|
||||
return reinterpret_cast<
|
||||
char const*>(p_.t + 1);
|
||||
}
|
||||
|
||||
char*
|
||||
end() noexcept
|
||||
{
|
||||
return data() + size();
|
||||
}
|
||||
|
||||
char const*
|
||||
end() const noexcept
|
||||
{
|
||||
return data() + size();
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
197
install/boost_1_75_0/include/boost/json/detail/utf8.hpp
Normal file
197
install/boost_1_75_0/include/boost/json/detail/utf8.hpp
Normal file
@@ -0,0 +1,197 @@
|
||||
//
|
||||
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_UTF8_HPP
|
||||
#define BOOST_JSON_DETAIL_UTF8_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
template<int N>
|
||||
std::uint32_t
|
||||
load_little_endian(void const* p)
|
||||
{
|
||||
// VFALCO do we need to initialize this to 0?
|
||||
std::uint32_t v;
|
||||
std::memcpy(&v, p, N);
|
||||
#ifdef BOOST_JSON_BIG_ENDIAN
|
||||
v = ((v & 0xFF000000) >> 24) |
|
||||
((v & 0x00FF0000) >> 8) |
|
||||
((v & 0x0000FF00) << 8) |
|
||||
((v & 0x000000FF) << 24);
|
||||
#endif
|
||||
return v;
|
||||
}
|
||||
|
||||
inline
|
||||
uint16_t
|
||||
classify_utf8(char c)
|
||||
{
|
||||
// 0x000 = invalid
|
||||
// 0x102 = 2 bytes, second byte [80, BF]
|
||||
// 0x203 = 3 bytes, second byte [A0, BF]
|
||||
// 0x303 = 3 bytes, second byte [80, BF]
|
||||
// 0x403 = 3 bytes, second byte [80, 9F]
|
||||
// 0x504 = 4 bytes, second byte [90, BF]
|
||||
// 0x604 = 4 bytes, second byte [80, BF]
|
||||
// 0x704 = 4 bytes, second byte [80, 8F]
|
||||
static constexpr uint16_t first[128]
|
||||
{
|
||||
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
|
||||
|
||||
0x000, 0x000, 0x102, 0x102, 0x102, 0x102, 0x102, 0x102,
|
||||
0x102, 0x102, 0x102, 0x102, 0x102, 0x102, 0x102, 0x102,
|
||||
0x102, 0x102, 0x102, 0x102, 0x102, 0x102, 0x102, 0x102,
|
||||
0x102, 0x102, 0x102, 0x102, 0x102, 0x102, 0x102, 0x102,
|
||||
0x203, 0x303, 0x303, 0x303, 0x303, 0x303, 0x303, 0x303,
|
||||
0x303, 0x303, 0x303, 0x303, 0x303, 0x403, 0x303, 0x303,
|
||||
0x504, 0x604, 0x604, 0x604, 0x704, 0x000, 0x000, 0x000,
|
||||
0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000,
|
||||
};
|
||||
return first[static_cast<unsigned char>(c)];
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
is_valid_utf8(const char* p, uint16_t first)
|
||||
{
|
||||
uint32_t v;
|
||||
switch(first >> 8)
|
||||
{
|
||||
default:
|
||||
return false;
|
||||
|
||||
// 2 bytes, second byte [80, BF]
|
||||
case 1:
|
||||
v = load_little_endian<2>(p);
|
||||
return (v & 0xC000) == 0x8000;
|
||||
|
||||
// 3 bytes, second byte [A0, BF]
|
||||
case 2:
|
||||
v = load_little_endian<3>(p);
|
||||
std::memcpy(&v, p, 3);
|
||||
return (v & 0xC0E000) == 0x80A000;
|
||||
|
||||
// 3 bytes, second byte [80, BF]
|
||||
case 3:
|
||||
v = load_little_endian<3>(p);
|
||||
return (v & 0xC0C000) == 0x808000;
|
||||
|
||||
// 3 bytes, second byte [80, 9F]
|
||||
case 4:
|
||||
v = load_little_endian<3>(p);
|
||||
return (v & 0xC0E000) == 0x808000;
|
||||
|
||||
// 4 bytes, second byte [90, BF]
|
||||
case 5:
|
||||
v = load_little_endian<4>(p);
|
||||
return (v & 0xC0C0FF00) + 0x7F7F7000 <= 0x2F00;
|
||||
|
||||
// 4 bytes, second byte [80, BF]
|
||||
case 6:
|
||||
v = load_little_endian<4>(p);
|
||||
return (v & 0xC0C0C000) == 0x80808000;
|
||||
|
||||
// 4 bytes, second byte [80, 8F]
|
||||
case 7:
|
||||
v = load_little_endian<4>(p);
|
||||
return (v & 0xC0C0F000) == 0x80808000;
|
||||
}
|
||||
}
|
||||
|
||||
class utf8_sequence
|
||||
{
|
||||
char seq_[4];
|
||||
uint16_t first_;
|
||||
uint8_t size_;
|
||||
|
||||
public:
|
||||
void
|
||||
save(
|
||||
const char* p,
|
||||
std::size_t remain) noexcept
|
||||
{
|
||||
first_ = classify_utf8(*p & 0x7F);
|
||||
if(remain >= length())
|
||||
size_ = length();
|
||||
else
|
||||
size_ = static_cast<uint8_t>(remain);
|
||||
std::memcpy(seq_, p, size_);
|
||||
}
|
||||
|
||||
uint8_t
|
||||
length() const noexcept
|
||||
{
|
||||
return first_ & 0xFF;
|
||||
}
|
||||
|
||||
bool
|
||||
complete() const noexcept
|
||||
{
|
||||
return size_ >= length();
|
||||
}
|
||||
|
||||
// returns true if complete
|
||||
bool
|
||||
append(
|
||||
const char* p,
|
||||
std::size_t remain) noexcept
|
||||
{
|
||||
if(BOOST_JSON_UNLIKELY(needed() == 0))
|
||||
return true;
|
||||
if(BOOST_JSON_LIKELY(remain >= needed()))
|
||||
{
|
||||
std::memcpy(
|
||||
seq_ + size_, p, needed());
|
||||
size_ = length();
|
||||
return true;
|
||||
}
|
||||
if(BOOST_JSON_LIKELY(remain > 0))
|
||||
{
|
||||
std::memcpy(seq_ + size_, p, remain);
|
||||
size_ += static_cast<uint8_t>(remain);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const char*
|
||||
data() const noexcept
|
||||
{
|
||||
return seq_;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
needed() const noexcept
|
||||
{
|
||||
return length() - size_;
|
||||
}
|
||||
|
||||
bool
|
||||
valid() const noexcept
|
||||
{
|
||||
BOOST_ASSERT(size_ >= length());
|
||||
return is_valid_utf8(seq_, first_);
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
277
install/boost_1_75_0/include/boost/json/detail/value.hpp
Normal file
277
install/boost_1_75_0/include/boost/json/detail/value.hpp
Normal file
@@ -0,0 +1,277 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_VALUE_HPP
|
||||
#define BOOST_JSON_DETAIL_VALUE_HPP
|
||||
|
||||
#include <boost/json/kind.hpp>
|
||||
#include <boost/json/storage_ptr.hpp>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <new>
|
||||
#include <utility>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
struct key_t
|
||||
{
|
||||
};
|
||||
|
||||
#if 0
|
||||
template<class T>
|
||||
struct to_number_limit
|
||||
: std::numeric_limits<T>
|
||||
{
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct to_number_limit<T const>
|
||||
: to_number_limit<T>
|
||||
{
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_number_limit<long long>
|
||||
{
|
||||
static constexpr long long (min)() noexcept
|
||||
{
|
||||
return -9223372036854774784;
|
||||
}
|
||||
|
||||
static constexpr long long (max)() noexcept
|
||||
{
|
||||
return 9223372036854774784;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct to_number_limit<unsigned long long>
|
||||
{
|
||||
static constexpr
|
||||
unsigned long long (min)() noexcept
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static constexpr
|
||||
unsigned long long (max)() noexcept
|
||||
{
|
||||
return 18446744073709549568ULL;
|
||||
}
|
||||
};
|
||||
#else
|
||||
|
||||
template<class T>
|
||||
class to_number_limit
|
||||
{
|
||||
// unsigned
|
||||
|
||||
static constexpr
|
||||
double min1(std::false_type)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
static constexpr
|
||||
double max1(std::false_type)
|
||||
{
|
||||
return max2u(std::integral_constant<
|
||||
bool, (std::numeric_limits<T>::max)() ==
|
||||
UINT64_MAX>{});
|
||||
}
|
||||
|
||||
static constexpr
|
||||
double max2u(std::false_type)
|
||||
{
|
||||
return static_cast<double>(
|
||||
(std::numeric_limits<T>::max)());
|
||||
}
|
||||
|
||||
static constexpr
|
||||
double max2u(std::true_type)
|
||||
{
|
||||
return 18446744073709549568.0;
|
||||
}
|
||||
|
||||
// signed
|
||||
|
||||
static constexpr
|
||||
double min1(std::true_type)
|
||||
{
|
||||
return min2s(std::integral_constant<
|
||||
bool, (std::numeric_limits<T>::max)() ==
|
||||
INT64_MAX>{});
|
||||
}
|
||||
|
||||
static constexpr
|
||||
double min2s(std::false_type)
|
||||
{
|
||||
return static_cast<double>(
|
||||
(std::numeric_limits<T>::min)());
|
||||
}
|
||||
|
||||
static constexpr
|
||||
double min2s(std::true_type)
|
||||
{
|
||||
return -9223372036854774784.0;
|
||||
}
|
||||
|
||||
static constexpr
|
||||
double max1(std::true_type)
|
||||
{
|
||||
return max2s(std::integral_constant<
|
||||
bool, (std::numeric_limits<T>::max)() ==
|
||||
INT64_MAX>{});
|
||||
}
|
||||
|
||||
static constexpr
|
||||
double max2s(std::false_type)
|
||||
{
|
||||
return static_cast<double>(
|
||||
(std::numeric_limits<T>::max)());
|
||||
}
|
||||
|
||||
static constexpr
|
||||
double max2s(std::true_type)
|
||||
{
|
||||
return 9223372036854774784.0;
|
||||
}
|
||||
|
||||
public:
|
||||
static constexpr
|
||||
double (min)() noexcept
|
||||
{
|
||||
return min1(std::is_signed<T>{});
|
||||
}
|
||||
|
||||
static constexpr
|
||||
double (max)() noexcept
|
||||
{
|
||||
return max1(std::is_signed<T>{});
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
struct scalar
|
||||
{
|
||||
storage_ptr sp; // must come first
|
||||
kind k; // must come second
|
||||
union
|
||||
{
|
||||
bool b;
|
||||
std::int64_t i;
|
||||
std::uint64_t u;
|
||||
double d;
|
||||
};
|
||||
|
||||
explicit
|
||||
scalar(storage_ptr sp_ = {}) noexcept
|
||||
: sp(std::move(sp_))
|
||||
, k(json::kind::null)
|
||||
{
|
||||
}
|
||||
|
||||
explicit
|
||||
scalar(bool b_,
|
||||
storage_ptr sp_ = {}) noexcept
|
||||
: sp(std::move(sp_))
|
||||
, k(json::kind::bool_)
|
||||
, b(b_)
|
||||
{
|
||||
}
|
||||
|
||||
explicit
|
||||
scalar(std::int64_t i_,
|
||||
storage_ptr sp_ = {}) noexcept
|
||||
: sp(std::move(sp_))
|
||||
, k(json::kind::int64)
|
||||
, i(i_)
|
||||
{
|
||||
}
|
||||
|
||||
explicit
|
||||
scalar(std::uint64_t u_,
|
||||
storage_ptr sp_ = {}) noexcept
|
||||
: sp(std::move(sp_))
|
||||
, k(json::kind::uint64)
|
||||
, u(u_)
|
||||
{
|
||||
}
|
||||
|
||||
explicit
|
||||
scalar(double d_,
|
||||
storage_ptr sp_ = {}) noexcept
|
||||
: sp(std::move(sp_))
|
||||
, k(json::kind::double_)
|
||||
, d(d_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct access
|
||||
{
|
||||
template<class Value, class... Args>
|
||||
static
|
||||
Value&
|
||||
construct_value(Value* p, Args&&... args)
|
||||
{
|
||||
return *reinterpret_cast<
|
||||
Value*>(::new(p) Value(
|
||||
std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<class KeyValuePair, class... Args>
|
||||
static
|
||||
KeyValuePair&
|
||||
construct_key_value_pair(
|
||||
KeyValuePair* p, Args&&... args)
|
||||
{
|
||||
return *reinterpret_cast<
|
||||
KeyValuePair*>(::new(p)
|
||||
KeyValuePair(
|
||||
std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<class Value>
|
||||
static
|
||||
char const*
|
||||
release_key(
|
||||
Value& jv,
|
||||
std::size_t& len) noexcept
|
||||
{
|
||||
BOOST_ASSERT(jv.is_string());
|
||||
jv.str_.sp_.~storage_ptr();
|
||||
return jv.str_.impl_.release_key(len);
|
||||
}
|
||||
|
||||
using index_t = std::uint32_t;
|
||||
|
||||
template<class KeyValuePair>
|
||||
static
|
||||
index_t&
|
||||
next(KeyValuePair& e) noexcept
|
||||
{
|
||||
return e.next_;
|
||||
}
|
||||
|
||||
template<class KeyValuePair>
|
||||
static
|
||||
index_t const&
|
||||
next(KeyValuePair const& e) noexcept
|
||||
{
|
||||
return e.next_;
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
193
install/boost_1_75_0/include/boost/json/detail/value_from.hpp
Normal file
193
install/boost_1_75_0/include/boost/json/detail/value_from.hpp
Normal file
@@ -0,0 +1,193 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
|
||||
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_VALUE_FROM_HPP
|
||||
#define BOOST_JSON_DETAIL_VALUE_FROM_HPP
|
||||
|
||||
#include <boost/json/storage_ptr.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/json/detail/value_traits.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
struct value_from_tag { };
|
||||
|
||||
template<class T, class = void>
|
||||
struct has_value_from;
|
||||
|
||||
namespace detail {
|
||||
|
||||
// The integral_constant parameter here is an
|
||||
// rvalue reference to make the standard conversion
|
||||
// sequence to that parameter better, see
|
||||
// http://eel.is/c++draft/over.ics.rank#3.2.6
|
||||
template<std::size_t N, class T>
|
||||
void
|
||||
tuple_to_array(
|
||||
T&&,
|
||||
array&,
|
||||
std::integral_constant<std::size_t, N>&&)
|
||||
{
|
||||
}
|
||||
|
||||
template<std::size_t N, std::size_t I, class T>
|
||||
void
|
||||
tuple_to_array(
|
||||
T&& t,
|
||||
array& arr,
|
||||
const std::integral_constant<std::size_t, I>&)
|
||||
{
|
||||
using std::get;
|
||||
arr.emplace_back(value_from(
|
||||
get<I>(std::forward<T>(t)), arr.storage()));
|
||||
return detail::tuple_to_array<N>(std::forward<T>(t),
|
||||
arr, std::integral_constant<std::size_t, I + 1>());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Native conversion
|
||||
|
||||
template<class T, typename std::enable_if<
|
||||
detail::value_constructible<T>::value>::type* = nullptr>
|
||||
void
|
||||
tag_invoke(
|
||||
value_from_tag,
|
||||
value& jv,
|
||||
T&& from)
|
||||
{
|
||||
jv = std::forward<T>(from);
|
||||
}
|
||||
|
||||
template<class T, typename std::enable_if<
|
||||
std::is_same<detail::remove_cvref<T>,
|
||||
std::nullptr_t>::value>::type* = nullptr>
|
||||
void
|
||||
tag_invoke(
|
||||
value_from_tag,
|
||||
value& jv,
|
||||
T&&)
|
||||
{
|
||||
// do nothing
|
||||
BOOST_ASSERT(jv.is_null());
|
||||
(void)jv;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Generic conversions
|
||||
|
||||
// string-like types
|
||||
// NOTE: original check for size used is_convertible but
|
||||
// MSVC-140 selects wrong specialisation if used
|
||||
template<class T, typename std::enable_if<
|
||||
std::is_constructible<remove_cvref<T>, const char*, std::size_t>::value &&
|
||||
std::is_convertible<decltype(std::declval<T&>().data()), const char*>::value &&
|
||||
std::is_integral<decltype(std::declval<T&>().size())>::value
|
||||
>::type* = nullptr>
|
||||
void
|
||||
value_from_generic(
|
||||
value& jv,
|
||||
T&& from,
|
||||
priority_tag<3>)
|
||||
{
|
||||
jv.emplace_string().assign(
|
||||
from.data(), from.size());
|
||||
}
|
||||
|
||||
// tuple-like types
|
||||
template<class T, typename std::enable_if<
|
||||
(std::tuple_size<remove_cvref<T>>::value > 0)>::type* = nullptr>
|
||||
void
|
||||
value_from_generic(
|
||||
value& jv,
|
||||
T&& from,
|
||||
priority_tag<2>)
|
||||
{
|
||||
constexpr std::size_t n =
|
||||
std::tuple_size<remove_cvref<T>>::value;
|
||||
array& arr = jv.emplace_array();
|
||||
arr.reserve(n);
|
||||
detail::tuple_to_array<n>(std::forward<T>(from),
|
||||
arr, std::integral_constant<std::size_t, 0>());
|
||||
}
|
||||
|
||||
// map-like types
|
||||
template<class T, typename std::enable_if<
|
||||
map_traits<T>::has_unique_keys &&
|
||||
has_value_from<typename map_traits<T>::pair_value_type>::value &&
|
||||
std::is_convertible<typename map_traits<T>::pair_key_type,
|
||||
string_view>::value>::type* = nullptr>
|
||||
void
|
||||
value_from_generic(
|
||||
value& jv,
|
||||
T&& from,
|
||||
priority_tag<1>)
|
||||
{
|
||||
using std::get;
|
||||
object& obj = jv.emplace_object();
|
||||
obj.reserve(container_traits<T>::try_size(from));
|
||||
for (auto&& elem : from)
|
||||
obj.emplace(get<0>(elem), value_from(
|
||||
get<1>(elem), obj.storage()));
|
||||
}
|
||||
|
||||
// all other containers
|
||||
template<class T, typename std::enable_if<
|
||||
has_value_from<typename container_traits<T>::
|
||||
value_type>::value>::type* = nullptr>
|
||||
void
|
||||
value_from_generic(
|
||||
value& jv,
|
||||
T&& from,
|
||||
priority_tag<0>)
|
||||
{
|
||||
array& result = jv.emplace_array();
|
||||
result.reserve(container_traits<T>::try_size(from));
|
||||
for (auto&& elem : from)
|
||||
result.emplace_back(
|
||||
value_from(elem, result.storage()));
|
||||
}
|
||||
|
||||
template<class T, void_t<typename std::enable_if<
|
||||
! detail::value_constructible<T>::value && ! std::is_same<
|
||||
detail::remove_cvref<T>, std::nullptr_t>::value>::type,
|
||||
decltype(detail::value_from_generic(std::declval<value&>(),
|
||||
std::declval<T&&>(), priority_tag<3>()))>* = nullptr>
|
||||
void
|
||||
tag_invoke(
|
||||
value_from_tag,
|
||||
value& jv,
|
||||
T&& from)
|
||||
{
|
||||
detail::value_from_generic(jv,
|
||||
std::forward<T>(from), priority_tag<3>());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
// Calls to value_from are forwarded to this function
|
||||
// so we can use ADL and hide the built-in tag_invoke
|
||||
// overloads in the detail namespace
|
||||
template<class T, void_t<
|
||||
decltype(tag_invoke(std::declval<value_from_tag&>(),
|
||||
std::declval<value&>(), std::declval<T&&>()))>* = nullptr>
|
||||
value
|
||||
value_from_impl(
|
||||
T&& from,
|
||||
storage_ptr sp)
|
||||
{
|
||||
value jv(std::move(sp));
|
||||
tag_invoke(value_from_tag(), jv, std::forward<T>(from));
|
||||
return jv;
|
||||
}
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
195
install/boost_1_75_0/include/boost/json/detail/value_to.hpp
Normal file
195
install/boost_1_75_0/include/boost/json/detail/value_to.hpp
Normal file
@@ -0,0 +1,195 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
|
||||
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_VALUE_TO_HPP
|
||||
#define BOOST_JSON_DETAIL_VALUE_TO_HPP
|
||||
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/json/detail/value_traits.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
template<class>
|
||||
struct value_to_tag { };
|
||||
|
||||
template<class, class = void>
|
||||
struct has_value_to;
|
||||
|
||||
template<class T, class U,
|
||||
typename std::enable_if<
|
||||
! std::is_reference<T>::value &&
|
||||
std::is_same<U, value>::value>::type* = nullptr>
|
||||
T value_to(U const&);
|
||||
|
||||
namespace detail {
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Use native conversion
|
||||
|
||||
// identity conversion
|
||||
inline
|
||||
value
|
||||
tag_invoke(
|
||||
value_to_tag<value>,
|
||||
value const& jv)
|
||||
{
|
||||
return jv;
|
||||
}
|
||||
|
||||
// object
|
||||
inline
|
||||
object
|
||||
tag_invoke(
|
||||
value_to_tag<object>,
|
||||
value const& jv)
|
||||
{
|
||||
return jv.as_object();
|
||||
}
|
||||
|
||||
// array
|
||||
inline
|
||||
array
|
||||
tag_invoke(
|
||||
value_to_tag<array>,
|
||||
value const& jv)
|
||||
{
|
||||
return jv.as_array();
|
||||
}
|
||||
|
||||
// string
|
||||
inline
|
||||
string
|
||||
tag_invoke(
|
||||
value_to_tag<string>,
|
||||
value const& jv)
|
||||
{
|
||||
return jv.as_string();
|
||||
}
|
||||
|
||||
// bool
|
||||
inline
|
||||
bool
|
||||
tag_invoke(
|
||||
value_to_tag<bool>,
|
||||
value const& jv)
|
||||
{
|
||||
return jv.as_bool();
|
||||
}
|
||||
|
||||
// integral and floating point
|
||||
template<class T, typename std::enable_if<
|
||||
std::is_arithmetic<T>::value>::type* = nullptr>
|
||||
T
|
||||
tag_invoke(
|
||||
value_to_tag<T>,
|
||||
value const& jv)
|
||||
{
|
||||
return jv.to_number<T>();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Use generic conversion
|
||||
|
||||
// string-like types
|
||||
// NOTE: original check for size used is_convertible but
|
||||
// MSVC-140 selects wrong specialisation if used
|
||||
template<class T, typename std::enable_if<
|
||||
std::is_constructible<T, const char*, std::size_t>::value &&
|
||||
std::is_convertible<decltype(std::declval<T&>().data()), const char*>::value &&
|
||||
std::is_integral<decltype(std::declval<T&>().size())>::value
|
||||
>::type* = nullptr>
|
||||
T
|
||||
value_to_generic(
|
||||
const value& jv,
|
||||
priority_tag<2>)
|
||||
{
|
||||
auto& str = jv.as_string();
|
||||
return T(str.data(), str.size());
|
||||
}
|
||||
|
||||
// map like containers
|
||||
template<class T, typename std::enable_if<
|
||||
has_value_to<typename map_traits<T>::pair_value_type>::value &&
|
||||
std::is_constructible<typename map_traits<T>::pair_key_type,
|
||||
string_view>::value>::type* = nullptr>
|
||||
T
|
||||
value_to_generic(
|
||||
const value& jv,
|
||||
priority_tag<1>)
|
||||
{
|
||||
using value_type = typename
|
||||
container_traits<T>::value_type;
|
||||
const object& obj = jv.as_object();
|
||||
T result;
|
||||
container_traits<T>::try_reserve(
|
||||
result, obj.size());
|
||||
for (const auto& val : obj)
|
||||
result.insert(value_type{typename map_traits<T>::
|
||||
pair_key_type(val.key()), value_to<typename
|
||||
map_traits<T>::pair_value_type>(val.value())});
|
||||
return result;
|
||||
}
|
||||
|
||||
// all other containers
|
||||
template<class T, typename std::enable_if<
|
||||
has_value_to<typename container_traits<T>::
|
||||
value_type>::value>::type* = nullptr>
|
||||
T
|
||||
value_to_generic(
|
||||
const value& jv,
|
||||
priority_tag<0>)
|
||||
{
|
||||
const array& arr = jv.as_array();
|
||||
T result;
|
||||
container_traits<T>::try_reserve(
|
||||
result, arr.size());
|
||||
for (const auto& val : arr)
|
||||
result.insert(end(result), value_to<typename
|
||||
container_traits<T>::value_type>(val));
|
||||
return result;
|
||||
}
|
||||
|
||||
// Matches containers
|
||||
template<class T, void_t<typename std::enable_if<
|
||||
!std::is_constructible<T, const value&>::value &&
|
||||
!std::is_arithmetic<T>::value>::type, decltype(
|
||||
value_to_generic<T>(std::declval<const value&>(),
|
||||
priority_tag<2>()))>* = nullptr>
|
||||
T
|
||||
tag_invoke(
|
||||
value_to_tag<T>,
|
||||
value const& jv)
|
||||
{
|
||||
return value_to_generic<T>(
|
||||
jv, priority_tag<2>());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
// Calls to value_to are forwarded to this function
|
||||
// so we can use ADL and hide the built-in tag_invoke
|
||||
// overloads in the detail namespace
|
||||
template<class T, void_t<
|
||||
decltype(tag_invoke(std::declval<value_to_tag<T>&>(),
|
||||
std::declval<const value&>()))>* = nullptr>
|
||||
T
|
||||
value_to_impl(
|
||||
value_to_tag<T> tag,
|
||||
value const& jv)
|
||||
{
|
||||
return tag_invoke(tag, jv);
|
||||
}
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
186
install/boost_1_75_0/include/boost/json/detail/value_traits.hpp
Normal file
186
install/boost_1_75_0/include/boost/json/detail/value_traits.hpp
Normal file
@@ -0,0 +1,186 @@
|
||||
//
|
||||
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_VALUE_TRAITS_HPP
|
||||
#define BOOST_JSON_DETAIL_VALUE_TRAITS_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <type_traits>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
namespace detail {
|
||||
|
||||
template<std::size_t N>
|
||||
struct priority_tag
|
||||
: priority_tag<N - 1> { };
|
||||
|
||||
template<>
|
||||
struct priority_tag<0> { };
|
||||
|
||||
using std::begin;
|
||||
using std::end;
|
||||
#ifdef __cpp_lib_nonmember_container_access
|
||||
using std::size;
|
||||
#endif
|
||||
|
||||
template<typename T, typename = void>
|
||||
struct container_traits
|
||||
{
|
||||
static constexpr bool is_container = false;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct container_traits<T, typename std::enable_if<
|
||||
std::is_same<decltype(begin(std::declval<T&>())),
|
||||
decltype(end(std::declval<T&>()))>::value>::type>
|
||||
{
|
||||
private:
|
||||
template<typename U, typename std::enable_if<
|
||||
std::is_convertible<decltype(std::declval<U&>().size()),
|
||||
std::size_t>::value>::type* = nullptr>
|
||||
static
|
||||
std::size_t
|
||||
size_impl(
|
||||
U&& cont,
|
||||
priority_tag<2>)
|
||||
{
|
||||
return cont.size();
|
||||
}
|
||||
|
||||
template<typename U, typename std::enable_if<
|
||||
std::is_convertible<decltype(size(std::declval<U&>())),
|
||||
std::size_t>::value>::type* = nullptr>
|
||||
static
|
||||
std::size_t
|
||||
size_impl(
|
||||
U& cont,
|
||||
priority_tag<1>)
|
||||
{
|
||||
return size(cont);
|
||||
}
|
||||
|
||||
template<typename U, std::size_t N>
|
||||
static
|
||||
std::size_t
|
||||
size_impl(
|
||||
U(&)[N],
|
||||
priority_tag<1>)
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
static
|
||||
std::size_t
|
||||
size_impl(U&, priority_tag<0>)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
static
|
||||
auto
|
||||
reserve_impl(
|
||||
U& cont,
|
||||
std::size_t size,
|
||||
priority_tag<1>) ->
|
||||
void_t<decltype(
|
||||
std::declval<U&>().reserve(0))>
|
||||
{
|
||||
cont.reserve(size);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
static
|
||||
void
|
||||
reserve_impl(
|
||||
U&,
|
||||
std::size_t,
|
||||
priority_tag<0>) { }
|
||||
public:
|
||||
static constexpr bool is_container = true;
|
||||
using value_type = remove_cvref<
|
||||
decltype(*begin(std::declval<T&>()))>;
|
||||
|
||||
template<typename U>
|
||||
static
|
||||
std::size_t
|
||||
try_size(U& cont)
|
||||
{
|
||||
return container_traits::size_impl(
|
||||
cont, priority_tag<2>());
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
static
|
||||
void
|
||||
try_reserve(
|
||||
U& cont,
|
||||
std::size_t size)
|
||||
{
|
||||
container_traits::reserve_impl(
|
||||
cont, size, priority_tag<1>());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename = void>
|
||||
struct map_traits
|
||||
{
|
||||
static constexpr bool is_map = false;
|
||||
static constexpr bool has_unique_keys = false;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct map_traits<T, void_t<typename remove_cvref<T>::key_type,
|
||||
typename std::enable_if<container_traits<T>::is_container &&
|
||||
std::tuple_size<typename remove_cvref<T>::
|
||||
value_type>::value == 2>::type>>
|
||||
{
|
||||
private:
|
||||
template<typename U, typename = void>
|
||||
struct unique_keys : std::false_type { };
|
||||
|
||||
template<typename U>
|
||||
struct unique_keys<U, typename std::enable_if<
|
||||
(std::tuple_size<remove_cvref<decltype(std::declval<
|
||||
remove_cvref<U>&>().emplace(std::declval<typename
|
||||
remove_cvref<U>::value_type>()))>>::value > 0)>::type>
|
||||
: std::true_type { };
|
||||
public:
|
||||
static constexpr bool is_map = true;
|
||||
static constexpr bool has_unique_keys = unique_keys<T>::value;
|
||||
using pair_key_type = typename std::tuple_element<
|
||||
0, typename remove_cvref<T>::value_type>::type;
|
||||
using pair_value_type = typename std::tuple_element<
|
||||
1, typename remove_cvref<T>::value_type>::type;
|
||||
static constexpr bool key_converts_to_string =
|
||||
std::is_convertible<pair_key_type, string_view>::value;
|
||||
};
|
||||
|
||||
// does not include std::nullptr_t
|
||||
template<class T>
|
||||
using value_constructible = std::integral_constant<bool,
|
||||
std::is_same<detail::remove_cvref<T>, value>::value ||
|
||||
std::is_same<detail::remove_cvref<T>, object>::value ||
|
||||
std::is_same<detail::remove_cvref<T>, array>::value ||
|
||||
std::is_same<detail::remove_cvref<T>, string>::value ||
|
||||
std::is_same<detail::remove_cvref<T>, string_view>::value ||
|
||||
std::is_arithmetic<detail::remove_cvref<T>>::value ||
|
||||
std::is_same<detail::remove_cvref<T>,
|
||||
std::initializer_list<value_ref>>::value ||
|
||||
std::is_same<detail::remove_cvref<T>, value_ref>::value>;
|
||||
|
||||
BOOST_STATIC_ASSERT(value_constructible<value>::value);
|
||||
|
||||
} // detail
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
233
install/boost_1_75_0/include/boost/json/error.hpp
Normal file
233
install/boost_1_75_0/include/boost/json/error.hpp
Normal file
@@ -0,0 +1,233 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_ERROR_HPP
|
||||
#define BOOST_JSON_ERROR_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#ifndef BOOST_JSON_STANDALONE
|
||||
# include <boost/system/error_code.hpp>
|
||||
# include <boost/system/system_error.hpp>
|
||||
#else
|
||||
# include <system_error>
|
||||
#endif
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
#ifdef BOOST_JSON_DOCS
|
||||
|
||||
/** The type of error code used by the library.
|
||||
|
||||
This type alias is set depending
|
||||
on how the library is configured:
|
||||
|
||||
@par Use with Boost
|
||||
|
||||
If the macro `BOOST_JSON_STANDALONE` is
|
||||
not defined, this type will be an alias
|
||||
for `boost::system::error_code`.
|
||||
Compiling a program using the library will
|
||||
require Boost, and a compiler conforming
|
||||
to C++11 or later.
|
||||
|
||||
@par Use without Boost
|
||||
|
||||
If the macro `BOOST_JSON_STANDALONE` is
|
||||
defined, this type will be an alias
|
||||
for `std::error_code`.
|
||||
Compiling a program using the library will
|
||||
require only a compiler conforming to C++17
|
||||
or later.
|
||||
|
||||
@see https://en.cppreference.com/w/cpp/error/error_code
|
||||
*/
|
||||
using error_code = __see_below__;
|
||||
|
||||
/** The type of error category used by the library.
|
||||
|
||||
This type alias is set depending
|
||||
on how the library is configured:
|
||||
|
||||
@par Use with Boost
|
||||
|
||||
If the macro `BOOST_JSON_STANDALONE` is
|
||||
not defined, this type will be an alias
|
||||
for `boost::system::error_category`.
|
||||
Compiling a program using the library will
|
||||
require Boost, and a compiler conforming
|
||||
to C++11 or later.
|
||||
|
||||
@par Use without Boost
|
||||
|
||||
If the macro `BOOST_JSON_STANDALONE` is
|
||||
defined, this type will be an alias
|
||||
for `std::error_category`.
|
||||
Compiling a program using the library will
|
||||
require only a compiler conforming to C++17
|
||||
or later.
|
||||
|
||||
@see https://en.cppreference.com/w/cpp/error/error_category
|
||||
*/
|
||||
using error_category = __see_below__;
|
||||
|
||||
/** The type of error condition used by the library.
|
||||
|
||||
This type alias is set depending
|
||||
on how the library is configured:
|
||||
|
||||
@par Use with Boost
|
||||
|
||||
If the macro `BOOST_JSON_STANDALONE` is
|
||||
not defined, this type will be an alias
|
||||
for `boost::system::error_condition`.
|
||||
Compiling a program using the library will
|
||||
require Boost, and a compiler conforming
|
||||
to C++11 or later.
|
||||
|
||||
@par Use without Boost
|
||||
|
||||
If the macro `BOOST_JSON_STANDALONE` is
|
||||
defined, this type will be an alias
|
||||
for `std::error_condition`.
|
||||
Compiling a program using the library will
|
||||
require only a compiler conforming to C++17
|
||||
or later.
|
||||
|
||||
@see https://en.cppreference.com/w/cpp/error/error_condition
|
||||
*/
|
||||
using error_condition = __see_below__;
|
||||
|
||||
/** The type of system error thrown by the library.
|
||||
|
||||
This type alias is set depending
|
||||
on how the library is configured:
|
||||
|
||||
@par Use with Boost
|
||||
|
||||
If the macro `BOOST_JSON_STANDALONE` is
|
||||
not defined, this type will be an alias
|
||||
for `boost::system::system_error`.
|
||||
Compiling a program using the library will
|
||||
require Boost, and a compiler conforming
|
||||
to C++11 or later.
|
||||
|
||||
@par Use without Boost
|
||||
|
||||
If the macro `BOOST_JSON_STANDALONE` is
|
||||
defined, this type will be an alias
|
||||
for `std::system_error`.
|
||||
Compiling a program using the library will
|
||||
require only a compiler conforming to C++17
|
||||
or later.
|
||||
|
||||
@see https://en.cppreference.com/w/cpp/error/system_error
|
||||
*/
|
||||
using system_error = __see_below__;
|
||||
|
||||
/// Returns the generic error category used by the library.
|
||||
error_category const&
|
||||
generic_category();
|
||||
|
||||
#elif ! defined(BOOST_JSON_STANDALONE)
|
||||
|
||||
using error_code = boost::system::error_code;
|
||||
using error_category = boost::system::error_category;
|
||||
using error_condition = boost::system::error_condition;
|
||||
using system_error = boost::system::system_error;
|
||||
using boost::system::generic_category;
|
||||
|
||||
#else
|
||||
|
||||
using error_code = std::error_code;
|
||||
using error_category = std::error_category;
|
||||
using error_condition = std::error_condition;
|
||||
using system_error = std::system_error;
|
||||
using std::generic_category;
|
||||
|
||||
#endif
|
||||
|
||||
/** Error codes returned by JSON operations
|
||||
|
||||
*/
|
||||
enum class error
|
||||
{
|
||||
//
|
||||
// parse errors
|
||||
//
|
||||
|
||||
/// syntax error
|
||||
syntax = 1,
|
||||
|
||||
/// extra data
|
||||
extra_data,
|
||||
|
||||
/// incomplete JSON
|
||||
incomplete,
|
||||
|
||||
/// exponent too large
|
||||
exponent_overflow,
|
||||
|
||||
/// too deep
|
||||
too_deep,
|
||||
|
||||
/// illegal leading surrogate
|
||||
illegal_leading_surrogate,
|
||||
|
||||
/// illegal trailing surrogate
|
||||
illegal_trailing_surrogate,
|
||||
|
||||
/// expected hex digit
|
||||
expected_hex_digit,
|
||||
|
||||
/// expected utf16 escape
|
||||
expected_utf16_escape,
|
||||
|
||||
/// An object contains too many elements
|
||||
object_too_large,
|
||||
|
||||
/// An array contains too many elements
|
||||
array_too_large,
|
||||
|
||||
/// A key is too large
|
||||
key_too_large,
|
||||
|
||||
/// A string is too large
|
||||
string_too_large,
|
||||
|
||||
/// The parser encountered an exception and must be reset
|
||||
exception,
|
||||
|
||||
//----------------------------------
|
||||
|
||||
/// not a number
|
||||
not_number,
|
||||
|
||||
/// number cast is not exact
|
||||
not_exact,
|
||||
|
||||
/// test failure
|
||||
test_failure,
|
||||
};
|
||||
|
||||
/** Error conditions corresponding to JSON errors
|
||||
*/
|
||||
enum class condition
|
||||
{
|
||||
/// A parser-related error
|
||||
parse_error = 1,
|
||||
|
||||
/// An error on assignment to or from a JSON value
|
||||
assign_error
|
||||
};
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#include <boost/json/impl/error.hpp>
|
||||
|
||||
#endif
|
||||
33
install/boost_1_75_0/include/boost/json/fwd.hpp
Normal file
33
install/boost_1_75_0/include/boost/json/fwd.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_FWD_HPP
|
||||
#define BOOST_JSON_FWD_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
// Forward declarations for value types
|
||||
|
||||
#ifndef BOOST_JSON_DOCS
|
||||
|
||||
class array;
|
||||
class object;
|
||||
class string;
|
||||
class value;
|
||||
|
||||
class key_value_pair;
|
||||
class storage_ptr;
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
554
install/boost_1_75_0/include/boost/json/impl/array.hpp
Normal file
554
install/boost_1_75_0/include/boost/json/impl/array.hpp
Normal file
@@ -0,0 +1,554 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_ARRAY_HPP
|
||||
#define BOOST_JSON_IMPL_ARRAY_HPP
|
||||
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/json/detail/except.hpp>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
struct alignas(value)
|
||||
array::table
|
||||
{
|
||||
std::uint32_t size = 0;
|
||||
std::uint32_t capacity = 0;
|
||||
|
||||
constexpr table();
|
||||
|
||||
value&
|
||||
operator[](std::size_t pos) noexcept
|
||||
{
|
||||
return (reinterpret_cast<
|
||||
value*>(this + 1))[pos];
|
||||
}
|
||||
|
||||
BOOST_JSON_DECL
|
||||
static
|
||||
table*
|
||||
allocate(
|
||||
std::size_t capacity,
|
||||
storage_ptr const& sp);
|
||||
|
||||
BOOST_JSON_DECL
|
||||
static
|
||||
void
|
||||
deallocate(
|
||||
table* p,
|
||||
storage_ptr const& sp);
|
||||
};
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
class array::revert_construct
|
||||
{
|
||||
array* arr_;
|
||||
|
||||
public:
|
||||
explicit
|
||||
revert_construct(
|
||||
array& arr) noexcept
|
||||
: arr_(&arr)
|
||||
{
|
||||
}
|
||||
|
||||
~revert_construct()
|
||||
{
|
||||
if(! arr_)
|
||||
return;
|
||||
arr_->destroy();
|
||||
}
|
||||
|
||||
void
|
||||
commit() noexcept
|
||||
{
|
||||
arr_ = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
class array::revert_insert
|
||||
{
|
||||
array* arr_;
|
||||
std::size_t const i_;
|
||||
std::size_t const n_;
|
||||
|
||||
public:
|
||||
value* p;
|
||||
|
||||
BOOST_JSON_DECL
|
||||
revert_insert(
|
||||
const_iterator pos,
|
||||
std::size_t n,
|
||||
array& arr);
|
||||
|
||||
BOOST_JSON_DECL
|
||||
~revert_insert();
|
||||
|
||||
value*
|
||||
commit() noexcept
|
||||
{
|
||||
auto it =
|
||||
arr_->data() + i_;
|
||||
arr_ = nullptr;
|
||||
return it;
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
array::
|
||||
relocate(
|
||||
value* dest,
|
||||
value* src,
|
||||
std::size_t n) noexcept
|
||||
{
|
||||
if(n == 0)
|
||||
return;
|
||||
std::memmove(
|
||||
static_cast<void*>(dest),
|
||||
static_cast<void const*>(src),
|
||||
n * sizeof(value));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Construction
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
template<class InputIt, class>
|
||||
array::
|
||||
array(
|
||||
InputIt first, InputIt last,
|
||||
storage_ptr sp)
|
||||
: array(
|
||||
first, last,
|
||||
std::move(sp),
|
||||
iter_cat<InputIt>{})
|
||||
{
|
||||
BOOST_STATIC_ASSERT(
|
||||
std::is_constructible<value,
|
||||
decltype(*first)>::value);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Modifiers
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
template<class InputIt, class>
|
||||
auto
|
||||
array::
|
||||
insert(
|
||||
const_iterator pos,
|
||||
InputIt first, InputIt last) ->
|
||||
iterator
|
||||
{
|
||||
BOOST_STATIC_ASSERT(
|
||||
std::is_constructible<value,
|
||||
decltype(*first)>::value);
|
||||
return insert(pos, first, last,
|
||||
iter_cat<InputIt>{});
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
auto
|
||||
array::
|
||||
emplace(
|
||||
const_iterator pos,
|
||||
Arg&& arg) ->
|
||||
iterator
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
pos >= begin() &&
|
||||
pos <= end());
|
||||
value jv(
|
||||
std::forward<Arg>(arg),
|
||||
storage());
|
||||
return insert(pos, pilfer(jv));
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
value&
|
||||
array::
|
||||
emplace_back(Arg&& arg)
|
||||
{
|
||||
value jv(
|
||||
std::forward<Arg>(arg),
|
||||
storage());
|
||||
return push_back(pilfer(jv));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Element access
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
value&
|
||||
array::
|
||||
at(std::size_t pos)
|
||||
{
|
||||
if(pos >= t_->size)
|
||||
detail::throw_out_of_range(
|
||||
BOOST_CURRENT_LOCATION);
|
||||
return (*t_)[pos];
|
||||
}
|
||||
|
||||
value const&
|
||||
array::
|
||||
at(std::size_t pos) const
|
||||
{
|
||||
if(pos >= t_->size)
|
||||
detail::throw_out_of_range(
|
||||
BOOST_CURRENT_LOCATION);
|
||||
return (*t_)[pos];
|
||||
}
|
||||
|
||||
value&
|
||||
array::
|
||||
operator[](std::size_t pos) noexcept
|
||||
{
|
||||
BOOST_ASSERT(pos < t_->size);
|
||||
return (*t_)[pos];
|
||||
}
|
||||
|
||||
value const&
|
||||
array::
|
||||
operator[](std::size_t pos) const noexcept
|
||||
{
|
||||
BOOST_ASSERT(pos < t_->size);
|
||||
return (*t_)[pos];
|
||||
}
|
||||
|
||||
value&
|
||||
array::
|
||||
front() noexcept
|
||||
{
|
||||
BOOST_ASSERT(t_->size > 0);
|
||||
return (*t_)[0];
|
||||
}
|
||||
|
||||
value const&
|
||||
array::
|
||||
front() const noexcept
|
||||
{
|
||||
BOOST_ASSERT(t_->size > 0);
|
||||
return (*t_)[0];
|
||||
}
|
||||
|
||||
value&
|
||||
array::
|
||||
back() noexcept
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
t_->size > 0);
|
||||
return (*t_)[t_->size - 1];
|
||||
}
|
||||
|
||||
value const&
|
||||
array::
|
||||
back() const noexcept
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
t_->size > 0);
|
||||
return (*t_)[t_->size - 1];
|
||||
}
|
||||
|
||||
value*
|
||||
array::
|
||||
data() noexcept
|
||||
{
|
||||
return &(*t_)[0];
|
||||
}
|
||||
|
||||
value const*
|
||||
array::
|
||||
data() const noexcept
|
||||
{
|
||||
return &(*t_)[0];
|
||||
}
|
||||
|
||||
value const*
|
||||
array::
|
||||
if_contains(
|
||||
std::size_t pos) const noexcept
|
||||
{
|
||||
if( pos < t_->size )
|
||||
return &(*t_)[pos];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
value*
|
||||
array::
|
||||
if_contains(
|
||||
std::size_t pos) noexcept
|
||||
{
|
||||
if( pos < t_->size )
|
||||
return &(*t_)[pos];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Iterators
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
auto
|
||||
array::
|
||||
begin() noexcept ->
|
||||
iterator
|
||||
{
|
||||
return &(*t_)[0];
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
begin() const noexcept ->
|
||||
const_iterator
|
||||
{
|
||||
return &(*t_)[0];
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
cbegin() const noexcept ->
|
||||
const_iterator
|
||||
{
|
||||
return &(*t_)[0];
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
end() noexcept ->
|
||||
iterator
|
||||
{
|
||||
return &(*t_)[t_->size];
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
end() const noexcept ->
|
||||
const_iterator
|
||||
{
|
||||
return &(*t_)[t_->size];
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
cend() const noexcept ->
|
||||
const_iterator
|
||||
{
|
||||
return &(*t_)[t_->size];
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
rbegin() noexcept ->
|
||||
reverse_iterator
|
||||
{
|
||||
return reverse_iterator(end());
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
rbegin() const noexcept ->
|
||||
const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
crbegin() const noexcept ->
|
||||
const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
rend() noexcept ->
|
||||
reverse_iterator
|
||||
{
|
||||
return reverse_iterator(begin());
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
rend() const noexcept ->
|
||||
const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
crend() const noexcept ->
|
||||
const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Capacity
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
std::size_t
|
||||
array::
|
||||
size() const noexcept
|
||||
{
|
||||
return t_->size;
|
||||
}
|
||||
|
||||
constexpr
|
||||
std::size_t
|
||||
array::
|
||||
max_size() noexcept
|
||||
{
|
||||
// max_size depends on the address model
|
||||
using min = std::integral_constant<std::size_t,
|
||||
(std::size_t(-1) - sizeof(table)) / sizeof(value)>;
|
||||
return min::value < BOOST_JSON_MAX_STRUCTURED_SIZE ?
|
||||
min::value : BOOST_JSON_MAX_STRUCTURED_SIZE;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
array::
|
||||
capacity() const noexcept
|
||||
{
|
||||
return t_->capacity;
|
||||
}
|
||||
|
||||
bool
|
||||
array::
|
||||
empty() const noexcept
|
||||
{
|
||||
return t_->size == 0;
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
reserve(
|
||||
std::size_t new_capacity)
|
||||
{
|
||||
// never shrink
|
||||
if(new_capacity <= t_->capacity)
|
||||
return;
|
||||
reserve_impl(new_capacity);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// private
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
template<class InputIt>
|
||||
array::
|
||||
array(
|
||||
InputIt first, InputIt last,
|
||||
storage_ptr sp,
|
||||
std::input_iterator_tag)
|
||||
: sp_(std::move(sp))
|
||||
, t_(&empty_)
|
||||
{
|
||||
revert_construct r(*this);
|
||||
while(first != last)
|
||||
{
|
||||
reserve(size() + 1);
|
||||
::new(end()) value(
|
||||
*first++, sp_);
|
||||
++t_->size;
|
||||
}
|
||||
r.commit();
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
array::
|
||||
array(
|
||||
InputIt first, InputIt last,
|
||||
storage_ptr sp,
|
||||
std::forward_iterator_tag)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
std::size_t n =
|
||||
std::distance(first, last);
|
||||
t_ = table::allocate(n, sp_);
|
||||
t_->size = 0;
|
||||
revert_construct r(*this);
|
||||
while(n--)
|
||||
{
|
||||
::new(end()) value(
|
||||
*first++, sp_);
|
||||
++t_->size;
|
||||
}
|
||||
r.commit();
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
auto
|
||||
array::
|
||||
insert(
|
||||
const_iterator pos,
|
||||
InputIt first, InputIt last,
|
||||
std::input_iterator_tag) ->
|
||||
iterator
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
pos >= begin() && pos <= end());
|
||||
if(first == last)
|
||||
return data() + (pos - data());
|
||||
array temp(first, last, sp_);
|
||||
revert_insert r(
|
||||
pos, temp.size(), *this);
|
||||
relocate(
|
||||
r.p,
|
||||
temp.data(),
|
||||
temp.size());
|
||||
temp.t_->size = 0;
|
||||
return r.commit();
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
auto
|
||||
array::
|
||||
insert(
|
||||
const_iterator pos,
|
||||
InputIt first, InputIt last,
|
||||
std::forward_iterator_tag) ->
|
||||
iterator
|
||||
{
|
||||
std::size_t n =
|
||||
std::distance(first, last);
|
||||
revert_insert r(pos, n, *this);
|
||||
while(n--)
|
||||
{
|
||||
::new(r.p) value(*first++);
|
||||
++r.p;
|
||||
}
|
||||
return r.commit();
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
757
install/boost_1_75_0/include/boost/json/impl/array.ipp
Normal file
757
install/boost_1_75_0/include/boost/json/impl/array.ipp
Normal file
@@ -0,0 +1,757 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_ARRAY_IPP
|
||||
#define BOOST_JSON_IMPL_ARRAY_IPP
|
||||
|
||||
#include <boost/json/array.hpp>
|
||||
#include <boost/json/pilfer.hpp>
|
||||
#include <boost/json/detail/except.hpp>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <new>
|
||||
#include <utility>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
constexpr array::table::table() = default;
|
||||
|
||||
// empty arrays point here
|
||||
BOOST_JSON_REQUIRE_CONST_INIT
|
||||
array::table array::empty_;
|
||||
|
||||
auto
|
||||
array::
|
||||
table::
|
||||
allocate(
|
||||
std::size_t capacity,
|
||||
storage_ptr const& sp) ->
|
||||
table*
|
||||
{
|
||||
BOOST_ASSERT(capacity > 0);
|
||||
if(capacity > array::max_size())
|
||||
detail::throw_length_error(
|
||||
"array too large",
|
||||
BOOST_CURRENT_LOCATION);
|
||||
auto p = reinterpret_cast<
|
||||
table*>(sp->allocate(
|
||||
sizeof(table) +
|
||||
capacity * sizeof(value),
|
||||
alignof(value)));
|
||||
p->capacity = static_cast<
|
||||
std::uint32_t>(capacity);
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
table::
|
||||
deallocate(
|
||||
table* p,
|
||||
storage_ptr const& sp)
|
||||
{
|
||||
if(p->capacity == 0)
|
||||
return;
|
||||
sp->deallocate(p,
|
||||
sizeof(table) +
|
||||
p->capacity * sizeof(value),
|
||||
alignof(value));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
array::
|
||||
revert_insert::
|
||||
revert_insert(
|
||||
const_iterator pos,
|
||||
std::size_t n,
|
||||
array& arr)
|
||||
: arr_(&arr)
|
||||
, i_(pos - arr_->data())
|
||||
, n_(n)
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
pos >= arr_->begin() &&
|
||||
pos <= arr_->end());
|
||||
if( n_ <= arr_->capacity() -
|
||||
arr_->size())
|
||||
{
|
||||
// fast path
|
||||
p = arr_->data() + i_;
|
||||
if(n_ == 0)
|
||||
return;
|
||||
relocate(
|
||||
p + n_,
|
||||
p,
|
||||
arr_->size() - i_);
|
||||
arr_->t_->size = static_cast<
|
||||
std::uint32_t>(
|
||||
arr_->t_->size + n_);
|
||||
return;
|
||||
}
|
||||
if(n_ > max_size() - arr_->size())
|
||||
detail::throw_length_error(
|
||||
"array too large",
|
||||
BOOST_CURRENT_LOCATION);
|
||||
auto t = table::allocate(
|
||||
arr_->growth(arr_->size() + n_),
|
||||
arr_->sp_);
|
||||
t->size = static_cast<std::uint32_t>(
|
||||
arr_->size() + n_);
|
||||
p = &(*t)[0] + i_;
|
||||
relocate(
|
||||
&(*t)[0],
|
||||
arr_->data(),
|
||||
i_);
|
||||
relocate(
|
||||
&(*t)[i_ + n_],
|
||||
arr_->data() + i_,
|
||||
arr_->size() - i_);
|
||||
t = detail::exchange(arr_->t_, t);
|
||||
table::deallocate(t, arr_->sp_);
|
||||
}
|
||||
|
||||
array::
|
||||
revert_insert::
|
||||
~revert_insert()
|
||||
{
|
||||
if(! arr_)
|
||||
return;
|
||||
BOOST_ASSERT(n_ != 0);
|
||||
auto const pos =
|
||||
arr_->data() + i_;
|
||||
arr_->destroy(pos, p);
|
||||
arr_->t_->size = static_cast<
|
||||
std::uint32_t>(
|
||||
arr_->t_->size - n_);
|
||||
relocate(
|
||||
pos,
|
||||
pos + n_,
|
||||
arr_->size() - i_);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
array::
|
||||
destroy(
|
||||
value* first, value* last) noexcept
|
||||
{
|
||||
if(sp_.is_not_shared_and_deallocate_is_trivial())
|
||||
return;
|
||||
while(last-- != first)
|
||||
last->~value();
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
destroy() noexcept
|
||||
{
|
||||
if(sp_.is_not_shared_and_deallocate_is_trivial())
|
||||
return;
|
||||
auto last = end();
|
||||
auto const first = begin();
|
||||
while(last-- != first)
|
||||
last->~value();
|
||||
table::deallocate(t_, sp_);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Special Members
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
array::
|
||||
array(detail::unchecked_array&& ua)
|
||||
: sp_(ua.storage())
|
||||
{
|
||||
BOOST_STATIC_ASSERT(
|
||||
alignof(table) == alignof(value));
|
||||
if(ua.size() == 0)
|
||||
{
|
||||
t_ = &empty_;
|
||||
return;
|
||||
}
|
||||
t_= table::allocate(
|
||||
ua.size(), sp_);
|
||||
t_->size = static_cast<
|
||||
std::uint32_t>(ua.size());
|
||||
ua.relocate(data());
|
||||
}
|
||||
|
||||
array::
|
||||
~array()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
array::
|
||||
array(
|
||||
std::size_t count,
|
||||
value const& v,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
if(count == 0)
|
||||
{
|
||||
t_ = &empty_;
|
||||
return;
|
||||
}
|
||||
t_= table::allocate(
|
||||
count, sp_);
|
||||
t_->size = 0;
|
||||
revert_construct r(*this);
|
||||
while(count--)
|
||||
{
|
||||
::new(end()) value(v, sp_);
|
||||
++t_->size;
|
||||
}
|
||||
r.commit();
|
||||
}
|
||||
|
||||
array::
|
||||
array(
|
||||
std::size_t count,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
if(count == 0)
|
||||
{
|
||||
t_ = &empty_;
|
||||
return;
|
||||
}
|
||||
t_ = table::allocate(
|
||||
count, sp_);
|
||||
t_->size = static_cast<
|
||||
std::uint32_t>(count);
|
||||
auto p = data();
|
||||
do
|
||||
{
|
||||
::new(p++) value(sp_);
|
||||
}
|
||||
while(--count);
|
||||
}
|
||||
|
||||
array::
|
||||
array(array const& other)
|
||||
: array(other, other.sp_)
|
||||
{
|
||||
}
|
||||
|
||||
array::
|
||||
array(
|
||||
array const& other,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
if(other.empty())
|
||||
{
|
||||
t_ = &empty_;
|
||||
return;
|
||||
}
|
||||
t_ = table::allocate(
|
||||
other.size(), sp_);
|
||||
t_->size = 0;
|
||||
revert_construct r(*this);
|
||||
auto src = other.data();
|
||||
auto dest = data();
|
||||
auto const n = other.size();
|
||||
do
|
||||
{
|
||||
::new(dest++) value(
|
||||
*src++, sp_);
|
||||
++t_->size;
|
||||
}
|
||||
while(t_->size < n);
|
||||
r.commit();
|
||||
}
|
||||
|
||||
array::
|
||||
array(
|
||||
array&& other,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
if(*sp_ == *other.sp_)
|
||||
{
|
||||
// same resource
|
||||
t_ = detail::exchange(
|
||||
other.t_, &empty_);
|
||||
return;
|
||||
}
|
||||
else if(other.empty())
|
||||
{
|
||||
t_ = &empty_;
|
||||
return;
|
||||
}
|
||||
// copy
|
||||
t_ = table::allocate(
|
||||
other.size(), sp_);
|
||||
t_->size = 0;
|
||||
revert_construct r(*this);
|
||||
auto src = other.data();
|
||||
auto dest = data();
|
||||
auto const n = other.size();
|
||||
do
|
||||
{
|
||||
::new(dest++) value(
|
||||
*src++, sp_);
|
||||
++t_->size;
|
||||
}
|
||||
while(t_->size < n);
|
||||
r.commit();
|
||||
}
|
||||
|
||||
array::
|
||||
array(
|
||||
std::initializer_list<
|
||||
value_ref> init,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
if(init.size() == 0)
|
||||
{
|
||||
t_ = &empty_;
|
||||
return;
|
||||
}
|
||||
t_ = table::allocate(
|
||||
init.size(), sp_);
|
||||
t_->size = 0;
|
||||
revert_construct r(*this);
|
||||
value_ref::write_array(
|
||||
data(), init, sp_);
|
||||
t_->size = static_cast<
|
||||
std::uint32_t>(init.size());
|
||||
r.commit();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
array&
|
||||
array::
|
||||
operator=(array const& other)
|
||||
{
|
||||
array(other,
|
||||
storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
array&
|
||||
array::
|
||||
operator=(array&& other)
|
||||
{
|
||||
array(std::move(other),
|
||||
storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
array&
|
||||
array::
|
||||
operator=(
|
||||
std::initializer_list<value_ref> init)
|
||||
{
|
||||
array(init,
|
||||
storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Capacity
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
array::
|
||||
shrink_to_fit() noexcept
|
||||
{
|
||||
if(capacity() <= size())
|
||||
return;
|
||||
if(size() == 0)
|
||||
{
|
||||
table::deallocate(t_, sp_);
|
||||
t_ = &empty_;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif
|
||||
auto t = table::allocate(
|
||||
size(), sp_);
|
||||
relocate(
|
||||
&(*t)[0],
|
||||
data(),
|
||||
size());
|
||||
t->size = static_cast<
|
||||
std::uint32_t>(size());
|
||||
t = detail::exchange(
|
||||
t_, t);
|
||||
table::deallocate(t, sp_);
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
// eat the exception
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Modifiers
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
array::
|
||||
clear() noexcept
|
||||
{
|
||||
if(size() == 0)
|
||||
return;
|
||||
destroy(
|
||||
begin(), end());
|
||||
t_->size = 0;
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
insert(
|
||||
const_iterator pos,
|
||||
value const& v) ->
|
||||
iterator
|
||||
{
|
||||
return emplace(pos, v);
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
insert(
|
||||
const_iterator pos,
|
||||
value&& v) ->
|
||||
iterator
|
||||
{
|
||||
return emplace(pos, std::move(v));
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
insert(
|
||||
const_iterator pos,
|
||||
std::size_t count,
|
||||
value const& v) ->
|
||||
iterator
|
||||
{
|
||||
revert_insert r(
|
||||
pos, count, *this);
|
||||
while(count--)
|
||||
{
|
||||
::new(r.p) value(v, sp_);
|
||||
++r.p;
|
||||
}
|
||||
return r.commit();
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
insert(
|
||||
const_iterator pos,
|
||||
std::initializer_list<
|
||||
value_ref> init) ->
|
||||
iterator
|
||||
{
|
||||
revert_insert r(
|
||||
pos, init.size(), *this);
|
||||
value_ref::write_array(
|
||||
r.p, init, sp_);
|
||||
return r.commit();
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
erase(
|
||||
const_iterator pos) noexcept ->
|
||||
iterator
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
pos >= begin() &&
|
||||
pos <= end());
|
||||
auto const p = &(*t_)[0] +
|
||||
(pos - &(*t_)[0]);
|
||||
destroy(p, p + 1);
|
||||
relocate(p, p + 1, 1);
|
||||
--t_->size;
|
||||
return p;
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
erase(
|
||||
const_iterator first,
|
||||
const_iterator last) noexcept ->
|
||||
iterator
|
||||
{
|
||||
std::size_t const n =
|
||||
last - first;
|
||||
auto const p = &(*t_)[0] +
|
||||
(first - &(*t_)[0]);
|
||||
destroy(p, p + n);
|
||||
relocate(p, p + n,
|
||||
t_->size - (last -
|
||||
&(*t_)[0]));
|
||||
t_->size = static_cast<
|
||||
std::uint32_t>(t_->size - n);
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
push_back(value const& v)
|
||||
{
|
||||
emplace_back(v);
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
push_back(value&& v)
|
||||
{
|
||||
emplace_back(std::move(v));
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
pop_back() noexcept
|
||||
{
|
||||
auto const p = &back();
|
||||
destroy(p, p + 1);
|
||||
--t_->size;
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
resize(std::size_t count)
|
||||
{
|
||||
if(count <= t_->size)
|
||||
{
|
||||
// shrink
|
||||
destroy(
|
||||
&(*t_)[0] + count,
|
||||
&(*t_)[0] + t_->size);
|
||||
t_->size = static_cast<
|
||||
std::uint32_t>(count);
|
||||
return;
|
||||
}
|
||||
|
||||
reserve(count);
|
||||
auto p = &(*t_)[t_->size];
|
||||
auto const end = &(*t_)[count];
|
||||
while(p != end)
|
||||
::new(p++) value(sp_);
|
||||
t_->size = static_cast<
|
||||
std::uint32_t>(count);
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
resize(
|
||||
std::size_t count,
|
||||
value const& v)
|
||||
{
|
||||
if(count <= size())
|
||||
{
|
||||
// shrink
|
||||
destroy(
|
||||
data() + count,
|
||||
data() + size());
|
||||
t_->size = static_cast<
|
||||
std::uint32_t>(count);
|
||||
return;
|
||||
}
|
||||
count -= size();
|
||||
revert_insert r(
|
||||
end(), count, *this);
|
||||
while(count--)
|
||||
{
|
||||
::new(r.p) value(v, sp_);
|
||||
++r.p;
|
||||
}
|
||||
r.commit();
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
swap(array& other)
|
||||
{
|
||||
BOOST_ASSERT(this != &other);
|
||||
if(*sp_ == *other.sp_)
|
||||
{
|
||||
t_ = detail::exchange(
|
||||
other.t_, t_);
|
||||
return;
|
||||
}
|
||||
array temp1(
|
||||
std::move(*this),
|
||||
other.storage());
|
||||
array temp2(
|
||||
std::move(other),
|
||||
this->storage());
|
||||
this->~array();
|
||||
::new(this) array(
|
||||
pilfer(temp2));
|
||||
other.~array();
|
||||
::new(&other) array(
|
||||
pilfer(temp1));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Private
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
std::size_t
|
||||
array::
|
||||
growth(
|
||||
std::size_t new_size) const
|
||||
{
|
||||
if(new_size > max_size())
|
||||
detail::throw_length_error(
|
||||
"array too large",
|
||||
BOOST_CURRENT_LOCATION);
|
||||
std::size_t const old = capacity();
|
||||
if(old > max_size() - old / 2)
|
||||
return new_size;
|
||||
std::size_t const g =
|
||||
old + old / 2; // 1.5x
|
||||
if(g < new_size)
|
||||
return new_size;
|
||||
return g;
|
||||
}
|
||||
|
||||
// precondition: new_capacity > capacity()
|
||||
void
|
||||
array::
|
||||
reserve_impl(
|
||||
std::size_t new_capacity)
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
new_capacity > t_->capacity);
|
||||
auto t = table::allocate(
|
||||
growth(new_capacity), sp_);
|
||||
relocate(
|
||||
&(*t)[0],
|
||||
&(*t_)[0],
|
||||
t_->size);
|
||||
t->size = t_->size;
|
||||
t = detail::exchange(t_, t);
|
||||
table::deallocate(t, sp_);
|
||||
}
|
||||
|
||||
// precondition: pv is not aliased
|
||||
value&
|
||||
array::
|
||||
push_back(
|
||||
pilfered<value> pv)
|
||||
{
|
||||
auto const n = t_->size;
|
||||
if(n < t_->capacity)
|
||||
{
|
||||
// fast path
|
||||
auto& v = *::new(
|
||||
&(*t_)[n]) value(pv);
|
||||
++t_->size;
|
||||
return v;
|
||||
}
|
||||
auto const t =
|
||||
detail::exchange(t_,
|
||||
table::allocate(
|
||||
growth(n + 1),
|
||||
sp_));
|
||||
auto& v = *::new(
|
||||
&(*t_)[n]) value(pv);
|
||||
relocate(
|
||||
&(*t_)[0],
|
||||
&(*t)[0],
|
||||
n);
|
||||
t_->size = n + 1;
|
||||
table::deallocate(t, sp_);
|
||||
return v;
|
||||
}
|
||||
|
||||
// precondition: pv is not aliased
|
||||
auto
|
||||
array::
|
||||
insert(
|
||||
const_iterator pos,
|
||||
pilfered<value> pv) ->
|
||||
iterator
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
pos >= begin() &&
|
||||
pos <= end());
|
||||
std::size_t const n =
|
||||
t_->size;
|
||||
std::size_t const i =
|
||||
pos - &(*t_)[0];
|
||||
if(n < t_->capacity)
|
||||
{
|
||||
// fast path
|
||||
auto const p =
|
||||
&(*t_)[i];
|
||||
relocate(
|
||||
p + 1,
|
||||
p,
|
||||
n - i);
|
||||
::new(p) value(pv);
|
||||
++t_->size;
|
||||
return p;
|
||||
}
|
||||
auto t =
|
||||
table::allocate(
|
||||
growth(n + 1), sp_);
|
||||
auto const p = &(*t)[i];
|
||||
::new(p) value(pv);
|
||||
relocate(
|
||||
&(*t)[0],
|
||||
&(*t_)[0],
|
||||
i);
|
||||
relocate(
|
||||
p + 1,
|
||||
&(*t_)[i],
|
||||
n - i);
|
||||
t->size = static_cast<
|
||||
std::uint32_t>(size() + 1);
|
||||
t = detail::exchange(t_, t);
|
||||
table::deallocate(t, sp_);
|
||||
return p;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
bool
|
||||
array::
|
||||
equal(
|
||||
array const& other) const noexcept
|
||||
{
|
||||
if(size() != other.size())
|
||||
return false;
|
||||
for(std::size_t i = 0; i < size(); ++i)
|
||||
if((*this)[i] != other[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
61
install/boost_1_75_0/include/boost/json/impl/error.hpp
Normal file
61
install/boost_1_75_0/include/boost/json/impl/error.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_ERROR_HPP
|
||||
#define BOOST_JSON_IMPL_ERROR_HPP
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#ifndef BOOST_JSON_STANDALONE
|
||||
|
||||
namespace boost {
|
||||
namespace system {
|
||||
template<>
|
||||
struct is_error_code_enum< ::boost::json::error >
|
||||
{
|
||||
static bool const value = true;
|
||||
};
|
||||
template<>
|
||||
struct is_error_condition_enum< ::boost::json::condition >
|
||||
{
|
||||
static bool const value = true;
|
||||
};
|
||||
} // system
|
||||
} // boost
|
||||
|
||||
#else
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct is_error_code_enum< ::boost::json::error >
|
||||
{
|
||||
static bool const value = true;
|
||||
};
|
||||
template<>
|
||||
struct is_error_condition_enum< ::boost::json::condition >
|
||||
{
|
||||
static bool const value = true;
|
||||
};
|
||||
} // std
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
BOOST_JSON_DECL
|
||||
error_code
|
||||
make_error_code(error e);
|
||||
|
||||
BOOST_JSON_DECL
|
||||
error_condition
|
||||
make_error_condition(condition c);
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
123
install/boost_1_75_0/include/boost/json/impl/error.ipp
Normal file
123
install/boost_1_75_0/include/boost/json/impl/error.ipp
Normal file
@@ -0,0 +1,123 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_ERROR_IPP
|
||||
#define BOOST_JSON_IMPL_ERROR_IPP
|
||||
|
||||
#include <boost/json/error.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
error_code
|
||||
make_error_code(error e)
|
||||
{
|
||||
struct codes : error_category
|
||||
{
|
||||
const char*
|
||||
name() const noexcept override
|
||||
{
|
||||
return "boost.json";
|
||||
}
|
||||
|
||||
std::string
|
||||
message(int ev) const override
|
||||
{
|
||||
switch(static_cast<error>(ev))
|
||||
{
|
||||
default:
|
||||
case error::syntax: return "syntax error";
|
||||
case error::extra_data: return "extra data";
|
||||
case error::incomplete: return "incomplete JSON";
|
||||
case error::exponent_overflow: return "exponent overflow";
|
||||
case error::too_deep: return "too deep";
|
||||
case error::illegal_leading_surrogate: return "illegal leading surrogate";
|
||||
case error::illegal_trailing_surrogate: return "illegal trailing surrogate";
|
||||
case error::expected_hex_digit: return "expected hex digit";
|
||||
case error::expected_utf16_escape: return "expected utf16 escape";
|
||||
case error::object_too_large: return "object too large";
|
||||
case error::array_too_large: return "array too large";
|
||||
case error::key_too_large: return "key too large";
|
||||
case error::string_too_large: return "string too large";
|
||||
case error::exception: return "got exception";
|
||||
case error::not_number: return "not a number";
|
||||
case error::not_exact: return "not exact";
|
||||
|
||||
case error::test_failure: return "test failure";
|
||||
}
|
||||
}
|
||||
|
||||
error_condition
|
||||
default_error_condition(
|
||||
int ev) const noexcept override
|
||||
{
|
||||
switch(static_cast<error>(ev))
|
||||
{
|
||||
default:
|
||||
return {ev, *this};
|
||||
|
||||
case error::syntax:
|
||||
case error::extra_data:
|
||||
case error::incomplete:
|
||||
case error::exponent_overflow:
|
||||
case error::too_deep:
|
||||
case error::illegal_leading_surrogate:
|
||||
case error::illegal_trailing_surrogate:
|
||||
case error::expected_hex_digit:
|
||||
case error::expected_utf16_escape:
|
||||
case error::object_too_large:
|
||||
case error::array_too_large:
|
||||
case error::key_too_large:
|
||||
case error::string_too_large:
|
||||
case error::exception:
|
||||
return condition::parse_error;
|
||||
|
||||
case error::not_number:
|
||||
case error::not_exact:
|
||||
return condition::assign_error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static codes const cat{};
|
||||
return error_code{static_cast<
|
||||
std::underlying_type<error>::type>(e), cat};
|
||||
}
|
||||
|
||||
error_condition
|
||||
make_error_condition(condition c)
|
||||
{
|
||||
struct codes : error_category
|
||||
{
|
||||
const char*
|
||||
name() const noexcept override
|
||||
{
|
||||
return "boost.json";
|
||||
}
|
||||
|
||||
std::string
|
||||
message(int cv) const override
|
||||
{
|
||||
switch(static_cast<condition>(cv))
|
||||
{
|
||||
default:
|
||||
case condition::parse_error:
|
||||
return "A JSON parse error occurred";
|
||||
case condition::assign_error:
|
||||
return "An error occurred during assignment";
|
||||
}
|
||||
}
|
||||
};
|
||||
static codes const cat{};
|
||||
return error_condition{static_cast<
|
||||
std::underlying_type<condition>::type>(c), cat};
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
44
install/boost_1_75_0/include/boost/json/impl/kind.ipp
Normal file
44
install/boost_1_75_0/include/boost/json/impl/kind.ipp
Normal file
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_KIND_IPP
|
||||
#define BOOST_JSON_IMPL_KIND_IPP
|
||||
|
||||
#include <boost/json/kind.hpp>
|
||||
#include <ostream>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
string_view
|
||||
to_string(kind k) noexcept
|
||||
{
|
||||
switch(k)
|
||||
{
|
||||
case kind::array: return "array";
|
||||
case kind::object: return "object";
|
||||
case kind::string: return "string";
|
||||
case kind::int64: return "int64";
|
||||
case kind::uint64: return "uint64";
|
||||
case kind::double_: return "double";
|
||||
case kind::bool_: return "bool";
|
||||
default: // satisfy warnings
|
||||
case kind::null: return "null";
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, kind k)
|
||||
{
|
||||
os << to_string(k);
|
||||
return os;
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,171 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
|
||||
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_MONOTONIC_RESOURCE_IPP
|
||||
#define BOOST_JSON_IMPL_MONOTONIC_RESOURCE_IPP
|
||||
|
||||
#include <boost/json/monotonic_resource.hpp>
|
||||
#include <boost/json/detail/align.hpp>
|
||||
#include <boost/json/detail/except.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
struct alignas(detail::max_align_t)
|
||||
monotonic_resource::block : block_base
|
||||
{
|
||||
};
|
||||
|
||||
constexpr
|
||||
std::size_t
|
||||
monotonic_resource::
|
||||
max_size()
|
||||
{
|
||||
return std::size_t(-1) - sizeof(block);
|
||||
}
|
||||
|
||||
// lowest power of 2 greater than or equal to n
|
||||
std::size_t
|
||||
monotonic_resource::
|
||||
round_pow2(
|
||||
std::size_t n) noexcept
|
||||
{
|
||||
if(n & (n - 1))
|
||||
return next_pow2(n);
|
||||
return n;
|
||||
}
|
||||
|
||||
// lowest power of 2 greater than n
|
||||
std::size_t
|
||||
monotonic_resource::
|
||||
next_pow2(
|
||||
std::size_t n) noexcept
|
||||
{
|
||||
std::size_t result = min_size_;
|
||||
while(result <= n)
|
||||
{
|
||||
if(result >= max_size() - result)
|
||||
{
|
||||
// overflow
|
||||
result = max_size();
|
||||
break;
|
||||
}
|
||||
result *= 2;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
monotonic_resource::
|
||||
~monotonic_resource()
|
||||
{
|
||||
release();
|
||||
}
|
||||
|
||||
monotonic_resource::
|
||||
monotonic_resource(
|
||||
std::size_t initial_size,
|
||||
storage_ptr upstream) noexcept
|
||||
: buffer_{
|
||||
nullptr, 0, 0, nullptr}
|
||||
, next_size_(round_pow2(initial_size))
|
||||
, upstream_(std::move(upstream))
|
||||
{
|
||||
}
|
||||
|
||||
monotonic_resource::
|
||||
monotonic_resource(
|
||||
unsigned char* buffer,
|
||||
std::size_t size,
|
||||
storage_ptr upstream) noexcept
|
||||
: buffer_{
|
||||
buffer, size, size, nullptr}
|
||||
, next_size_(next_pow2(size))
|
||||
, upstream_(std::move(upstream))
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
monotonic_resource::
|
||||
release() noexcept
|
||||
{
|
||||
auto p = head_;
|
||||
while(p != &buffer_)
|
||||
{
|
||||
auto next = p->next;
|
||||
upstream_->deallocate(p, p->size);
|
||||
p = next;
|
||||
}
|
||||
buffer_.p = reinterpret_cast<
|
||||
unsigned char*>(buffer_.p) - (
|
||||
buffer_.size - buffer_.avail);
|
||||
buffer_.avail = buffer_.size;
|
||||
head_ = &buffer_;
|
||||
}
|
||||
|
||||
void*
|
||||
monotonic_resource::
|
||||
do_allocate(
|
||||
std::size_t n,
|
||||
std::size_t align)
|
||||
{
|
||||
auto p = detail::align(
|
||||
align, n, head_->p, head_->avail);
|
||||
if(p)
|
||||
{
|
||||
head_->p = reinterpret_cast<
|
||||
unsigned char*>(p) + n;
|
||||
head_->avail -= n;
|
||||
return p;
|
||||
}
|
||||
|
||||
if(next_size_ < n)
|
||||
next_size_ = round_pow2(n);
|
||||
auto b = ::new(upstream_->allocate(
|
||||
sizeof(block) + next_size_)) block;
|
||||
b->p = b + 1;
|
||||
b->avail = next_size_;
|
||||
b->size = next_size_;
|
||||
b->next = head_;
|
||||
head_ = b;
|
||||
next_size_ = next_pow2(next_size_);
|
||||
|
||||
p = detail::align(
|
||||
align, n, head_->p, head_->avail);
|
||||
BOOST_ASSERT(p);
|
||||
head_->p = reinterpret_cast<
|
||||
unsigned char*>(p) + n;
|
||||
head_->avail -= n;
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
monotonic_resource::
|
||||
do_deallocate(
|
||||
void*,
|
||||
std::size_t,
|
||||
std::size_t)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
bool
|
||||
monotonic_resource::
|
||||
do_is_equal(
|
||||
memory_resource const& mr) const noexcept
|
||||
{
|
||||
return this == &mr;
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
101
install/boost_1_75_0/include/boost/json/impl/null_resource.ipp
Normal file
101
install/boost_1_75_0/include/boost/json/impl/null_resource.ipp
Normal file
@@ -0,0 +1,101 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_NULL_RESOURCE_IPP
|
||||
#define BOOST_JSON_IMPL_NULL_RESOURCE_IPP
|
||||
|
||||
#include <boost/json/null_resource.hpp>
|
||||
#include <boost/json/detail/except.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
namespace detail {
|
||||
|
||||
/** A resource which always fails.
|
||||
|
||||
This memory resource always throws the exception
|
||||
`std::bad_alloc` in calls to `allocate`.
|
||||
*/
|
||||
class null_resource final
|
||||
: public memory_resource
|
||||
{
|
||||
public:
|
||||
/// Copy constructor (deleted)
|
||||
null_resource(
|
||||
null_resource const&) = delete;
|
||||
|
||||
/// Copy assignment (deleted)
|
||||
null_resource& operator=(
|
||||
null_resource const&) = delete;
|
||||
|
||||
/** Destructor
|
||||
|
||||
This destroys the resource.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@part Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
~null_resource() noexcept = default;
|
||||
|
||||
/** Constructor
|
||||
|
||||
This constructs the resource.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
/** @{ */
|
||||
null_resource() noexcept = default;
|
||||
|
||||
protected:
|
||||
void*
|
||||
do_allocate(
|
||||
std::size_t,
|
||||
std::size_t) override
|
||||
{
|
||||
detail::throw_bad_alloc(
|
||||
BOOST_CURRENT_LOCATION);
|
||||
}
|
||||
|
||||
void
|
||||
do_deallocate(
|
||||
void*,
|
||||
std::size_t,
|
||||
std::size_t) override
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
bool
|
||||
do_is_equal(
|
||||
memory_resource const& mr
|
||||
) const noexcept override
|
||||
{
|
||||
return this == &mr;
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
|
||||
memory_resource*
|
||||
get_null_resource() noexcept
|
||||
{
|
||||
static detail::null_resource mr;
|
||||
return &mr;
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
530
install/boost_1_75_0/include/boost/json/impl/object.hpp
Normal file
530
install/boost_1_75_0/include/boost/json/impl/object.hpp
Normal file
@@ -0,0 +1,530 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_OBJECT_HPP
|
||||
#define BOOST_JSON_IMPL_OBJECT_HPP
|
||||
|
||||
#include <boost/json/value.hpp>
|
||||
#include <iterator>
|
||||
#include <cmath>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Objects with size less than or equal
|
||||
// to this number will use a linear search
|
||||
// instead of the more expensive hash function.
|
||||
static
|
||||
constexpr
|
||||
std::size_t
|
||||
small_object_size_ = 18;
|
||||
|
||||
BOOST_STATIC_ASSERT(
|
||||
small_object_size_ <
|
||||
BOOST_JSON_MAX_STRUCTURED_SIZE);
|
||||
|
||||
} // detail
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
struct alignas(key_value_pair)
|
||||
object::table
|
||||
{
|
||||
std::uint32_t size = 0;
|
||||
std::uint32_t capacity = 0;
|
||||
std::uintptr_t salt = 0;
|
||||
|
||||
#if defined(_MSC_VER) && BOOST_JSON_ARCH == 32
|
||||
// VFALCO If we make key_value_pair smaller,
|
||||
// then we might want to revisit this
|
||||
// padding.
|
||||
BOOST_STATIC_ASSERT(
|
||||
sizeof(key_value_pair) == 32);
|
||||
char pad[4] = {}; // silence warnings
|
||||
#endif
|
||||
|
||||
constexpr table();
|
||||
|
||||
// returns true if we use a linear
|
||||
// search instead of the hash table.
|
||||
bool is_small() const noexcept
|
||||
{
|
||||
return capacity <=
|
||||
detail::small_object_size_;
|
||||
}
|
||||
|
||||
key_value_pair&
|
||||
operator[](
|
||||
std::size_t pos) noexcept
|
||||
{
|
||||
return reinterpret_cast<
|
||||
key_value_pair*>(
|
||||
this + 1)[pos];
|
||||
}
|
||||
|
||||
// VFALCO This is exported for tests
|
||||
BOOST_JSON_DECL
|
||||
std::size_t
|
||||
digest(string_view key) const noexcept;
|
||||
|
||||
inline
|
||||
index_t&
|
||||
bucket(std::size_t hash) noexcept;
|
||||
|
||||
inline
|
||||
index_t&
|
||||
bucket(string_view key) noexcept;
|
||||
|
||||
inline
|
||||
void
|
||||
clear() noexcept;
|
||||
|
||||
static
|
||||
inline
|
||||
table*
|
||||
allocate(
|
||||
std::size_t capacity,
|
||||
std::uintptr_t salt,
|
||||
storage_ptr const& sp);
|
||||
|
||||
static
|
||||
void
|
||||
deallocate(
|
||||
table* p,
|
||||
storage_ptr const& sp) noexcept
|
||||
{
|
||||
if(p->capacity == 0)
|
||||
return;
|
||||
if(p->is_small())
|
||||
sp->deallocate(p,
|
||||
sizeof(table) + p->capacity * (
|
||||
sizeof(key_value_pair) +
|
||||
sizeof(index_t)));
|
||||
else
|
||||
sp->deallocate(p,
|
||||
sizeof(table) + p->capacity *
|
||||
sizeof(key_value_pair));
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
class object::revert_construct
|
||||
{
|
||||
object* obj_;
|
||||
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
destroy() noexcept;
|
||||
|
||||
public:
|
||||
explicit
|
||||
revert_construct(
|
||||
object& obj) noexcept
|
||||
: obj_(&obj)
|
||||
{
|
||||
}
|
||||
|
||||
~revert_construct()
|
||||
{
|
||||
if(! obj_)
|
||||
return;
|
||||
destroy();
|
||||
}
|
||||
|
||||
void
|
||||
commit() noexcept
|
||||
{
|
||||
obj_ = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
class object::revert_insert
|
||||
{
|
||||
object* obj_;
|
||||
std::size_t size_;
|
||||
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
destroy() noexcept;
|
||||
|
||||
public:
|
||||
explicit
|
||||
revert_insert(
|
||||
object& obj) noexcept
|
||||
: obj_(&obj)
|
||||
, size_(obj_->size())
|
||||
{
|
||||
}
|
||||
|
||||
~revert_insert()
|
||||
{
|
||||
if(! obj_)
|
||||
return;
|
||||
destroy();
|
||||
obj_->t_->size = static_cast<
|
||||
index_t>(size_);
|
||||
}
|
||||
|
||||
void
|
||||
commit() noexcept
|
||||
{
|
||||
obj_ = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Iterators
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
auto
|
||||
object::
|
||||
begin() noexcept ->
|
||||
iterator
|
||||
{
|
||||
return &(*t_)[0];
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
begin() const noexcept ->
|
||||
const_iterator
|
||||
{
|
||||
return &(*t_)[0];
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
cbegin() const noexcept ->
|
||||
const_iterator
|
||||
{
|
||||
return &(*t_)[0];
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
end() noexcept ->
|
||||
iterator
|
||||
{
|
||||
return &(*t_)[t_->size];
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
end() const noexcept ->
|
||||
const_iterator
|
||||
{
|
||||
return &(*t_)[t_->size];
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
cend() const noexcept ->
|
||||
const_iterator
|
||||
{
|
||||
return &(*t_)[t_->size];
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
rbegin() noexcept ->
|
||||
reverse_iterator
|
||||
{
|
||||
return reverse_iterator(end());
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
rbegin() const noexcept ->
|
||||
const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
crbegin() const noexcept ->
|
||||
const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
rend() noexcept ->
|
||||
reverse_iterator
|
||||
{
|
||||
return reverse_iterator(begin());
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
rend() const noexcept ->
|
||||
const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
crend() const noexcept ->
|
||||
const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Capacity
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
bool
|
||||
object::
|
||||
empty() const noexcept
|
||||
{
|
||||
return t_->size == 0;
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
size() const noexcept ->
|
||||
std::size_t
|
||||
{
|
||||
return t_->size;
|
||||
}
|
||||
|
||||
constexpr
|
||||
std::size_t
|
||||
object::
|
||||
max_size() noexcept
|
||||
{
|
||||
// max_size depends on the address model
|
||||
using min = std::integral_constant<std::size_t,
|
||||
(std::size_t(-1) - sizeof(table)) /
|
||||
(sizeof(key_value_pair) + sizeof(index_t))>;
|
||||
return min::value < BOOST_JSON_MAX_STRUCTURED_SIZE ?
|
||||
min::value : BOOST_JSON_MAX_STRUCTURED_SIZE;
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
capacity() const noexcept ->
|
||||
std::size_t
|
||||
{
|
||||
return t_->capacity;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Lookup
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
auto
|
||||
object::
|
||||
at(string_view key) ->
|
||||
value&
|
||||
{
|
||||
auto it = find(key);
|
||||
if(it == end())
|
||||
detail::throw_out_of_range(
|
||||
BOOST_CURRENT_LOCATION);
|
||||
return it->value();
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
at(string_view key) const ->
|
||||
value const&
|
||||
{
|
||||
auto it = find(key);
|
||||
if(it == end())
|
||||
detail::throw_out_of_range(
|
||||
BOOST_CURRENT_LOCATION);
|
||||
return it->value();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
template<class P, class>
|
||||
auto
|
||||
object::
|
||||
insert(P&& p) ->
|
||||
std::pair<iterator, bool>
|
||||
{
|
||||
key_value_pair v(
|
||||
std::forward<P>(p), sp_);
|
||||
return insert_impl(pilfer(v));
|
||||
}
|
||||
|
||||
template<class M>
|
||||
auto
|
||||
object::
|
||||
insert_or_assign(
|
||||
string_view key, M&& m) ->
|
||||
std::pair<iterator, bool>
|
||||
{
|
||||
reserve(size() + 1);
|
||||
auto const result = find_impl(key);
|
||||
if(result.first)
|
||||
{
|
||||
value(std::forward<M>(m),
|
||||
sp_).swap(result.first->value());
|
||||
return { result.first, false };
|
||||
}
|
||||
key_value_pair kv(key,
|
||||
std::forward<M>(m), sp_);
|
||||
return { insert_impl(pilfer(kv),
|
||||
result.second), true };
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
auto
|
||||
object::
|
||||
emplace(
|
||||
string_view key,
|
||||
Arg&& arg) ->
|
||||
std::pair<iterator, bool>
|
||||
{
|
||||
reserve(size() + 1);
|
||||
auto const result = find_impl(key);
|
||||
if(result.first)
|
||||
return { result.first, false };
|
||||
key_value_pair kv(key,
|
||||
std::forward<Arg>(arg), sp_);
|
||||
return { insert_impl(pilfer(kv),
|
||||
result.second), true };
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// (private)
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
object::
|
||||
construct(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
std::size_t min_capacity,
|
||||
std::input_iterator_tag)
|
||||
{
|
||||
reserve(min_capacity);
|
||||
revert_construct r(*this);
|
||||
while(first != last)
|
||||
{
|
||||
insert(*first);
|
||||
++first;
|
||||
}
|
||||
r.commit();
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
object::
|
||||
construct(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
std::size_t min_capacity,
|
||||
std::forward_iterator_tag)
|
||||
{
|
||||
auto n = static_cast<
|
||||
std::size_t>(std::distance(
|
||||
first, last));
|
||||
if( n < min_capacity)
|
||||
n = min_capacity;
|
||||
reserve(n);
|
||||
revert_construct r(*this);
|
||||
while(first != last)
|
||||
{
|
||||
insert(*first);
|
||||
++first;
|
||||
}
|
||||
r.commit();
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
object::
|
||||
insert(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
std::input_iterator_tag)
|
||||
{
|
||||
// Since input iterators cannot be rewound,
|
||||
// we keep inserted elements on an exception.
|
||||
//
|
||||
while(first != last)
|
||||
{
|
||||
insert(*first);
|
||||
++first;
|
||||
}
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
object::
|
||||
insert(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
std::forward_iterator_tag)
|
||||
{
|
||||
auto const n =
|
||||
static_cast<std::size_t>(
|
||||
std::distance(first, last));
|
||||
auto const n0 = size();
|
||||
if(n > max_size() - n0)
|
||||
detail::throw_length_error(
|
||||
"object too large",
|
||||
BOOST_CURRENT_LOCATION);
|
||||
reserve(n0 + n);
|
||||
revert_insert r(*this);
|
||||
while(first != last)
|
||||
{
|
||||
insert(*first);
|
||||
++first;
|
||||
}
|
||||
r.commit();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
namespace detail {
|
||||
|
||||
unchecked_object::
|
||||
~unchecked_object()
|
||||
{
|
||||
if(! data_)
|
||||
return;
|
||||
if(sp_.is_not_shared_and_deallocate_is_trivial())
|
||||
return;
|
||||
value* p = data_;
|
||||
while(size_--)
|
||||
{
|
||||
p[0].~value();
|
||||
p[1].~value();
|
||||
p += 2;
|
||||
}
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
825
install/boost_1_75_0/include/boost/json/impl/object.ipp
Normal file
825
install/boost_1_75_0/include/boost/json/impl/object.ipp
Normal file
@@ -0,0 +1,825 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_OBJECT_IPP
|
||||
#define BOOST_JSON_IMPL_OBJECT_IPP
|
||||
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/detail/digest.hpp>
|
||||
#include <boost/json/detail/except.hpp>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <new>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
constexpr object::table::table() = default;
|
||||
|
||||
// empty objects point here
|
||||
BOOST_JSON_REQUIRE_CONST_INIT
|
||||
object::table object::empty_;
|
||||
|
||||
std::size_t
|
||||
object::table::
|
||||
digest(string_view key) const noexcept
|
||||
{
|
||||
BOOST_ASSERT(salt != 0);
|
||||
return detail::digest(
|
||||
key.data(), key.size(), salt);
|
||||
}
|
||||
|
||||
auto
|
||||
object::table::
|
||||
bucket(std::size_t hash) noexcept ->
|
||||
index_t&
|
||||
{
|
||||
return reinterpret_cast<
|
||||
index_t*>(&(*this)[capacity])[
|
||||
hash % capacity];
|
||||
}
|
||||
|
||||
auto
|
||||
object::table::
|
||||
bucket(string_view key) noexcept ->
|
||||
index_t&
|
||||
{
|
||||
return bucket(digest(key));
|
||||
}
|
||||
|
||||
void
|
||||
object::table::
|
||||
clear() noexcept
|
||||
{
|
||||
BOOST_ASSERT(! is_small());
|
||||
// initialize buckets
|
||||
std::memset(
|
||||
reinterpret_cast<index_t*>(
|
||||
&(*this)[capacity]),
|
||||
0xff, // null_index_
|
||||
capacity * sizeof(index_t));
|
||||
}
|
||||
|
||||
object::table*
|
||||
object::table::
|
||||
allocate(
|
||||
std::size_t capacity,
|
||||
std::uintptr_t salt,
|
||||
storage_ptr const& sp)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(
|
||||
alignof(key_value_pair) >=
|
||||
alignof(index_t));
|
||||
BOOST_ASSERT(capacity > 0);
|
||||
BOOST_ASSERT(capacity <= max_size());
|
||||
table* p;
|
||||
if(capacity <= detail::small_object_size_)
|
||||
{
|
||||
p = reinterpret_cast<
|
||||
table*>(sp->allocate(
|
||||
sizeof(table) + capacity *
|
||||
sizeof(key_value_pair)));
|
||||
p->capacity = static_cast<
|
||||
std::uint32_t>(capacity);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = reinterpret_cast<
|
||||
table*>(sp->allocate(
|
||||
sizeof(table) + capacity * (
|
||||
sizeof(key_value_pair) +
|
||||
sizeof(index_t))));
|
||||
p->capacity = static_cast<
|
||||
std::uint32_t>(capacity);
|
||||
p->clear();
|
||||
}
|
||||
if(salt)
|
||||
{
|
||||
p->salt = salt;
|
||||
}
|
||||
else
|
||||
{
|
||||
// VFALCO This would be better if it
|
||||
// was random, but maybe this
|
||||
// is good enough.
|
||||
p->salt = reinterpret_cast<
|
||||
std::uintptr_t>(p);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
object::
|
||||
revert_construct::
|
||||
destroy() noexcept
|
||||
{
|
||||
obj_->destroy();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
object::
|
||||
revert_insert::
|
||||
destroy() noexcept
|
||||
{
|
||||
obj_->destroy(
|
||||
&(*obj_->t_)[size_],
|
||||
obj_->end());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Construction
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
object::
|
||||
object(detail::unchecked_object&& uo)
|
||||
: sp_(uo.storage())
|
||||
{
|
||||
if(uo.size() == 0)
|
||||
{
|
||||
t_ = &empty_;
|
||||
return;
|
||||
}
|
||||
// should already be checked
|
||||
BOOST_ASSERT(
|
||||
uo.size() <= max_size());
|
||||
t_ = table::allocate(
|
||||
uo.size(), 0, sp_);
|
||||
|
||||
// insert all elements, keeping
|
||||
// the last of any duplicate keys.
|
||||
auto dest = begin();
|
||||
auto src = uo.release();
|
||||
auto const end = src + 2 * uo.size();
|
||||
if(t_->is_small())
|
||||
{
|
||||
t_->size = 0;
|
||||
while(src != end)
|
||||
{
|
||||
access::construct_key_value_pair(
|
||||
dest, pilfer(src[0]), pilfer(src[1]));
|
||||
src += 2;
|
||||
auto result = find_impl(dest->key());
|
||||
if(! result.first)
|
||||
{
|
||||
++dest;
|
||||
++t_->size;
|
||||
continue;
|
||||
}
|
||||
// handle duplicate
|
||||
auto& v = *result.first;
|
||||
// don't bother to check if
|
||||
// storage deallocate is trivial
|
||||
v.~key_value_pair();
|
||||
// trivial relocate
|
||||
std::memcpy(
|
||||
static_cast<void*>(&v),
|
||||
dest, sizeof(v));
|
||||
}
|
||||
return;
|
||||
}
|
||||
while(src != end)
|
||||
{
|
||||
access::construct_key_value_pair(
|
||||
dest, pilfer(src[0]), pilfer(src[1]));
|
||||
src += 2;
|
||||
auto& head = t_->bucket(dest->key());
|
||||
auto i = head;
|
||||
for(;;)
|
||||
{
|
||||
if(i == null_index_)
|
||||
{
|
||||
// end of bucket
|
||||
access::next(
|
||||
*dest) = head;
|
||||
head = static_cast<index_t>(
|
||||
dest - begin());
|
||||
++dest;
|
||||
break;
|
||||
}
|
||||
auto& v = (*t_)[i];
|
||||
if(v.key() != dest->key())
|
||||
{
|
||||
i = access::next(v);
|
||||
continue;
|
||||
}
|
||||
|
||||
// handle duplicate
|
||||
access::next(*dest) =
|
||||
access::next(v);
|
||||
// don't bother to check if
|
||||
// storage deallocate is trivial
|
||||
v.~key_value_pair();
|
||||
// trivial relocate
|
||||
std::memcpy(
|
||||
static_cast<void*>(&v),
|
||||
dest, sizeof(v));
|
||||
break;
|
||||
}
|
||||
}
|
||||
t_->size = static_cast<
|
||||
index_t>(dest - begin());
|
||||
}
|
||||
|
||||
object::
|
||||
~object()
|
||||
{
|
||||
if(sp_.is_not_shared_and_deallocate_is_trivial())
|
||||
return;
|
||||
if(t_->capacity == 0)
|
||||
return;
|
||||
destroy();
|
||||
}
|
||||
|
||||
object::
|
||||
object(
|
||||
std::size_t min_capacity,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
, t_(&empty_)
|
||||
{
|
||||
reserve(min_capacity);
|
||||
}
|
||||
|
||||
object::
|
||||
object(object&& other) noexcept
|
||||
: sp_(other.sp_)
|
||||
, t_(detail::exchange(
|
||||
other.t_, &empty_))
|
||||
{
|
||||
}
|
||||
|
||||
object::
|
||||
object(
|
||||
object&& other,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
if(*sp_ == *other.sp_)
|
||||
{
|
||||
t_ = detail::exchange(
|
||||
other.t_, &empty_);
|
||||
return;
|
||||
}
|
||||
|
||||
t_ = &empty_;
|
||||
object(other, sp_).swap(*this);
|
||||
}
|
||||
|
||||
object::
|
||||
object(
|
||||
object const& other,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
, t_(&empty_)
|
||||
{
|
||||
reserve(other.size());
|
||||
revert_construct r(*this);
|
||||
if(t_->is_small())
|
||||
{
|
||||
for(auto const& v : other)
|
||||
{
|
||||
::new(end())
|
||||
key_value_pair(v, sp_);
|
||||
++t_->size;
|
||||
}
|
||||
r.commit();
|
||||
return;
|
||||
}
|
||||
for(auto const& v : other)
|
||||
{
|
||||
// skip duplicate checking
|
||||
auto& head =
|
||||
t_->bucket(v.key());
|
||||
auto pv = ::new(end())
|
||||
key_value_pair(v, sp_);
|
||||
access::next(*pv) = head;
|
||||
head = t_->size;
|
||||
++t_->size;
|
||||
}
|
||||
r.commit();
|
||||
}
|
||||
|
||||
object::
|
||||
object(
|
||||
std::initializer_list<std::pair<
|
||||
string_view, value_ref>> init,
|
||||
std::size_t min_capacity,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
, t_(&empty_)
|
||||
{
|
||||
if( min_capacity < init.size())
|
||||
min_capacity = init.size();
|
||||
reserve(min_capacity);
|
||||
revert_construct r(*this);
|
||||
insert(init);
|
||||
r.commit();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Assignment
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
object&
|
||||
object::
|
||||
operator=(object const& other)
|
||||
{
|
||||
object tmp(other, sp_);
|
||||
this->~object();
|
||||
::new(this) object(pilfer(tmp));
|
||||
return *this;
|
||||
}
|
||||
|
||||
object&
|
||||
object::
|
||||
operator=(object&& other)
|
||||
{
|
||||
object tmp(std::move(other), sp_);
|
||||
this->~object();
|
||||
::new(this) object(pilfer(tmp));
|
||||
return *this;
|
||||
}
|
||||
|
||||
object&
|
||||
object::
|
||||
operator=(
|
||||
std::initializer_list<std::pair<
|
||||
string_view, value_ref>> init)
|
||||
{
|
||||
object tmp(init, sp_);
|
||||
this->~object();
|
||||
::new(this) object(pilfer(tmp));
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Modifiers
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
object::
|
||||
clear() noexcept
|
||||
{
|
||||
if(empty())
|
||||
return;
|
||||
if(! sp_.is_not_shared_and_deallocate_is_trivial())
|
||||
destroy(begin(), end());
|
||||
if(! t_->is_small())
|
||||
t_->clear();
|
||||
t_->size = 0;
|
||||
}
|
||||
|
||||
void
|
||||
object::
|
||||
insert(
|
||||
std::initializer_list<std::pair<
|
||||
string_view, value_ref>> init)
|
||||
{
|
||||
auto const n0 = size();
|
||||
if(init.size() > max_size() - n0)
|
||||
detail::throw_length_error(
|
||||
"object too large",
|
||||
BOOST_CURRENT_LOCATION);
|
||||
reserve(n0 + init.size());
|
||||
revert_insert r(*this);
|
||||
if(t_->is_small())
|
||||
{
|
||||
for(auto& iv : init)
|
||||
{
|
||||
auto result =
|
||||
find_impl(iv.first);
|
||||
if(result.first)
|
||||
{
|
||||
// ignore duplicate
|
||||
continue;
|
||||
}
|
||||
::new(end()) key_value_pair(
|
||||
iv.first,
|
||||
iv.second.make_value(sp_));
|
||||
++t_->size;
|
||||
}
|
||||
r.commit();
|
||||
return;
|
||||
}
|
||||
for(auto& iv : init)
|
||||
{
|
||||
auto& head = t_->bucket(iv.first);
|
||||
auto i = head;
|
||||
for(;;)
|
||||
{
|
||||
if(i == null_index_)
|
||||
{
|
||||
// VFALCO value_ref should construct
|
||||
// a key_value_pair using placement
|
||||
auto& v = *::new(end())
|
||||
key_value_pair(
|
||||
iv.first,
|
||||
iv.second.make_value(sp_));
|
||||
access::next(v) = head;
|
||||
head = static_cast<index_t>(
|
||||
t_->size);
|
||||
++t_->size;
|
||||
break;
|
||||
}
|
||||
auto& v = (*t_)[i];
|
||||
if(v.key() == iv.first)
|
||||
{
|
||||
// ignore duplicate
|
||||
break;
|
||||
}
|
||||
i = access::next(v);
|
||||
}
|
||||
}
|
||||
r.commit();
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
erase(const_iterator pos) noexcept ->
|
||||
iterator
|
||||
{
|
||||
auto p = begin() + (pos - begin());
|
||||
if(t_->is_small())
|
||||
{
|
||||
p->~value_type();
|
||||
--t_->size;
|
||||
auto const pb = end();
|
||||
if(p != end())
|
||||
{
|
||||
// the casts silence warnings
|
||||
std::memcpy(
|
||||
static_cast<void*>(p),
|
||||
static_cast<void const*>(pb),
|
||||
sizeof(*p));
|
||||
}
|
||||
return p;
|
||||
}
|
||||
remove(t_->bucket(p->key()), *p);
|
||||
p->~value_type();
|
||||
--t_->size;
|
||||
auto const pb = end();
|
||||
if(p != end())
|
||||
{
|
||||
auto& head = t_->bucket(pb->key());
|
||||
remove(head, *pb);
|
||||
// the casts silence warnings
|
||||
std::memcpy(
|
||||
static_cast<void*>(p),
|
||||
static_cast<void const*>(pb),
|
||||
sizeof(*p));
|
||||
access::next(*p) = head;
|
||||
head = static_cast<
|
||||
index_t>(p - begin());
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
erase(string_view key) noexcept ->
|
||||
std::size_t
|
||||
{
|
||||
auto it = find(key);
|
||||
if(it == end())
|
||||
return 0;
|
||||
erase(it);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
object::
|
||||
swap(object& other)
|
||||
{
|
||||
if(*sp_ == *other.sp_)
|
||||
{
|
||||
t_ = detail::exchange(
|
||||
other.t_, t_);
|
||||
return;
|
||||
}
|
||||
object temp1(
|
||||
std::move(*this),
|
||||
other.storage());
|
||||
object temp2(
|
||||
std::move(other),
|
||||
this->storage());
|
||||
other.~object();
|
||||
::new(&other) object(pilfer(temp1));
|
||||
this->~object();
|
||||
::new(this) object(pilfer(temp2));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Lookup
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
auto
|
||||
object::
|
||||
operator[](string_view key) ->
|
||||
value&
|
||||
{
|
||||
auto const result =
|
||||
emplace(key, nullptr);
|
||||
return result.first->value();
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
count(string_view key) const noexcept ->
|
||||
std::size_t
|
||||
{
|
||||
if(find(key) == end())
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
find(string_view key) noexcept ->
|
||||
iterator
|
||||
{
|
||||
if(empty())
|
||||
return end();
|
||||
auto const p =
|
||||
find_impl(key).first;
|
||||
if(p)
|
||||
return p;
|
||||
return end();
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
find(string_view key) const noexcept ->
|
||||
const_iterator
|
||||
{
|
||||
if(empty())
|
||||
return end();
|
||||
auto const p =
|
||||
find_impl(key).first;
|
||||
if(p)
|
||||
return p;
|
||||
return end();
|
||||
}
|
||||
|
||||
bool
|
||||
object::
|
||||
contains(
|
||||
string_view key) const noexcept
|
||||
{
|
||||
if(empty())
|
||||
return false;
|
||||
return find_impl(
|
||||
key).first != nullptr;
|
||||
}
|
||||
|
||||
value const*
|
||||
object::
|
||||
if_contains(
|
||||
string_view key) const noexcept
|
||||
{
|
||||
auto const it = find(key);
|
||||
if(it != end())
|
||||
return &it->value();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
value*
|
||||
object::
|
||||
if_contains(
|
||||
string_view key) noexcept
|
||||
{
|
||||
auto const it = find(key);
|
||||
if(it != end())
|
||||
return &it->value();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// (private)
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
auto
|
||||
object::
|
||||
find_impl(
|
||||
string_view key) const noexcept ->
|
||||
std::pair<
|
||||
key_value_pair*,
|
||||
std::size_t>
|
||||
{
|
||||
BOOST_ASSERT(t_->capacity > 0);
|
||||
if(t_->is_small())
|
||||
{
|
||||
auto it = &(*t_)[0];
|
||||
auto const last =
|
||||
&(*t_)[t_->size];
|
||||
for(;it != last; ++it)
|
||||
if(key == it->key())
|
||||
return { it, 0 };
|
||||
return { nullptr, 0 };
|
||||
}
|
||||
std::pair<
|
||||
key_value_pair*,
|
||||
std::size_t> result;
|
||||
result.second = t_->digest(key);
|
||||
auto i = t_->bucket(
|
||||
result.second);
|
||||
while(i != null_index_)
|
||||
{
|
||||
auto& v = (*t_)[i];
|
||||
if(v.key() == key)
|
||||
{
|
||||
result.first = &v;
|
||||
return result;
|
||||
}
|
||||
i = access::next(v);
|
||||
}
|
||||
result.first = nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
auto
|
||||
object::
|
||||
insert_impl(
|
||||
pilfered<key_value_pair> p) ->
|
||||
std::pair<iterator, bool>
|
||||
{
|
||||
// caller is responsible
|
||||
// for preventing aliasing.
|
||||
reserve(size() + 1);
|
||||
auto const result =
|
||||
find_impl(p.get().key());
|
||||
if(result.first)
|
||||
return { result.first, false };
|
||||
return { insert_impl(
|
||||
p, result.second), true };
|
||||
}
|
||||
|
||||
key_value_pair*
|
||||
object::
|
||||
insert_impl(
|
||||
pilfered<key_value_pair> p,
|
||||
std::size_t hash)
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
capacity() > size());
|
||||
if(t_->is_small())
|
||||
{
|
||||
auto const pv = ::new(end())
|
||||
key_value_pair(p);
|
||||
++t_->size;
|
||||
return pv;
|
||||
}
|
||||
auto& head =
|
||||
t_->bucket(hash);
|
||||
auto const pv = ::new(end())
|
||||
key_value_pair(p);
|
||||
access::next(*pv) = head;
|
||||
head = t_->size;
|
||||
++t_->size;
|
||||
return pv;
|
||||
}
|
||||
|
||||
// rehash to at least `n` buckets
|
||||
void
|
||||
object::
|
||||
rehash(std::size_t new_capacity)
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
new_capacity > t_->capacity);
|
||||
auto t = table::allocate(
|
||||
growth(new_capacity),
|
||||
t_->salt, sp_);
|
||||
if(! empty())
|
||||
std::memcpy(
|
||||
static_cast<
|
||||
void*>(&(*t)[0]),
|
||||
begin(),
|
||||
size() * sizeof(
|
||||
key_value_pair));
|
||||
t->size = t_->size;
|
||||
table::deallocate(t_, sp_);
|
||||
t_ = t;
|
||||
|
||||
if(! t_->is_small())
|
||||
{
|
||||
// rebuild hash table,
|
||||
// without dup checks
|
||||
auto p = end();
|
||||
index_t i = t_->size;
|
||||
while(i-- > 0)
|
||||
{
|
||||
--p;
|
||||
auto& head =
|
||||
t_->bucket(p->key());
|
||||
access::next(*p) = head;
|
||||
head = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
object::
|
||||
equal(object const& other) const noexcept
|
||||
{
|
||||
if(size() != other.size())
|
||||
return false;
|
||||
auto const end_ = other.end();
|
||||
for(auto e : *this)
|
||||
{
|
||||
auto it = other.find(e.key());
|
||||
if(it == end_)
|
||||
return false;
|
||||
if(it->value() != e.value())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
object::
|
||||
growth(
|
||||
std::size_t new_size) const
|
||||
{
|
||||
if(new_size > max_size())
|
||||
detail::throw_length_error(
|
||||
"object too large",
|
||||
BOOST_CURRENT_LOCATION);
|
||||
std::size_t const old = capacity();
|
||||
if(old > max_size() - old / 2)
|
||||
return new_size;
|
||||
std::size_t const g =
|
||||
old + old / 2; // 1.5x
|
||||
if(g < new_size)
|
||||
return new_size;
|
||||
return g;
|
||||
}
|
||||
|
||||
void
|
||||
object::
|
||||
remove(
|
||||
index_t& head,
|
||||
key_value_pair& v) noexcept
|
||||
{
|
||||
BOOST_ASSERT(! t_->is_small());
|
||||
auto const i = static_cast<
|
||||
index_t>(&v - begin());
|
||||
if(head == i)
|
||||
{
|
||||
head = access::next(v);
|
||||
return;
|
||||
}
|
||||
auto* pn =
|
||||
&access::next((*t_)[head]);
|
||||
while(*pn != i)
|
||||
pn = &access::next((*t_)[*pn]);
|
||||
*pn = access::next(v);
|
||||
}
|
||||
|
||||
void
|
||||
object::
|
||||
destroy() noexcept
|
||||
{
|
||||
BOOST_ASSERT(t_->capacity > 0);
|
||||
BOOST_ASSERT(! sp_.is_not_shared_and_deallocate_is_trivial());
|
||||
destroy(begin(), end());
|
||||
table::deallocate(t_, sp_);
|
||||
}
|
||||
|
||||
void
|
||||
object::
|
||||
destroy(
|
||||
key_value_pair* first,
|
||||
key_value_pair* last) noexcept
|
||||
{
|
||||
BOOST_ASSERT(! sp_.is_not_shared_and_deallocate_is_trivial());
|
||||
while(last != first)
|
||||
(--last)->~key_value_pair();
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
54
install/boost_1_75_0/include/boost/json/impl/parse.ipp
Normal file
54
install/boost_1_75_0/include/boost/json/impl/parse.ipp
Normal file
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
|
||||
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_PARSE_IPP
|
||||
#define BOOST_JSON_IMPL_PARSE_IPP
|
||||
|
||||
#include <boost/json/parse.hpp>
|
||||
#include <boost/json/parser.hpp>
|
||||
#include <boost/json/detail/except.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
value
|
||||
parse(
|
||||
string_view s,
|
||||
error_code& ec,
|
||||
storage_ptr sp,
|
||||
const parse_options& opt)
|
||||
{
|
||||
unsigned char temp[
|
||||
BOOST_JSON_STACK_BUFFER_SIZE];
|
||||
parser p(storage_ptr(), opt, temp);
|
||||
p.reset(std::move(sp));
|
||||
p.write(s, ec);
|
||||
if(ec)
|
||||
return nullptr;
|
||||
return p.release();
|
||||
}
|
||||
|
||||
value
|
||||
parse(
|
||||
string_view s,
|
||||
storage_ptr sp,
|
||||
const parse_options& opt)
|
||||
{
|
||||
error_code ec;
|
||||
auto jv = parse(
|
||||
s, ec, std::move(sp), opt);
|
||||
if(ec)
|
||||
detail::throw_system_error(ec,
|
||||
BOOST_CURRENT_LOCATION);
|
||||
return jv;
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
136
install/boost_1_75_0/include/boost/json/impl/parser.ipp
Normal file
136
install/boost_1_75_0/include/boost/json/impl/parser.ipp
Normal file
@@ -0,0 +1,136 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_PARSER_IPP
|
||||
#define BOOST_JSON_IMPL_PARSER_IPP
|
||||
|
||||
#include <boost/json/parser.hpp>
|
||||
#include <boost/json/basic_parser_impl.hpp>
|
||||
#include <boost/json/error.hpp>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
parser::
|
||||
parser(
|
||||
storage_ptr sp,
|
||||
parse_options const& opt,
|
||||
unsigned char* buffer,
|
||||
std::size_t size) noexcept
|
||||
: p_(
|
||||
opt,
|
||||
std::move(sp),
|
||||
buffer,
|
||||
size)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
parser::
|
||||
parser(
|
||||
storage_ptr sp,
|
||||
parse_options const& opt) noexcept
|
||||
: p_(
|
||||
opt,
|
||||
std::move(sp),
|
||||
nullptr,
|
||||
0)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void
|
||||
parser::
|
||||
reset(storage_ptr sp) noexcept
|
||||
{
|
||||
p_.reset();
|
||||
p_.handler().st.reset(sp);
|
||||
}
|
||||
|
||||
std::size_t
|
||||
parser::
|
||||
write_some(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec)
|
||||
{
|
||||
auto const n = p_.write_some(
|
||||
false, data, size, ec);
|
||||
BOOST_ASSERT(ec || p_.done());
|
||||
return n;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
parser::
|
||||
write_some(
|
||||
char const* data,
|
||||
std::size_t size)
|
||||
{
|
||||
error_code ec;
|
||||
auto const n = write_some(
|
||||
data, size, ec);
|
||||
if(ec)
|
||||
detail::throw_system_error(ec,
|
||||
BOOST_CURRENT_LOCATION);
|
||||
return n;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
parser::
|
||||
write(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec)
|
||||
{
|
||||
auto const n = write_some(
|
||||
data, size, ec);
|
||||
if(! ec && n < size)
|
||||
{
|
||||
ec = error::extra_data;
|
||||
p_.fail(ec);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
parser::
|
||||
write(
|
||||
char const* data,
|
||||
std::size_t size)
|
||||
{
|
||||
error_code ec;
|
||||
auto const n = write(
|
||||
data, size, ec);
|
||||
if(ec)
|
||||
detail::throw_system_error(ec,
|
||||
BOOST_CURRENT_LOCATION);
|
||||
return n;
|
||||
}
|
||||
|
||||
value
|
||||
parser::
|
||||
release()
|
||||
{
|
||||
if( ! p_.done())
|
||||
{
|
||||
// prevent undefined behavior
|
||||
if(! p_.last_error())
|
||||
p_.fail(error::incomplete);
|
||||
detail::throw_system_error(
|
||||
p_.last_error(),
|
||||
BOOST_CURRENT_LOCATION);
|
||||
}
|
||||
return p_.handler().st.release();
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
191
install/boost_1_75_0/include/boost/json/impl/serialize.ipp
Normal file
191
install/boost_1_75_0/include/boost/json/impl/serialize.ipp
Normal file
@@ -0,0 +1,191 @@
|
||||
//
|
||||
// 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/boostorg/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(
|
||||
std::string& s,
|
||||
serializer& sr)
|
||||
{
|
||||
// serialize to a small buffer to avoid
|
||||
// the first few allocations in std::string
|
||||
char buf[BOOST_JSON_STACK_BUFFER_SIZE];
|
||||
string_view sv;
|
||||
sv = sr.read(buf);
|
||||
if(sr.done())
|
||||
{
|
||||
// fast path
|
||||
s.append(
|
||||
sv.data(), sv.size());
|
||||
return;
|
||||
}
|
||||
std::size_t len = sv.size();
|
||||
s.reserve(len * 2);
|
||||
s.resize(s.capacity());
|
||||
BOOST_ASSERT(
|
||||
s.size() >= len * 2);
|
||||
std::memcpy(&s[0],
|
||||
sv.data(), sv.size());
|
||||
for(;;)
|
||||
{
|
||||
sv = sr.read(
|
||||
&s[0] + len,
|
||||
s.size() - len);
|
||||
len += sv.size();
|
||||
if(sr.done())
|
||||
break;
|
||||
s.resize(
|
||||
s.capacity() + 1);
|
||||
}
|
||||
s.resize(len);
|
||||
}
|
||||
|
||||
std::string
|
||||
serialize(
|
||||
value const& jv)
|
||||
{
|
||||
std::string s;
|
||||
serializer sr;
|
||||
sr.reset(&jv);
|
||||
serialize_impl(s, sr);
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string
|
||||
serialize(
|
||||
array const& arr)
|
||||
{
|
||||
std::string s;
|
||||
serializer sr;
|
||||
sr.reset(&arr);
|
||||
serialize_impl(s, sr);
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string
|
||||
serialize(
|
||||
object const& obj)
|
||||
{
|
||||
std::string s;
|
||||
serializer sr;
|
||||
sr.reset(&obj);
|
||||
serialize_impl(s, sr);
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string
|
||||
serialize(
|
||||
string const& str)
|
||||
{
|
||||
std::string s;
|
||||
serializer sr;
|
||||
sr.reset(&str);
|
||||
serialize_impl(s, sr);
|
||||
return s;
|
||||
}
|
||||
|
||||
// this is here for key_value_pair::key()
|
||||
std::string
|
||||
serialize(
|
||||
string_view sv)
|
||||
{
|
||||
std::string s;
|
||||
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[ BOOST_JSON_STACK_BUFFER_SIZE ];
|
||||
|
||||
// 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)
|
||||
{
|
||||
while(! sr.done())
|
||||
{
|
||||
char buf[BOOST_JSON_STACK_BUFFER_SIZE];
|
||||
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
|
||||
822
install/boost_1_75_0/include/boost/json/impl/serializer.ipp
Normal file
822
install/boost_1_75_0/include/boost/json/impl/serializer.ipp
Normal file
@@ -0,0 +1,822 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_SERIALIZER_IPP
|
||||
#define BOOST_JSON_IMPL_SERIALIZER_IPP
|
||||
|
||||
#include <boost/json/serializer.hpp>
|
||||
#include <boost/json/detail/format.hpp>
|
||||
#include <boost/json/detail/sse2.hpp>
|
||||
#include <ostream>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
enum class serializer::state : char
|
||||
{
|
||||
nul1, nul2, nul3, nul4,
|
||||
tru1, tru2, tru3, tru4,
|
||||
fal1, fal2, fal3, fal4, fal5,
|
||||
str1, str2, str3, str4, esc1,
|
||||
utf1, utf2, utf3, utf4, utf5,
|
||||
num,
|
||||
arr1, arr2, arr3, arr4,
|
||||
obj1, obj2, obj3, obj4, obj5, obj6
|
||||
};
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
serializer::
|
||||
~serializer() noexcept = default;
|
||||
|
||||
bool
|
||||
serializer::
|
||||
suspend(state st)
|
||||
{
|
||||
st_.push(st);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
serializer::
|
||||
suspend(
|
||||
state st,
|
||||
array::const_iterator it,
|
||||
array const* pa)
|
||||
{
|
||||
st_.push(pa);
|
||||
st_.push(it);
|
||||
st_.push(st);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
serializer::
|
||||
suspend(
|
||||
state st,
|
||||
object::const_iterator it,
|
||||
object const* po)
|
||||
{
|
||||
st_.push(po);
|
||||
st_.push(it);
|
||||
st_.push(st);
|
||||
return false;
|
||||
}
|
||||
|
||||
template<bool StackEmpty>
|
||||
bool
|
||||
serializer::
|
||||
write_null(stream& ss0)
|
||||
{
|
||||
local_stream ss(ss0);
|
||||
if(! StackEmpty && ! st_.empty())
|
||||
{
|
||||
state st;
|
||||
st_.pop(st);
|
||||
switch(st)
|
||||
{
|
||||
default:
|
||||
case state::nul1: goto do_nul1;
|
||||
case state::nul2: goto do_nul2;
|
||||
case state::nul3: goto do_nul3;
|
||||
case state::nul4: goto do_nul4;
|
||||
}
|
||||
}
|
||||
do_nul1:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('n');
|
||||
else
|
||||
return suspend(state::nul1);
|
||||
do_nul2:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('u');
|
||||
else
|
||||
return suspend(state::nul2);
|
||||
do_nul3:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('l');
|
||||
else
|
||||
return suspend(state::nul3);
|
||||
do_nul4:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('l');
|
||||
else
|
||||
return suspend(state::nul4);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<bool StackEmpty>
|
||||
bool
|
||||
serializer::
|
||||
write_true(stream& ss0)
|
||||
{
|
||||
local_stream ss(ss0);
|
||||
if(! StackEmpty && ! st_.empty())
|
||||
{
|
||||
state st;
|
||||
st_.pop(st);
|
||||
switch(st)
|
||||
{
|
||||
default:
|
||||
case state::tru1: goto do_tru1;
|
||||
case state::tru2: goto do_tru2;
|
||||
case state::tru3: goto do_tru3;
|
||||
case state::tru4: goto do_tru4;
|
||||
}
|
||||
}
|
||||
do_tru1:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('t');
|
||||
else
|
||||
return suspend(state::tru1);
|
||||
do_tru2:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('r');
|
||||
else
|
||||
return suspend(state::tru2);
|
||||
do_tru3:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('u');
|
||||
else
|
||||
return suspend(state::tru3);
|
||||
do_tru4:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('e');
|
||||
else
|
||||
return suspend(state::tru4);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<bool StackEmpty>
|
||||
bool
|
||||
serializer::
|
||||
write_false(stream& ss0)
|
||||
{
|
||||
local_stream ss(ss0);
|
||||
if(! StackEmpty && ! st_.empty())
|
||||
{
|
||||
state st;
|
||||
st_.pop(st);
|
||||
switch(st)
|
||||
{
|
||||
default:
|
||||
case state::fal1: goto do_fal1;
|
||||
case state::fal2: goto do_fal2;
|
||||
case state::fal3: goto do_fal3;
|
||||
case state::fal4: goto do_fal4;
|
||||
case state::fal5: goto do_fal5;
|
||||
}
|
||||
}
|
||||
do_fal1:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('f');
|
||||
else
|
||||
return suspend(state::fal1);
|
||||
do_fal2:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('a');
|
||||
else
|
||||
return suspend(state::fal2);
|
||||
do_fal3:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('l');
|
||||
else
|
||||
return suspend(state::fal3);
|
||||
do_fal4:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('s');
|
||||
else
|
||||
return suspend(state::fal4);
|
||||
do_fal5:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('e');
|
||||
else
|
||||
return suspend(state::fal5);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<bool StackEmpty>
|
||||
bool
|
||||
serializer::
|
||||
write_string(stream& ss0)
|
||||
{
|
||||
local_stream ss(ss0);
|
||||
local_const_stream cs(cs0_);
|
||||
if(! StackEmpty && ! st_.empty())
|
||||
{
|
||||
state st;
|
||||
st_.pop(st);
|
||||
switch(st)
|
||||
{
|
||||
default:
|
||||
case state::str1: goto do_str1;
|
||||
case state::str2: goto do_str2;
|
||||
case state::str3: goto do_str3;
|
||||
case state::str4: goto do_str4;
|
||||
case state::esc1: goto do_esc1;
|
||||
case state::utf1: goto do_utf1;
|
||||
case state::utf2: goto do_utf2;
|
||||
case state::utf3: goto do_utf3;
|
||||
case state::utf4: goto do_utf4;
|
||||
case state::utf5: goto do_utf5;
|
||||
}
|
||||
}
|
||||
static constexpr char hex[] = "0123456789abcdef";
|
||||
static constexpr char esc[] =
|
||||
"uuuuuuuubtnufruuuuuuuuuuuuuuuuuu"
|
||||
"\0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
|
||||
|
||||
// opening quote
|
||||
do_str1:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('\x22'); // '"'
|
||||
else
|
||||
return suspend(state::str1);
|
||||
|
||||
// fast loop,
|
||||
// copy unescaped
|
||||
do_str2:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
{
|
||||
std::size_t n = cs.remain();
|
||||
if(BOOST_JSON_LIKELY(n > 0))
|
||||
{
|
||||
if(ss.remain() > n)
|
||||
n = detail::count_unescaped(
|
||||
cs.data(), n);
|
||||
else
|
||||
n = detail::count_unescaped(
|
||||
cs.data(), ss.remain());
|
||||
if(n > 0)
|
||||
{
|
||||
ss.append(cs.data(), n);
|
||||
cs.skip(n);
|
||||
if(! ss)
|
||||
return suspend(state::str2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ss.append('\x22'); // '"'
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return suspend(state::str2);
|
||||
}
|
||||
|
||||
// slow loop,
|
||||
// handle escapes
|
||||
do_str3:
|
||||
while(BOOST_JSON_LIKELY(ss))
|
||||
{
|
||||
if(BOOST_JSON_LIKELY(cs))
|
||||
{
|
||||
auto const ch = *cs;
|
||||
auto const c = esc[static_cast<
|
||||
unsigned char>(ch)];
|
||||
++cs;
|
||||
if(! c)
|
||||
{
|
||||
ss.append(ch);
|
||||
}
|
||||
else if(c != 'u')
|
||||
{
|
||||
ss.append('\\');
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
{
|
||||
ss.append(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
buf_[0] = c;
|
||||
return suspend(
|
||||
state::esc1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(BOOST_JSON_LIKELY(
|
||||
ss.remain() >= 6))
|
||||
{
|
||||
ss.append("\\u00", 4);
|
||||
ss.append(hex[static_cast<
|
||||
unsigned char>(ch) >> 4]);
|
||||
ss.append(hex[static_cast<
|
||||
unsigned char>(ch) & 15]);
|
||||
}
|
||||
else
|
||||
{
|
||||
ss.append('\\');
|
||||
buf_[0] = hex[static_cast<
|
||||
unsigned char>(ch) >> 4];
|
||||
buf_[1] = hex[static_cast<
|
||||
unsigned char>(ch) & 15];
|
||||
goto do_utf1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ss.append('\x22'); // '"'
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return suspend(state::str3);
|
||||
|
||||
do_str4:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('\x22'); // '"'
|
||||
else
|
||||
return suspend(state::str4);
|
||||
|
||||
do_esc1:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append(buf_[0]);
|
||||
else
|
||||
return suspend(state::esc1);
|
||||
goto do_str3;
|
||||
|
||||
do_utf1:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('u');
|
||||
else
|
||||
return suspend(state::utf1);
|
||||
do_utf2:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('0');
|
||||
else
|
||||
return suspend(state::utf2);
|
||||
do_utf3:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('0');
|
||||
else
|
||||
return suspend(state::utf3);
|
||||
do_utf4:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append(buf_[0]);
|
||||
else
|
||||
return suspend(state::utf4);
|
||||
do_utf5:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append(buf_[1]);
|
||||
else
|
||||
return suspend(state::utf5);
|
||||
goto do_str3;
|
||||
}
|
||||
|
||||
template<bool StackEmpty>
|
||||
bool
|
||||
serializer::
|
||||
write_number(stream& ss0)
|
||||
{
|
||||
local_stream ss(ss0);
|
||||
if(StackEmpty || st_.empty())
|
||||
{
|
||||
switch(jv_->kind())
|
||||
{
|
||||
default:
|
||||
case kind::int64:
|
||||
if(BOOST_JSON_LIKELY(
|
||||
ss.remain() >=
|
||||
detail::max_number_chars))
|
||||
{
|
||||
ss.advance(detail::format_int64(
|
||||
ss.data(), jv_->get_int64()));
|
||||
return true;
|
||||
}
|
||||
cs0_ = { buf_, detail::format_int64(
|
||||
buf_, jv_->get_int64()) };
|
||||
break;
|
||||
|
||||
case kind::uint64:
|
||||
if(BOOST_JSON_LIKELY(
|
||||
ss.remain() >=
|
||||
detail::max_number_chars))
|
||||
{
|
||||
ss.advance(detail::format_uint64(
|
||||
ss.data(), jv_->get_uint64()));
|
||||
return true;
|
||||
}
|
||||
cs0_ = { buf_, detail::format_uint64(
|
||||
buf_, jv_->get_uint64()) };
|
||||
break;
|
||||
|
||||
case kind::double_:
|
||||
if(BOOST_JSON_LIKELY(
|
||||
ss.remain() >=
|
||||
detail::max_number_chars))
|
||||
{
|
||||
ss.advance(detail::format_double(
|
||||
ss.data(), jv_->get_double()));
|
||||
return true;
|
||||
}
|
||||
cs0_ = { buf_, detail::format_double(
|
||||
buf_, jv_->get_double()) };
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
state st;
|
||||
st_.pop(st);
|
||||
BOOST_ASSERT(
|
||||
st == state::num);
|
||||
}
|
||||
auto const n = ss.remain();
|
||||
if(n < cs0_.remain())
|
||||
{
|
||||
ss.append(cs0_.data(), n);
|
||||
cs0_.skip(n);
|
||||
return suspend(state::num);
|
||||
}
|
||||
ss.append(
|
||||
cs0_.data(), cs0_.remain());
|
||||
return true;
|
||||
}
|
||||
|
||||
template<bool StackEmpty>
|
||||
bool
|
||||
serializer::
|
||||
write_array(stream& ss0)
|
||||
{
|
||||
array const* pa;
|
||||
local_stream ss(ss0);
|
||||
array::const_iterator it;
|
||||
array::const_iterator end;
|
||||
if(StackEmpty || st_.empty())
|
||||
{
|
||||
pa = pa_;
|
||||
it = pa->begin();
|
||||
end = pa->end();
|
||||
}
|
||||
else
|
||||
{
|
||||
state st;
|
||||
st_.pop(st);
|
||||
st_.pop(it);
|
||||
st_.pop(pa);
|
||||
end = pa->end();
|
||||
switch(st)
|
||||
{
|
||||
default:
|
||||
case state::arr1: goto do_arr1;
|
||||
case state::arr2: goto do_arr2;
|
||||
case state::arr3: goto do_arr3;
|
||||
case state::arr4: goto do_arr4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
do_arr1:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('[');
|
||||
else
|
||||
return suspend(
|
||||
state::arr1, it, pa);
|
||||
if(it == end)
|
||||
goto do_arr4;
|
||||
for(;;)
|
||||
{
|
||||
do_arr2:
|
||||
jv_ = &*it;
|
||||
if(! write_value<StackEmpty>(ss))
|
||||
return suspend(
|
||||
state::arr2, it, pa);
|
||||
if(BOOST_JSON_UNLIKELY(
|
||||
++it == end))
|
||||
break;
|
||||
do_arr3:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append(',');
|
||||
else
|
||||
return suspend(
|
||||
state::arr3, it, pa);
|
||||
}
|
||||
do_arr4:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append(']');
|
||||
else
|
||||
return suspend(
|
||||
state::arr4, it, pa);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<bool StackEmpty>
|
||||
bool
|
||||
serializer::
|
||||
write_object(stream& ss0)
|
||||
{
|
||||
object const* po;
|
||||
local_stream ss(ss0);
|
||||
object::const_iterator it;
|
||||
object::const_iterator end;
|
||||
if(StackEmpty || st_.empty())
|
||||
{
|
||||
po = po_;
|
||||
it = po->begin();
|
||||
end = po->end();
|
||||
}
|
||||
else
|
||||
{
|
||||
state st;
|
||||
st_.pop(st);
|
||||
st_.pop(it);
|
||||
st_.pop(po);
|
||||
end = po->end();
|
||||
switch(st)
|
||||
{
|
||||
default:
|
||||
case state::obj1: goto do_obj1;
|
||||
case state::obj2: goto do_obj2;
|
||||
case state::obj3: goto do_obj3;
|
||||
case state::obj4: goto do_obj4;
|
||||
case state::obj5: goto do_obj5;
|
||||
case state::obj6: goto do_obj6;
|
||||
break;
|
||||
}
|
||||
}
|
||||
do_obj1:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append('{');
|
||||
else
|
||||
return suspend(
|
||||
state::obj1, it, po);
|
||||
if(BOOST_JSON_UNLIKELY(
|
||||
it == end))
|
||||
goto do_obj6;
|
||||
for(;;)
|
||||
{
|
||||
cs0_ = {
|
||||
it->key().data(),
|
||||
it->key().size() };
|
||||
do_obj2:
|
||||
if(BOOST_JSON_UNLIKELY(
|
||||
! write_string<StackEmpty>(ss)))
|
||||
return suspend(
|
||||
state::obj2, it, po);
|
||||
do_obj3:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append(':');
|
||||
else
|
||||
return suspend(
|
||||
state::obj3, it, po);
|
||||
do_obj4:
|
||||
jv_ = &it->value();
|
||||
if(BOOST_JSON_UNLIKELY(
|
||||
! write_value<StackEmpty>(ss)))
|
||||
return suspend(
|
||||
state::obj4, it, po);
|
||||
++it;
|
||||
if(BOOST_JSON_UNLIKELY(it == end))
|
||||
break;
|
||||
do_obj5:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
ss.append(',');
|
||||
else
|
||||
return suspend(
|
||||
state::obj5, it, po);
|
||||
}
|
||||
do_obj6:
|
||||
if(BOOST_JSON_LIKELY(ss))
|
||||
{
|
||||
ss.append('}');
|
||||
return true;
|
||||
}
|
||||
return suspend(
|
||||
state::obj6, it, po);
|
||||
}
|
||||
|
||||
template<bool StackEmpty>
|
||||
bool
|
||||
serializer::
|
||||
write_value(stream& ss)
|
||||
{
|
||||
if(StackEmpty || st_.empty())
|
||||
{
|
||||
auto const& jv(*jv_);
|
||||
switch(jv.kind())
|
||||
{
|
||||
default:
|
||||
case kind::object:
|
||||
po_ = &jv.get_object();
|
||||
return write_object<true>(ss);
|
||||
|
||||
case kind::array:
|
||||
pa_ = &jv.get_array();
|
||||
return write_array<true>(ss);
|
||||
|
||||
case kind::string:
|
||||
{
|
||||
auto const& js = jv.get_string();
|
||||
cs0_ = { js.data(), js.size() };
|
||||
return write_string<true>(ss);
|
||||
}
|
||||
|
||||
case kind::int64:
|
||||
case kind::uint64:
|
||||
case kind::double_:
|
||||
return write_number<true>(ss);
|
||||
|
||||
case kind::bool_:
|
||||
if(jv.get_bool())
|
||||
{
|
||||
if(BOOST_JSON_LIKELY(
|
||||
ss.remain() >= 4))
|
||||
{
|
||||
ss.append("true", 4);
|
||||
return true;
|
||||
}
|
||||
return write_true<true>(ss);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(BOOST_JSON_LIKELY(
|
||||
ss.remain() >= 5))
|
||||
{
|
||||
ss.append("false", 5);
|
||||
return true;
|
||||
}
|
||||
return write_false<true>(ss);
|
||||
}
|
||||
|
||||
case kind::null:
|
||||
if(BOOST_JSON_LIKELY(
|
||||
ss.remain() >= 4))
|
||||
{
|
||||
ss.append("null", 4);
|
||||
return true;
|
||||
}
|
||||
return write_null<true>(ss);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
state st;
|
||||
st_.peek(st);
|
||||
switch(st)
|
||||
{
|
||||
default:
|
||||
case state::nul1: case state::nul2:
|
||||
case state::nul3: case state::nul4:
|
||||
return write_null<StackEmpty>(ss);
|
||||
|
||||
case state::tru1: case state::tru2:
|
||||
case state::tru3: case state::tru4:
|
||||
return write_true<StackEmpty>(ss);
|
||||
|
||||
case state::fal1: case state::fal2:
|
||||
case state::fal3: case state::fal4:
|
||||
case state::fal5:
|
||||
return write_false<StackEmpty>(ss);
|
||||
|
||||
case state::str1: case state::str2:
|
||||
case state::str3: case state::str4:
|
||||
case state::esc1:
|
||||
case state::utf1: case state::utf2:
|
||||
case state::utf3: case state::utf4:
|
||||
case state::utf5:
|
||||
return write_string<StackEmpty>(ss);
|
||||
|
||||
case state::num:
|
||||
return write_number<StackEmpty>(ss);
|
||||
|
||||
case state::arr1: case state::arr2:
|
||||
case state::arr3: case state::arr4:
|
||||
return write_array<StackEmpty>(ss);
|
||||
|
||||
case state::obj1: case state::obj2:
|
||||
case state::obj3: case state::obj4:
|
||||
case state::obj5: case state::obj6:
|
||||
return write_object<StackEmpty>(ss);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string_view
|
||||
serializer::
|
||||
read_some(
|
||||
char* dest, std::size_t size)
|
||||
{
|
||||
// If this goes off it means you forgot
|
||||
// to call reset() before seriailzing a
|
||||
// new value, or you never checked done()
|
||||
// to see if you should stop.
|
||||
BOOST_ASSERT(! done_);
|
||||
|
||||
stream ss(dest, size);
|
||||
if(st_.empty())
|
||||
(this->*fn0_)(ss);
|
||||
else
|
||||
(this->*fn1_)(ss);
|
||||
if(st_.empty())
|
||||
{
|
||||
done_ = true;
|
||||
jv_ = nullptr;
|
||||
}
|
||||
return string_view(
|
||||
dest, ss.used(dest));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
serializer::
|
||||
serializer() noexcept
|
||||
{
|
||||
// ensure room for \uXXXX escape plus one
|
||||
BOOST_STATIC_ASSERT(
|
||||
sizeof(serializer::buf_) >= 7);
|
||||
}
|
||||
|
||||
void
|
||||
serializer::
|
||||
reset(value const* p) noexcept
|
||||
{
|
||||
pv_ = p;
|
||||
fn0_ = &serializer::write_value<true>;
|
||||
fn1_ = &serializer::write_value<false>;
|
||||
|
||||
jv_ = p;
|
||||
st_.clear();
|
||||
done_ = false;
|
||||
}
|
||||
|
||||
void
|
||||
serializer::
|
||||
reset(array const* p) noexcept
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
string_view
|
||||
serializer::
|
||||
read(char* dest, std::size_t size)
|
||||
{
|
||||
if(! jv_)
|
||||
{
|
||||
static value const null;
|
||||
jv_ = &null;
|
||||
}
|
||||
return read_some(dest, size);
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,78 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_STATIC_RESOURCE_IPP
|
||||
#define BOOST_JSON_IMPL_STATIC_RESOURCE_IPP
|
||||
|
||||
#include <boost/json/static_resource.hpp>
|
||||
#include <boost/json/detail/align.hpp>
|
||||
#include <boost/json/detail/except.hpp>
|
||||
#include <memory>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
static_resource::
|
||||
~static_resource() noexcept = default;
|
||||
|
||||
static_resource::
|
||||
static_resource(
|
||||
unsigned char* buffer,
|
||||
std::size_t size) noexcept
|
||||
: p_(buffer)
|
||||
, n_(size)
|
||||
, size_(size)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
static_resource::
|
||||
release() noexcept
|
||||
{
|
||||
p_ = reinterpret_cast<
|
||||
char*>(p_) - (size_ - n_);
|
||||
n_ = size_;
|
||||
}
|
||||
|
||||
void*
|
||||
static_resource::
|
||||
do_allocate(
|
||||
std::size_t n,
|
||||
std::size_t align)
|
||||
{
|
||||
auto p = detail::align(
|
||||
align, n, p_, n_);
|
||||
if(! p)
|
||||
detail::throw_bad_alloc(
|
||||
BOOST_CURRENT_LOCATION);
|
||||
p_ = reinterpret_cast<char*>(p) + n;
|
||||
n_ -= n;
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
static_resource::
|
||||
do_deallocate(
|
||||
void*,
|
||||
std::size_t,
|
||||
std::size_t)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
bool
|
||||
static_resource::
|
||||
do_is_equal(
|
||||
memory_resource const& mr) const noexcept
|
||||
{
|
||||
return this == &mr;
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
148
install/boost_1_75_0/include/boost/json/impl/stream_parser.ipp
Normal file
148
install/boost_1_75_0/include/boost/json/impl/stream_parser.ipp
Normal file
@@ -0,0 +1,148 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_STREAM_PARSER_IPP
|
||||
#define BOOST_JSON_IMPL_STREAM_PARSER_IPP
|
||||
|
||||
#include <boost/json/stream_parser.hpp>
|
||||
#include <boost/json/basic_parser_impl.hpp>
|
||||
#include <boost/json/error.hpp>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
stream_parser::
|
||||
stream_parser(
|
||||
storage_ptr sp,
|
||||
parse_options const& opt,
|
||||
unsigned char* buffer,
|
||||
std::size_t size) noexcept
|
||||
: p_(
|
||||
opt,
|
||||
std::move(sp),
|
||||
buffer,
|
||||
size)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
stream_parser::
|
||||
stream_parser(
|
||||
storage_ptr sp,
|
||||
parse_options const& opt) noexcept
|
||||
: p_(
|
||||
opt,
|
||||
std::move(sp),
|
||||
nullptr,
|
||||
0)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void
|
||||
stream_parser::
|
||||
reset(storage_ptr sp) noexcept
|
||||
{
|
||||
p_.reset();
|
||||
p_.handler().st.reset(sp);
|
||||
}
|
||||
|
||||
std::size_t
|
||||
stream_parser::
|
||||
write_some(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec)
|
||||
{
|
||||
return p_.write_some(
|
||||
true, data, size, ec);
|
||||
}
|
||||
|
||||
std::size_t
|
||||
stream_parser::
|
||||
write_some(
|
||||
char const* data,
|
||||
std::size_t size)
|
||||
{
|
||||
error_code ec;
|
||||
auto const n = write_some(
|
||||
data, size, ec);
|
||||
if(ec)
|
||||
detail::throw_system_error(ec,
|
||||
BOOST_CURRENT_LOCATION);
|
||||
return n;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
stream_parser::
|
||||
write(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec)
|
||||
{
|
||||
auto const n = write_some(
|
||||
data, size, ec);
|
||||
if(! ec && n < size)
|
||||
{
|
||||
ec = error::extra_data;
|
||||
p_.fail(ec);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
stream_parser::
|
||||
write(
|
||||
char const* data,
|
||||
std::size_t size)
|
||||
{
|
||||
error_code ec;
|
||||
auto const n = write(
|
||||
data, size, ec);
|
||||
if(ec)
|
||||
detail::throw_system_error(ec,
|
||||
BOOST_CURRENT_LOCATION);
|
||||
return n;
|
||||
}
|
||||
|
||||
void
|
||||
stream_parser::
|
||||
finish(error_code& ec)
|
||||
{
|
||||
p_.write_some(false, nullptr, 0, ec);
|
||||
}
|
||||
|
||||
void
|
||||
stream_parser::
|
||||
finish()
|
||||
{
|
||||
error_code ec;
|
||||
finish(ec);
|
||||
if(ec)
|
||||
detail::throw_system_error(ec,
|
||||
BOOST_CURRENT_LOCATION);
|
||||
}
|
||||
|
||||
value
|
||||
stream_parser::
|
||||
release()
|
||||
{
|
||||
if(! p_.done())
|
||||
{
|
||||
// prevent undefined behavior
|
||||
finish();
|
||||
}
|
||||
return p_.handler().st.release();
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
236
install/boost_1_75_0/include/boost/json/impl/string.hpp
Normal file
236
install/boost_1_75_0/include/boost/json/impl/string.hpp
Normal file
@@ -0,0 +1,236 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_STRING_HPP
|
||||
#define BOOST_JSON_IMPL_STRING_HPP
|
||||
|
||||
#include <utility>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
string::
|
||||
string(
|
||||
detail::key_t const&,
|
||||
string_view s,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
, impl_(detail::key_t{},
|
||||
s, sp_)
|
||||
{
|
||||
}
|
||||
|
||||
string::
|
||||
string(
|
||||
detail::key_t const&,
|
||||
string_view s1,
|
||||
string_view s2,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
, impl_(detail::key_t{},
|
||||
s1, s2, sp_)
|
||||
{
|
||||
}
|
||||
|
||||
template<class InputIt, class>
|
||||
string::
|
||||
string(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
, impl_(first, last, sp_,
|
||||
iter_cat<InputIt>{})
|
||||
{
|
||||
}
|
||||
|
||||
template<class InputIt, class>
|
||||
string&
|
||||
string::
|
||||
assign(
|
||||
InputIt first,
|
||||
InputIt last)
|
||||
{
|
||||
assign(first, last,
|
||||
iter_cat<InputIt>{});
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class InputIt, class>
|
||||
string&
|
||||
string::
|
||||
append(InputIt first, InputIt last)
|
||||
{
|
||||
append(first, last,
|
||||
iter_cat<InputIt>{});
|
||||
return *this;
|
||||
}
|
||||
|
||||
// KRYSTIAN TODO: this can be done without copies when
|
||||
// reallocation is not needed, when the iterator is a
|
||||
// FowardIterator or better, as we can use std::distance
|
||||
template<class InputIt, class>
|
||||
auto
|
||||
string::
|
||||
insert(
|
||||
size_type pos,
|
||||
InputIt first,
|
||||
InputIt last) ->
|
||||
string&
|
||||
{
|
||||
struct cleanup
|
||||
{
|
||||
detail::string_impl& s;
|
||||
storage_ptr const& sp;
|
||||
|
||||
~cleanup()
|
||||
{
|
||||
s.destroy(sp);
|
||||
}
|
||||
};
|
||||
|
||||
// We use the default storage because
|
||||
// the allocation is immediately freed.
|
||||
storage_ptr dsp;
|
||||
detail::string_impl tmp(
|
||||
first, last, dsp,
|
||||
iter_cat<InputIt>{});
|
||||
cleanup c{tmp, dsp};
|
||||
std::memcpy(
|
||||
impl_.insert_unchecked(pos, tmp.size(), sp_),
|
||||
tmp.data(),
|
||||
tmp.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// KRYSTIAN TODO: this can be done without copies when
|
||||
// reallocation is not needed, when the iterator is a
|
||||
// FowardIterator or better, as we can use std::distance
|
||||
template<class InputIt, class>
|
||||
auto
|
||||
string::
|
||||
replace(
|
||||
const_iterator first,
|
||||
const_iterator last,
|
||||
InputIt first2,
|
||||
InputIt last2) ->
|
||||
string&
|
||||
{
|
||||
struct cleanup
|
||||
{
|
||||
detail::string_impl& s;
|
||||
storage_ptr const& sp;
|
||||
|
||||
~cleanup()
|
||||
{
|
||||
s.destroy(sp);
|
||||
}
|
||||
};
|
||||
|
||||
// We use the default storage because
|
||||
// the allocation is immediately freed.
|
||||
storage_ptr dsp;
|
||||
detail::string_impl tmp(
|
||||
first2, last2, dsp,
|
||||
iter_cat<InputIt>{});
|
||||
cleanup c{tmp, dsp};
|
||||
std::memcpy(
|
||||
impl_.replace_unchecked(
|
||||
first - begin(),
|
||||
last - first,
|
||||
tmp.size(),
|
||||
sp_),
|
||||
tmp.data(),
|
||||
tmp.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
string::
|
||||
assign(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
std::random_access_iterator_tag)
|
||||
{
|
||||
auto dest = impl_.assign(static_cast<
|
||||
size_type>(last - first), sp_);
|
||||
while(first != last)
|
||||
*dest++ = *first++;
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
string::
|
||||
assign(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
std::input_iterator_tag)
|
||||
{
|
||||
if(first == last)
|
||||
{
|
||||
impl_.term(0);
|
||||
return;
|
||||
}
|
||||
detail::string_impl tmp(
|
||||
first, last, sp_,
|
||||
std::input_iterator_tag{});
|
||||
impl_.destroy(sp_);
|
||||
impl_ = tmp;
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
string::
|
||||
append(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
std::random_access_iterator_tag)
|
||||
{
|
||||
auto const n = static_cast<
|
||||
size_type>(last - first);
|
||||
std::copy(first, last,
|
||||
impl_.append(n, sp_));
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
string::
|
||||
append(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
std::input_iterator_tag)
|
||||
{
|
||||
struct cleanup
|
||||
{
|
||||
detail::string_impl& s;
|
||||
storage_ptr const& sp;
|
||||
|
||||
~cleanup()
|
||||
{
|
||||
s.destroy(sp);
|
||||
}
|
||||
};
|
||||
|
||||
// We use the default storage because
|
||||
// the allocation is immediately freed.
|
||||
storage_ptr dsp;
|
||||
detail::string_impl tmp(
|
||||
first, last, dsp,
|
||||
std::input_iterator_tag{});
|
||||
cleanup c{tmp, dsp};
|
||||
std::memcpy(
|
||||
impl_.append(tmp.size(), sp_),
|
||||
tmp.data(), tmp.size());
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
416
install/boost_1_75_0/include/boost/json/impl/string.ipp
Normal file
416
install/boost_1_75_0/include/boost/json/impl/string.ipp
Normal file
@@ -0,0 +1,416 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_STRING_IPP
|
||||
#define BOOST_JSON_IMPL_STRING_IPP
|
||||
|
||||
#include <boost/json/detail/except.hpp>
|
||||
#include <algorithm>
|
||||
#include <new>
|
||||
#include <ostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Construction
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
string::
|
||||
string(
|
||||
std::size_t count,
|
||||
char ch,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
assign(count, ch);
|
||||
}
|
||||
|
||||
string::
|
||||
string(
|
||||
char const* s,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
assign(s);
|
||||
}
|
||||
|
||||
string::
|
||||
string(
|
||||
char const* s,
|
||||
std::size_t count,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
assign(s, count);
|
||||
}
|
||||
|
||||
string::
|
||||
string(string const& other)
|
||||
: sp_(other.sp_)
|
||||
{
|
||||
assign(other);
|
||||
}
|
||||
|
||||
string::
|
||||
string(
|
||||
string const& other,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
assign(other);
|
||||
}
|
||||
|
||||
string::
|
||||
string(
|
||||
string&& other,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
assign(std::move(other));
|
||||
}
|
||||
|
||||
string::
|
||||
string(
|
||||
string_view s,
|
||||
storage_ptr sp)
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
assign(s);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Assignment
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
string&
|
||||
string::
|
||||
operator=(string const& other)
|
||||
{
|
||||
return assign(other);
|
||||
}
|
||||
|
||||
string&
|
||||
string::
|
||||
operator=(string&& other)
|
||||
{
|
||||
return assign(std::move(other));
|
||||
}
|
||||
|
||||
string&
|
||||
string::
|
||||
operator=(char const* s)
|
||||
{
|
||||
return assign(s);
|
||||
}
|
||||
|
||||
string&
|
||||
string::
|
||||
operator=(string_view s)
|
||||
{
|
||||
return assign(s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
string&
|
||||
string::
|
||||
assign(
|
||||
size_type count,
|
||||
char ch)
|
||||
{
|
||||
std::char_traits<char>::assign(
|
||||
impl_.assign(count, sp_),
|
||||
count,
|
||||
ch);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string&
|
||||
string::
|
||||
assign(
|
||||
string const& other)
|
||||
{
|
||||
if(this == &other)
|
||||
return *this;
|
||||
return assign(
|
||||
other.data(),
|
||||
other.size());
|
||||
}
|
||||
|
||||
string&
|
||||
string::
|
||||
assign(string&& other)
|
||||
{
|
||||
if(*sp_ == *other.sp_)
|
||||
{
|
||||
impl_.destroy(sp_);
|
||||
impl_ = other.impl_;
|
||||
::new(&other.impl_) detail::string_impl();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// copy
|
||||
return assign(other);
|
||||
}
|
||||
|
||||
string&
|
||||
string::
|
||||
assign(
|
||||
char const* s,
|
||||
size_type count)
|
||||
{
|
||||
std::char_traits<char>::copy(
|
||||
impl_.assign(count, sp_),
|
||||
s, count);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string&
|
||||
string::
|
||||
assign(
|
||||
char const* s)
|
||||
{
|
||||
return assign(s, std::char_traits<
|
||||
char>::length(s));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Capacity
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
string::
|
||||
shrink_to_fit()
|
||||
{
|
||||
impl_.shrink_to_fit(sp_);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Operations
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
string::
|
||||
clear() noexcept
|
||||
{
|
||||
impl_.term(0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
string::
|
||||
push_back(char ch)
|
||||
{
|
||||
*impl_.append(1, sp_) = ch;
|
||||
}
|
||||
|
||||
void
|
||||
string::
|
||||
pop_back()
|
||||
{
|
||||
back() = 0;
|
||||
impl_.size(impl_.size() - 1);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
string&
|
||||
string::
|
||||
append(size_type count, char ch)
|
||||
{
|
||||
std::char_traits<char>::assign(
|
||||
impl_.append(count, sp_),
|
||||
count, ch);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string&
|
||||
string::
|
||||
append(string_view sv)
|
||||
{
|
||||
std::char_traits<char>::copy(
|
||||
impl_.append(sv.size(), sp_),
|
||||
sv.data(), sv.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
string&
|
||||
string::
|
||||
insert(
|
||||
size_type pos,
|
||||
string_view sv)
|
||||
{
|
||||
impl_.insert(pos, sv.data(), sv.size(), sp_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string&
|
||||
string::
|
||||
insert(
|
||||
std::size_t pos,
|
||||
std::size_t count,
|
||||
char ch)
|
||||
{
|
||||
std::char_traits<char>::assign(
|
||||
impl_.insert_unchecked(pos, count, sp_),
|
||||
count, ch);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
string&
|
||||
string::
|
||||
replace(
|
||||
std::size_t pos,
|
||||
std::size_t count,
|
||||
string_view sv)
|
||||
{
|
||||
impl_.replace(pos, count, sv.data(), sv.size(), sp_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string&
|
||||
string::
|
||||
replace(
|
||||
std::size_t pos,
|
||||
std::size_t count,
|
||||
std::size_t count2,
|
||||
char ch)
|
||||
{
|
||||
std::char_traits<char>::assign(
|
||||
impl_.replace_unchecked(pos, count, count2, sp_),
|
||||
count2, ch);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
string&
|
||||
string::
|
||||
erase(
|
||||
size_type pos,
|
||||
size_type count)
|
||||
{
|
||||
if(pos > impl_.size())
|
||||
detail::throw_out_of_range(
|
||||
BOOST_CURRENT_LOCATION);
|
||||
if( count > impl_.size() - pos)
|
||||
count = impl_.size() - pos;
|
||||
std::char_traits<char>::move(
|
||||
impl_.data() + pos,
|
||||
impl_.data() + pos + count,
|
||||
impl_.size() - pos - count + 1);
|
||||
impl_.term(impl_.size() - count);
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto
|
||||
string::
|
||||
erase(const_iterator pos) ->
|
||||
iterator
|
||||
{
|
||||
return erase(pos, pos+1);
|
||||
}
|
||||
|
||||
auto
|
||||
string::
|
||||
erase(
|
||||
const_iterator first,
|
||||
const_iterator last) ->
|
||||
iterator
|
||||
{
|
||||
auto const pos = first - begin();
|
||||
auto const count = last - first;
|
||||
erase(pos, count);
|
||||
return data() + pos;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
string::
|
||||
resize(size_type count, char ch)
|
||||
{
|
||||
if(count <= impl_.size())
|
||||
{
|
||||
impl_.term(count);
|
||||
return;
|
||||
}
|
||||
|
||||
reserve(count);
|
||||
std::char_traits<char>::assign(
|
||||
impl_.end(),
|
||||
count - impl_.size(),
|
||||
ch);
|
||||
grow(count - size());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
string::
|
||||
swap(string& other)
|
||||
{
|
||||
BOOST_ASSERT(this != &other);
|
||||
if(*sp_ == *other.sp_)
|
||||
{
|
||||
std::swap(impl_, other.impl_);
|
||||
return;
|
||||
}
|
||||
string temp1(
|
||||
std::move(*this), other.sp_);
|
||||
string temp2(
|
||||
std::move(other), sp_);
|
||||
this->~string();
|
||||
::new(this) string(pilfer(temp2));
|
||||
other.~string();
|
||||
::new(&other) string(pilfer(temp1));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
string::
|
||||
reserve_impl(size_type new_cap)
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
new_cap >= impl_.capacity());
|
||||
if(new_cap > impl_.capacity())
|
||||
{
|
||||
// grow
|
||||
new_cap = detail::string_impl::growth(
|
||||
new_cap, impl_.capacity());
|
||||
detail::string_impl tmp(new_cap, sp_);
|
||||
std::char_traits<char>::copy(tmp.data(),
|
||||
impl_.data(), impl_.size() + 1);
|
||||
tmp.size(impl_.size());
|
||||
impl_.destroy(sp_);
|
||||
impl_ = tmp;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
497
install/boost_1_75_0/include/boost/json/impl/value.ipp
Normal file
497
install/boost_1_75_0/include/boost/json/impl/value.ipp
Normal file
@@ -0,0 +1,497 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_VALUE_IPP
|
||||
#define BOOST_JSON_IMPL_VALUE_IPP
|
||||
|
||||
#include <boost/json/value.hpp>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <new>
|
||||
#include <utility>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
value::
|
||||
~value()
|
||||
{
|
||||
switch(kind())
|
||||
{
|
||||
case json::kind::null:
|
||||
case json::kind::bool_:
|
||||
case json::kind::int64:
|
||||
case json::kind::uint64:
|
||||
case json::kind::double_:
|
||||
sca_.~scalar();
|
||||
break;
|
||||
|
||||
case json::kind::string:
|
||||
str_.~string();
|
||||
break;
|
||||
|
||||
case json::kind::array:
|
||||
arr_.~array();
|
||||
break;
|
||||
|
||||
case json::kind::object:
|
||||
obj_.~object();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
value::
|
||||
value(
|
||||
value const& other,
|
||||
storage_ptr sp)
|
||||
{
|
||||
switch(other.kind())
|
||||
{
|
||||
case json::kind::null:
|
||||
::new(&sca_) scalar(
|
||||
std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::bool_:
|
||||
::new(&sca_) scalar(
|
||||
other.sca_.b,
|
||||
std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::int64:
|
||||
::new(&sca_) scalar(
|
||||
other.sca_.i,
|
||||
std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::uint64:
|
||||
::new(&sca_) scalar(
|
||||
other.sca_.u,
|
||||
std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::double_:
|
||||
::new(&sca_) scalar(
|
||||
other.sca_.d,
|
||||
std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::string:
|
||||
::new(&str_) string(
|
||||
other.str_,
|
||||
std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::array:
|
||||
::new(&arr_) array(
|
||||
other.arr_,
|
||||
std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::object:
|
||||
::new(&obj_) object(
|
||||
other.obj_,
|
||||
std::move(sp));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
value::
|
||||
value(value&& other) noexcept
|
||||
{
|
||||
relocate(this, other);
|
||||
::new(&other.sca_) scalar(sp_);
|
||||
}
|
||||
|
||||
value::
|
||||
value(
|
||||
value&& other,
|
||||
storage_ptr sp)
|
||||
{
|
||||
switch(other.kind())
|
||||
{
|
||||
case json::kind::null:
|
||||
::new(&sca_) scalar(
|
||||
std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::bool_:
|
||||
::new(&sca_) scalar(
|
||||
other.sca_.b, std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::int64:
|
||||
::new(&sca_) scalar(
|
||||
other.sca_.i, std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::uint64:
|
||||
::new(&sca_) scalar(
|
||||
other.sca_.u, std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::double_:
|
||||
::new(&sca_) scalar(
|
||||
other.sca_.d, std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::string:
|
||||
::new(&str_) string(
|
||||
std::move(other.str_),
|
||||
std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::array:
|
||||
::new(&arr_) array(
|
||||
std::move(other.arr_),
|
||||
std::move(sp));
|
||||
break;
|
||||
|
||||
case json::kind::object:
|
||||
::new(&obj_) object(
|
||||
std::move(other.obj_),
|
||||
std::move(sp));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Conversion
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
value::
|
||||
value(
|
||||
std::initializer_list<value_ref> init,
|
||||
storage_ptr sp)
|
||||
{
|
||||
if(value_ref::maybe_object(init))
|
||||
::new(&obj_) object(
|
||||
value_ref::make_object(
|
||||
init, std::move(sp)));
|
||||
else
|
||||
::new(&arr_) array(
|
||||
value_ref::make_array(
|
||||
init, std::move(sp)));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Assignment
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
value&
|
||||
value::
|
||||
operator=(value const& other)
|
||||
{
|
||||
value(other,
|
||||
storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
value&
|
||||
value::
|
||||
operator=(value&& other)
|
||||
{
|
||||
value(std::move(other),
|
||||
storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
value&
|
||||
value::
|
||||
operator=(
|
||||
std::initializer_list<value_ref> init)
|
||||
{
|
||||
value(init,
|
||||
storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
value&
|
||||
value::
|
||||
operator=(string_view s)
|
||||
{
|
||||
value(s, storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
value&
|
||||
value::
|
||||
operator=(char const* s)
|
||||
{
|
||||
value(s, storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
value&
|
||||
value::
|
||||
operator=(string const& str)
|
||||
{
|
||||
value(str, storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
value&
|
||||
value::
|
||||
operator=(string&& str)
|
||||
{
|
||||
value(std::move(str),
|
||||
storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
value&
|
||||
value::
|
||||
operator=(array const& arr)
|
||||
{
|
||||
value(arr, storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
value&
|
||||
value::
|
||||
operator=(array&& arr)
|
||||
{
|
||||
value(std::move(arr),
|
||||
storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
value&
|
||||
value::
|
||||
operator=(object const& obj)
|
||||
{
|
||||
value(obj, storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
value&
|
||||
value::
|
||||
operator=(object&& obj)
|
||||
{
|
||||
value(std::move(obj),
|
||||
storage()).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// Modifiers
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
string&
|
||||
value::
|
||||
emplace_string() noexcept
|
||||
{
|
||||
return *::new(&str_) string(destroy());
|
||||
}
|
||||
|
||||
array&
|
||||
value::
|
||||
emplace_array() noexcept
|
||||
{
|
||||
return *::new(&arr_) array(destroy());
|
||||
}
|
||||
|
||||
object&
|
||||
value::
|
||||
emplace_object() noexcept
|
||||
{
|
||||
return *::new(&obj_) object(destroy());
|
||||
}
|
||||
|
||||
void
|
||||
value::
|
||||
swap(value& other)
|
||||
{
|
||||
if(*storage() == *other.storage())
|
||||
{
|
||||
// fast path
|
||||
union U
|
||||
{
|
||||
value tmp;
|
||||
U(){}
|
||||
~U(){}
|
||||
};
|
||||
U u;
|
||||
relocate(&u.tmp, *this);
|
||||
relocate(this, other);
|
||||
relocate(&other, u.tmp);
|
||||
return;
|
||||
}
|
||||
|
||||
// copy
|
||||
value temp1(
|
||||
std::move(*this),
|
||||
other.storage());
|
||||
value temp2(
|
||||
std::move(other),
|
||||
this->storage());
|
||||
other.~value();
|
||||
::new(&other) value(pilfer(temp1));
|
||||
this->~value();
|
||||
::new(this) value(pilfer(temp2));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// private
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
storage_ptr
|
||||
value::
|
||||
destroy() noexcept
|
||||
{
|
||||
switch(kind())
|
||||
{
|
||||
case json::kind::null:
|
||||
case json::kind::bool_:
|
||||
case json::kind::int64:
|
||||
case json::kind::uint64:
|
||||
case json::kind::double_:
|
||||
break;
|
||||
|
||||
case json::kind::string:
|
||||
{
|
||||
auto sp = str_.storage();
|
||||
str_.~string();
|
||||
return sp;
|
||||
}
|
||||
|
||||
case json::kind::array:
|
||||
{
|
||||
auto sp = arr_.storage();
|
||||
arr_.~array();
|
||||
return sp;
|
||||
}
|
||||
|
||||
case json::kind::object:
|
||||
{
|
||||
auto sp = obj_.storage();
|
||||
obj_.~object();
|
||||
return sp;
|
||||
}
|
||||
|
||||
}
|
||||
return std::move(sp_);
|
||||
}
|
||||
|
||||
bool
|
||||
value::
|
||||
equal(value const& other) const noexcept
|
||||
{
|
||||
switch(kind())
|
||||
{
|
||||
default: // unreachable()?
|
||||
case json::kind::null:
|
||||
return other.kind() == json::kind::null;
|
||||
|
||||
case json::kind::bool_:
|
||||
return
|
||||
other.kind() == json::kind::bool_ &&
|
||||
get_bool() == other.get_bool();
|
||||
|
||||
case json::kind::int64:
|
||||
switch(other.kind())
|
||||
{
|
||||
case json::kind::int64:
|
||||
return get_int64() == other.get_int64();
|
||||
case json::kind::uint64:
|
||||
if(get_int64() < 0)
|
||||
return false;
|
||||
return static_cast<std::uint64_t>(
|
||||
get_int64()) == other.get_uint64();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
case json::kind::uint64:
|
||||
switch(other.kind())
|
||||
{
|
||||
case json::kind::uint64:
|
||||
return get_uint64() == other.get_uint64();
|
||||
case json::kind::int64:
|
||||
if(other.get_int64() < 0)
|
||||
return false;
|
||||
return static_cast<std::uint64_t>(
|
||||
other.get_int64()) == get_uint64();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
case json::kind::double_:
|
||||
return
|
||||
other.kind() == json::kind::double_ &&
|
||||
get_double() == other.get_double();
|
||||
|
||||
case json::kind::string:
|
||||
return
|
||||
other.kind() == json::kind::string &&
|
||||
get_string() == other.get_string();
|
||||
|
||||
case json::kind::array:
|
||||
return
|
||||
other.kind() == json::kind::array &&
|
||||
get_array() == other.get_array();
|
||||
|
||||
case json::kind::object:
|
||||
return
|
||||
other.kind() == json::kind::object &&
|
||||
get_object() == other.get_object();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
//
|
||||
// key_value_pair
|
||||
//
|
||||
//----------------------------------------------------------
|
||||
|
||||
// empty keys point here
|
||||
BOOST_JSON_REQUIRE_CONST_INIT
|
||||
char const
|
||||
key_value_pair::empty_[1] = { 0 };
|
||||
|
||||
key_value_pair::
|
||||
key_value_pair(
|
||||
pilfered<json::value> key,
|
||||
pilfered<json::value> value) noexcept
|
||||
: value_(value)
|
||||
{
|
||||
std::size_t len;
|
||||
key_ = access::release_key(key.get(), len);
|
||||
len_ = static_cast<std::uint32_t>(len);
|
||||
}
|
||||
|
||||
key_value_pair::
|
||||
key_value_pair(
|
||||
key_value_pair const& other,
|
||||
storage_ptr sp)
|
||||
: value_(other.value_, std::move(sp))
|
||||
{
|
||||
auto p = reinterpret_cast<
|
||||
char*>(value_.storage()->
|
||||
allocate(other.len_ + 1,
|
||||
alignof(char)));
|
||||
std::memcpy(
|
||||
p, other.key_, other.len_);
|
||||
len_ = other.len_;
|
||||
p[len_] = 0;
|
||||
key_ = p;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
58
install/boost_1_75_0/include/boost/json/impl/value_ref.hpp
Normal file
58
install/boost_1_75_0/include/boost/json/impl/value_ref.hpp
Normal file
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_VALUE_REF_HPP
|
||||
#define BOOST_JSON_IMPL_VALUE_REF_HPP
|
||||
|
||||
#include <boost/json/value_from.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
template<class T>
|
||||
value
|
||||
value_ref::
|
||||
from_builtin(
|
||||
void const* p,
|
||||
storage_ptr sp) noexcept
|
||||
{
|
||||
return value(
|
||||
*reinterpret_cast<
|
||||
T const*>(p),
|
||||
std::move(sp));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
value
|
||||
value_ref::
|
||||
from_const(
|
||||
void const* p,
|
||||
storage_ptr sp)
|
||||
{
|
||||
return value_from(
|
||||
*reinterpret_cast<
|
||||
T const*>(p),
|
||||
std::move(sp));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
value
|
||||
value_ref::
|
||||
from_rvalue(
|
||||
void* p,
|
||||
storage_ptr sp)
|
||||
{
|
||||
return value_from(
|
||||
std::move(
|
||||
*reinterpret_cast<T*>(p)),
|
||||
std::move(sp));
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
187
install/boost_1_75_0/include/boost/json/impl/value_ref.ipp
Normal file
187
install/boost_1_75_0/include/boost/json/impl/value_ref.ipp
Normal file
@@ -0,0 +1,187 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_VALUE_REF_IPP
|
||||
#define BOOST_JSON_IMPL_VALUE_REF_IPP
|
||||
|
||||
#include <boost/json/value_ref.hpp>
|
||||
#include <boost/json/array.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
value_ref::
|
||||
operator
|
||||
value() const
|
||||
{
|
||||
return make_value({});
|
||||
}
|
||||
|
||||
value
|
||||
value_ref::
|
||||
from_init_list(
|
||||
void const* p,
|
||||
storage_ptr sp)
|
||||
{
|
||||
return make_value(
|
||||
*reinterpret_cast<
|
||||
init_list const*>(p),
|
||||
std::move(sp));
|
||||
}
|
||||
|
||||
bool
|
||||
value_ref::
|
||||
is_key_value_pair() const noexcept
|
||||
{
|
||||
if(what_ != what::ini)
|
||||
return false;
|
||||
if(arg_.init_list_.size() != 2)
|
||||
return false;
|
||||
auto const& e =
|
||||
*arg_.init_list_.begin();
|
||||
if( e.what_ != what::str &&
|
||||
e.what_ != what::strfunc)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
value_ref::
|
||||
maybe_object(
|
||||
std::initializer_list<
|
||||
value_ref> init) noexcept
|
||||
{
|
||||
for(auto const& e : init)
|
||||
if(! e.is_key_value_pair())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
string_view
|
||||
value_ref::
|
||||
get_string() const noexcept
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
what_ == what::str ||
|
||||
what_ == what::strfunc);
|
||||
if (what_ == what::strfunc)
|
||||
return *static_cast<const string*>(f_.p);
|
||||
return arg_.str_;
|
||||
}
|
||||
|
||||
value
|
||||
value_ref::
|
||||
make_value(
|
||||
storage_ptr sp) const
|
||||
{
|
||||
switch(what_)
|
||||
{
|
||||
default:
|
||||
case what::str:
|
||||
return string(
|
||||
arg_.str_,
|
||||
std::move(sp));
|
||||
|
||||
case what::ini:
|
||||
return make_value(
|
||||
arg_.init_list_,
|
||||
std::move(sp));
|
||||
|
||||
case what::func:
|
||||
return f_.f(f_.p,
|
||||
std::move(sp));
|
||||
|
||||
case what::strfunc:
|
||||
return f_.f(f_.p,
|
||||
std::move(sp));
|
||||
|
||||
case what::cfunc:
|
||||
return cf_.f(cf_.p,
|
||||
std::move(sp));
|
||||
}
|
||||
}
|
||||
|
||||
value
|
||||
value_ref::
|
||||
make_value(
|
||||
std::initializer_list<
|
||||
value_ref> init,
|
||||
storage_ptr sp)
|
||||
{
|
||||
if(maybe_object(init))
|
||||
return make_object(
|
||||
init, std::move(sp));
|
||||
return make_array(
|
||||
init, std::move(sp));
|
||||
}
|
||||
|
||||
object
|
||||
value_ref::
|
||||
make_object(
|
||||
std::initializer_list<value_ref> init,
|
||||
storage_ptr sp)
|
||||
{
|
||||
object obj(std::move(sp));
|
||||
obj.reserve(init.size());
|
||||
for(auto const& e : init)
|
||||
obj.emplace(
|
||||
e.arg_.init_list_.begin()[0].get_string(),
|
||||
e.arg_.init_list_.begin()[1].make_value(
|
||||
obj.storage()));
|
||||
return obj;
|
||||
}
|
||||
|
||||
array
|
||||
value_ref::
|
||||
make_array(
|
||||
std::initializer_list<
|
||||
value_ref> init,
|
||||
storage_ptr sp)
|
||||
{
|
||||
array arr(std::move(sp));
|
||||
arr.reserve(init.size());
|
||||
for(auto const& e : init)
|
||||
arr.emplace_back(
|
||||
e.make_value(
|
||||
arr.storage()));
|
||||
return arr;
|
||||
}
|
||||
|
||||
void
|
||||
value_ref::
|
||||
write_array(
|
||||
value* dest,
|
||||
std::initializer_list<
|
||||
value_ref> init,
|
||||
storage_ptr const& sp)
|
||||
{
|
||||
struct undo
|
||||
{
|
||||
value* const base;
|
||||
value* pos;
|
||||
~undo()
|
||||
{
|
||||
if(pos)
|
||||
while(pos > base)
|
||||
(--pos)->~value();
|
||||
}
|
||||
};
|
||||
undo u{dest, dest};
|
||||
for(auto const& e : init)
|
||||
{
|
||||
::new(u.pos) value(
|
||||
e.make_value(sp));
|
||||
++u.pos;
|
||||
}
|
||||
u.pos = nullptr;
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
472
install/boost_1_75_0/include/boost/json/impl/value_stack.ipp
Normal file
472
install/boost_1_75_0/include/boost/json/impl/value_stack.ipp
Normal file
@@ -0,0 +1,472 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_VALUE_STACK_IPP
|
||||
#define BOOST_JSON_IMPL_VALUE_STACK_IPP
|
||||
|
||||
#include <boost/json/value_stack.hpp>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
//--------------------------------------
|
||||
|
||||
value_stack::
|
||||
stack::
|
||||
~stack()
|
||||
{
|
||||
clear();
|
||||
if( begin_ != temp_ &&
|
||||
begin_ != nullptr)
|
||||
sp_->deallocate(
|
||||
begin_,
|
||||
(end_ - begin_) *
|
||||
sizeof(value));
|
||||
}
|
||||
|
||||
value_stack::
|
||||
stack::
|
||||
stack(
|
||||
storage_ptr sp,
|
||||
void* temp,
|
||||
std::size_t size) noexcept
|
||||
: sp_(std::move(sp))
|
||||
, temp_(temp)
|
||||
{
|
||||
if(size >= min_size_ *
|
||||
sizeof(value))
|
||||
{
|
||||
begin_ = reinterpret_cast<
|
||||
value*>(temp);
|
||||
top_ = begin_;
|
||||
end_ = begin_ +
|
||||
size / sizeof(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
begin_ = nullptr;
|
||||
top_ = nullptr;
|
||||
end_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
value_stack::
|
||||
stack::
|
||||
run_dtors(bool b) noexcept
|
||||
{
|
||||
run_dtors_ = b;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
value_stack::
|
||||
stack::
|
||||
size() const noexcept
|
||||
{
|
||||
return top_ - begin_;
|
||||
}
|
||||
|
||||
bool
|
||||
value_stack::
|
||||
stack::
|
||||
has_chars()
|
||||
{
|
||||
return chars_ != 0;
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
|
||||
// destroy the values but
|
||||
// not the stack allocation.
|
||||
void
|
||||
value_stack::
|
||||
stack::
|
||||
clear() noexcept
|
||||
{
|
||||
if(top_ != begin_)
|
||||
{
|
||||
if(run_dtors_)
|
||||
for(auto it = top_;
|
||||
it-- != begin_;)
|
||||
it->~value();
|
||||
top_ = begin_;
|
||||
}
|
||||
chars_ = 0;
|
||||
}
|
||||
|
||||
void
|
||||
value_stack::
|
||||
stack::
|
||||
maybe_grow()
|
||||
{
|
||||
if(top_ >= end_)
|
||||
grow_one();
|
||||
}
|
||||
|
||||
// make room for at least one more value
|
||||
void
|
||||
value_stack::
|
||||
stack::
|
||||
grow_one()
|
||||
{
|
||||
BOOST_ASSERT(chars_ == 0);
|
||||
std::size_t const capacity =
|
||||
end_ - begin_;
|
||||
std::size_t new_cap = min_size_;
|
||||
// VFALCO check overflow here
|
||||
while(new_cap < capacity + 1)
|
||||
new_cap <<= 1;
|
||||
auto const begin =
|
||||
reinterpret_cast<value*>(
|
||||
sp_->allocate(
|
||||
new_cap * sizeof(value)));
|
||||
if(begin_)
|
||||
{
|
||||
std::memcpy(
|
||||
reinterpret_cast<char*>(begin),
|
||||
reinterpret_cast<char*>(begin_),
|
||||
size() * sizeof(value));
|
||||
if(begin_ != temp_)
|
||||
sp_->deallocate(begin_,
|
||||
capacity * sizeof(value));
|
||||
}
|
||||
// book-keeping
|
||||
top_ = begin + (top_ - begin_);
|
||||
end_ = begin + new_cap;
|
||||
begin_ = begin;
|
||||
}
|
||||
|
||||
// make room for nchars additional characters.
|
||||
void
|
||||
value_stack::
|
||||
stack::
|
||||
grow(std::size_t nchars)
|
||||
{
|
||||
// needed capacity in values
|
||||
std::size_t const needed =
|
||||
size() +
|
||||
1 +
|
||||
((chars_ + nchars +
|
||||
sizeof(value) - 1) /
|
||||
sizeof(value));
|
||||
std::size_t const capacity =
|
||||
end_ - begin_;
|
||||
BOOST_ASSERT(
|
||||
needed > capacity);
|
||||
std::size_t new_cap = min_size_;
|
||||
// VFALCO check overflow here
|
||||
while(new_cap < needed)
|
||||
new_cap <<= 1;
|
||||
auto const begin =
|
||||
reinterpret_cast<value*>(
|
||||
sp_->allocate(
|
||||
new_cap * sizeof(value)));
|
||||
if(begin_)
|
||||
{
|
||||
std::size_t amount =
|
||||
size() * sizeof(value);
|
||||
if(chars_ > 0)
|
||||
amount += sizeof(value) + chars_;
|
||||
std::memcpy(
|
||||
reinterpret_cast<char*>(begin),
|
||||
reinterpret_cast<char*>(begin_),
|
||||
amount);
|
||||
if(begin_ != temp_)
|
||||
sp_->deallocate(begin_,
|
||||
capacity * sizeof(value));
|
||||
}
|
||||
// book-keeping
|
||||
top_ = begin + (top_ - begin_);
|
||||
end_ = begin + new_cap;
|
||||
begin_ = begin;
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
|
||||
void
|
||||
value_stack::
|
||||
stack::
|
||||
append(string_view s)
|
||||
{
|
||||
std::size_t const bytes_avail =
|
||||
reinterpret_cast<
|
||||
char const*>(end_) -
|
||||
reinterpret_cast<
|
||||
char const*>(top_);
|
||||
// make sure there is room for
|
||||
// pushing one more value without
|
||||
// clobbering the string.
|
||||
if(sizeof(value) + chars_ +
|
||||
s.size() > bytes_avail)
|
||||
grow(s.size());
|
||||
|
||||
// copy the new piece
|
||||
std::memcpy(
|
||||
reinterpret_cast<char*>(
|
||||
top_ + 1) + chars_,
|
||||
s.data(), s.size());
|
||||
chars_ += s.size();
|
||||
|
||||
// ensure a pushed value cannot
|
||||
// clobber the released string.
|
||||
BOOST_ASSERT(
|
||||
reinterpret_cast<char*>(
|
||||
top_ + 1) + chars_ <=
|
||||
reinterpret_cast<char*>(
|
||||
end_));
|
||||
}
|
||||
|
||||
string_view
|
||||
value_stack::
|
||||
stack::
|
||||
release_string() noexcept
|
||||
{
|
||||
// ensure a pushed value cannot
|
||||
// clobber the released string.
|
||||
BOOST_ASSERT(
|
||||
reinterpret_cast<char*>(
|
||||
top_ + 1) + chars_ <=
|
||||
reinterpret_cast<char*>(
|
||||
end_));
|
||||
auto const n = chars_;
|
||||
chars_ = 0;
|
||||
return { reinterpret_cast<
|
||||
char const*>(top_ + 1), n };
|
||||
}
|
||||
|
||||
// transfer ownership of the top n
|
||||
// elements of the stack to the caller
|
||||
value*
|
||||
value_stack::
|
||||
stack::
|
||||
release(std::size_t n) noexcept
|
||||
{
|
||||
BOOST_ASSERT(n <= size());
|
||||
BOOST_ASSERT(chars_ == 0);
|
||||
top_ -= n;
|
||||
return top_;
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
value&
|
||||
value_stack::
|
||||
stack::
|
||||
push(Args&&... args)
|
||||
{
|
||||
BOOST_ASSERT(chars_ == 0);
|
||||
if(top_ >= end_)
|
||||
grow_one();
|
||||
value& jv = detail::access::
|
||||
construct_value(top_,
|
||||
std::forward<Args>(args)...);
|
||||
++top_;
|
||||
return jv;
|
||||
}
|
||||
|
||||
template<class Unchecked>
|
||||
void
|
||||
value_stack::
|
||||
stack::
|
||||
exchange(Unchecked&& u)
|
||||
{
|
||||
BOOST_ASSERT(chars_ == 0);
|
||||
union U
|
||||
{
|
||||
value v;
|
||||
U() {}
|
||||
~U() {}
|
||||
} jv;
|
||||
// construct value on the stack
|
||||
// to avoid clobbering top_[0],
|
||||
// which belongs to `u`.
|
||||
detail::access::
|
||||
construct_value(
|
||||
&jv.v, std::move(u));
|
||||
std::memcpy(
|
||||
reinterpret_cast<
|
||||
char*>(top_),
|
||||
&jv.v, sizeof(value));
|
||||
++top_;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
value_stack::
|
||||
~value_stack()
|
||||
{
|
||||
// default dtor is here so the
|
||||
// definition goes in the library
|
||||
// instead of the caller's TU.
|
||||
}
|
||||
|
||||
value_stack::
|
||||
value_stack(
|
||||
storage_ptr sp,
|
||||
unsigned char* temp_buffer,
|
||||
std::size_t temp_size) noexcept
|
||||
: st_(
|
||||
std::move(sp),
|
||||
temp_buffer,
|
||||
temp_size)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
value_stack::
|
||||
reset(storage_ptr sp) noexcept
|
||||
{
|
||||
st_.clear();
|
||||
|
||||
sp_.~storage_ptr();
|
||||
::new(&sp_) storage_ptr(
|
||||
pilfer(sp));
|
||||
|
||||
// `stack` needs this
|
||||
// to clean up correctly
|
||||
st_.run_dtors(
|
||||
! sp_.is_not_shared_and_deallocate_is_trivial());
|
||||
}
|
||||
|
||||
value
|
||||
value_stack::
|
||||
release() noexcept
|
||||
{
|
||||
// This means the caller did not
|
||||
// cause a single top level element
|
||||
// to be produced.
|
||||
BOOST_ASSERT(st_.size() == 1);
|
||||
|
||||
// give up shared ownership
|
||||
sp_ = {};
|
||||
|
||||
return pilfer(*st_.release(1));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
void
|
||||
value_stack::
|
||||
push_array(std::size_t n)
|
||||
{
|
||||
// we already have room if n > 0
|
||||
if(BOOST_JSON_UNLIKELY(n == 0))
|
||||
st_.maybe_grow();
|
||||
detail::unchecked_array ua(
|
||||
st_.release(n), n, sp_);
|
||||
st_.exchange(std::move(ua));
|
||||
}
|
||||
|
||||
void
|
||||
value_stack::
|
||||
push_object(std::size_t n)
|
||||
{
|
||||
// we already have room if n > 0
|
||||
if(BOOST_JSON_UNLIKELY(n == 0))
|
||||
st_.maybe_grow();
|
||||
detail::unchecked_object uo(
|
||||
st_.release(n * 2), n, sp_);
|
||||
st_.exchange(std::move(uo));
|
||||
}
|
||||
|
||||
void
|
||||
value_stack::
|
||||
push_chars(
|
||||
string_view s)
|
||||
{
|
||||
st_.append(s);
|
||||
}
|
||||
|
||||
void
|
||||
value_stack::
|
||||
push_key(
|
||||
string_view s)
|
||||
{
|
||||
if(! st_.has_chars())
|
||||
{
|
||||
st_.push(detail::key_t{}, s, sp_);
|
||||
return;
|
||||
}
|
||||
auto part = st_.release_string();
|
||||
st_.push(detail::key_t{}, part, s, sp_);
|
||||
}
|
||||
|
||||
void
|
||||
value_stack::
|
||||
push_string(
|
||||
string_view s)
|
||||
{
|
||||
if(! st_.has_chars())
|
||||
{
|
||||
// fast path
|
||||
st_.push(s, sp_);
|
||||
return;
|
||||
}
|
||||
|
||||
// VFALCO We could add a special
|
||||
// private ctor to string that just
|
||||
// creates uninitialized space,
|
||||
// to reduce member function calls.
|
||||
auto part = st_.release_string();
|
||||
auto& str = st_.push(
|
||||
string_kind, sp_).get_string();
|
||||
str.reserve(
|
||||
part.size() + s.size());
|
||||
std::memcpy(
|
||||
str.data(),
|
||||
part.data(), part.size());
|
||||
std::memcpy(
|
||||
str.data() + part.size(),
|
||||
s.data(), s.size());
|
||||
str.grow(part.size() + s.size());
|
||||
}
|
||||
|
||||
void
|
||||
value_stack::
|
||||
push_int64(
|
||||
int64_t i)
|
||||
{
|
||||
st_.push(i, sp_);
|
||||
}
|
||||
|
||||
void
|
||||
value_stack::
|
||||
push_uint64(
|
||||
uint64_t u)
|
||||
{
|
||||
st_.push(u, sp_);
|
||||
}
|
||||
|
||||
void
|
||||
value_stack::
|
||||
push_double(
|
||||
double d)
|
||||
{
|
||||
st_.push(d, sp_);
|
||||
}
|
||||
|
||||
void
|
||||
value_stack::
|
||||
push_bool(
|
||||
bool b)
|
||||
{
|
||||
st_.push(b, sp_);
|
||||
}
|
||||
|
||||
void
|
||||
value_stack::
|
||||
push_null()
|
||||
{
|
||||
st_.push(nullptr, sp_);
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
59
install/boost_1_75_0/include/boost/json/impl/visit.hpp
Normal file
59
install/boost_1_75_0/include/boost/json/impl/visit.hpp
Normal file
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_VISIT_HPP
|
||||
#define BOOST_JSON_IMPL_VISIT_HPP
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
template<class Visitor>
|
||||
auto
|
||||
visit(
|
||||
Visitor&& v,
|
||||
value& jv) -> decltype(
|
||||
std::declval<Visitor>()(nullptr))
|
||||
{
|
||||
switch(jv.kind())
|
||||
{
|
||||
default: // unreachable()?
|
||||
case kind::null: return std::forward<Visitor>(v)(nullptr);
|
||||
case kind::bool_: return std::forward<Visitor>(v)(jv.get_bool());
|
||||
case kind::int64: return std::forward<Visitor>(v)(jv.get_int64());
|
||||
case kind::uint64: return std::forward<Visitor>(v)(jv.get_uint64());
|
||||
case kind::double_: return std::forward<Visitor>(v)(jv.get_double());
|
||||
case kind::string: return std::forward<Visitor>(v)(jv.get_string());
|
||||
case kind::array: return std::forward<Visitor>(v)(jv.get_array());
|
||||
case kind::object: return std::forward<Visitor>(v)(jv.get_object());
|
||||
}
|
||||
}
|
||||
|
||||
template<class Visitor>
|
||||
auto
|
||||
visit(
|
||||
Visitor&& v,
|
||||
value const& jv) -> decltype(
|
||||
std::declval<Visitor>()(nullptr))
|
||||
{
|
||||
switch (jv.kind())
|
||||
{
|
||||
default: // unreachable()?
|
||||
case kind::null: return std::forward<Visitor>(v)(nullptr);
|
||||
case kind::bool_: return std::forward<Visitor>(v)(jv.get_bool());
|
||||
case kind::int64: return std::forward<Visitor>(v)(jv.get_int64());
|
||||
case kind::uint64: return std::forward<Visitor>(v)(jv.get_uint64());
|
||||
case kind::double_: return std::forward<Visitor>(v)(jv.get_double());
|
||||
case kind::string: return std::forward<Visitor>(v)(jv.get_string());
|
||||
case kind::array: return std::forward<Visitor>(v)(jv.get_array());
|
||||
case kind::object: return std::forward<Visitor>(v)(jv.get_object());
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
163
install/boost_1_75_0/include/boost/json/kind.hpp
Normal file
163
install/boost_1_75_0/include/boost/json/kind.hpp
Normal file
@@ -0,0 +1,163 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_KIND_HPP
|
||||
#define BOOST_JSON_KIND_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/string_view.hpp>
|
||||
#include <iosfwd>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
/** Constants for identifying the type of a value
|
||||
|
||||
These values are returned from @ref value::kind
|
||||
*/
|
||||
// Order matters
|
||||
enum class kind : unsigned char
|
||||
{
|
||||
/// The null value.
|
||||
null,
|
||||
|
||||
/// A `bool`.
|
||||
bool_,
|
||||
|
||||
/// A `std::int64_t`
|
||||
int64,
|
||||
|
||||
/// A `std::uint64_t`
|
||||
uint64,
|
||||
|
||||
/// A `double`.
|
||||
double_,
|
||||
|
||||
/// A @ref string.
|
||||
string,
|
||||
|
||||
/// An @ref array.
|
||||
array,
|
||||
|
||||
/// An @ref object.
|
||||
object
|
||||
};
|
||||
|
||||
/** Return a string representing a kind.
|
||||
|
||||
This provides a human-readable string
|
||||
representing a @ref kind. This may be
|
||||
useful for diagnostics.
|
||||
|
||||
@returns The string.
|
||||
|
||||
@param k The kind.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
string_view
|
||||
to_string(kind k) noexcept;
|
||||
|
||||
/** Format a kind to an output stream.
|
||||
|
||||
This allows a @ref kind to be formatted as
|
||||
a string, typically for diagnostics.
|
||||
|
||||
@returns The output stream.
|
||||
|
||||
@param os The output stream to format to.
|
||||
|
||||
@param k The kind to format.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, kind k);
|
||||
|
||||
/** A tag type used to select a @ref value constructor overload.
|
||||
|
||||
The library provides the constant @ref array_kind
|
||||
which may be used to select the @ref value constructor
|
||||
that creates an empty @ref array.
|
||||
|
||||
@see @ref array_kind
|
||||
*/
|
||||
struct array_kind_t
|
||||
{
|
||||
};
|
||||
|
||||
/** A tag type used to select a @ref value constructor overload.
|
||||
|
||||
The library provides the constant @ref object_kind
|
||||
which may be used to select the @ref value constructor
|
||||
that creates an empty @ref object.
|
||||
|
||||
@see @ref object_kind
|
||||
*/
|
||||
struct object_kind_t
|
||||
{
|
||||
};
|
||||
|
||||
/** A tag type used to select a @ref value constructor overload.
|
||||
|
||||
The library provides the constant @ref string_kind
|
||||
which may be used to select the @ref value constructor
|
||||
that creates an empty @ref string.
|
||||
|
||||
@see @ref string_kind
|
||||
*/
|
||||
struct string_kind_t
|
||||
{
|
||||
};
|
||||
|
||||
/** A constant used to select a @ref value constructor overload.
|
||||
|
||||
The library provides this constant to allow efficient
|
||||
construction of a @ref value containing an empty @ref array.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
storage_ptr sp;
|
||||
value jv( array_kind, sp ); // sp is an optional parameter
|
||||
@endcode
|
||||
|
||||
@see @ref array_kind_t
|
||||
*/
|
||||
BOOST_JSON_INLINE_VARIABLE(array_kind, array_kind_t);
|
||||
|
||||
/** A constant used to select a @ref value constructor overload.
|
||||
|
||||
The library provides this constant to allow efficient
|
||||
construction of a @ref value containing an empty @ref object.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
storage_ptr sp;
|
||||
value jv( object_kind, sp ); // sp is an optional parameter
|
||||
@endcode
|
||||
|
||||
@see @ref object_kind_t
|
||||
*/
|
||||
BOOST_JSON_INLINE_VARIABLE(object_kind, object_kind_t);
|
||||
|
||||
/** A constant used to select a @ref value constructor overload.
|
||||
|
||||
The library provides this constant to allow efficient
|
||||
construction of a @ref value containing an empty @ref string.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
storage_ptr sp;
|
||||
value jv( string_kind, sp ); // sp is an optional parameter
|
||||
@endcode
|
||||
|
||||
@see @ref string_kind_t
|
||||
*/
|
||||
BOOST_JSON_INLINE_VARIABLE(string_kind, string_kind_t);
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
178
install/boost_1_75_0/include/boost/json/memory_resource.hpp
Normal file
178
install/boost_1_75_0/include/boost/json/memory_resource.hpp
Normal file
@@ -0,0 +1,178 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_MEMORY_RESOURCE_HPP
|
||||
#define BOOST_JSON_MEMORY_RESOURCE_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
|
||||
#ifdef BOOST_JSON_STANDALONE
|
||||
# if __has_include(<memory_resource>)
|
||||
# include <memory_resource>
|
||||
# ifndef __cpp_lib_memory_resource
|
||||
# error Support for std::memory_resource is required to use Boost.JSON standalone
|
||||
# endif
|
||||
# elif __has_include(<experimental/memory_resource>)
|
||||
# include <experimental/memory_resource>
|
||||
# warning Support for std::memory_resource is required to use Boost.JSON standalone, using std::experimental::memory_resource as fallback
|
||||
# else
|
||||
# error Header <memory_resource> is required to use Boost.JSON standalone
|
||||
# endif
|
||||
#else
|
||||
# include <boost/container/pmr/memory_resource.hpp>
|
||||
# include <boost/container/pmr/polymorphic_allocator.hpp>
|
||||
#endif
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
#ifdef BOOST_JSON_DOCS
|
||||
|
||||
/** The type of memory resource used by the library.
|
||||
|
||||
This type alias is set depending
|
||||
on how the library is configured:
|
||||
|
||||
@par Use with Boost
|
||||
|
||||
If the macro `BOOST_JSON_STANDALONE` is
|
||||
not defined, this type will be an alias
|
||||
for `boost::container::pmr::memory_resource`.
|
||||
Compiling a program using the library will
|
||||
require Boost, and a compiler conforming
|
||||
to C++11 or later.
|
||||
|
||||
@par Use without Boost
|
||||
|
||||
If the macro `BOOST_JSON_STANDALONE` is
|
||||
defined, this type will be an alias
|
||||
for `std::pmr::memory_resource`.
|
||||
Compiling a program using the library will
|
||||
require only a compiler conforming to C++17
|
||||
or later.
|
||||
|
||||
@see https://en.cppreference.com/w/cpp/memory/memory_resource
|
||||
*/
|
||||
class memory_resource
|
||||
{
|
||||
};
|
||||
|
||||
/** The type of polymorphic allocator used by the library.
|
||||
|
||||
This type alias is set depending
|
||||
on how the library is configured:
|
||||
|
||||
@par Use with Boost
|
||||
|
||||
If the macro `BOOST_JSON_STANDALONE` is
|
||||
not defined, this type will be an alias template
|
||||
for `boost::container::pmr::polymorphic_allocator`.
|
||||
Compiling a program using the library will
|
||||
require Boost, and a compiler conforming
|
||||
to C++11 or later.
|
||||
|
||||
@par Use without Boost
|
||||
|
||||
If the macro `BOOST_JSON_STANDALONE` is
|
||||
defined, this type will be an alias template
|
||||
for `std::pmr::polymorphic_allocator`.
|
||||
Compiling a program using the library will
|
||||
require only a compiler conforming to C++17
|
||||
or later.
|
||||
|
||||
@see https://en.cppreference.com/w/cpp/memory/polymorphic_allocator
|
||||
*/
|
||||
template<class T>
|
||||
class polymorphic_allocator;
|
||||
|
||||
// VFALCO Bug: doc toolchain won't make this a ref
|
||||
//using memory_resource = __see_below__;
|
||||
|
||||
#elif defined(BOOST_JSON_STANDALONE)
|
||||
|
||||
# if __has_include(<memory_resource>)
|
||||
using memory_resource = std::pmr::memory_resource;
|
||||
template<class T>
|
||||
using polymorphic_allocator =
|
||||
std::pmr::polymorphic_allocator<T>;
|
||||
|
||||
# else
|
||||
using memory_resource = std::experimental::pmr::memory_resource;
|
||||
template<class T>
|
||||
using polymorphic_allocator =
|
||||
std::experimental::pmr::polymorphic_allocator<T>;
|
||||
|
||||
# endif
|
||||
|
||||
#else
|
||||
using memory_resource = boost::container::pmr::memory_resource;
|
||||
|
||||
template<class T>
|
||||
using polymorphic_allocator =
|
||||
boost::container::pmr::polymorphic_allocator<T>;
|
||||
#endif
|
||||
|
||||
/** Return true if a memory resource's deallocate function has no effect.
|
||||
|
||||
This metafunction may be specialized to indicate to
|
||||
the library that calls to the `deallocate` function of
|
||||
a @ref memory_resource have no effect. The implementation
|
||||
will elide such calls when it is safe to do so. By default,
|
||||
the implementation assumes that all memory resources
|
||||
require a call to `deallocate` for each memory region
|
||||
obtained by calling `allocate`.
|
||||
|
||||
@par Example
|
||||
|
||||
This example specializes the metafuction for `my_resource`,
|
||||
to indicate that calls to deallocate have no effect:
|
||||
|
||||
@code
|
||||
|
||||
// Forward-declaration for a user-defined memory resource
|
||||
struct my_resource;
|
||||
|
||||
// It is necessary to specialize the template from
|
||||
// inside the namespace in which it is declared:
|
||||
|
||||
namespace boost {
|
||||
namespace json {
|
||||
|
||||
template<>
|
||||
struct is_deallocate_trivial< my_resource >
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
} // namespace json
|
||||
} // namespace boost
|
||||
|
||||
@endcode
|
||||
|
||||
It is usually not necessary for users to check this trait.
|
||||
Instead, they can call @ref storage_ptr::is_deallocate_trivial
|
||||
to determine if the pointed-to memory resource has a trivial
|
||||
deallocate function.
|
||||
|
||||
@see
|
||||
@ref memory_resource,
|
||||
@ref storage_ptr
|
||||
*/
|
||||
template<class T>
|
||||
struct is_deallocate_trivial
|
||||
{
|
||||
/** A bool equal to true if calls to `T::do_deallocate` have no effect.
|
||||
|
||||
The primary template sets `value` to false.
|
||||
*/
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
350
install/boost_1_75_0/include/boost/json/monotonic_resource.hpp
Normal file
350
install/boost_1_75_0/include/boost/json/monotonic_resource.hpp
Normal file
@@ -0,0 +1,350 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
|
||||
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_MONOTONIC_RESOURCE_HPP
|
||||
#define BOOST_JSON_MONOTONIC_RESOURCE_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/memory_resource.hpp>
|
||||
#include <boost/json/storage_ptr.hpp>
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4251) // class needs to have dll-interface to be used by clients of class
|
||||
#pragma warning(disable: 4275) // non dll-interface class used as base for dll-interface class
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
/** A dynamically allocating resource with a trivial deallocate
|
||||
|
||||
This memory resource is a special-purpose resource
|
||||
that releases allocated memory only when the resource
|
||||
is destroyed (or when @ref release is called).
|
||||
It has a trivial deallocate function; that is, the
|
||||
metafunction @ref is_deallocate_trivial returns `true`.
|
||||
\n
|
||||
The resource can be constructed with an initial buffer.
|
||||
If there is no initial buffer, or if the buffer is
|
||||
exhausted, subsequent dynamic allocations are made from
|
||||
the system heap. The size of buffers obtained in this
|
||||
fashion follow a geometric progression.
|
||||
\n
|
||||
The purpose of this resource is to optimize the use
|
||||
case for performing many allocations, followed by
|
||||
deallocating everything at once. This is precisely the
|
||||
pattern of memory allocation which occurs when parsing:
|
||||
allocation is performed for each parsed element, and
|
||||
when the the resulting @ref value is no longer needed,
|
||||
the entire structure is destroyed. However, it is not
|
||||
suited for modifying the value after parsing is
|
||||
complete; reallocations waste memory, since the
|
||||
older buffer is not reclaimed until the resource
|
||||
is destroyed.
|
||||
|
||||
@par Example
|
||||
|
||||
This parses a JSON into a value which uses a local
|
||||
stack buffer, then prints the result.
|
||||
|
||||
@code
|
||||
|
||||
unsigned char buf[ 4000 ];
|
||||
monotonic_resource mr( buf );
|
||||
|
||||
// Parse the string, using our memory resource
|
||||
auto const jv = parse( "[1,2,3]", &mr );
|
||||
|
||||
// Print the JSON
|
||||
std::cout << jv;
|
||||
|
||||
@endcode
|
||||
|
||||
@note The total amount of memory dynamically
|
||||
allocated is monotonically increasing; That is,
|
||||
it never decreases.
|
||||
|
||||
@par Thread Safety
|
||||
Members of the same instance may not be
|
||||
called concurrently.
|
||||
|
||||
@see
|
||||
https://en.wikipedia.org/wiki/Region-based_memory_management
|
||||
*/
|
||||
class BOOST_JSON_CLASS_DECL
|
||||
monotonic_resource final
|
||||
: public memory_resource
|
||||
{
|
||||
struct block;
|
||||
struct block_base
|
||||
{
|
||||
void* p;
|
||||
std::size_t avail;
|
||||
std::size_t size;
|
||||
block_base* next;
|
||||
};
|
||||
|
||||
block_base buffer_;
|
||||
block_base* head_ = &buffer_;
|
||||
std::size_t next_size_ = 1024;
|
||||
storage_ptr upstream_;
|
||||
|
||||
static constexpr std::size_t min_size_ = 1024;
|
||||
inline static constexpr std::size_t max_size();
|
||||
inline static std::size_t round_pow2(
|
||||
std::size_t n) noexcept;
|
||||
inline static std::size_t next_pow2(
|
||||
std::size_t n) noexcept;
|
||||
|
||||
public:
|
||||
/// Copy constructor (deleted)
|
||||
monotonic_resource(
|
||||
monotonic_resource const&) = delete;
|
||||
|
||||
/// Copy assignment (deleted)
|
||||
monotonic_resource& operator=(
|
||||
monotonic_resource const&) = delete;
|
||||
|
||||
/** Destructor
|
||||
|
||||
Deallocates all the memory owned by this resource.
|
||||
|
||||
@par Effects
|
||||
@code
|
||||
this->release();
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in the number of deallocations performed.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
~monotonic_resource();
|
||||
|
||||
/** Constructor
|
||||
|
||||
This constructs the resource and indicates
|
||||
that the first internal dynamic allocation
|
||||
shall be at least `initial_size` bytes.
|
||||
\n
|
||||
This constructor is guaranteed not to perform
|
||||
any dynamic allocations.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param initial_size The size of the first
|
||||
internal dynamic allocation. If this is lower
|
||||
than the implementation-defined lower limit, then
|
||||
the lower limit is used instead.
|
||||
|
||||
@param upstream An optional upstream memory resource
|
||||
to use for performing internal dynamic allocations.
|
||||
If this parameter is omitted, the default resource
|
||||
is used.
|
||||
*/
|
||||
explicit
|
||||
monotonic_resource(
|
||||
std::size_t initial_size = 1024,
|
||||
storage_ptr upstream = {}) noexcept;
|
||||
|
||||
/** Constructor
|
||||
|
||||
This constructs the resource and indicates that
|
||||
subsequent allocations should use the specified
|
||||
caller-owned buffer.
|
||||
When this buffer is exhausted, dynamic allocations
|
||||
from the upstream resource are made.
|
||||
\n
|
||||
This constructor is guaranteed not to perform
|
||||
any dynamic allocations.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param buffer The buffer to use.
|
||||
Ownership is not transferred; the caller is
|
||||
responsible for ensuring that the lifetime of
|
||||
the buffer extends until the resource is destroyed.
|
||||
|
||||
@param size The number of valid bytes pointed
|
||||
to by `buffer`.
|
||||
|
||||
@param upstream An optional upstream memory resource
|
||||
to use for performing internal dynamic allocations.
|
||||
If this parameter is omitted, the default resource
|
||||
is used.
|
||||
*/
|
||||
/** @{ */
|
||||
monotonic_resource(
|
||||
unsigned char* buffer,
|
||||
std::size_t size,
|
||||
storage_ptr upstream = {}) noexcept;
|
||||
|
||||
#if defined(__cpp_lib_byte) || defined(BOOST_JSON_DOCS)
|
||||
monotonic_resource(
|
||||
std::byte* buffer,
|
||||
std::size_t size,
|
||||
storage_ptr upstream) noexcept
|
||||
: monotonic_resource(reinterpret_cast<
|
||||
unsigned char*>(buffer), size,
|
||||
std::move(upstream))
|
||||
{
|
||||
}
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/** Constructor
|
||||
|
||||
This constructs the resource and indicates that
|
||||
subsequent allocations should use the specified
|
||||
caller-owned buffer.
|
||||
When this buffer is exhausted, dynamic allocations
|
||||
from the upstream resource are made.
|
||||
\n
|
||||
This constructor is guaranteed not to perform
|
||||
any dynamic allocations.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param buffer The buffer to use.
|
||||
Ownership is not transferred; the caller is
|
||||
responsible for ensuring that the lifetime of
|
||||
the buffer extends until the resource is destroyed.
|
||||
|
||||
@param upstream An optional upstream memory resource
|
||||
to use for performing internal dynamic allocations.
|
||||
If this parameter is omitted, the default resource
|
||||
is used.
|
||||
*/
|
||||
/** @{ */
|
||||
template<std::size_t N>
|
||||
explicit
|
||||
monotonic_resource(
|
||||
unsigned char(&buffer)[N],
|
||||
storage_ptr upstream = {}) noexcept
|
||||
: monotonic_resource(&buffer[0],
|
||||
N, std::move(upstream))
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(__cpp_lib_byte) || defined(BOOST_JSON_DOCS)
|
||||
template<std::size_t N>
|
||||
explicit
|
||||
monotonic_resource(
|
||||
std::byte(&buffer)[N],
|
||||
storage_ptr upstream = {}) noexcept
|
||||
: monotonic_resource(&buffer[0],
|
||||
N, std::move(upstream))
|
||||
{
|
||||
}
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
#ifndef BOOST_JSON_DOCS
|
||||
// Safety net for accidental buffer overflows
|
||||
template<std::size_t N>
|
||||
monotonic_resource(
|
||||
unsigned char(&buffer)[N],
|
||||
std::size_t n,
|
||||
storage_ptr upstream = {}) noexcept
|
||||
: monotonic_resource(&buffer[0],
|
||||
n, std::move(upstream))
|
||||
{
|
||||
// If this goes off, check your parameters
|
||||
// closely, chances are you passed an array
|
||||
// thinking it was a pointer.
|
||||
BOOST_ASSERT(n <= N);
|
||||
}
|
||||
|
||||
#ifdef __cpp_lib_byte
|
||||
// Safety net for accidental buffer overflows
|
||||
template<std::size_t N>
|
||||
monotonic_resource(
|
||||
std::byte(&buffer)[N],
|
||||
std::size_t n,
|
||||
storage_ptr upstream = {}) noexcept
|
||||
: monotonic_resource(&buffer[0],
|
||||
n, std::move(upstream))
|
||||
{
|
||||
// If this goes off, check your parameters
|
||||
// closely, chances are you passed an array
|
||||
// thinking it was a pointer.
|
||||
BOOST_ASSERT(n <= N);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** Release all allocated memory.
|
||||
|
||||
This function deallocates all allocated memory.
|
||||
If an initial buffer was provided upon construction,
|
||||
then all of the bytes will be available again for
|
||||
allocation. Allocated memory is deallocated even
|
||||
if deallocate has not been called for some of
|
||||
the allocated blocks.
|
||||
|
||||
@par Complexity
|
||||
Linear in the number of deallocations performed.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
void
|
||||
release() noexcept;
|
||||
|
||||
protected:
|
||||
#ifndef BOOST_JSON_DOCS
|
||||
void*
|
||||
do_allocate(
|
||||
std::size_t n,
|
||||
std::size_t align) override;
|
||||
|
||||
void
|
||||
do_deallocate(
|
||||
void* p,
|
||||
std::size_t n,
|
||||
std::size_t align) override;
|
||||
|
||||
bool
|
||||
do_is_equal(
|
||||
memory_resource const& mr) const noexcept override;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
template<>
|
||||
struct is_deallocate_trivial<
|
||||
monotonic_resource>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
35
install/boost_1_75_0/include/boost/json/null_resource.hpp
Normal file
35
install/boost_1_75_0/include/boost/json/null_resource.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// Copyright (c) 2020 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_NULL_RESOURCE_HPP
|
||||
#define BOOST_JSON_NULL_RESOURCE_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/memory_resource.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
/** Return a pointer to the null resource.
|
||||
|
||||
This memory resource always throws the exception
|
||||
`std::bad_alloc` in calls to `allocate`.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
memory_resource*
|
||||
get_null_resource() noexcept;
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
1568
install/boost_1_75_0/include/boost/json/object.hpp
Normal file
1568
install/boost_1_75_0/include/boost/json/object.hpp
Normal file
File diff suppressed because it is too large
Load Diff
106
install/boost_1_75_0/include/boost/json/parse.hpp
Normal file
106
install/boost_1_75_0/include/boost/json/parse.hpp
Normal file
@@ -0,0 +1,106 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
|
||||
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_PARSE_HPP
|
||||
#define BOOST_JSON_PARSE_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/error.hpp>
|
||||
#include <boost/json/parse_options.hpp>
|
||||
#include <boost/json/storage_ptr.hpp>
|
||||
#include <boost/json/string_view.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
/** Return parsed JSON as a @ref value.
|
||||
|
||||
This function parses an entire string in one
|
||||
step to produce a complete JSON object, returned
|
||||
as a @ref value. If the buffer does not contain a
|
||||
complete serialized JSON, an error occurs. In this
|
||||
case the returned value will be null, using the
|
||||
default memory resource.
|
||||
|
||||
@par Complexity
|
||||
Linear in `s.size()`.
|
||||
|
||||
@par Exception Safety
|
||||
Strong guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
|
||||
@return A value representing the parsed JSON,
|
||||
or a null if any error occurred.
|
||||
|
||||
@param s The string to parse.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
|
||||
@param sp The memory resource that the new value and all
|
||||
of its elements will use. If this parameter is omitted,
|
||||
the default memory resource is used.
|
||||
|
||||
@param opt The options for the parser. If this parameter
|
||||
is omitted, the parser will accept only standard JSON.
|
||||
|
||||
@see
|
||||
@ref parse_options,
|
||||
@ref stream_parser.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
value
|
||||
parse(
|
||||
string_view s,
|
||||
error_code& ec,
|
||||
storage_ptr sp = {},
|
||||
parse_options const& opt = {});
|
||||
|
||||
/** Parse a string of JSON into a @ref value.
|
||||
|
||||
This function parses an entire string in one
|
||||
step to produce a complete JSON object, returned
|
||||
as a @ref value. If the buffer does not contain a
|
||||
complete serialized JSON, an exception is thrown.
|
||||
|
||||
@par Complexity
|
||||
Linear in `s.size()`.
|
||||
|
||||
@par Exception Safety
|
||||
Strong guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
|
||||
@return A value representing the parsed
|
||||
JSON upon success.
|
||||
|
||||
@param s The string to parse.
|
||||
|
||||
@param sp The memory resource that the new value and all
|
||||
of its elements will use. If this parameter is omitted,
|
||||
the default memory resource is used.
|
||||
|
||||
@param opt The options for the parser. If this parameter
|
||||
is omitted, the parser will accept only standard JSON.
|
||||
|
||||
@throw system_error Thrown on failure.
|
||||
|
||||
@see
|
||||
@ref parse_options,
|
||||
@ref stream_parser.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
value
|
||||
parse(
|
||||
string_view s,
|
||||
storage_ptr sp = {},
|
||||
parse_options const& opt = {});
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
83
install/boost_1_75_0/include/boost/json/parse_options.hpp
Normal file
83
install/boost_1_75_0/include/boost/json/parse_options.hpp
Normal file
@@ -0,0 +1,83 @@
|
||||
//
|
||||
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_PARSE_OPTIONS_HPP
|
||||
#define BOOST_JSON_PARSE_OPTIONS_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
/** Parser options
|
||||
|
||||
This structure is used for specifying
|
||||
maximum parsing depth, and whether
|
||||
to allow various non-standard extensions.
|
||||
Default-constructed options set maximum
|
||||
parsing depth to 32 and specify that only
|
||||
standard JSON is allowed,
|
||||
|
||||
@see
|
||||
@ref basic_parser,
|
||||
@ref parser.
|
||||
*/
|
||||
struct parse_options
|
||||
{
|
||||
/** Maximum nesting level of arrays and objects.
|
||||
|
||||
This specifies the maximum number of nested
|
||||
structures allowed while parsing a JSON. If
|
||||
this limit is exceeded during a parse, an
|
||||
error is returned.
|
||||
|
||||
@see
|
||||
@ref basic_parser,
|
||||
@ref stream_parser.
|
||||
*/
|
||||
std::size_t max_depth = 32;
|
||||
|
||||
/** Non-standard extension option
|
||||
|
||||
Allow C and C++ style comments to appear
|
||||
anywhere that whitespace is permissible.
|
||||
|
||||
@see
|
||||
@ref basic_parser,
|
||||
@ref stream_parser.
|
||||
*/
|
||||
bool allow_comments = false;
|
||||
|
||||
/** Non-standard extension option
|
||||
|
||||
Allow a trailing comma to appear after
|
||||
the last element of any array or object.
|
||||
|
||||
@see
|
||||
@ref basic_parser,
|
||||
@ref stream_parser.
|
||||
*/
|
||||
bool allow_trailing_commas = false;
|
||||
|
||||
/** Non-standard extension option
|
||||
|
||||
Allow invalid UTF-8 sequnces to appear
|
||||
in keys and strings.
|
||||
|
||||
@note This increases parsing performance.
|
||||
|
||||
@see
|
||||
@ref basic_parser,
|
||||
@ref stream_parser.
|
||||
*/
|
||||
bool allow_invalid_utf8 = false;
|
||||
};
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
787
install/boost_1_75_0/include/boost/json/parser.hpp
Normal file
787
install/boost_1_75_0/include/boost/json/parser.hpp
Normal file
@@ -0,0 +1,787 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_PARSER_HPP
|
||||
#define BOOST_JSON_PARSER_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/basic_parser.hpp>
|
||||
#include <boost/json/storage_ptr.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/json/detail/handler.hpp>
|
||||
#include <type_traits>
|
||||
#include <cstddef>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
/** A DOM parser for JSON contained in a single buffer.
|
||||
|
||||
This class is used to parse a JSON contained in a
|
||||
single character buffer, into a @ref value container.
|
||||
|
||||
@par Usage
|
||||
|
||||
To use the parser first construct it, then optionally
|
||||
call @ref reset to specify a @ref storage_ptr to use
|
||||
for the resulting @ref value. Then call @ref write
|
||||
to parse a character buffer containing a complete
|
||||
JSON. If the parse is successful, call @ref release
|
||||
to take ownership of the value:
|
||||
@code
|
||||
parser p; // construct a parser
|
||||
size_t n = p.write( "[1,2,3]" ); // parse a complete JSON
|
||||
assert( n == 7 ); // all characters consumed
|
||||
value jv = p.release(); // take ownership of the value
|
||||
@endcode
|
||||
|
||||
@par Extra Data
|
||||
|
||||
When the character buffer provided as input contains
|
||||
additional data that is not part of the complete
|
||||
JSON, an error is returned. The @ref write_some
|
||||
function is an alternative which allows the parse
|
||||
to finish early, without consuming all the characters
|
||||
in the buffer. This allows parsing of a buffer
|
||||
containing multiple individual JSONs or containing
|
||||
different protocol data:
|
||||
@code
|
||||
parser p; // construct a parser
|
||||
size_t n = p.write_some( "[1,2,3] null" ); // parse a complete JSON
|
||||
assert( n == 8 ); // only some characters consumed
|
||||
value jv = p.release(); // take ownership of the value
|
||||
@endcode
|
||||
|
||||
@par Temporary Storage
|
||||
|
||||
The parser may dynamically allocate temporary
|
||||
storage as needed to accommodate the nesting level
|
||||
of the JSON being parsed. Temporary storage is
|
||||
first obtained from an optional, caller-owned
|
||||
buffer specified upon construction. When that
|
||||
is exhausted, the next allocation uses the
|
||||
@ref memory_resource passed to the constructor; if
|
||||
no such argument is specified, the default memory
|
||||
resource is used. Temporary storage is freed only
|
||||
when the parser is destroyed; The performance of
|
||||
parsing multiple JSONs may be improved by reusing
|
||||
the same parser instance.
|
||||
\n
|
||||
It is important to note that the @ref memory_resource
|
||||
supplied upon construction is used for temporary
|
||||
storage only, and not for allocating the elements
|
||||
which make up the parsed value. That other memory
|
||||
resource is optionally supplied in each call
|
||||
to @ref reset.
|
||||
|
||||
@par Duplicate Keys
|
||||
|
||||
If there are object elements with duplicate keys;
|
||||
that is, if multiple elements in an object have
|
||||
keys that compare equal, only the last equivalent
|
||||
element will be inserted.
|
||||
|
||||
@par Non-Standard JSON
|
||||
|
||||
The @ref parse_options structure optionally
|
||||
provided upon construction is used to customize
|
||||
some parameters of the parser, including which
|
||||
non-standard JSON extensions should be allowed.
|
||||
A default-constructed parse options allows only
|
||||
standard JSON.
|
||||
|
||||
@par Thread Safety
|
||||
|
||||
Distinct instances may be accessed concurrently.
|
||||
Non-const member functions of a shared instance
|
||||
may not be called concurrently with any other
|
||||
member functions of that instance.
|
||||
|
||||
@see
|
||||
@ref parse,
|
||||
@ref parse_options,
|
||||
@ref stream_parser.
|
||||
*/
|
||||
class parser
|
||||
{
|
||||
basic_parser<detail::handler> p_;
|
||||
|
||||
public:
|
||||
/// Copy constructor (deleted)
|
||||
parser(
|
||||
parser const&) = delete;
|
||||
|
||||
/// Copy assignment (deleted)
|
||||
parser& operator=(
|
||||
parser const&) = delete;
|
||||
|
||||
/** Destructor.
|
||||
|
||||
All dynamically allocated memory, including
|
||||
any incomplete parsing results, is freed.
|
||||
|
||||
@par Complexity
|
||||
Linear in the size of partial results
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
~parser() = default;
|
||||
|
||||
/** Constructor.
|
||||
|
||||
This constructs a new parser which first uses
|
||||
the caller-owned storage pointed to by `buffer`
|
||||
for temporary storage, falling back to the memory
|
||||
resource `sp` if needed. The parser will use the
|
||||
specified parsing options.
|
||||
\n
|
||||
The parsed value will use the default memory
|
||||
resource for storage. To use a different resource,
|
||||
call @ref reset after construction.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param sp The memory resource to use for
|
||||
temporary storage after `buffer` is exhausted.
|
||||
|
||||
@param opt The parsing options to use.
|
||||
|
||||
@param buffer A pointer to valid memory of at least
|
||||
`size` bytes for the parser to use for temporary storage.
|
||||
Ownership is not transferred, the caller is responsible
|
||||
for ensuring the lifetime of the memory pointed to by
|
||||
`buffer` extends until the parser is destroyed.
|
||||
|
||||
@param size The number of valid bytes in `buffer`.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
parser(
|
||||
storage_ptr sp,
|
||||
parse_options const& opt,
|
||||
unsigned char* buffer,
|
||||
std::size_t size) noexcept;
|
||||
|
||||
/** Constructor.
|
||||
|
||||
This constructs a new parser which uses the default
|
||||
memory resource for temporary storage, and accepts
|
||||
only strict JSON.
|
||||
\n
|
||||
The parsed value will use the default memory
|
||||
resource for storage. To use a different resource,
|
||||
call @ref reset after construction.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
parser() noexcept
|
||||
: parser({}, {})
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor.
|
||||
|
||||
This constructs a new parser which uses the
|
||||
specified memory resource for temporary storage,
|
||||
and is configured to use the specified parsing
|
||||
options.
|
||||
\n
|
||||
The parsed value will use the default memory
|
||||
resource for storage. To use a different resource,
|
||||
call @ref reset after construction.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param sp The memory resource to use for temporary storage.
|
||||
|
||||
@param opt The parsing options to use.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
parser(
|
||||
storage_ptr sp,
|
||||
parse_options const& opt) noexcept;
|
||||
|
||||
/** Constructor.
|
||||
|
||||
This constructs a new parser which uses the
|
||||
specified memory resource for temporary storage,
|
||||
and accepts only strict JSON.
|
||||
\n
|
||||
The parsed value will use the default memory
|
||||
resource for storage. To use a different resource,
|
||||
call @ref reset after construction.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param sp The memory resource to use for temporary storage.
|
||||
*/
|
||||
explicit
|
||||
parser(storage_ptr sp) noexcept
|
||||
: parser(std::move(sp), {})
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor.
|
||||
|
||||
This constructs a new parser which first uses the
|
||||
caller-owned storage `buffer` for temporary storage,
|
||||
falling back to the memory resource `sp` if needed.
|
||||
The parser will use the specified parsing options.
|
||||
\n
|
||||
The parsed value will use the default memory
|
||||
resource for storage. To use a different resource,
|
||||
call @ref reset after construction.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param sp The memory resource to use for
|
||||
temporary storage after `buffer` is exhausted.
|
||||
|
||||
@param opt The parsing options to use.
|
||||
|
||||
@param buffer A buffer for the parser to use for
|
||||
temporary storage. Ownership is not transferred,
|
||||
the caller is responsible for ensuring the lifetime
|
||||
of `buffer` extends until the parser is destroyed.
|
||||
*/
|
||||
template<std::size_t N>
|
||||
parser(
|
||||
storage_ptr sp,
|
||||
parse_options const& opt,
|
||||
unsigned char(&buffer)[N]) noexcept
|
||||
: parser(std::move(sp),
|
||||
opt, &buffer[0], N)
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(__cpp_lib_byte) || defined(BOOST_JSON_DOCS)
|
||||
/** Constructor.
|
||||
|
||||
This constructs a new parser which first uses
|
||||
the caller-owned storage pointed to by `buffer`
|
||||
for temporary storage, falling back to the memory
|
||||
resource `sp` if needed. The parser will use the
|
||||
specified parsing options.
|
||||
\n
|
||||
The parsed value will use the default memory
|
||||
resource for storage. To use a different resource,
|
||||
call @ref reset after construction.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param sp The memory resource to use for
|
||||
temporary storage after `buffer` is exhausted.
|
||||
|
||||
@param opt The parsing options to use.
|
||||
|
||||
@param buffer A pointer to valid memory of at least
|
||||
`size` bytes for the parser to use for temporary storage.
|
||||
Ownership is not transferred, the caller is responsible
|
||||
for ensuring the lifetime of the memory pointed to by
|
||||
`buffer` extends until the parser is destroyed.
|
||||
|
||||
@param size The number of valid bytes in `buffer`.
|
||||
*/
|
||||
parser(
|
||||
storage_ptr sp,
|
||||
parse_options const& opt,
|
||||
std::byte* buffer,
|
||||
std::size_t size) noexcept
|
||||
: parser(sp, opt, reinterpret_cast<
|
||||
unsigned char*>(buffer), size)
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor.
|
||||
|
||||
This constructs a new parser which first uses the
|
||||
caller-owned storage `buffer` for temporary storage,
|
||||
falling back to the memory resource `sp` if needed.
|
||||
The parser will use the specified parsing options.
|
||||
\n
|
||||
The parsed value will use the default memory
|
||||
resource for storage. To use a different resource,
|
||||
call @ref reset after construction.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param sp The memory resource to use for
|
||||
temporary storage after `buffer` is exhausted.
|
||||
|
||||
@param opt The parsing options to use.
|
||||
|
||||
@param buffer A buffer for the parser to use for
|
||||
temporary storage. Ownership is not transferred,
|
||||
the caller is responsible for ensuring the lifetime
|
||||
of `buffer` extends until the parser is destroyed.
|
||||
*/
|
||||
template<std::size_t N>
|
||||
parser(
|
||||
storage_ptr sp,
|
||||
parse_options const& opt,
|
||||
std::byte(&buffer)[N]) noexcept
|
||||
: parser(std::move(sp),
|
||||
opt, &buffer[0], N)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_JSON_DOCS
|
||||
// Safety net for accidental buffer overflows
|
||||
template<std::size_t N>
|
||||
parser(
|
||||
storage_ptr sp,
|
||||
parse_options const& opt,
|
||||
unsigned char(&buffer)[N],
|
||||
std::size_t n) noexcept
|
||||
: parser(std::move(sp),
|
||||
opt, &buffer[0], n)
|
||||
{
|
||||
// If this goes off, check your parameters
|
||||
// closely, chances are you passed an array
|
||||
// thinking it was a pointer.
|
||||
BOOST_ASSERT(n <= N);
|
||||
}
|
||||
|
||||
#ifdef __cpp_lib_byte
|
||||
// Safety net for accidental buffer overflows
|
||||
template<std::size_t N>
|
||||
parser(
|
||||
storage_ptr sp,
|
||||
parse_options const& opt,
|
||||
std::byte(&buffer)[N], std::size_t n) noexcept
|
||||
: parser(std::move(sp),
|
||||
opt, &buffer[0], n)
|
||||
{
|
||||
// If this goes off, check your parameters
|
||||
// closely, chances are you passed an array
|
||||
// thinking it was a pointer.
|
||||
BOOST_ASSERT(n <= N);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** Reset the parser for a new JSON.
|
||||
|
||||
This function is used to reset the parser to
|
||||
prepare it for parsing a new complete JSON.
|
||||
Any previous partial results are destroyed.
|
||||
|
||||
@par Complexity
|
||||
Constant or linear in the size of any previous
|
||||
partial parsing results.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param sp A pointer to the @ref memory_resource
|
||||
to use for the resulting @ref value. The parser
|
||||
will acquire shared ownership.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
reset(storage_ptr sp = {}) noexcept;
|
||||
|
||||
/** Parse a buffer containing a complete JSON.
|
||||
|
||||
This function parses a complete JSON contained
|
||||
in the specified character buffer. Additional
|
||||
characters past the end of the complete JSON
|
||||
are ignored. The function returns the actual
|
||||
number of characters parsed, which may be less
|
||||
than the size of the input. This allows parsing
|
||||
of a buffer containing multiple individual JSONs
|
||||
or containing different protocol data:
|
||||
|
||||
@par Example
|
||||
@code
|
||||
parser p; // construct a parser
|
||||
size_t n = p.write_some( "[1,2,3] null" ); // parse a complete JSON
|
||||
assert( n == 8 ); // only some characters consumed
|
||||
value jv = p.release(); // take ownership of the value
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `size`.
|
||||
|
||||
@par Exception Safety
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
Upon error or exception, subsequent calls will
|
||||
fail until @ref reset is called to parse a new JSON.
|
||||
|
||||
@return The number of characters consumed from
|
||||
the buffer.
|
||||
|
||||
@param data A pointer to a buffer of `size`
|
||||
characters to parse.
|
||||
|
||||
@param size The number of characters pointed to
|
||||
by `data`.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
std::size_t
|
||||
write_some(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec);
|
||||
|
||||
/** Parse a buffer containing a complete JSON.
|
||||
|
||||
This function parses a complete JSON contained
|
||||
in the specified character buffer. Additional
|
||||
characters past the end of the complete JSON
|
||||
are ignored. The function returns the actual
|
||||
number of characters parsed, which may be less
|
||||
than the size of the input. This allows parsing
|
||||
of a buffer containing multiple individual JSONs
|
||||
or containing different protocol data:
|
||||
|
||||
@par Example
|
||||
@code
|
||||
parser p; // construct a parser
|
||||
size_t n = p.write_some( "[1,2,3] null" ); // parse a complete JSON
|
||||
assert( n == 8 ); // only some characters consumed
|
||||
value jv = p.release(); // take ownership of the value
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `size`.
|
||||
|
||||
@par Exception Safety
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
Upon error or exception, subsequent calls will
|
||||
fail until @ref reset is called to parse a new JSON.
|
||||
|
||||
@return The number of characters consumed from
|
||||
the buffer.
|
||||
|
||||
@param data A pointer to a buffer of `size`
|
||||
characters to parse.
|
||||
|
||||
@param size The number of characters pointed to
|
||||
by `data`.
|
||||
|
||||
@throw system_error Thrown on error.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
std::size_t
|
||||
write_some(
|
||||
char const* data,
|
||||
std::size_t size);
|
||||
|
||||
/** Parse a buffer containing a complete JSON.
|
||||
|
||||
This function parses a complete JSON contained
|
||||
in the specified character buffer. Additional
|
||||
characters past the end of the complete JSON
|
||||
are ignored. The function returns the actual
|
||||
number of characters parsed, which may be less
|
||||
than the size of the input. This allows parsing
|
||||
of a buffer containing multiple individual JSONs
|
||||
or containing different protocol data:
|
||||
|
||||
@par Example
|
||||
@code
|
||||
parser p; // construct a parser
|
||||
size_t n = p.write_some( "[1,2,3] null" ); // parse a complete JSON
|
||||
assert( n == 8 ); // only some characters consumed
|
||||
value jv = p.release(); // take ownership of the value
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `size`.
|
||||
|
||||
@par Exception Safety
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
Upon error or exception, subsequent calls will
|
||||
fail until @ref reset is called to parse a new JSON.
|
||||
|
||||
@return The number of characters consumed from
|
||||
the buffer.
|
||||
|
||||
@param s The character string to parse.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
std::size_t
|
||||
write_some(
|
||||
string_view s,
|
||||
error_code& ec)
|
||||
{
|
||||
return write_some(
|
||||
s.data(), s.size(), ec);
|
||||
}
|
||||
|
||||
/** Parse a buffer containing a complete JSON.
|
||||
|
||||
This function parses a complete JSON contained
|
||||
in the specified character buffer. Additional
|
||||
characters past the end of the complete JSON
|
||||
are ignored. The function returns the actual
|
||||
number of characters parsed, which may be less
|
||||
than the size of the input. This allows parsing
|
||||
of a buffer containing multiple individual JSONs
|
||||
or containing different protocol data:
|
||||
|
||||
@par Example
|
||||
@code
|
||||
parser p; // construct a parser
|
||||
size_t n = p.write_some( "[1,2,3] null" ); // parse a complete JSON
|
||||
assert( n == 8 ); // only some characters consumed
|
||||
value jv = p.release(); // take ownership of the value
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `size`.
|
||||
|
||||
@par Exception Safety
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
Upon error or exception, subsequent calls will
|
||||
fail until @ref reset is called to parse a new JSON.
|
||||
|
||||
@return The number of characters consumed from
|
||||
the buffer.
|
||||
|
||||
@param s The character string to parse.
|
||||
|
||||
@throw system_error Thrown on error.
|
||||
*/
|
||||
std::size_t
|
||||
write_some(
|
||||
string_view s)
|
||||
{
|
||||
return write_some(
|
||||
s.data(), s.size());
|
||||
}
|
||||
|
||||
/** Parse a buffer containing a complete JSON.
|
||||
|
||||
This function parses a complete JSON contained
|
||||
in the specified character buffer. The entire
|
||||
buffer must be consumed; if there are additional
|
||||
characters past the end of the complete JSON,
|
||||
the parse fails and an error is returned.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
parser p; // construct a parser
|
||||
size_t n = p.write( "[1,2,3]" ); // parse a complete JSON
|
||||
assert( n == 7 ); // all characters consumed
|
||||
value jv = p.release(); // take ownership of the value
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `size`.
|
||||
|
||||
@par Exception Safety
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
Upon error or exception, subsequent calls will
|
||||
fail until @ref reset is called to parse a new JSON.
|
||||
|
||||
@return The number of characters consumed from
|
||||
the buffer.
|
||||
|
||||
@param data A pointer to a buffer of `size`
|
||||
characters to parse.
|
||||
|
||||
@param size The number of characters pointed to
|
||||
by `data`.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
std::size_t
|
||||
write(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec);
|
||||
|
||||
/** Parse a buffer containing a complete JSON.
|
||||
|
||||
This function parses a complete JSON contained
|
||||
in the specified character buffer. The entire
|
||||
buffer must be consumed; if there are additional
|
||||
characters past the end of the complete JSON,
|
||||
the parse fails and an error is returned.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
parser p; // construct a parser
|
||||
size_t n = p.write( "[1,2,3]" ); // parse a complete JSON
|
||||
assert( n == 7 ); // all characters consumed
|
||||
value jv = p.release(); // take ownership of the value
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `size`.
|
||||
|
||||
@par Exception Safety
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
Upon error or exception, subsequent calls will
|
||||
fail until @ref reset is called to parse a new JSON.
|
||||
|
||||
@return The number of characters consumed from
|
||||
the buffer.
|
||||
|
||||
@param data A pointer to a buffer of `size`
|
||||
characters to parse.
|
||||
|
||||
@param size The number of characters pointed to
|
||||
by `data`.
|
||||
|
||||
@throw system_error Thrown on error.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
std::size_t
|
||||
write(
|
||||
char const* data,
|
||||
std::size_t size);
|
||||
|
||||
/** Parse a buffer containing a complete JSON.
|
||||
|
||||
This function parses a complete JSON contained
|
||||
in the specified character buffer. The entire
|
||||
buffer must be consumed; if there are additional
|
||||
characters past the end of the complete JSON,
|
||||
the parse fails and an error is returned.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
parser p; // construct a parser
|
||||
size_t n = p.write( "[1,2,3]" ); // parse a complete JSON
|
||||
assert( n == 7 ); // all characters consumed
|
||||
value jv = p.release(); // take ownership of the value
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `size`.
|
||||
|
||||
@par Exception Safety
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
Upon error or exception, subsequent calls will
|
||||
fail until @ref reset is called to parse a new JSON.
|
||||
|
||||
@return The number of characters consumed from
|
||||
the buffer.
|
||||
|
||||
@param s The character string to parse.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
std::size_t
|
||||
write(
|
||||
string_view s,
|
||||
error_code& ec)
|
||||
{
|
||||
return write(
|
||||
s.data(), s.size(), ec);
|
||||
}
|
||||
|
||||
/** Parse a buffer containing a complete JSON.
|
||||
|
||||
This function parses a complete JSON contained
|
||||
in the specified character buffer. The entire
|
||||
buffer must be consumed; if there are additional
|
||||
characters past the end of the complete JSON,
|
||||
the parse fails and an error is returned.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
parser p; // construct a parser
|
||||
size_t n = p.write( "[1,2,3]" ); // parse a complete JSON
|
||||
assert( n == 7 ); // all characters consumed
|
||||
value jv = p.release(); // take ownership of the value
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `size`.
|
||||
|
||||
@par Exception Safety
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
Upon error or exception, subsequent calls will
|
||||
fail until @ref reset is called to parse a new JSON.
|
||||
|
||||
@return The number of characters consumed from
|
||||
the buffer.
|
||||
|
||||
@param s The character string to parse.
|
||||
|
||||
@throw system_error Thrown on error.
|
||||
*/
|
||||
std::size_t
|
||||
write(
|
||||
string_view s)
|
||||
{
|
||||
return write(
|
||||
s.data(), s.size());
|
||||
}
|
||||
|
||||
/** Return the parsed JSON as a @ref value.
|
||||
|
||||
This returns the parsed value, or throws
|
||||
an exception if the parsing is incomplete or
|
||||
failed. It is necessary to call @ref reset
|
||||
after calling this function in order to parse
|
||||
another JSON.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@return The parsed value. Ownership of this
|
||||
value is transferred to the caller.
|
||||
|
||||
@throw system_error Thrown on failure.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
value
|
||||
release();
|
||||
};
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
217
install/boost_1_75_0/include/boost/json/pilfer.hpp
Normal file
217
install/boost_1_75_0/include/boost/json/pilfer.hpp
Normal file
@@ -0,0 +1,217 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_PILFER_HPP
|
||||
#define BOOST_JSON_PILFER_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
/*
|
||||
Implements "pilfering" from P0308R0
|
||||
|
||||
@see
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
namespace json {
|
||||
|
||||
/** Tag wrapper to specify pilfer-construction.
|
||||
|
||||
This wrapper is used to specify a pilfer constructor
|
||||
overload.
|
||||
|
||||
@par Example
|
||||
|
||||
A pilfer constructor accepts a single argument
|
||||
of type @ref pilfered and throws nothing:
|
||||
|
||||
@code
|
||||
struct T
|
||||
{
|
||||
T( pilfered<T> ) noexcept;
|
||||
};
|
||||
@endcode
|
||||
|
||||
@note
|
||||
|
||||
The constructor should not be marked explicit.
|
||||
|
||||
@see @ref pilfer, @ref is_pilfer_constructible,
|
||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html">
|
||||
Valueless Variants Considered Harmful</a>
|
||||
*/
|
||||
template<class T>
|
||||
class pilfered
|
||||
{
|
||||
T& t_;
|
||||
|
||||
public:
|
||||
/** Constructor
|
||||
|
||||
Construct the wrapper from `t`.
|
||||
|
||||
@param t The pilferable object. Ownership
|
||||
is not transferred.
|
||||
*/
|
||||
explicit
|
||||
constexpr
|
||||
pilfered(T&& t) noexcept
|
||||
: t_(t)
|
||||
{
|
||||
}
|
||||
|
||||
/** Return a reference to the pilferable object.
|
||||
|
||||
This returns a reference to the wrapped object.
|
||||
*/
|
||||
constexpr T&
|
||||
get() const noexcept
|
||||
{
|
||||
return t_;
|
||||
}
|
||||
|
||||
/** Return a pointer to the pilferable object.
|
||||
|
||||
This returns a pointer to the wrapped object.
|
||||
*/
|
||||
constexpr T*
|
||||
operator->() const noexcept
|
||||
{
|
||||
//return std::addressof(t_);
|
||||
return reinterpret_cast<T*>(
|
||||
const_cast<char *>(
|
||||
&reinterpret_cast<
|
||||
const volatile char &>(t_)));
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef BOOST_JSON_DOCS
|
||||
// VFALCO Renamed this to work around an msvc bug
|
||||
namespace detail_pilfer {
|
||||
template<class>
|
||||
struct not_pilfered
|
||||
{
|
||||
};
|
||||
} // detail_pilfer
|
||||
#endif
|
||||
|
||||
/** Metafunction returning `true` if `T` is <em>PilferConstructible</em>
|
||||
|
||||
If `T` can be pilfer constructed, this metafunction is
|
||||
equal to `std::true_type`. Otherwise it is equal to
|
||||
`std::false_type`.
|
||||
|
||||
@see @ref pilfer, @ref pilfered,
|
||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html">
|
||||
Valueless Variants Considered Harmful</a>
|
||||
*/
|
||||
template<class T>
|
||||
struct is_pilfer_constructible
|
||||
#ifndef BOOST_JSON_DOCS
|
||||
: std::integral_constant<bool,
|
||||
std::is_nothrow_move_constructible<T>::value ||
|
||||
(
|
||||
std::is_nothrow_constructible<
|
||||
T, pilfered<T> >::value &&
|
||||
! std::is_nothrow_constructible<
|
||||
T, detail_pilfer::not_pilfered<T> >::value
|
||||
)>
|
||||
#endif
|
||||
{
|
||||
};
|
||||
|
||||
/** Indicate that an object `t` may be pilfered from.
|
||||
|
||||
A <em>pilfer</em> operation is the construction
|
||||
of a new object of type `T` from an existing
|
||||
object `t`. After the construction, the only
|
||||
valid operation on the pilfered-from object is
|
||||
destruction. This permits optimizations beyond
|
||||
those available for a move-construction, as the
|
||||
pilfered-from object is not required to be in
|
||||
a "usable" state.
|
||||
\n
|
||||
This is used similarly to `std::move`.
|
||||
|
||||
@par Example
|
||||
|
||||
A pilfer constructor accepts a single argument
|
||||
of type @ref pilfered and throws nothing:
|
||||
|
||||
@code
|
||||
struct T
|
||||
{
|
||||
T( pilfered<T> ) noexcept;
|
||||
};
|
||||
@endcode
|
||||
|
||||
Pilfer construction is performed using @ref pilfer :
|
||||
|
||||
@code
|
||||
{
|
||||
T t1; // default construction
|
||||
T t2( pilfer( t1 ) ); // pilfer-construct from t1
|
||||
|
||||
// At this point, t1 may only be destroyed
|
||||
}
|
||||
@endcode
|
||||
|
||||
@see @ref pilfered, @ref is_pilfer_constructible,
|
||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html">
|
||||
Valueless Variants Considered Harmful</a>
|
||||
*/
|
||||
template<class T>
|
||||
auto
|
||||
pilfer(T&& t) noexcept ->
|
||||
typename std::conditional<
|
||||
std::is_nothrow_constructible<
|
||||
typename std::remove_reference<T>::type,
|
||||
pilfered<typename
|
||||
std::remove_reference<T>::type> >::value &&
|
||||
! std::is_nothrow_constructible<
|
||||
typename std::remove_reference<T>::type,
|
||||
detail_pilfer::not_pilfered<typename
|
||||
std::remove_reference<T>::type> >::value,
|
||||
pilfered<typename std::remove_reference<T>::type>,
|
||||
typename std::remove_reference<T>::type&&
|
||||
>::type
|
||||
{
|
||||
using U =
|
||||
typename std::remove_reference<T>::type;
|
||||
static_assert(
|
||||
is_pilfer_constructible<U>::value, "");
|
||||
return typename std::conditional<
|
||||
std::is_nothrow_constructible<
|
||||
U, pilfered<U> >::value &&
|
||||
! std::is_nothrow_constructible<
|
||||
U, detail_pilfer::not_pilfered<U> >::value,
|
||||
pilfered<U>, U&&
|
||||
>::type(std::move(t));
|
||||
}
|
||||
|
||||
/*
|
||||
template<class T>
|
||||
void
|
||||
relocate(T* dest, T& src) noexcept
|
||||
{
|
||||
static_assert(
|
||||
is_pilfer_constructible<T>::value, "");
|
||||
::new(dest) T(pilfer(src));
|
||||
src.~T();
|
||||
}
|
||||
*/
|
||||
|
||||
} // json
|
||||
} // boost
|
||||
|
||||
|
||||
#endif
|
||||
104
install/boost_1_75_0/include/boost/json/serialize.hpp
Normal file
104
install/boost_1_75_0/include/boost/json/serialize.hpp
Normal file
@@ -0,0 +1,104 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_SERIALIZE_HPP
|
||||
#define BOOST_JSON_SERIALIZE_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
/** Return a string representing a serialized element.
|
||||
|
||||
This function serializes `t` as JSON and returns
|
||||
it as a `std::string`.
|
||||
|
||||
@par Complexity
|
||||
Constant or linear in the size of `t`.
|
||||
|
||||
@par Exception Safety
|
||||
Strong guarantee.
|
||||
Calls to allocate may throw.
|
||||
|
||||
@return The serialized string
|
||||
|
||||
@param t The value to serialize
|
||||
*/
|
||||
/** @{ */
|
||||
BOOST_JSON_DECL
|
||||
std::string
|
||||
serialize(value const& t);
|
||||
|
||||
BOOST_JSON_DECL
|
||||
std::string
|
||||
serialize(array const& t);
|
||||
|
||||
BOOST_JSON_DECL
|
||||
std::string
|
||||
serialize(object const& t);
|
||||
|
||||
BOOST_JSON_DECL
|
||||
std::string
|
||||
serialize(string const& t);
|
||||
|
||||
BOOST_JSON_DECL
|
||||
std::string
|
||||
serialize(string_view t);
|
||||
/** @} */
|
||||
|
||||
/** 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
|
||||
286
install/boost_1_75_0/include/boost/json/serializer.hpp
Normal file
286
install/boost_1_75_0/include/boost/json/serializer.hpp
Normal file
@@ -0,0 +1,286 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_SERIALIZER_HPP
|
||||
#define BOOST_JSON_SERIALIZER_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/json/detail/format.hpp>
|
||||
#include <boost/json/detail/stack.hpp>
|
||||
#include <boost/json/detail/stream.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
/** A serializer for JSON.
|
||||
|
||||
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
|
||||
|
||||
This demonstrates how the serializer may
|
||||
be used to print a JSON value to an output
|
||||
stream.
|
||||
|
||||
@code
|
||||
|
||||
void print( std::ostream& os, value const& jv)
|
||||
{
|
||||
serializer sr;
|
||||
sr.reset( &jv );
|
||||
while( ! sr.done() )
|
||||
{
|
||||
char buf[ 4000 ];
|
||||
os << sr.read( buf );
|
||||
}
|
||||
}
|
||||
|
||||
@endcode
|
||||
|
||||
@par Thread Safety
|
||||
|
||||
The same instance may not be accessed concurrently.
|
||||
*/
|
||||
class serializer
|
||||
{
|
||||
enum class state : char;
|
||||
// VFALCO Too many streams
|
||||
using stream = detail::stream;
|
||||
using const_stream = detail::const_stream;
|
||||
using local_stream = detail::local_stream;
|
||||
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_;
|
||||
char buf_[detail::max_number_chars + 1];
|
||||
bool done_ = false;
|
||||
|
||||
inline bool suspend(state st);
|
||||
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:
|
||||
/// Move constructor (deleted)
|
||||
serializer(serializer&&) = delete;
|
||||
|
||||
/** Destructor
|
||||
|
||||
All temporary storage is deallocated.
|
||||
|
||||
@par Complexity
|
||||
Constant
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
~serializer() noexcept;
|
||||
|
||||
/** Default 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.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
serializer() noexcept;
|
||||
|
||||
/** Returns `true` if the serialization is complete
|
||||
|
||||
This function returns `true` when all of the
|
||||
characters in the serialized representation of
|
||||
the value have been read.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
bool
|
||||
done() const noexcept
|
||||
{
|
||||
return done_;
|
||||
}
|
||||
|
||||
/** Reset the serializer for a new element
|
||||
|
||||
This function prepares the serializer to emit
|
||||
a new serialized JSON representing `*p`.
|
||||
Any internally allocated memory is
|
||||
preserved and re-used for the new output.
|
||||
|
||||
@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(string_view sv) noexcept;
|
||||
|
||||
/** Read the next buffer of serialized JSON
|
||||
|
||||
This function attempts to fill the caller
|
||||
provided buffer starting at `dest` with
|
||||
up to `size` characters of the serialized
|
||||
JSON that represents the value. If the
|
||||
buffer is not large enough, multiple calls
|
||||
may be required.
|
||||
\n
|
||||
If serialization completes during this call;
|
||||
that is, that all of the characters belonging
|
||||
to the serialized value have been written to
|
||||
caller-provided buffers, the function
|
||||
@ref done will return `true`.
|
||||
|
||||
@par Preconditions
|
||||
`this->done() == true`
|
||||
|
||||
@par Complexity
|
||||
Linear in `size`.
|
||||
|
||||
@par Exception Safety
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
|
||||
@return A @ref string_view containing the
|
||||
characters written, which may be less than
|
||||
`size`.
|
||||
|
||||
@param dest A pointer to valid memory of at
|
||||
least `size` bytes.
|
||||
|
||||
@param size The maximum number of characters
|
||||
to write to the memory pointed to by `dest`.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
string_view
|
||||
read(char* dest, std::size_t size);
|
||||
|
||||
/** Read the next buffer of serialized JSON
|
||||
|
||||
This function allows reading into a
|
||||
character array, with a deduced maximum size.
|
||||
|
||||
@par Preconditions
|
||||
`this->done() == true`
|
||||
|
||||
@par Effects
|
||||
@code
|
||||
return this->read( dest, N );
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Linear in `N`.
|
||||
|
||||
@par Exception Safety
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
|
||||
@return A @ref string_view containing the
|
||||
characters written, which may be less than
|
||||
`size`.
|
||||
|
||||
@param dest The character array to write to.
|
||||
*/
|
||||
template<std::size_t N>
|
||||
string_view
|
||||
read(char(&dest)[N])
|
||||
{
|
||||
return read(dest, N);
|
||||
}
|
||||
|
||||
#ifndef BOOST_JSON_DOCS
|
||||
// Safety net for accidental buffer overflows
|
||||
template<std::size_t N>
|
||||
string_view
|
||||
read(char(&dest)[N], std::size_t n)
|
||||
{
|
||||
// If this goes off, check your parameters
|
||||
// closely, chances are you passed an array
|
||||
// thinking it was a pointer.
|
||||
BOOST_ASSERT(n <= N);
|
||||
return read(dest, n);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
58
install/boost_1_75_0/include/boost/json/src.hpp
Normal file
58
install/boost_1_75_0/include/boost/json/src.hpp
Normal file
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_SRC_HPP
|
||||
#define BOOST_JSON_SRC_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is meant to be included once,
|
||||
in a translation unit of the program.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef BOOST_JSON_SOURCE
|
||||
#define BOOST_JSON_SOURCE
|
||||
#endif
|
||||
|
||||
// We include this in case someone is using
|
||||
// src.hpp as their main JSON header file
|
||||
// https://github.com/boostorg/json/issues/223#issuecomment-689264149
|
||||
#include <boost/json.hpp>
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
|
||||
#include <boost/json/impl/array.ipp>
|
||||
#include <boost/json/impl/error.ipp>
|
||||
#include <boost/json/impl/kind.ipp>
|
||||
#include <boost/json/impl/monotonic_resource.ipp>
|
||||
#include <boost/json/impl/null_resource.ipp>
|
||||
#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/stream_parser.ipp>
|
||||
#include <boost/json/impl/string.ipp>
|
||||
#include <boost/json/impl/value.ipp>
|
||||
#include <boost/json/impl/value_stack.ipp>
|
||||
#include <boost/json/impl/value_ref.ipp>
|
||||
|
||||
#include <boost/json/detail/impl/shared_resource.ipp>
|
||||
#include <boost/json/detail/impl/default_resource.ipp>
|
||||
#include <boost/json/detail/impl/except.ipp>
|
||||
#include <boost/json/detail/impl/format.ipp>
|
||||
#include <boost/json/detail/impl/handler.ipp>
|
||||
#include <boost/json/detail/impl/stack.ipp>
|
||||
#include <boost/json/detail/impl/string_impl.ipp>
|
||||
|
||||
#include <boost/json/detail/ryu/impl/d2s.ipp>
|
||||
|
||||
#endif
|
||||
243
install/boost_1_75_0/include/boost/json/static_resource.hpp
Normal file
243
install/boost_1_75_0/include/boost/json/static_resource.hpp
Normal file
@@ -0,0 +1,243 @@
|
||||
//
|
||||
// Copyright (c) 2020 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_STATIC_RESOURCE_HPP
|
||||
#define BOOST_JSON_STATIC_RESOURCE_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/memory_resource.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4275) // non dll-interface class used as base for dll-interface class
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
/** A resource using a caller-owned buffer, with a trivial deallocate
|
||||
|
||||
This memory resource is a special-purpose resource
|
||||
that releases allocated memory only when the resource
|
||||
is destroyed (or when @ref release is called).
|
||||
It has a trivial deallocate function; that is, the
|
||||
metafunction @ref is_deallocate_trivial returns `true`.
|
||||
\n
|
||||
The resource is constructed from a caller-owned buffer
|
||||
from which subsequent calls to allocate are apportioned.
|
||||
When a memory request cannot be satisfied from the
|
||||
free bytes remaining in the buffer, the allocation
|
||||
request fails with the exception `std::bad_alloc`.
|
||||
\n
|
||||
@par Example
|
||||
|
||||
This parses a JSON into a value which uses a local
|
||||
stack buffer, then prints the result.
|
||||
|
||||
@code
|
||||
|
||||
unsigned char buf[ 4000 ];
|
||||
static_resource mr( buf );
|
||||
|
||||
// Parse the string, using our memory resource
|
||||
value const jv = parse( "[1,2,3]", &mr );
|
||||
|
||||
// Print the JSON
|
||||
std::cout << jv;
|
||||
|
||||
@endcode
|
||||
|
||||
@par Thread Safety
|
||||
Members of the same instance may not be
|
||||
called concurrently.
|
||||
|
||||
@see
|
||||
https://en.wikipedia.org/wiki/Region-based_memory_management
|
||||
*/
|
||||
class BOOST_JSON_CLASS_DECL
|
||||
static_resource final
|
||||
: public memory_resource
|
||||
{
|
||||
void* p_;
|
||||
std::size_t n_;
|
||||
std::size_t size_;
|
||||
|
||||
public:
|
||||
/// Copy constructor (deleted)
|
||||
static_resource(
|
||||
static_resource const&) = delete;
|
||||
|
||||
/// Copy assignment (deleted)
|
||||
static_resource& operator=(
|
||||
static_resource const&) = delete;
|
||||
|
||||
/** Destructor
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
~static_resource() noexcept;
|
||||
|
||||
/** Constructor
|
||||
|
||||
This constructs the resource to use the specified
|
||||
buffer for subsequent calls to allocate. When the
|
||||
buffer is exhausted, allocate will throw
|
||||
`std::bad_alloc`.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param buffer The buffer to use.
|
||||
Ownership is not transferred; the caller is
|
||||
responsible for ensuring that the lifetime of
|
||||
the buffer extends until the resource is destroyed.
|
||||
|
||||
@param size The number of valid bytes pointed
|
||||
to by `buffer`.
|
||||
*/
|
||||
/** @{ */
|
||||
static_resource(
|
||||
unsigned char* buffer,
|
||||
std::size_t size) noexcept;
|
||||
|
||||
#if defined(__cpp_lib_byte) || defined(BOOST_JSON_DOCS)
|
||||
static_resource(
|
||||
std::byte* buffer,
|
||||
std::size_t size) noexcept
|
||||
: static_resource(reinterpret_cast<
|
||||
unsigned char*>(buffer), size)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/** Constructor
|
||||
|
||||
This constructs the resource to use the specified
|
||||
buffer for subsequent calls to allocate. When the
|
||||
buffer is exhausted, allocate will throw
|
||||
`std::bad_alloc`.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param buffer The buffer to use.
|
||||
Ownership is not transferred; the caller is
|
||||
responsible for ensuring that the lifetime of
|
||||
the buffer extends until the resource is destroyed.
|
||||
*/
|
||||
/** @{ */
|
||||
template<std::size_t N>
|
||||
explicit
|
||||
static_resource(
|
||||
unsigned char(&buffer)[N]) noexcept
|
||||
: static_resource(&buffer[0], N)
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(__cpp_lib_byte) || defined(BOOST_JSON_DOCS)
|
||||
template<std::size_t N>
|
||||
explicit
|
||||
static_resource(
|
||||
std::byte(&buffer)[N]) noexcept
|
||||
: static_resource(&buffer[0], N)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
#ifndef BOOST_JSON_DOCS
|
||||
// Safety net for accidental buffer overflows
|
||||
template<std::size_t N>
|
||||
static_resource(
|
||||
unsigned char(&buffer)[N], std::size_t n) noexcept
|
||||
: static_resource(&buffer[0], n)
|
||||
{
|
||||
// If this goes off, check your parameters
|
||||
// closely, chances are you passed an array
|
||||
// thinking it was a pointer.
|
||||
BOOST_ASSERT(n <= N);
|
||||
}
|
||||
|
||||
#ifdef __cpp_lib_byte
|
||||
// Safety net for accidental buffer overflows
|
||||
template<std::size_t N>
|
||||
static_resource(
|
||||
std::byte(&buffer)[N], std::size_t n) noexcept
|
||||
: static_resource(&buffer[0], n)
|
||||
{
|
||||
// If this goes off, check your parameters
|
||||
// closely, chances are you passed an array
|
||||
// thinking it was a pointer.
|
||||
BOOST_ASSERT(n <= N);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** Release all allocated memory.
|
||||
|
||||
This function resets the buffer provided upon
|
||||
construction so that all of the valid bytes are
|
||||
available for subsequent allocation.
|
||||
|
||||
@par Complexity
|
||||
Constant
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
void
|
||||
release() noexcept;
|
||||
|
||||
protected:
|
||||
#ifndef BOOST_JSON_DOCS
|
||||
void*
|
||||
do_allocate(
|
||||
std::size_t n,
|
||||
std::size_t align) override;
|
||||
|
||||
void
|
||||
do_deallocate(
|
||||
void* p,
|
||||
std::size_t n,
|
||||
std::size_t align) override;
|
||||
|
||||
bool
|
||||
do_is_equal(
|
||||
memory_resource const& mr
|
||||
) const noexcept override;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
template<>
|
||||
struct is_deallocate_trivial<
|
||||
static_resource>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
529
install/boost_1_75_0/include/boost/json/storage_ptr.hpp
Normal file
529
install/boost_1_75_0/include/boost/json/storage_ptr.hpp
Normal file
@@ -0,0 +1,529 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_STORAGE_PTR_HPP
|
||||
#define BOOST_JSON_STORAGE_PTR_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/memory_resource.hpp>
|
||||
#include <boost/json/detail/shared_resource.hpp>
|
||||
#include <boost/json/detail/default_resource.hpp>
|
||||
#include <cstddef>
|
||||
#include <new>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
/** A smart pointer to a @ref memory_resource
|
||||
|
||||
This container is used to hold a pointer to a
|
||||
memory resource. The pointed-to resource is
|
||||
always valid; default-constructed pointers
|
||||
use the default memory resource, which calls
|
||||
into the standard global system heap.
|
||||
Depending on the means of construction, the
|
||||
ownership will be either:
|
||||
|
||||
@li Non-owning, when constructing from a raw
|
||||
pointer to @ref memory_resource or from a
|
||||
@ref polymorphic_allocator. In this case the
|
||||
caller is responsible for ensuring that the
|
||||
lifetime of the memory resource extends until
|
||||
there are no more calls to allocate or
|
||||
deallocate.
|
||||
|
||||
@li Owning, when constructing using the function
|
||||
@ref make_shared_resource. In this case
|
||||
ownership is shared; the lifetime of the memory
|
||||
resource extends until the last copy of the
|
||||
@ref storage_ptr is destroyed.
|
||||
|
||||
@par Examples
|
||||
|
||||
These statements create a memory resource on the
|
||||
stack and construct a pointer from it without
|
||||
taking ownership:
|
||||
@code
|
||||
monotonic_resource mr; // Create our memory resource on the stack
|
||||
storage_ptr sp( &mr ); // Construct a non-owning pointer to the resource
|
||||
@endcode
|
||||
|
||||
This function creates a pointer to a memory
|
||||
resource using shared ownership and returns it.
|
||||
The lifetime of the memory resource extends until
|
||||
the last copy of the pointer is destroyed:
|
||||
@code
|
||||
// Create a counted memory resource and return it
|
||||
storage_ptr make_storage()
|
||||
{
|
||||
return make_shared_resource< monotonic_resource >();
|
||||
}
|
||||
@endcode
|
||||
|
||||
@par Thread Safety
|
||||
|
||||
Instances of this type provide the default level of
|
||||
thread safety for all C++ objects. Specifically, it
|
||||
conforms to
|
||||
<a href="http://eel.is/c++draft/res.on.data.races">
|
||||
16.4.6.10 Data race avoidance</a>.
|
||||
|
||||
@see
|
||||
@ref make_shared_resource,
|
||||
@ref memory_resource,
|
||||
@ref polymorphic_allocator
|
||||
*/
|
||||
class storage_ptr
|
||||
{
|
||||
#ifndef BOOST_JSON_DOCS
|
||||
// VFALCO doc toolchain shows this when it shouldn't
|
||||
friend struct detail::shared_resource;
|
||||
#endif
|
||||
using shared_resource =
|
||||
detail::shared_resource;
|
||||
|
||||
using default_resource =
|
||||
detail::default_resource;
|
||||
|
||||
std::uintptr_t i_;
|
||||
|
||||
shared_resource*
|
||||
get_shared() const noexcept
|
||||
{
|
||||
return static_cast<shared_resource*>(
|
||||
reinterpret_cast<memory_resource*>(
|
||||
i_ & ~3));
|
||||
}
|
||||
|
||||
void
|
||||
addref() const noexcept
|
||||
{
|
||||
if(is_shared())
|
||||
get_shared()->refs.fetch_add(
|
||||
1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void
|
||||
release() const noexcept
|
||||
{
|
||||
if(is_shared())
|
||||
{
|
||||
auto const p = get_shared();
|
||||
if(p->refs.fetch_sub(1,
|
||||
std::memory_order_acq_rel) == 1)
|
||||
delete p;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
storage_ptr(
|
||||
detail::shared_resource_impl<T>* p) noexcept
|
||||
: i_(reinterpret_cast<std::uintptr_t>(
|
||||
static_cast<memory_resource*>(p)) + 1 +
|
||||
(json::is_deallocate_trivial<T>::value ? 2 : 0))
|
||||
{
|
||||
BOOST_ASSERT(p);
|
||||
}
|
||||
|
||||
public:
|
||||
/** Destructor
|
||||
|
||||
If the pointer has shared ownership of the
|
||||
resource, the shared ownership is released.
|
||||
If this is the last owned copy, the memory
|
||||
resource is destroyed.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
~storage_ptr()
|
||||
{
|
||||
release();
|
||||
}
|
||||
|
||||
/** Constructor
|
||||
|
||||
This constructs a non-owning pointer that refers
|
||||
to the default memory resource, which uses the
|
||||
standard global system heap to allocate and
|
||||
free memory.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
storage_ptr() noexcept
|
||||
: i_(0)
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor
|
||||
|
||||
This constructs a non-owning pointer that
|
||||
points to the memory resource `r`.
|
||||
The caller is responsible for maintaining the
|
||||
lifetime of the pointed-to @ref memory_resource.
|
||||
|
||||
@par Constraints
|
||||
@code
|
||||
std::is_convertible< T*, memory_resource* >::value == true
|
||||
@endcode
|
||||
|
||||
@par Preconditions
|
||||
@code
|
||||
r != nullptr
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param r A pointer to the memory resource to use.
|
||||
This may not be null.
|
||||
*/
|
||||
template<class T
|
||||
#ifndef BOOST_JSON_DOCS
|
||||
, class = typename std::enable_if<
|
||||
std::is_convertible<T*,
|
||||
memory_resource*>::value>::type
|
||||
#endif
|
||||
>
|
||||
storage_ptr(T* r) noexcept
|
||||
: i_(reinterpret_cast<std::uintptr_t>(
|
||||
static_cast<memory_resource *>(r)) +
|
||||
(json::is_deallocate_trivial<T>::value ? 2 : 0))
|
||||
{
|
||||
BOOST_ASSERT(r);
|
||||
}
|
||||
|
||||
/** Constructor
|
||||
|
||||
This constructs a non-owning pointer that
|
||||
points to the same memory resource as `alloc`,
|
||||
obtained by calling `alloc.resource()`.
|
||||
The caller is responsible for maintaining the
|
||||
lifetime of the pointed-to @ref memory_resource.
|
||||
|
||||
@par Constraints
|
||||
@code
|
||||
std::is_convertible< T*, memory_resource* >::value == true
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param alloc A @ref polymorphic_allocator to
|
||||
construct from.
|
||||
*/
|
||||
template<class T>
|
||||
storage_ptr(
|
||||
polymorphic_allocator<T> const& alloc) noexcept
|
||||
: i_(reinterpret_cast<std::uintptr_t>(
|
||||
alloc.resource()))
|
||||
{
|
||||
}
|
||||
|
||||
/** Move constructor
|
||||
|
||||
This function constructs a pointer that
|
||||
points to the same memory resource as `other`,
|
||||
with the same ownership:
|
||||
|
||||
@li If `other` is non-owning, then `*this`
|
||||
will be be non-owning.
|
||||
|
||||
@li If `other` has shared ownership, then
|
||||
ownership will be transferred to `*this`.
|
||||
|
||||
After construction, `other` will point
|
||||
to the default memory resource.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param other The pointer to construct from.
|
||||
*/
|
||||
storage_ptr(
|
||||
storage_ptr&& other) noexcept
|
||||
: i_(detail::exchange(other.i_, 0))
|
||||
{
|
||||
}
|
||||
|
||||
/** Copy constructor
|
||||
|
||||
This function constructs a pointer that
|
||||
points to the same memory resource as `other`,
|
||||
with the same ownership:
|
||||
|
||||
@li If `other` is non-owning, then `*this`
|
||||
will be be non-owning.
|
||||
|
||||
@li If `other` has shared ownership, then
|
||||
`*this` will acquire shared ownership.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param other The pointer to construct from.
|
||||
*/
|
||||
storage_ptr(
|
||||
storage_ptr const& other) noexcept
|
||||
: i_(other.i_)
|
||||
{
|
||||
addref();
|
||||
}
|
||||
|
||||
/** Move assignment
|
||||
|
||||
This function assigns a pointer that
|
||||
points to the same memory resource as `other`,
|
||||
with the same ownership:
|
||||
|
||||
@li If `other` is non-owning, then `*this`
|
||||
will be be non-owning.
|
||||
|
||||
@li If `other` has shared ownership, then
|
||||
ownership will be transferred to `*this`.
|
||||
|
||||
After assignment, `other` will point
|
||||
to the default memory resource.
|
||||
If `*this` previously had shared ownership,
|
||||
it is released before the function returns.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param other The storage pointer to move.
|
||||
*/
|
||||
storage_ptr&
|
||||
operator=(
|
||||
storage_ptr&& other) noexcept
|
||||
{
|
||||
release();
|
||||
i_ = detail::exchange(other.i_, 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Copy assignment.
|
||||
|
||||
This function assigns a pointer that
|
||||
points to the same memory resource as `other`,
|
||||
with the same ownership:
|
||||
|
||||
@li If `other` is non-owning, then `*this`
|
||||
will be be non-owning.
|
||||
|
||||
@li If `other` has shared ownership, then
|
||||
`*this` will acquire shared ownership.
|
||||
|
||||
If `*this` previously had shared ownership,
|
||||
it is released before the function returns.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param other The storage pointer to copy.
|
||||
*/
|
||||
storage_ptr&
|
||||
operator=(
|
||||
storage_ptr const& other) noexcept
|
||||
{
|
||||
other.addref();
|
||||
release();
|
||||
i_ = other.i_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Return `true` if ownership of the memory resource is shared.
|
||||
|
||||
This function returns true for memory resources
|
||||
created using @ref make_shared_resource.
|
||||
*/
|
||||
bool
|
||||
is_shared() const noexcept
|
||||
{
|
||||
return (i_ & 1) != 0;
|
||||
}
|
||||
|
||||
/** Return `true` if calling `deallocate` on the memory resource has no effect.
|
||||
|
||||
This function is used to determine if the deallocate
|
||||
function of the pointed to memory resource is trivial.
|
||||
The value of @ref is_deallocate_trivial is evaluated
|
||||
and saved when the memory resource is constructed
|
||||
and the type is known, before the type is erased.
|
||||
*/
|
||||
bool
|
||||
is_deallocate_trivial() const noexcept
|
||||
{
|
||||
return (i_ & 2) != 0;
|
||||
}
|
||||
|
||||
/** Return `true` if ownership of the memory resource is not shared and deallocate is trivial.
|
||||
|
||||
This function is used to determine if calls to deallocate
|
||||
can effectively be skipped.
|
||||
|
||||
@par Effects
|
||||
Returns `! this->is_shared() && this->is_deallocate_trivial()`
|
||||
*/
|
||||
bool
|
||||
is_not_shared_and_deallocate_is_trivial() const noexcept
|
||||
{
|
||||
return (i_ & 3) == 2;
|
||||
}
|
||||
|
||||
/** Return a pointer to the memory resource.
|
||||
|
||||
This function returns a pointer to the
|
||||
referenced @ref memory_resource.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
memory_resource*
|
||||
get() const noexcept
|
||||
{
|
||||
if(i_ != 0)
|
||||
return reinterpret_cast<
|
||||
memory_resource*>(i_ & ~3);
|
||||
return default_resource::get();
|
||||
}
|
||||
|
||||
/** Return a pointer to the memory resource.
|
||||
|
||||
This function returns a pointer to the
|
||||
referenced @ref memory_resource.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
memory_resource*
|
||||
operator->() const noexcept
|
||||
{
|
||||
return get();
|
||||
}
|
||||
|
||||
/** Return a reference to the memory resource.
|
||||
|
||||
This function returns a reference to the
|
||||
pointed-to @ref memory_resource.
|
||||
|
||||
@par Complexity
|
||||
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
|
||||
No-throw guarantee.
|
||||
*/
|
||||
memory_resource&
|
||||
operator*() const noexcept
|
||||
{
|
||||
return *get();
|
||||
}
|
||||
|
||||
template<class U, class... Args>
|
||||
friend
|
||||
storage_ptr
|
||||
make_shared_resource(Args&&... args);
|
||||
};
|
||||
|
||||
/** Return shared ownership of a new, dynamically allocated memory resource.
|
||||
|
||||
This function dynamically allocates a new memory resource
|
||||
as if by `operator new` that uses shared ownership. The
|
||||
lifetime of the memory resource will be extended until
|
||||
the last @ref storage_ptr which points to it is destroyed.
|
||||
|
||||
@par Mandates
|
||||
@code
|
||||
std::is_base_of< memory_resource, T >::value == true
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Same as `new T( std::forward<Args>(args)... )`.
|
||||
|
||||
@par Exception Safety
|
||||
Strong guarantee.
|
||||
|
||||
@tparam T The type of memory resource to create.
|
||||
|
||||
@param args Parameters forwarded to the constructor of `T`.
|
||||
*/
|
||||
template<class T, class... Args>
|
||||
storage_ptr
|
||||
make_shared_resource(Args&&... args)
|
||||
{
|
||||
// If this generates an error, it means that
|
||||
// `T` is not a memory resource.
|
||||
BOOST_STATIC_ASSERT(
|
||||
std::is_base_of<
|
||||
memory_resource, T>::value);
|
||||
return storage_ptr(new
|
||||
detail::shared_resource_impl<T>(
|
||||
std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
/** Return true if two storage pointers point to the same memory resource.
|
||||
|
||||
This function returns `true` if the @ref memory_resource
|
||||
objects pointed to by `lhs` and `rhs` have the
|
||||
same address.
|
||||
*/
|
||||
inline
|
||||
bool
|
||||
operator==(
|
||||
storage_ptr const& lhs,
|
||||
storage_ptr const& rhs) noexcept
|
||||
{
|
||||
return lhs.get() == rhs.get();
|
||||
}
|
||||
|
||||
/** Return true if two storage pointers point to different memory resources.
|
||||
|
||||
This function returns `true` if the @ref memory_resource
|
||||
objects pointed to by `lhs` and `rhs` have different
|
||||
addresses.
|
||||
*/
|
||||
inline
|
||||
bool
|
||||
operator!=(
|
||||
storage_ptr const& lhs,
|
||||
storage_ptr const& rhs) noexcept
|
||||
{
|
||||
return lhs.get() != rhs.get();
|
||||
}
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
985
install/boost_1_75_0/include/boost/json/stream_parser.hpp
Normal file
985
install/boost_1_75_0/include/boost/json/stream_parser.hpp
Normal file
@@ -0,0 +1,985 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_STREAM_PARSER_HPP
|
||||
#define BOOST_JSON_STREAM_PARSER_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/basic_parser.hpp>
|
||||
#include <boost/json/parse_options.hpp>
|
||||
#include <boost/json/storage_ptr.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/json/detail/handler.hpp>
|
||||
#include <type_traits>
|
||||
#include <cstddef>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
/** A DOM parser for JSON contained in multiple buffers.
|
||||
|
||||
This class is used to parse a JSON contained in a
|
||||
series of one or more character buffers, into a
|
||||
@ref value container. It implements a
|
||||
<a href="https://en.wikipedia.org/wiki/Streaming_algorithm">
|
||||
<em>streaming algorithm</em></a>, allowing these
|
||||
parsing strategies:
|
||||
|
||||
@li Parse a JSON file a piece at a time.
|
||||
|
||||
@li Parse incoming JSON as it arrives,
|
||||
one buffer at a time.
|
||||
|
||||
@li Parse with bounded resource consumption
|
||||
per cycle.
|
||||
|
||||
@par Usage
|
||||
|
||||
To use the parser first construct it, then optionally
|
||||
call @ref reset to specify a @ref storage_ptr to use
|
||||
for the resulting @ref value. Then call @ref write
|
||||
one or more times to parse a single, complete JSON.
|
||||
Call @ref done to determine if the parse has completed.
|
||||
To indicate there are no more buffers, call @ref finish.
|
||||
If the parse is successful, call @ref release to take
|
||||
ownership of the value:
|
||||
|
||||
@code
|
||||
stream_parser p; // construct a parser
|
||||
p.write( "[1,2" ); // parse some of a JSON
|
||||
p.write( ",3,4]" ); // parse the rest of the JSON
|
||||
assert( p.done() ); // we have a complete JSON
|
||||
value jv = p.release(); // take ownership of the value
|
||||
@endcode
|
||||
|
||||
@par Extra Data
|
||||
|
||||
When the character buffer provided as input contains
|
||||
additional data that is not part of the complete
|
||||
JSON, an error is returned. The @ref write_some
|
||||
function is an alternative which allows the parse
|
||||
to finish early, without consuming all the characters
|
||||
in the buffer. This allows parsing of a buffer
|
||||
containing multiple individual JSONs or containing
|
||||
different protocol data:
|
||||
@code
|
||||
stream_parser p; // construct a parser
|
||||
std::size_t n; // number of characters used
|
||||
n = p.write_some( "[1,2" ); // parse some of a JSON
|
||||
assert( n == 4 ); // all characters consumed
|
||||
n = p.write_some( ",3,4] null" ); // parse the remainder of the JSON
|
||||
assert( n == 6 ); // only some characters consumed
|
||||
assert( p.done() ); // we have a complete JSON
|
||||
value jv = p.release(); // take ownership of the value
|
||||
@endcode
|
||||
|
||||
@par Temporary Storage
|
||||
|
||||
The parser may dynamically allocate temporary
|
||||
storage as needed to accommodate the nesting level
|
||||
of the JSON being parsed. Temporary storage is
|
||||
first obtained from an optional, caller-owned
|
||||
buffer specified upon construction. When that
|
||||
is exhausted, the next allocation uses the
|
||||
@ref memory_resource passed to the constructor; if
|
||||
no such argument is specified, the default memory
|
||||
resource is used. Temporary storage is freed only
|
||||
when the parser is destroyed; The performance of
|
||||
parsing multiple JSONs may be improved by reusing
|
||||
the same parser instance.
|
||||
\n
|
||||
It is important to note that the @ref memory_resource
|
||||
supplied upon construction is used for temporary
|
||||
storage only, and not for allocating the elements
|
||||
which make up the parsed value. That other memory
|
||||
resource is optionally supplied in each call
|
||||
to @ref reset.
|
||||
|
||||
@par Duplicate Keys
|
||||
|
||||
If there are object elements with duplicate keys;
|
||||
that is, if multiple elements in an object have
|
||||
keys that compare equal, only the last equivalent
|
||||
element will be inserted.
|
||||
|
||||
@par Non-Standard JSON
|
||||
|
||||
The @ref parse_options structure optionally
|
||||
provided upon construction is used to customize
|
||||
some parameters of the parser, including which
|
||||
non-standard JSON extensions should be allowed.
|
||||
A default-constructed parse options allows only
|
||||
standard JSON.
|
||||
|
||||
@par Thread Safety
|
||||
|
||||
Distinct instances may be accessed concurrently.
|
||||
Non-const member functions of a shared instance
|
||||
may not be called concurrently with any other
|
||||
member functions of that instance.
|
||||
|
||||
@see
|
||||
@ref parse,
|
||||
@ref parser,
|
||||
@ref parse_options,
|
||||
*/
|
||||
class stream_parser
|
||||
{
|
||||
basic_parser<detail::handler> p_;
|
||||
|
||||
public:
|
||||
/// Copy constructor (deleted)
|
||||
stream_parser(
|
||||
stream_parser const&) = delete;
|
||||
|
||||
/// Copy assignment (deleted)
|
||||
stream_parser& operator=(
|
||||
stream_parser const&) = delete;
|
||||
|
||||
/** Destructor.
|
||||
|
||||
All dynamically allocated memory, including
|
||||
any incomplete parsing results, is freed.
|
||||
|
||||
@par Complexity
|
||||
Linear in the size of partial results
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
~stream_parser() = default;
|
||||
|
||||
/** Constructor.
|
||||
|
||||
This constructs a new parser which first uses
|
||||
the caller-owned storage pointed to by `buffer`
|
||||
for temporary storage, falling back to the memory
|
||||
resource `sp` if needed. The parser will use the
|
||||
specified parsing options.
|
||||
\n
|
||||
The parsed value will use the default memory
|
||||
resource for storage. To use a different resource,
|
||||
call @ref reset after construction.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param sp The memory resource to use for
|
||||
temporary storage after `buffer` is exhausted.
|
||||
|
||||
@param opt The parsing options to use.
|
||||
|
||||
@param buffer A pointer to valid memory of at least
|
||||
`size` bytes for the parser to use for temporary storage.
|
||||
Ownership is not transferred, the caller is responsible
|
||||
for ensuring the lifetime of the memory pointed to by
|
||||
`buffer` extends until the parser is destroyed.
|
||||
|
||||
@param size The number of valid bytes in `buffer`.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
stream_parser(
|
||||
storage_ptr sp,
|
||||
parse_options const& opt,
|
||||
unsigned char* buffer,
|
||||
std::size_t size) noexcept;
|
||||
|
||||
/** Constructor.
|
||||
|
||||
This constructs a new parser which uses the default
|
||||
memory resource for temporary storage, and accepts
|
||||
only strict JSON.
|
||||
\n
|
||||
The parsed value will use the default memory
|
||||
resource for storage. To use a different resource,
|
||||
call @ref reset after construction.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
stream_parser() noexcept
|
||||
: stream_parser({}, {})
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor.
|
||||
|
||||
This constructs a new parser which uses the
|
||||
specified memory resource for temporary storage,
|
||||
and is configured to use the specified parsing
|
||||
options.
|
||||
\n
|
||||
The parsed value will use the default memory
|
||||
resource for storage. To use a different resource,
|
||||
call @ref reset after construction.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param sp The memory resource to use for temporary storage.
|
||||
|
||||
@param opt The parsing options to use.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
stream_parser(
|
||||
storage_ptr sp,
|
||||
parse_options const& opt) noexcept;
|
||||
|
||||
/** Constructor.
|
||||
|
||||
This constructs a new parser which uses the
|
||||
specified memory resource for temporary storage,
|
||||
and accepts only strict JSON.
|
||||
\n
|
||||
The parsed value will use the default memory
|
||||
resource for storage. To use a different resource,
|
||||
call @ref reset after construction.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param sp The memory resource to use for temporary storage.
|
||||
*/
|
||||
explicit
|
||||
stream_parser(storage_ptr sp) noexcept
|
||||
: stream_parser(std::move(sp), {})
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor.
|
||||
|
||||
This constructs a new parser which first uses the
|
||||
caller-owned storage `buffer` for temporary storage,
|
||||
falling back to the memory resource `sp` if needed.
|
||||
The parser will use the specified parsing options.
|
||||
\n
|
||||
The parsed value will use the default memory
|
||||
resource for storage. To use a different resource,
|
||||
call @ref reset after construction.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param sp The memory resource to use for
|
||||
temporary storage after `buffer` is exhausted.
|
||||
|
||||
@param opt The parsing options to use.
|
||||
|
||||
@param buffer A buffer for the parser to use for
|
||||
temporary storage. Ownership is not transferred,
|
||||
the caller is responsible for ensuring the lifetime
|
||||
of `buffer` extends until the parser is destroyed.
|
||||
*/
|
||||
template<std::size_t N>
|
||||
stream_parser(
|
||||
storage_ptr sp,
|
||||
parse_options const& opt,
|
||||
unsigned char(&buffer)[N]) noexcept
|
||||
: stream_parser(std::move(sp),
|
||||
opt, &buffer[0], N)
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(__cpp_lib_byte) || defined(BOOST_JSON_DOCS)
|
||||
/** Constructor.
|
||||
|
||||
This constructs a new parser which first uses
|
||||
the caller-owned storage pointed to by `buffer`
|
||||
for temporary storage, falling back to the memory
|
||||
resource `sp` if needed. The parser will use the
|
||||
specified parsing options.
|
||||
\n
|
||||
The parsed value will use the default memory
|
||||
resource for storage. To use a different resource,
|
||||
call @ref reset after construction.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param sp The memory resource to use for
|
||||
temporary storage after `buffer` is exhausted.
|
||||
|
||||
@param opt The parsing options to use.
|
||||
|
||||
@param buffer A pointer to valid memory of at least
|
||||
`size` bytes for the parser to use for temporary storage.
|
||||
Ownership is not transferred, the caller is responsible
|
||||
for ensuring the lifetime of the memory pointed to by
|
||||
`buffer` extends until the parser is destroyed.
|
||||
|
||||
@param size The number of valid bytes in `buffer`.
|
||||
*/
|
||||
stream_parser(
|
||||
storage_ptr sp,
|
||||
parse_options const& opt,
|
||||
std::byte* buffer,
|
||||
std::size_t size) noexcept
|
||||
: stream_parser(sp, opt, reinterpret_cast<
|
||||
unsigned char*>(buffer), size)
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor.
|
||||
|
||||
This constructs a new parser which first uses the
|
||||
caller-owned storage `buffer` for temporary storage,
|
||||
falling back to the memory resource `sp` if needed.
|
||||
The parser will use the specified parsing options.
|
||||
\n
|
||||
The parsed value will use the default memory
|
||||
resource for storage. To use a different resource,
|
||||
call @ref reset after construction.
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param sp The memory resource to use for
|
||||
temporary storage after `buffer` is exhausted.
|
||||
|
||||
@param opt The parsing options to use.
|
||||
|
||||
@param buffer A buffer for the parser to use for
|
||||
temporary storage. Ownership is not transferred,
|
||||
the caller is responsible for ensuring the lifetime
|
||||
of `buffer` extends until the parser is destroyed.
|
||||
*/
|
||||
template<std::size_t N>
|
||||
stream_parser(
|
||||
storage_ptr sp,
|
||||
parse_options const& opt,
|
||||
std::byte(&buffer)[N]) noexcept
|
||||
: stream_parser(std::move(sp),
|
||||
opt, &buffer[0], N)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_JSON_DOCS
|
||||
// Safety net for accidental buffer overflows
|
||||
template<std::size_t N>
|
||||
stream_parser(
|
||||
storage_ptr sp,
|
||||
parse_options const& opt,
|
||||
unsigned char(&buffer)[N],
|
||||
std::size_t n) noexcept
|
||||
: stream_parser(std::move(sp),
|
||||
opt, &buffer[0], n)
|
||||
{
|
||||
// If this goes off, check your parameters
|
||||
// closely, chances are you passed an array
|
||||
// thinking it was a pointer.
|
||||
BOOST_ASSERT(n <= N);
|
||||
}
|
||||
|
||||
#ifdef __cpp_lib_byte
|
||||
// Safety net for accidental buffer overflows
|
||||
template<std::size_t N>
|
||||
stream_parser(
|
||||
storage_ptr sp,
|
||||
parse_options const& opt,
|
||||
std::byte(&buffer)[N], std::size_t n) noexcept
|
||||
: stream_parser(std::move(sp),
|
||||
opt, &buffer[0], n)
|
||||
{
|
||||
// If this goes off, check your parameters
|
||||
// closely, chances are you passed an array
|
||||
// thinking it was a pointer.
|
||||
BOOST_ASSERT(n <= N);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** Reset the parser for a new JSON.
|
||||
|
||||
This function is used to reset the parser to
|
||||
prepare it for parsing a new complete JSON.
|
||||
Any previous partial results are destroyed.
|
||||
|
||||
@par Complexity
|
||||
Constant or linear in the size of any previous
|
||||
partial parsing results.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
|
||||
@param sp A pointer to the @ref memory_resource
|
||||
to use for the resulting @ref value. The parser
|
||||
will acquire shared ownership.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
reset(storage_ptr sp = {}) noexcept;
|
||||
|
||||
/** Return true if a complete JSON has been parsed.
|
||||
|
||||
This function returns `true` when all of these
|
||||
conditions are met:
|
||||
|
||||
@li A complete serialized JSON has been
|
||||
presented to the parser, and
|
||||
|
||||
@li No error has occurred since the parser
|
||||
was constructed, or since the last call
|
||||
to @ref reset,
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
bool
|
||||
done() const noexcept
|
||||
{
|
||||
return p_.done();
|
||||
}
|
||||
|
||||
/** Parse a buffer containing all or part of a complete JSON.
|
||||
|
||||
This function parses JSON contained in the
|
||||
specified character buffer. If parsing completes,
|
||||
any additional characters past the end of the
|
||||
complete JSON are ignored. The function returns the
|
||||
actual number of characters parsed, which may be
|
||||
less than the size of the input. This allows parsing
|
||||
of a buffer containing multiple individual JSONs or
|
||||
containing different protocol data.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
stream_parser p; // construct a parser
|
||||
std::size_t n; // number of characters used
|
||||
n = p.write_some( "[1,2" ); // parse the first part of the JSON
|
||||
assert( n == 4 ); // all characters consumed
|
||||
n = p.write_some( "3,4] null" ); // parse the rest of the JSON
|
||||
assert( n == 5 ); // only some characters consumed
|
||||
value jv = p.release(); // take ownership of the value
|
||||
@endcode
|
||||
|
||||
@note
|
||||
|
||||
To indicate there are no more character buffers,
|
||||
such as when @ref done returns `false` after
|
||||
writing, call @ref finish.
|
||||
|
||||
@par Complexity
|
||||
Linear in `size`.
|
||||
|
||||
@par Exception Safety
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
Upon error or exception, subsequent calls will
|
||||
fail until @ref reset is called to parse a new JSON.
|
||||
|
||||
@return The number of characters consumed from
|
||||
the buffer.
|
||||
|
||||
@param data A pointer to a buffer of `size`
|
||||
characters to parse.
|
||||
|
||||
@param size The number of characters pointed to
|
||||
by `data`.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
std::size_t
|
||||
write_some(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec);
|
||||
|
||||
/** Parse a buffer containing all or part of a complete JSON.
|
||||
|
||||
This function parses JSON contained in the
|
||||
specified character buffer. If parsing completes,
|
||||
any additional characters past the end of the
|
||||
complete JSON are ignored. The function returns the
|
||||
actual number of characters parsed, which may be
|
||||
less than the size of the input. This allows parsing
|
||||
of a buffer containing multiple individual JSONs or
|
||||
containing different protocol data.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
stream_parser p; // construct a parser
|
||||
std::size_t n; // number of characters used
|
||||
n = p.write_some( "[1,2" ); // parse the first part of the JSON
|
||||
assert( n == 4 ); // all characters consumed
|
||||
n = p.write_some( "3,4] null" ); // parse the rest of the JSON
|
||||
assert( n == 5 ); // only some characters consumed
|
||||
value jv = p.release(); // take ownership of the value
|
||||
@endcode
|
||||
|
||||
@note
|
||||
|
||||
To indicate there are no more character buffers,
|
||||
such as when @ref done returns `false` after
|
||||
writing, call @ref finish.
|
||||
|
||||
@par Complexity
|
||||
Linear in `size`.
|
||||
|
||||
@par Exception Safety
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
Upon error or exception, subsequent calls will
|
||||
fail until @ref reset is called to parse a new JSON.
|
||||
|
||||
@return The number of characters consumed from
|
||||
the buffer.
|
||||
|
||||
@param data A pointer to a buffer of `size`
|
||||
characters to parse.
|
||||
|
||||
@param size The number of characters pointed to
|
||||
by `data`.
|
||||
|
||||
@throw system_error Thrown on error.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
std::size_t
|
||||
write_some(
|
||||
char const* data,
|
||||
std::size_t size);
|
||||
|
||||
/** Parse a buffer containing all or part of a complete JSON.
|
||||
|
||||
This function parses JSON contained in the
|
||||
specified character buffer. If parsing completes,
|
||||
any additional characters past the end of the
|
||||
complete JSON are ignored. The function returns the
|
||||
actual number of characters parsed, which may be
|
||||
less than the size of the input. This allows parsing
|
||||
of a buffer containing multiple individual JSONs or
|
||||
containing different protocol data.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
stream_parser p; // construct a parser
|
||||
std::size_t n; // number of characters used
|
||||
n = p.write_some( "[1,2" ); // parse the first part of the JSON
|
||||
assert( n == 4 ); // all characters consumed
|
||||
n = p.write_some( "3,4] null" ); // parse the rest of the JSON
|
||||
assert( n == 5 ); // only some characters consumed
|
||||
value jv = p.release(); // take ownership of the value
|
||||
@endcode
|
||||
|
||||
@note
|
||||
|
||||
To indicate there are no more character buffers,
|
||||
such as when @ref done returns `false` after
|
||||
writing, call @ref finish.
|
||||
|
||||
@par Complexity
|
||||
Linear in `size`.
|
||||
|
||||
@par Exception Safety
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
Upon error or exception, subsequent calls will
|
||||
fail until @ref reset is called to parse a new JSON.
|
||||
|
||||
@return The number of characters consumed from
|
||||
the buffer.
|
||||
|
||||
@param s The character string to parse.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
std::size_t
|
||||
write_some(
|
||||
string_view s,
|
||||
error_code& ec)
|
||||
{
|
||||
return write_some(
|
||||
s.data(), s.size(), ec);
|
||||
}
|
||||
|
||||
/** Parse a buffer containing all or part of a complete JSON.
|
||||
|
||||
This function parses JSON contained in the
|
||||
specified character buffer. If parsing completes,
|
||||
any additional characters past the end of the
|
||||
complete JSON are ignored. The function returns the
|
||||
actual number of characters parsed, which may be
|
||||
less than the size of the input. This allows parsing
|
||||
of a buffer containing multiple individual JSONs or
|
||||
containing different protocol data.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
stream_parser p; // construct a parser
|
||||
std::size_t n; // number of characters used
|
||||
n = p.write_some( "[1,2" ); // parse the first part of the JSON
|
||||
assert( n == 4 ); // all characters consumed
|
||||
n = p.write_some( "3,4] null" ); // parse the rest of the JSON
|
||||
assert( n == 5 ); // only some characters consumed
|
||||
value jv = p.release(); // take ownership of the value
|
||||
@endcode
|
||||
|
||||
@note
|
||||
|
||||
To indicate there are no more character buffers,
|
||||
such as when @ref done returns `false` after
|
||||
writing, call @ref finish.
|
||||
|
||||
@par Complexity
|
||||
Linear in `size`.
|
||||
|
||||
@par Exception Safety
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
Upon error or exception, subsequent calls will
|
||||
fail until @ref reset is called to parse a new JSON.
|
||||
|
||||
@return The number of characters consumed from
|
||||
the buffer.
|
||||
|
||||
@param s The character string to parse.
|
||||
|
||||
@throw system_error Thrown on error.
|
||||
*/
|
||||
std::size_t
|
||||
write_some(
|
||||
string_view s)
|
||||
{
|
||||
return write_some(
|
||||
s.data(), s.size());
|
||||
}
|
||||
|
||||
/** Parse a buffer containing all or part of a complete JSON.
|
||||
|
||||
This function parses a all or part of a JSON
|
||||
contained in the specified character buffer. The
|
||||
entire buffer must be consumed; if there are
|
||||
additional characters past the end of the complete
|
||||
JSON, the parse fails and an error is returned.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
stream_parser p; // construct a parser
|
||||
std::size_t n; // number of characters used
|
||||
n = p.write( "[1,2" ); // parse some of the JSON
|
||||
assert( n == 4 ); // all characters consumed
|
||||
n = p.write( "3,4]" ); // parse the rest of the JSON
|
||||
assert( n == 4 ); // all characters consumed
|
||||
value jv = p.release(); // take ownership of the value
|
||||
@endcode
|
||||
|
||||
@note
|
||||
|
||||
To indicate there are no more character buffers,
|
||||
such as when @ref done returns `false` after
|
||||
writing, call @ref finish.
|
||||
|
||||
@par Complexity
|
||||
Linear in `size`.
|
||||
|
||||
@par Exception Safety
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
Upon error or exception, subsequent calls will
|
||||
fail until @ref reset is called to parse a new JSON.
|
||||
|
||||
@return The number of characters consumed from
|
||||
the buffer.
|
||||
|
||||
@param data A pointer to a buffer of `size`
|
||||
characters to parse.
|
||||
|
||||
@param size The number of characters pointed to
|
||||
by `data`.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
std::size_t
|
||||
write(
|
||||
char const* data,
|
||||
std::size_t size,
|
||||
error_code& ec);
|
||||
|
||||
/** Parse a buffer containing all or part of a complete JSON.
|
||||
|
||||
This function parses a all or part of a JSON
|
||||
contained in the specified character buffer. The
|
||||
entire buffer must be consumed; if there are
|
||||
additional characters past the end of the complete
|
||||
JSON, the parse fails and an error is returned.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
stream_parser p; // construct a parser
|
||||
std::size_t n; // number of characters used
|
||||
n = p.write( "[1,2" ); // parse some of the JSON
|
||||
assert( n == 4 ); // all characters consumed
|
||||
n = p.write( "3,4]" ); // parse the rest of the JSON
|
||||
assert( n == 4 ); // all characters consumed
|
||||
value jv = p.release(); // take ownership of the value
|
||||
@endcode
|
||||
|
||||
@note
|
||||
|
||||
To indicate there are no more character buffers,
|
||||
such as when @ref done returns `false` after
|
||||
writing, call @ref finish.
|
||||
|
||||
@par Complexity
|
||||
Linear in `size`.
|
||||
|
||||
@par Exception Safety
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
Upon error or exception, subsequent calls will
|
||||
fail until @ref reset is called to parse a new JSON.
|
||||
|
||||
@return The number of characters consumed from
|
||||
the buffer.
|
||||
|
||||
@param data A pointer to a buffer of `size`
|
||||
characters to parse.
|
||||
|
||||
@param size The number of characters pointed to
|
||||
by `data`.
|
||||
|
||||
@throw system_error Thrown on error.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
std::size_t
|
||||
write(
|
||||
char const* data,
|
||||
std::size_t size);
|
||||
|
||||
/** Parse a buffer containing all or part of a complete JSON.
|
||||
|
||||
This function parses a all or part of a JSON
|
||||
contained in the specified character buffer. The
|
||||
entire buffer must be consumed; if there are
|
||||
additional characters past the end of the complete
|
||||
JSON, the parse fails and an error is returned.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
stream_parser p; // construct a parser
|
||||
std::size_t n; // number of characters used
|
||||
n = p.write( "[1,2" ); // parse some of the JSON
|
||||
assert( n == 4 ); // all characters consumed
|
||||
n = p.write( "3,4]" ); // parse the rest of the JSON
|
||||
assert( n == 4 ); // all characters consumed
|
||||
value jv = p.release(); // take ownership of the value
|
||||
@endcode
|
||||
|
||||
@note
|
||||
|
||||
To indicate there are no more character buffers,
|
||||
such as when @ref done returns `false` after
|
||||
writing, call @ref finish.
|
||||
|
||||
@par Complexity
|
||||
Linear in `size`.
|
||||
|
||||
@par Exception Safety
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
Upon error or exception, subsequent calls will
|
||||
fail until @ref reset is called to parse a new JSON.
|
||||
|
||||
@return The number of characters consumed from
|
||||
the buffer.
|
||||
|
||||
@param s The character string to parse.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
std::size_t
|
||||
write(
|
||||
string_view s,
|
||||
error_code& ec)
|
||||
{
|
||||
return write(
|
||||
s.data(), s.size(), ec);
|
||||
}
|
||||
|
||||
/** Parse a buffer containing all or part of a complete JSON.
|
||||
|
||||
This function parses a all or part of a JSON
|
||||
contained in the specified character buffer. The
|
||||
entire buffer must be consumed; if there are
|
||||
additional characters past the end of the complete
|
||||
JSON, the parse fails and an error is returned.
|
||||
|
||||
@par Example
|
||||
@code
|
||||
stream_parser p; // construct a parser
|
||||
std::size_t n; // number of characters used
|
||||
n = p.write( "[1,2" ); // parse some of the JSON
|
||||
assert( n == 4 ); // all characters consumed
|
||||
n = p.write( "3,4]" ); // parse the rest of the JSON
|
||||
assert( n == 4 ); // all characters consumed
|
||||
value jv = p.release(); // take ownership of the value
|
||||
@endcode
|
||||
|
||||
@note
|
||||
|
||||
To indicate there are no more character buffers,
|
||||
such as when @ref done returns `false` after
|
||||
writing, call @ref finish.
|
||||
|
||||
@par Complexity
|
||||
Linear in `size`.
|
||||
|
||||
@par Exception Safety
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
Upon error or exception, subsequent calls will
|
||||
fail until @ref reset is called to parse a new JSON.
|
||||
|
||||
@return The number of characters consumed from
|
||||
the buffer.
|
||||
|
||||
@param s The character string to parse.
|
||||
|
||||
@throw system_error Thrown on error.
|
||||
*/
|
||||
std::size_t
|
||||
write(
|
||||
string_view s)
|
||||
{
|
||||
return write(
|
||||
s.data(), s.size());
|
||||
}
|
||||
|
||||
/** Indicate the end of JSON input.
|
||||
|
||||
This function is used to indicate that there
|
||||
are no more character buffers in the current
|
||||
JSON being parsed. If ther resulting JSON is
|
||||
incomplete, the error is set to indicate a
|
||||
parsing failure.
|
||||
|
||||
@par Example
|
||||
In the code below, @ref finish is called to
|
||||
indicate there are no more digits in the
|
||||
resulting number:
|
||||
@code
|
||||
stream_parser p; // construct a parser
|
||||
p.write( "3." ); // write the first part of the number
|
||||
p.write( "14" ); // write the second part of the number
|
||||
assert( ! p.done() ); // there could be more digits
|
||||
p.finish(); // indicate the end of the JSON input
|
||||
assert( p.done() ); // now we are finished
|
||||
value jv = p.release(); // take ownership of the value
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
Upon error or exception, subsequent calls will
|
||||
fail until @ref reset is called to parse a new JSON.
|
||||
|
||||
@param ec Set to the error, if any occurred.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
finish(error_code& ec);
|
||||
|
||||
/** Indicate the end of JSON input.
|
||||
|
||||
This function is used to indicate that there
|
||||
are no more character buffers in the current
|
||||
JSON being parsed. If ther resulting JSON is
|
||||
incomplete, the error is set to indicate a
|
||||
parsing failure.
|
||||
|
||||
@par Example
|
||||
In the code below, @ref finish is called to
|
||||
indicate there are no more digits in the
|
||||
resulting number:
|
||||
@code
|
||||
stream_parser p; // construct a parser
|
||||
p.write( "3." ); // write the first part of the number
|
||||
p.write( "14" ); // write the second part of the number
|
||||
assert( ! p.done() ); // there could be more digits
|
||||
p.finish(); // indicate the end of the JSON input
|
||||
assert( p.done() ); // now we are finished
|
||||
value jv = p.release(); // take ownership of the value
|
||||
@endcode
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@par Exception Safety
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
Upon error or exception, subsequent calls will
|
||||
fail until @ref reset is called to parse a new JSON.
|
||||
|
||||
@throw system_error Thrown on error.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
finish();
|
||||
|
||||
/** Return the parsed JSON as a @ref value.
|
||||
|
||||
This returns the parsed value, or throws
|
||||
an exception if the parsing is incomplete or
|
||||
failed. It is necessary to call @ref reset
|
||||
after calling this function in order to parse
|
||||
another JSON.
|
||||
|
||||
@par Effects
|
||||
@code
|
||||
if( ! this->done() )
|
||||
this->finish();
|
||||
@endcode
|
||||
@note
|
||||
|
||||
@par Complexity
|
||||
Constant.
|
||||
|
||||
@return The parsed value. Ownership of this
|
||||
value is transferred to the caller.
|
||||
|
||||
@throw system_error Thrown on failure.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
value
|
||||
release();
|
||||
};
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
2913
install/boost_1_75_0/include/boost/json/string.hpp
Normal file
2913
install/boost_1_75_0/include/boost/json/string.hpp
Normal file
File diff suppressed because it is too large
Load Diff
83
install/boost_1_75_0/include/boost/json/string_view.hpp
Normal file
83
install/boost_1_75_0/include/boost/json/string_view.hpp
Normal file
@@ -0,0 +1,83 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_STRING_VIEW_HPP
|
||||
#define BOOST_JSON_STRING_VIEW_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#ifndef BOOST_JSON_STANDALONE
|
||||
# include <boost/utility/string_view.hpp>
|
||||
#else
|
||||
# if __has_include(<string_view>)
|
||||
# include <string_view>
|
||||
# if __cpp_lib_string_view < 201603L
|
||||
# error Support for std::string_view is required to use Boost.JSON standalone
|
||||
# endif
|
||||
# else
|
||||
# error Header <string_view> is required to use Boost.JSON standalone
|
||||
# endif
|
||||
#endif
|
||||
#include <type_traits>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
#ifdef BOOST_JSON_DOCS
|
||||
|
||||
/** The type of string view used by the library.
|
||||
|
||||
This type alias is set depending
|
||||
on how the library is configured:
|
||||
|
||||
@par Use with Boost
|
||||
|
||||
If the macro `BOOST_JSON_STANDALONE` is
|
||||
not defined, this type will be an alias
|
||||
for `boost::string_view`.
|
||||
Compiling a program using the library will
|
||||
require Boost, and a compiler conforming
|
||||
to C++11 or later.
|
||||
|
||||
@par Use without Boost
|
||||
|
||||
If the macro `BOOST_JSON_STANDALONE` is
|
||||
defined, this type will be an alias
|
||||
for `std::string_view`.
|
||||
Compiling a program using the library will
|
||||
require only a compiler conforming to C++17
|
||||
or later.
|
||||
|
||||
@see https://en.cppreference.com/w/cpp/string/basic_string_view
|
||||
*/
|
||||
using string_view = __see_below__;
|
||||
|
||||
#elif ! defined(BOOST_JSON_STANDALONE)
|
||||
|
||||
using string_view = boost::string_view;
|
||||
|
||||
#else
|
||||
|
||||
using string_view = std::string_view;
|
||||
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class T>
|
||||
using is_string_viewish = typename std::enable_if<
|
||||
std::is_convertible<
|
||||
T const&, string_view>::value &&
|
||||
! std::is_convertible<
|
||||
T const&, char const*>::value
|
||||
>::type;
|
||||
|
||||
} // detail
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
57
install/boost_1_75_0/include/boost/json/system_error.hpp
Normal file
57
install/boost_1_75_0/include/boost/json/system_error.hpp
Normal file
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_SYSTEM_ERROR_HPP
|
||||
#define BOOST_JSON_SYSTEM_ERROR_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#ifndef BOOST_JSON_STANDALONE
|
||||
# include <boost/system/error_code.hpp>
|
||||
# include <boost/system/system_error.hpp>
|
||||
#else
|
||||
# include <system_error>
|
||||
#endif
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
#ifndef BOOST_JSON_STANDALONE
|
||||
|
||||
/// The type of error code used by the library.
|
||||
using error_code = boost::system::error_code;
|
||||
|
||||
/// The type of error category used by the library.
|
||||
using error_category = boost::system::error_category;
|
||||
|
||||
/// The type of error condition used by the library.
|
||||
using error_condition = boost::system::error_condition;
|
||||
|
||||
/// The type of system error thrown by the library.
|
||||
using system_error = boost::system::system_error;
|
||||
|
||||
#ifdef BOOST_JSON_DOCS
|
||||
/// Returns the generic error category used by the library.
|
||||
error_category const&
|
||||
generic_category();
|
||||
#else
|
||||
using boost::system::generic_category;
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
using error_code = std::error_code;
|
||||
using error_category = std::error_category;
|
||||
using error_condition = std::error_condition;
|
||||
using system_error = std::system_error;
|
||||
using std::generic_category;
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
3926
install/boost_1_75_0/include/boost/json/value.hpp
Normal file
3926
install/boost_1_75_0/include/boost/json/value.hpp
Normal file
File diff suppressed because it is too large
Load Diff
116
install/boost_1_75_0/include/boost/json/value_from.hpp
Normal file
116
install/boost_1_75_0/include/boost/json/value_from.hpp
Normal file
@@ -0,0 +1,116 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
|
||||
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_VALUE_FROM_HPP
|
||||
#define BOOST_JSON_VALUE_FROM_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/json/detail/value_from.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
/** Customization point tag.
|
||||
|
||||
This tag type is used by the function
|
||||
@ref value_from to select overloads
|
||||
of `tag_invoke`.
|
||||
|
||||
@note This type is empty; it has no members.
|
||||
|
||||
@see @ref value_from, @ref value_to, @ref value_to_tag,
|
||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf">
|
||||
tag_invoke: A general pattern for supporting customisable functions</a>
|
||||
*/
|
||||
#ifndef BOOST_JSON_DOCS
|
||||
struct value_from_tag;
|
||||
#else
|
||||
// VFALCO Doc toolchain doesn't like
|
||||
// forward declared ordinary classes.
|
||||
struct value_from_tag {};
|
||||
#endif
|
||||
|
||||
/** Convert an object of type `T` to @ref value.
|
||||
|
||||
This function attempts to convert an object
|
||||
of type `T` to @ref value using
|
||||
|
||||
@li one of @ref value's constructors,
|
||||
|
||||
@li a library-provided generic conversion, or
|
||||
|
||||
@li a user-provided overload of `tag_invoke`.
|
||||
|
||||
In all cases, the conversion is done by calling
|
||||
an overload of `tag_invoke` found by argument-dependent
|
||||
lookup. Its signature should be similar to:
|
||||
|
||||
@code
|
||||
void tag_invoke( value_from_tag, value&, T );
|
||||
@endcode
|
||||
|
||||
A @ref value constructed
|
||||
with the @ref storage_ptr passed to @ref value_from is
|
||||
passed as the second argument to ensure that the memory
|
||||
resource is correctly propagated.
|
||||
|
||||
@par Exception Safety
|
||||
Strong guarantee.
|
||||
|
||||
@tparam T The type of the object to convert.
|
||||
|
||||
@returns `t` converted to @ref value.
|
||||
|
||||
@param t The object to convert.
|
||||
|
||||
@param sp A storage pointer referring to the memory resource
|
||||
to use for the returned @ref value. The default argument for this
|
||||
parameter is `{}`.
|
||||
|
||||
@see @ref value_from_tag, @ref value_to,
|
||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf">
|
||||
tag_invoke: A general pattern for supporting customisable functions</a>
|
||||
*/
|
||||
template<class T>
|
||||
value
|
||||
value_from(
|
||||
T&& t,
|
||||
storage_ptr sp = {})
|
||||
{
|
||||
return detail::value_from_impl(
|
||||
std::forward<T>(t), std::move(sp));
|
||||
}
|
||||
|
||||
/** Determine if `T` can be converted to @ref value.
|
||||
|
||||
If `T` can be converted to @ref value via a
|
||||
call to @ref value_from, the static data member `value`
|
||||
is defined as `true`. Otherwise, `value` is
|
||||
defined as `false`.
|
||||
|
||||
@see @ref value_from
|
||||
*/
|
||||
#ifdef BOOST_JSON_DOCS
|
||||
template<class T>
|
||||
using has_value_from = __see_below__;
|
||||
#else
|
||||
template<class T, class>
|
||||
struct has_value_from : std::false_type { };
|
||||
|
||||
template<class T>
|
||||
struct has_value_from<T, detail::void_t<
|
||||
decltype(detail::value_from_impl(std::declval<T&&>(),
|
||||
std::declval<storage_ptr>()))>>
|
||||
: std::true_type { };
|
||||
#endif
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
493
install/boost_1_75_0/include/boost/json/value_ref.hpp
Normal file
493
install/boost_1_75_0/include/boost/json/value_ref.hpp
Normal file
@@ -0,0 +1,493 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_VALUE_REF_HPP
|
||||
#define BOOST_JSON_VALUE_REF_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/storage_ptr.hpp>
|
||||
#include <boost/json/string.hpp>
|
||||
#include <initializer_list>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
#ifndef BOOST_JSON_DOCS
|
||||
class value;
|
||||
class object;
|
||||
class array;
|
||||
class string;
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
/** The type used in initializer lists.
|
||||
|
||||
This type is used in initializer lists for
|
||||
lazy construction of and assignment to the
|
||||
container types @ref value, @ref array,
|
||||
and @ref object. The two types of initializer
|
||||
lists used are:
|
||||
|
||||
@li `std::initializer_list< value_ref >` for
|
||||
constructing or assigning a @ref value or
|
||||
@ref array, and
|
||||
|
||||
@li `std::initializer_list< std::pair< string_view, value_ref > >`
|
||||
for constructing or assigning an @ref object.
|
||||
|
||||
A `value_ref` uses reference semantics. Creation
|
||||
of the actual container from the initializer
|
||||
list is lazily deferred until the list is used.
|
||||
This means that the @ref memory_resource used to
|
||||
construct a container can be specified after the
|
||||
point where the initializer list is specified.
|
||||
|
||||
@par Example
|
||||
|
||||
This example demonstrates how a user-defined type
|
||||
containing a JSON value can be constructed from
|
||||
an initializer list:
|
||||
|
||||
@code
|
||||
|
||||
class my_type
|
||||
{
|
||||
value jv_;
|
||||
|
||||
public:
|
||||
my_type( std::initializer_list< value_ref > init )
|
||||
: jv_(init)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
@endcode
|
||||
|
||||
@note Never declare a variable of type
|
||||
`std::initializer_list` except in function
|
||||
parameter lists, otherwise the behavior may
|
||||
be undefined.
|
||||
|
||||
@see
|
||||
@ref value,
|
||||
@ref array,
|
||||
@ref object
|
||||
*/
|
||||
class value_ref
|
||||
{
|
||||
friend class value;
|
||||
friend class object;
|
||||
friend class array;
|
||||
|
||||
friend class value_ref_test;
|
||||
|
||||
enum class what
|
||||
{
|
||||
str,
|
||||
ini,
|
||||
func,
|
||||
cfunc,
|
||||
strfunc,
|
||||
};
|
||||
|
||||
using init_list =
|
||||
std::initializer_list<value_ref>;
|
||||
|
||||
struct func_type
|
||||
{
|
||||
value(*f)(void*, storage_ptr);
|
||||
void* p;
|
||||
};
|
||||
|
||||
struct cfunc_type
|
||||
{
|
||||
value(*f)(void const*, storage_ptr);
|
||||
void const* p;
|
||||
};
|
||||
|
||||
union arg_type
|
||||
{
|
||||
string_view str_;
|
||||
init_list init_list_;
|
||||
|
||||
signed char schar_;
|
||||
short short_;
|
||||
int int_;
|
||||
long long_;
|
||||
long long long_long_;
|
||||
unsigned char uchar_;
|
||||
unsigned short ushort_;
|
||||
unsigned int uint_;
|
||||
unsigned long ulong_;
|
||||
unsigned long long ulong_long_;
|
||||
float float_;
|
||||
double double_;
|
||||
bool bool_;
|
||||
std::nullptr_t nullptr_;
|
||||
|
||||
arg_type() {}
|
||||
explicit arg_type(string_view t) noexcept : str_(t) {}
|
||||
explicit arg_type(init_list t) noexcept : init_list_(t) {}
|
||||
explicit arg_type(signed char t) noexcept : schar_(t) {}
|
||||
explicit arg_type(short t) noexcept : short_(t) {}
|
||||
explicit arg_type(int t) noexcept : int_(t) {}
|
||||
explicit arg_type(long t) noexcept : long_(t) {}
|
||||
explicit arg_type(long long t) noexcept : long_long_(t) {}
|
||||
explicit arg_type(unsigned char t) noexcept : uchar_(t) {}
|
||||
explicit arg_type(unsigned short t) noexcept : ushort_(t) {}
|
||||
explicit arg_type(unsigned int t) noexcept : uint_(t) {}
|
||||
explicit arg_type(unsigned long t) noexcept : ulong_(t) {}
|
||||
explicit arg_type(unsigned long long t) noexcept : ulong_long_(t) {}
|
||||
explicit arg_type(float t) noexcept : float_(t) {}
|
||||
explicit arg_type(double t) noexcept : double_(t) {}
|
||||
explicit arg_type(bool t) noexcept : bool_(t) {}
|
||||
explicit arg_type(std::nullptr_t) noexcept : nullptr_() {}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
using is_builtin =
|
||||
std::integral_constant<bool,
|
||||
std::is_same<T, signed char>::value ||
|
||||
std::is_same<T, short>::value ||
|
||||
std::is_same<T, int>::value ||
|
||||
std::is_same<T, long>::value ||
|
||||
std::is_same<T, long long>::value ||
|
||||
std::is_same<T, unsigned char>::value ||
|
||||
std::is_same<T, unsigned short>::value ||
|
||||
std::is_same<T, unsigned int>::value ||
|
||||
std::is_same<T, unsigned long>::value ||
|
||||
std::is_same<T, unsigned long long>::value ||
|
||||
std::is_same<T, float>::value ||
|
||||
std::is_same<T, double>::value ||
|
||||
std::is_same<T, std::nullptr_t>::value>;
|
||||
|
||||
arg_type arg_;
|
||||
#ifndef BOOST_JSON_DOCS
|
||||
// VFALCO doc toolchain erroneously
|
||||
// displays private, anonymous unions as public
|
||||
union
|
||||
{
|
||||
func_type f_;
|
||||
cfunc_type cf_;
|
||||
};
|
||||
#endif
|
||||
what what_;
|
||||
|
||||
public:
|
||||
/// Constructor
|
||||
value_ref(
|
||||
value_ref const&) = default;
|
||||
|
||||
/// Constructor
|
||||
#ifdef BOOST_JSON_DOCS
|
||||
value_ref(string_view s) noexcept;
|
||||
#else
|
||||
template<
|
||||
class T
|
||||
,class = typename
|
||||
std::enable_if<
|
||||
std::is_constructible<
|
||||
string_view, T>::value>::type
|
||||
>
|
||||
value_ref(
|
||||
T const& t) noexcept
|
||||
: arg_(string_view(t))
|
||||
, what_(what::str)
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Constructor
|
||||
template<class T>
|
||||
value_ref(
|
||||
T const& t
|
||||
#ifndef BOOST_JSON_DOCS
|
||||
,typename std::enable_if<
|
||||
! std::is_constructible<
|
||||
string_view, T>::value &&
|
||||
! std::is_same<bool, T>::value
|
||||
>::type* = 0
|
||||
#endif
|
||||
) noexcept
|
||||
: cf_{&from_const<T>, &t}
|
||||
, what_(what::cfunc)
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructor
|
||||
template<class T>
|
||||
value_ref(
|
||||
T&& t
|
||||
#ifndef BOOST_JSON_DOCS
|
||||
,typename std::enable_if<
|
||||
(! std::is_constructible<
|
||||
string_view, T>::value ||
|
||||
std::is_same<string, T>::value) &&
|
||||
! std::is_same<bool,
|
||||
detail::remove_cvref<T>>::value &&
|
||||
std::is_same<T, detail::remove_cvref<T>>
|
||||
::value>::type* = 0
|
||||
#endif
|
||||
) noexcept
|
||||
: f_{&from_rvalue<
|
||||
detail::remove_cvref<T>>, &t}
|
||||
, what_(std::is_same<string, T>::value ?
|
||||
what::strfunc : what::func)
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructor
|
||||
#ifdef BOOST_JSON_DOCS
|
||||
value_ref(bool b) noexcept;
|
||||
#else
|
||||
template<
|
||||
class Bool
|
||||
,class = typename std::enable_if<
|
||||
std::is_same<Bool, bool>::value>::type
|
||||
>
|
||||
value_ref(
|
||||
Bool b) noexcept
|
||||
: arg_(b)
|
||||
, cf_{&from_builtin<bool>, &arg_.bool_}
|
||||
, what_(what::cfunc)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Constructor
|
||||
value_ref(
|
||||
std::initializer_list<
|
||||
value_ref> t) noexcept
|
||||
: arg_(t)
|
||||
, what_(what::ini)
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructor
|
||||
value_ref(signed char t) noexcept
|
||||
: arg_(t)
|
||||
, cf_{&from_builtin<signed char>, &arg_.schar_}
|
||||
, what_(what::cfunc)
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructor
|
||||
value_ref(short t) noexcept
|
||||
: arg_(t)
|
||||
, cf_{&from_builtin<short>, &arg_.short_}
|
||||
, what_(what::cfunc)
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructor
|
||||
value_ref(int t) noexcept
|
||||
: arg_(t)
|
||||
, cf_{&from_builtin<int>, &arg_.int_}
|
||||
, what_(what::cfunc)
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructor
|
||||
value_ref(long t) noexcept
|
||||
: arg_(t)
|
||||
, cf_{&from_builtin<
|
||||
long>, &arg_.long_}
|
||||
, what_(what::cfunc)
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructor
|
||||
value_ref(long long t) noexcept
|
||||
: arg_(t)
|
||||
, cf_{&from_builtin<
|
||||
long long>, &arg_.long_long_}
|
||||
, what_(what::cfunc)
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructor
|
||||
value_ref(unsigned char t) noexcept
|
||||
: arg_(t)
|
||||
, cf_{&from_builtin<
|
||||
unsigned char>, &arg_.uchar_}
|
||||
, what_(what::cfunc)
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructor
|
||||
value_ref(unsigned short t) noexcept
|
||||
: arg_(t)
|
||||
, cf_{&from_builtin<
|
||||
unsigned short>, &arg_.ushort_}
|
||||
, what_(what::cfunc)
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructor
|
||||
value_ref(unsigned int t) noexcept
|
||||
: arg_(t)
|
||||
, cf_{&from_builtin<
|
||||
unsigned int>, &arg_.uint_}
|
||||
, what_(what::cfunc)
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructor
|
||||
value_ref(unsigned long t) noexcept
|
||||
: arg_(t)
|
||||
, cf_{&from_builtin<
|
||||
unsigned long>, &arg_.ulong_}
|
||||
, what_(what::cfunc)
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructor
|
||||
value_ref(unsigned long long t) noexcept
|
||||
: arg_(t)
|
||||
, cf_{&from_builtin<
|
||||
unsigned long long>, &arg_.ulong_long_}
|
||||
, what_(what::cfunc)
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructor
|
||||
value_ref(float t) noexcept
|
||||
: arg_(t)
|
||||
, cf_{&from_builtin<
|
||||
float>, &arg_.float_}
|
||||
, what_(what::cfunc)
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructor
|
||||
value_ref(double t) noexcept
|
||||
: arg_(t)
|
||||
, cf_{&from_builtin<
|
||||
double>, &arg_.double_}
|
||||
, what_(what::cfunc)
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructor
|
||||
value_ref(std::nullptr_t) noexcept
|
||||
: arg_(nullptr)
|
||||
, cf_{&from_builtin<
|
||||
std::nullptr_t>, &arg_.nullptr_}
|
||||
, what_(what::cfunc)
|
||||
{
|
||||
}
|
||||
|
||||
#ifndef BOOST_JSON_DOCS
|
||||
// Not public
|
||||
//private:
|
||||
// VFALCO Why is this needed?
|
||||
/** Operator conversion to @ref value
|
||||
|
||||
This allows creation of a @ref value from
|
||||
an initializer list element.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
operator value() const;
|
||||
#endif
|
||||
|
||||
private:
|
||||
template<class T>
|
||||
static
|
||||
value
|
||||
from_builtin(
|
||||
void const* p,
|
||||
storage_ptr sp) noexcept;
|
||||
|
||||
template<class T>
|
||||
static
|
||||
value
|
||||
from_const(
|
||||
void const* p,
|
||||
storage_ptr sp);
|
||||
|
||||
template<class T>
|
||||
static
|
||||
value
|
||||
from_rvalue(
|
||||
void* p,
|
||||
storage_ptr sp);
|
||||
|
||||
static
|
||||
BOOST_JSON_DECL
|
||||
value
|
||||
from_init_list(
|
||||
void const* p,
|
||||
storage_ptr sp);
|
||||
|
||||
inline
|
||||
bool
|
||||
is_key_value_pair() const noexcept;
|
||||
|
||||
static
|
||||
inline
|
||||
bool
|
||||
maybe_object(
|
||||
std::initializer_list<
|
||||
value_ref> init) noexcept;
|
||||
|
||||
inline
|
||||
string_view
|
||||
get_string() const noexcept;
|
||||
|
||||
BOOST_JSON_DECL
|
||||
value
|
||||
make_value(
|
||||
storage_ptr sp) const;
|
||||
|
||||
BOOST_JSON_DECL
|
||||
static
|
||||
value
|
||||
make_value(
|
||||
std::initializer_list<
|
||||
value_ref> init,
|
||||
storage_ptr sp);
|
||||
|
||||
BOOST_JSON_DECL
|
||||
static
|
||||
object
|
||||
make_object(
|
||||
std::initializer_list<value_ref> init,
|
||||
storage_ptr sp);
|
||||
|
||||
BOOST_JSON_DECL
|
||||
static
|
||||
array
|
||||
make_array(
|
||||
std::initializer_list<
|
||||
value_ref> init,
|
||||
storage_ptr sp);
|
||||
|
||||
BOOST_JSON_DECL
|
||||
static
|
||||
void
|
||||
write_array(
|
||||
value* dest,
|
||||
std::initializer_list<
|
||||
value_ref> init,
|
||||
storage_ptr const& sp);
|
||||
};
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
// Must be included here for this file to stand alone
|
||||
#include <boost/json/value.hpp>
|
||||
|
||||
// includes are at the bottom of <boost/json/value.hpp>
|
||||
//#include <boost/json/impl/value.hpp>
|
||||
//#include <boost/json/impl/value.ipp>
|
||||
|
||||
#endif
|
||||
508
install/boost_1_75_0/include/boost/json/value_stack.hpp
Normal file
508
install/boost_1_75_0/include/boost/json/value_stack.hpp
Normal file
@@ -0,0 +1,508 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_VALUE_STACK_HPP
|
||||
#define BOOST_JSON_VALUE_STACK_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/error.hpp>
|
||||
#include <boost/json/storage_ptr.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <stddef.h>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
/** A stack of @ref value elements, for building a document.
|
||||
|
||||
This stack of @ref value allows iterative
|
||||
construction of a JSON document in memory.
|
||||
The implementation uses temporary internal
|
||||
storage to buffer elements so that arrays, objects,
|
||||
and strings in the document are constructed using a
|
||||
single memory allocation. This improves performance
|
||||
and makes efficient use of the @ref memory_resource
|
||||
used to create the resulting @ref value.
|
||||
|
||||
Temporary storage used by the implementation
|
||||
initially comes from an optional memory buffer
|
||||
owned by the caller. If that storage is exhausted,
|
||||
then memory is obtained dynamically from the
|
||||
@ref memory_resource provided on construction.
|
||||
|
||||
@par Usage
|
||||
|
||||
Construct the stack with an optional initial
|
||||
temporary buffer, and a @ref storage_ptr to use for
|
||||
more storage when the initial buffer is exhausted.
|
||||
Then to build a @ref value, first call @ref reset
|
||||
and optionally specify the @ref memory_resource
|
||||
which will be used for the value. Then push elements
|
||||
onto the stack by calling the corresponding functions.
|
||||
After the document has been fully created, call
|
||||
@ref release to acquire ownership of the top-level
|
||||
@ref value.
|
||||
|
||||
@par Performance
|
||||
|
||||
The initial buffer and any dynamically allocated
|
||||
temporary buffers are retained until the stack
|
||||
is destroyed. This improves performance when using
|
||||
a single stack instance to produce multiple
|
||||
values.
|
||||
|
||||
@par Example
|
||||
|
||||
The following code constructs a @ref value which
|
||||
when serialized produces a JSON object with three
|
||||
elements. It uses a local buffer for the temporary
|
||||
storage, and a separate local buffer for the storage
|
||||
of the resulting value. No memory is dynamically
|
||||
allocated; this shows how to construct a value
|
||||
without using the heap.
|
||||
|
||||
@code
|
||||
|
||||
// This example builds a json::value without any dynamic memory allocations:
|
||||
|
||||
// Construct the value stack using a local buffer
|
||||
unsigned char temp[4096];
|
||||
value_stack st( storage_ptr(), temp, sizeof(temp) );
|
||||
|
||||
// Create a static resource with a local initial buffer
|
||||
unsigned char buf[4096];
|
||||
static_resource mr( buf, sizeof(buf) );
|
||||
|
||||
// All values on the stack will use `mr`
|
||||
st.reset(&mr);
|
||||
|
||||
// Push the key/value pair "a":1.
|
||||
st.push_key("a");
|
||||
st.push_int64(1);
|
||||
|
||||
// Push "b":null
|
||||
st.push_key("b");
|
||||
st.push_null();
|
||||
|
||||
// Push "c":"hello"
|
||||
st.push_key("c");
|
||||
st.push_string("hello");
|
||||
|
||||
// Pop the three key/value pairs and push an object with those three values.
|
||||
st.push_object(3);
|
||||
|
||||
// Pop the object from the stack and take ownership.
|
||||
value jv = st.release();
|
||||
|
||||
assert( serialize(jv) == "{\"a\":1,\"b\":null,\"c\":\"hello\"}" );
|
||||
|
||||
// At this point we could re-use the stack by calling reset
|
||||
|
||||
@endcode
|
||||
|
||||
@par Thread Safety
|
||||
|
||||
Distinct instances may be accessed concurrently.
|
||||
Non-const member functions of a shared instance
|
||||
may not be called concurrently with any other
|
||||
member functions of that instance.
|
||||
*/
|
||||
class value_stack
|
||||
{
|
||||
class stack
|
||||
{
|
||||
enum
|
||||
{
|
||||
min_size_ = 16
|
||||
};
|
||||
|
||||
storage_ptr sp_;
|
||||
void* temp_;
|
||||
value* begin_;
|
||||
value* top_;
|
||||
value* end_;
|
||||
// string starts at top_+1
|
||||
std::size_t chars_ = 0;
|
||||
bool run_dtors_ = true;
|
||||
|
||||
public:
|
||||
inline ~stack();
|
||||
inline stack(
|
||||
storage_ptr sp,
|
||||
void* temp, std::size_t size) noexcept;
|
||||
inline void run_dtors(bool b) noexcept;
|
||||
inline std::size_t size() const noexcept;
|
||||
inline bool has_chars();
|
||||
|
||||
inline void clear() noexcept;
|
||||
inline void maybe_grow();
|
||||
inline void grow_one();
|
||||
inline void grow(std::size_t nchars);
|
||||
|
||||
inline void append(string_view s);
|
||||
inline string_view release_string() noexcept;
|
||||
inline value* release(std::size_t n) noexcept;
|
||||
template<class... Args> value& push(Args&&... args);
|
||||
template<class Unchecked> void exchange(Unchecked&& u);
|
||||
};
|
||||
|
||||
stack st_;
|
||||
storage_ptr sp_;
|
||||
|
||||
public:
|
||||
/// Copy constructor (deleted)
|
||||
value_stack(
|
||||
value_stack const&) = delete;
|
||||
|
||||
/// Copy assignment (deleted)
|
||||
value_stack& operator=(
|
||||
value_stack const&) = delete;
|
||||
|
||||
/** Destructor.
|
||||
|
||||
All dynamically allocated memory and
|
||||
partial or complete elements is freed.
|
||||
|
||||
@par Complexity
|
||||
Linear in the size of partial results.
|
||||
|
||||
@par Exception Safety
|
||||
No-throw guarantee.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
~value_stack();
|
||||
|
||||
/** Constructor.
|
||||
|
||||
Constructs an empty stack. Before any
|
||||
@ref value can be built, the function
|
||||
@ref reset must be called.
|
||||
|
||||
The `sp` parameter is only used to allocate
|
||||
intermediate storage; it will not be used
|
||||
for the @ref value returned by @ref release.
|
||||
|
||||
@param sp A pointer to the @ref memory_resource
|
||||
to use for intermediate storage allocations. If
|
||||
this argument is omitted, the default memory
|
||||
resource is used.
|
||||
|
||||
@param temp_buffer A pointer to a caller-owned
|
||||
buffer which will be used to store temporary
|
||||
data used while building the value. If this
|
||||
pointer is null, the builder will use the
|
||||
storage pointer to allocate temporary data.
|
||||
|
||||
@param temp_size The number of valid bytes of
|
||||
storage pointed to by `temp_buffer`.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
value_stack(
|
||||
storage_ptr sp = {},
|
||||
unsigned char* temp_buffer = nullptr,
|
||||
std::size_t temp_size = 0) noexcept;
|
||||
|
||||
/** Prepare to build a new document.
|
||||
|
||||
This function must be called before constructing
|
||||
a new top-level @ref value. Any previously existing
|
||||
partial or complete elements are destroyed, but
|
||||
internal dynamically allocated memory is preserved
|
||||
which may be reused to build new values.
|
||||
|
||||
@par Exception Safety
|
||||
|
||||
No-throw guarantee.
|
||||
|
||||
@param sp A pointer to the @ref memory_resource
|
||||
to use for top-level @ref value and all child
|
||||
values. The stack will acquire shared ownership
|
||||
of the memory resource until @ref release or
|
||||
@ref reset is called, or when the stack is
|
||||
destroyed.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
reset(storage_ptr sp = {}) noexcept;
|
||||
|
||||
/** Return the top-level @ref value.
|
||||
|
||||
This function transfers ownership of the
|
||||
constructed top-level value to the caller.
|
||||
The behavior is undefined if there is not
|
||||
a single, top-level element.
|
||||
|
||||
@par Exception Safety
|
||||
|
||||
No-throw guarantee.
|
||||
|
||||
@return A __value__ holding the result.
|
||||
Ownership of this value is transferred
|
||||
to the caller. Ownership of the memory
|
||||
resource used in the last call to @ref reset
|
||||
is released.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
value
|
||||
release() noexcept;
|
||||
|
||||
//--------------------------------------------
|
||||
|
||||
/** Push an array formed by popping `n` values from the stack.
|
||||
|
||||
This function pushes an @ref array value
|
||||
onto the stack. The array is formed by first
|
||||
popping the top `n` values from the stack.
|
||||
If the stack contains fewer than `n` values,
|
||||
or if any of the top `n` values on the stack
|
||||
is a key, the behavior is undefined.
|
||||
|
||||
@par Example
|
||||
|
||||
The following statements produce an array
|
||||
with the contents 1, 2, 3:
|
||||
|
||||
@code
|
||||
|
||||
value_stack st;
|
||||
|
||||
// reset must be called first or else the behavior is undefined
|
||||
st.reset();
|
||||
|
||||
// Place three values on the stack
|
||||
st.push_int64( 1 );
|
||||
st.push_int64( 2 );
|
||||
st.push_int64( 3 );
|
||||
|
||||
// Remove the 3 values, and push an array with those 3 elements on the stack
|
||||
st.push_array( 3 );
|
||||
|
||||
// Pop the object from the stack and take ownership.
|
||||
value jv = st.release();
|
||||
|
||||
assert( serialize(jv) == "[1,2,3]" );
|
||||
|
||||
// At this point, reset must be called again to use the stack
|
||||
|
||||
@endcode
|
||||
|
||||
@param n The number of values to pop from the
|
||||
top of the stack to form the array.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
push_array(std::size_t n);
|
||||
|
||||
/** Push an object formed by popping `n` key/value pairs from the stack.
|
||||
|
||||
This function pushes an @ref object value
|
||||
onto the stack. The object is formed by first
|
||||
popping the top `n` key/value pairs from the
|
||||
stack. If the stack contains fewer than `n`
|
||||
key/value pairs, or if any of the top `n` key/value
|
||||
pairs on the stack does not consist of exactly one
|
||||
key followed by one value, the behavior is undefined.
|
||||
|
||||
@note
|
||||
|
||||
A key/value pair is formed by pushing a key, and then
|
||||
pushing a value.
|
||||
|
||||
@par Example
|
||||
|
||||
The following code creates an object on the stack
|
||||
with a single element, where key is "x" and value
|
||||
is true:
|
||||
|
||||
@code
|
||||
|
||||
value_stack st;
|
||||
|
||||
// reset must be called first or else the behavior is undefined
|
||||
st.reset();
|
||||
|
||||
// Place a key/value pair onto the stack
|
||||
st.push_key( "x" );
|
||||
st.push_bool( true );
|
||||
|
||||
// Replace the key/value pair with an object containing a single element
|
||||
st.push_object( 1 );
|
||||
|
||||
// Pop the object from the stack and take ownership.
|
||||
value jv = st.release();
|
||||
|
||||
assert( serialize(jv) == "{\"x\",true}" );
|
||||
|
||||
// At this point, reset must be called again to use the stack
|
||||
|
||||
@endcode
|
||||
|
||||
@par Duplicate Keys
|
||||
|
||||
If there are object elements with duplicate keys;
|
||||
that is, if multiple elements in an object have
|
||||
keys that compare equal, only the last equivalent
|
||||
element will be inserted.
|
||||
|
||||
@param n The number of key/value pairs to pop from the
|
||||
top of the stack to form the array.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
push_object(std::size_t n);
|
||||
|
||||
/** Push part of a key or string onto the stack.
|
||||
|
||||
This function pushes the characters in `s` onto
|
||||
the stack, appending to any existing characters
|
||||
or creating new characters as needed. Once a
|
||||
string part is placed onto the stack, the only
|
||||
valid stack operations are:
|
||||
|
||||
@li @ref push_chars to append additional
|
||||
characters to the key or string being built,
|
||||
|
||||
@li @ref push_key or @ref push_string to
|
||||
finish building the key or string and place
|
||||
the value onto the stack.
|
||||
|
||||
@par Exception Safety
|
||||
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
|
||||
@param s The characters to append. This may be empty.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
push_chars(
|
||||
string_view s);
|
||||
|
||||
/** Push a key onto the stack.
|
||||
|
||||
This function notionally removes all the
|
||||
characters currently on the stack, then
|
||||
pushes a @ref value containing a key onto
|
||||
the stack formed by appending `s` to the
|
||||
removed characters.
|
||||
|
||||
@par Exception Safety
|
||||
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
|
||||
@param s The characters to append. This may be empty.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
push_key(
|
||||
string_view s);
|
||||
|
||||
/** Place a string value onto the stack.
|
||||
|
||||
This function notionally removes all the
|
||||
characters currently on the stack, then
|
||||
pushes a @ref value containing a @ref string
|
||||
onto the stack formed by appending `s` to the
|
||||
removed characters.
|
||||
|
||||
@par Exception Safety
|
||||
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
|
||||
@param s The characters to append. This may be empty.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
push_string(
|
||||
string_view s);
|
||||
|
||||
/** Push a number onto the stack
|
||||
|
||||
This function pushes a number value onto the stack.
|
||||
|
||||
@par Exception Safety
|
||||
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
|
||||
@param i The number to insert.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
push_int64(
|
||||
int64_t i);
|
||||
|
||||
/** Push a number onto the stack
|
||||
|
||||
This function pushes a number value onto the stack.
|
||||
|
||||
@par Exception Safety
|
||||
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
|
||||
@param u The number to insert.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
push_uint64(
|
||||
uint64_t u);
|
||||
|
||||
/** Push a number onto the stack
|
||||
|
||||
This function pushes a number value onto the stack.
|
||||
|
||||
@par Exception Safety
|
||||
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
|
||||
@param d The number to insert.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
push_double(
|
||||
double d);
|
||||
|
||||
/** Push a `bool` onto the stack
|
||||
|
||||
This function pushes a boolean value onto the stack.
|
||||
|
||||
@par Exception Safety
|
||||
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
|
||||
@param b The boolean to insert.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
push_bool(
|
||||
bool b);
|
||||
|
||||
/** Push a null onto the stack
|
||||
|
||||
This function pushes a boolean value onto the stack.
|
||||
|
||||
@par Exception Safety
|
||||
|
||||
Basic guarantee.
|
||||
Calls to `memory_resource::allocate` may throw.
|
||||
*/
|
||||
BOOST_JSON_DECL
|
||||
void
|
||||
push_null();
|
||||
};
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
123
install/boost_1_75_0/include/boost/json/value_to.hpp
Normal file
123
install/boost_1_75_0/include/boost/json/value_to.hpp
Normal file
@@ -0,0 +1,123 @@
|
||||
//
|
||||
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
|
||||
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_VALUE_TO_HPP
|
||||
#define BOOST_JSON_VALUE_TO_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/json/detail/value_to.hpp>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
/** Customization point tag type.
|
||||
|
||||
This tag type is used by the function
|
||||
@ref value_to to select overloads
|
||||
of `tag_invoke`.
|
||||
|
||||
@note This type is empty; it has no members.
|
||||
|
||||
@see @ref value_from, @ref value_from_tag, @ref value_to,
|
||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf">
|
||||
tag_invoke: A general pattern for supporting customisable functions</a>
|
||||
*/
|
||||
template<class T>
|
||||
struct value_to_tag;
|
||||
|
||||
/** Convert a @ref value to an object of type `T`.
|
||||
|
||||
This function attempts to convert a @ref value
|
||||
to `T` using
|
||||
|
||||
@li one of @ref value's accessors, or
|
||||
|
||||
@li a library-provided generic conversion, or
|
||||
|
||||
@li a user-provided overload of `tag_invoke`.
|
||||
|
||||
In all cases, the conversion is done by calling
|
||||
an overload of `tag_invoke` found by argument-dependent
|
||||
lookup. Its signature should be similar to:
|
||||
|
||||
@code
|
||||
T tag_invoke( value_to_tag<T>, value );
|
||||
@endcode
|
||||
|
||||
The object returned by the function call is
|
||||
returned by @ref value_to as the result of the
|
||||
conversion.
|
||||
|
||||
@par Constraints
|
||||
@code
|
||||
! std::is_reference< T >::value
|
||||
@endcode
|
||||
|
||||
@par Exception Safety
|
||||
Strong guarantee.
|
||||
|
||||
@tparam T The type to convert to.
|
||||
|
||||
@returns `jv` converted to `T`.
|
||||
|
||||
@param jv The @ref value to convert.
|
||||
|
||||
@see @ref value_to_tag, @ref value_from,
|
||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1895r0.pdf">
|
||||
tag_invoke: A general pattern for supporting customisable functions</a>
|
||||
*/
|
||||
#ifdef BOOST_JSON_DOCS
|
||||
template<class T>
|
||||
T
|
||||
value_to(const value& jv);
|
||||
#else
|
||||
template<class T, class U
|
||||
, typename std::enable_if<
|
||||
! std::is_reference<T>::value &&
|
||||
std::is_same<U, value>::value>::type*
|
||||
>
|
||||
T
|
||||
value_to(const U& jv)
|
||||
{
|
||||
return detail::value_to_impl(
|
||||
value_to_tag<typename std::remove_cv<T>::type>(), jv);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Determine a @ref value can be converted to `T`.
|
||||
|
||||
If @ref value can be converted to `T` via a
|
||||
call to @ref value_to, the static data member `value`
|
||||
is defined as `true`. Otherwise, `value` is
|
||||
defined as `false`.
|
||||
|
||||
@see @ref value_to
|
||||
*/
|
||||
#ifdef BOOST_JSON_DOCS
|
||||
template<class T>
|
||||
using has_value_to = __see_below__;
|
||||
#else
|
||||
template<class T, class>
|
||||
struct has_value_to
|
||||
: std::false_type { };
|
||||
|
||||
template<class T>
|
||||
struct has_value_to<T, detail::void_t<decltype(
|
||||
detail::value_to_impl(
|
||||
value_to_tag<detail::remove_cvref<T>>(),
|
||||
std::declval<const value&>())),
|
||||
typename std::enable_if<
|
||||
! std::is_reference<T>::value>::type
|
||||
> > : std::true_type { };
|
||||
#endif
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#endif
|
||||
48
install/boost_1_75_0/include/boost/json/visit.hpp
Normal file
48
install/boost_1_75_0/include/boost/json/visit.hpp
Normal file
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// 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/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_VISIT_HPP
|
||||
#define BOOST_JSON_VISIT_HPP
|
||||
|
||||
#include <boost/json/detail/config.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
BOOST_JSON_NS_BEGIN
|
||||
|
||||
/** Invoke a function object with the contents of a @ref value
|
||||
|
||||
@return The value returned by Visitor.
|
||||
|
||||
@param v The visitation function to invoke
|
||||
|
||||
@param jv The value to visit.
|
||||
*/
|
||||
/** @{ */
|
||||
template<class Visitor>
|
||||
auto
|
||||
visit(
|
||||
Visitor&& v,
|
||||
value& jv) -> decltype(
|
||||
std::declval<Visitor>()(nullptr));
|
||||
|
||||
template<class Visitor>
|
||||
auto
|
||||
visit(
|
||||
Visitor &&v,
|
||||
value const &jv) -> decltype(
|
||||
std::declval<Visitor>()(nullptr));
|
||||
/** @} */
|
||||
|
||||
BOOST_JSON_NS_END
|
||||
|
||||
#include <boost/json/impl/visit.hpp>
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user