mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
3rdparty: Update rapidyaml to v0.9.0
This commit is contained in:
15
3rdparty/rapidyaml/CMakeLists.txt
vendored
15
3rdparty/rapidyaml/CMakeLists.txt
vendored
@@ -34,15 +34,26 @@ add_library(pcsx2-rapidyaml
|
||||
include/c4/yml/detail/stack.hpp
|
||||
include/c4/yml/emit.def.hpp
|
||||
include/c4/yml/emit.hpp
|
||||
include/c4/yml/event_handler_stack.hpp
|
||||
include/c4/yml/event_handler_tree.hpp
|
||||
include/c4/yml/filter_processor.hpp
|
||||
include/c4/yml/fwd.hpp
|
||||
include/c4/yml/export.hpp
|
||||
include/c4/yml/node.hpp
|
||||
include/c4/yml/node_type.hpp
|
||||
include/c4/yml/parse.hpp
|
||||
include/c4/yml/parse_engine.def.hpp
|
||||
include/c4/yml/parse_engine.hpp
|
||||
include/c4/yml/parser_state.hpp
|
||||
include/c4/yml/reference_resolver.hpp
|
||||
include/c4/yml/preprocess.hpp
|
||||
include/c4/yml/std/map.hpp
|
||||
include/c4/yml/std/std.hpp
|
||||
include/c4/yml/std/string.hpp
|
||||
include/c4/yml/std/vector.hpp
|
||||
include/c4/yml/tag.hpp
|
||||
include/c4/yml/tree.hpp
|
||||
include/c4/yml/version.hpp
|
||||
include/c4/yml/writer.hpp
|
||||
include/c4/yml/yml.hpp
|
||||
include/ryml.hpp
|
||||
@@ -58,6 +69,10 @@ add_library(pcsx2-rapidyaml
|
||||
src/c4/yml/parse.cpp
|
||||
src/c4/yml/preprocess.cpp
|
||||
src/c4/yml/tree.cpp
|
||||
src/c4/yml/node_type.cpp
|
||||
src/c4/yml/reference_resolver.cpp
|
||||
src/c4/yml/tag.cpp
|
||||
src/c4/yml/version.cpp
|
||||
)
|
||||
|
||||
target_include_directories(pcsx2-rapidyaml PRIVATE
|
||||
|
||||
26
3rdparty/rapidyaml/include/c4/blob.hpp
vendored
26
3rdparty/rapidyaml/include/c4/blob.hpp
vendored
@@ -18,6 +18,8 @@ template<class T> struct is_blob_type<blob_<T>> : std::integral_constant<bool, t
|
||||
template<class T> struct is_blob_value_type : std::integral_constant<bool, (std::is_fundamental<T>::value || std::is_trivially_copyable<T>::value)> {};
|
||||
} // namespace
|
||||
|
||||
// NOLINTBEGIN(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
|
||||
|
||||
template<class T>
|
||||
struct blob_
|
||||
{
|
||||
@@ -37,23 +39,25 @@ public:
|
||||
C4_ALWAYS_INLINE blob_& operator=(blob_ && that) noexcept = default;
|
||||
C4_ALWAYS_INLINE blob_& operator=(blob_ const& that) noexcept = default;
|
||||
|
||||
template<class U, class=typename std::enable_if<std::is_const<T>::value && std::is_same<typename std::add_const<U>::type, T>::value, U>::type> C4_ALWAYS_INLINE blob_(blob_<U> const& that) noexcept : buf(that.buf), len(that.len) {}
|
||||
template<class U, class=typename std::enable_if<std::is_const<T>::value && std::is_same<typename std::add_const<U>::type, T>::value, U>::type> C4_ALWAYS_INLINE blob_(blob_<U> && that) noexcept : buf(that.buf), len(that.len) {}
|
||||
template<class U, class=typename std::enable_if<std::is_const<T>::value && std::is_same<typename std::add_const<U>::type, T>::value, U>::type> C4_ALWAYS_INLINE blob_& operator=(blob_<U> && that) noexcept { buf = that.buf; len = that.len; }
|
||||
template<class U, class=typename std::enable_if<std::is_const<T>::value && std::is_same<typename std::add_const<U>::type, T>::value, U>::type> C4_ALWAYS_INLINE blob_& operator=(blob_<U> const& that) noexcept { buf = that.buf; len = that.len; }
|
||||
template<class U, class=typename std::enable_if<std::is_const<T>::value && std::is_same<typename std::add_const<U>::type, T>::value, U>::type> C4_ALWAYS_INLINE blob_(blob_<U> const& that) noexcept : buf(that.buf), len(that.len) {} // NOLINT
|
||||
template<class U, class=typename std::enable_if<std::is_const<T>::value && std::is_same<typename std::add_const<U>::type, T>::value, U>::type> C4_ALWAYS_INLINE blob_(blob_<U> && that) noexcept : buf(that.buf), len(that.len) {} // NOLINT
|
||||
template<class U, class=typename std::enable_if<std::is_const<T>::value && std::is_same<typename std::add_const<U>::type, T>::value, U>::type> C4_ALWAYS_INLINE blob_& operator=(blob_<U> && that) noexcept { buf = that.buf; len = that.len; } // NOLINT
|
||||
template<class U, class=typename std::enable_if<std::is_const<T>::value && std::is_same<typename std::add_const<U>::type, T>::value, U>::type> C4_ALWAYS_INLINE blob_& operator=(blob_<U> const& that) noexcept { buf = that.buf; len = that.len; } // NOLINT
|
||||
|
||||
C4_ALWAYS_INLINE blob_(void *ptr, size_t n) noexcept : buf(reinterpret_cast<T*>(ptr)), len(n) {}
|
||||
C4_ALWAYS_INLINE blob_(void const *ptr, size_t n) noexcept : buf(reinterpret_cast<T*>(ptr)), len(n) {}
|
||||
C4_ALWAYS_INLINE blob_(void *ptr, size_t n) noexcept : buf(reinterpret_cast<T*>(ptr)), len(n) {} // NOLINT
|
||||
C4_ALWAYS_INLINE blob_(void const *ptr, size_t n) noexcept : buf(reinterpret_cast<T*>(ptr)), len(n) {} // NOLINT
|
||||
|
||||
#define _C4_REQUIRE_BLOBTYPE(ty) class=typename std::enable_if<((!detail::is_blob_type<ty>::value) && (detail::is_blob_value_type<ty>::value)), T>::type
|
||||
template<class U, _C4_REQUIRE_BLOBTYPE(U)> C4_ALWAYS_INLINE blob_(U &var) noexcept : buf(reinterpret_cast<T*>(&var)), len(sizeof(U)) {}
|
||||
template<class U, _C4_REQUIRE_BLOBTYPE(U)> C4_ALWAYS_INLINE blob_(U *ptr, size_t n) noexcept : buf(reinterpret_cast<T*>(ptr)), len(sizeof(U) * n) { C4_ASSERT(is_aligned(ptr)); }
|
||||
template<class U, _C4_REQUIRE_BLOBTYPE(U)> C4_ALWAYS_INLINE blob_& operator= (U &var) noexcept { buf = reinterpret_cast<T*>(&var); len = sizeof(U); return *this; }
|
||||
template<class U, size_t N, _C4_REQUIRE_BLOBTYPE(U)> C4_ALWAYS_INLINE blob_(U (&arr)[N]) noexcept : buf(reinterpret_cast<T*>(arr)), len(sizeof(U) * N) {}
|
||||
template<class U, size_t N, _C4_REQUIRE_BLOBTYPE(U)> C4_ALWAYS_INLINE blob_& operator= (U (&arr)[N]) noexcept { buf = reinterpret_cast<T*>(arr); len = sizeof(U) * N; return *this; }
|
||||
template<class U, _C4_REQUIRE_BLOBTYPE(U)> C4_ALWAYS_INLINE blob_(U &var) noexcept : buf(reinterpret_cast<T*>(&var)), len(sizeof(U)) {} // NOLINT
|
||||
template<class U, _C4_REQUIRE_BLOBTYPE(U)> C4_ALWAYS_INLINE blob_(U *ptr, size_t n) noexcept : buf(reinterpret_cast<T*>(ptr)), len(sizeof(U) * n) { C4_ASSERT(is_aligned(ptr)); } // NOLINT
|
||||
template<class U, _C4_REQUIRE_BLOBTYPE(U)> C4_ALWAYS_INLINE blob_& operator= (U &var) noexcept { buf = reinterpret_cast<T*>(&var); len = sizeof(U); return *this; } // NOLINT
|
||||
template<class U, size_t N, _C4_REQUIRE_BLOBTYPE(U)> C4_ALWAYS_INLINE blob_(U (&arr)[N]) noexcept : buf(reinterpret_cast<T*>(arr)), len(sizeof(U) * N) {} // NOLINT
|
||||
template<class U, size_t N, _C4_REQUIRE_BLOBTYPE(U)> C4_ALWAYS_INLINE blob_& operator= (U (&arr)[N]) noexcept { buf = reinterpret_cast<T*>(arr); len = sizeof(U) * N; return *this; } // NOLINT
|
||||
#undef _C4_REQUIRE_BLOBTYPE
|
||||
};
|
||||
|
||||
// NOLINTEND(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
|
||||
|
||||
/** an immutable binary blob */
|
||||
using cblob = blob_<cbyte>;
|
||||
/** a mutable binary blob */
|
||||
|
||||
148
3rdparty/rapidyaml/include/c4/charconv.hpp
vendored
148
3rdparty/rapidyaml/include/c4/charconv.hpp
vendored
@@ -55,14 +55,7 @@
|
||||
# define C4CORE_HAVE_FAST_FLOAT 1
|
||||
# endif
|
||||
# if C4CORE_HAVE_FAST_FLOAT
|
||||
C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wsign-conversion")
|
||||
C4_SUPPRESS_WARNING_GCC("-Warray-bounds")
|
||||
# if defined(__GNUC__) && __GNUC__ >= 5
|
||||
C4_SUPPRESS_WARNING_GCC("-Wshift-count-overflow")
|
||||
# endif
|
||||
//# include "c4/ext/fast_float.hpp"
|
||||
#include "fast_float/fast_float.h"
|
||||
C4_SUPPRESS_WARNING_GCC_POP
|
||||
# endif
|
||||
#elif (C4_CPP >= 17)
|
||||
# define C4CORE_HAVE_FAST_FLOAT 0
|
||||
@@ -102,15 +95,13 @@
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4996) // snprintf/scanf: this function or variable may be unsafe
|
||||
# if C4_MSVC_VERSION != C4_MSVC_VERSION_2017
|
||||
# pragma warning(disable: 4800) //'int': forcing value to bool 'true' or 'false' (performance warning)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
#elif defined(__clang__)
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare"
|
||||
# pragma clang diagnostic ignored "-Wformat-nonliteral"
|
||||
@@ -136,6 +127,7 @@
|
||||
#define C4_NO_UBSAN_IOVRFLW
|
||||
#endif
|
||||
|
||||
// NOLINTBEGIN(hicpp-signed-bitwise)
|
||||
|
||||
namespace c4 {
|
||||
|
||||
@@ -144,11 +136,11 @@ namespace c4 {
|
||||
* Lightweight, very fast generic type-safe wrappers for converting
|
||||
* individual values to/from strings. These are the main generic
|
||||
* functions:
|
||||
* - @ref doc_to_chars and its alias @ref doc_xtoa: implemented by calling @ref itoa()/@ref utoa()/@ref ftoa()/@ref dtoa() (or generically @ref xtoa())
|
||||
* - @ref doc_from_chars and its alias @ref doc_atox: implemented by calling @ref atoi()/@ref atou()/@ref atof()/@ref atod() (or generically @ref atox())
|
||||
* - @ref doc_to_chars and its alias @ref xtoa(): implemented by calling @ref itoa() / @ref utoa() / @ref ftoa() / @ref dtoa() (or generically @ref xtoa())
|
||||
* - @ref doc_from_chars and its alias @ref atox(): implemented by calling @ref atoi() / @ref atou() / @ref atof() / @ref atod() (or generically @ref atox())
|
||||
* - @ref to_chars_sub()
|
||||
* - @ref from_chars_first()
|
||||
* - @ref xtoa()/@ref atox() are implemented in terms @ref write_dec()/@ref read_dec() et al (see @ref doc_write/@ref doc_read())
|
||||
* - @ref xtoa() and @ref atox() are implemented in terms of @ref write_dec() / @ref read_dec() et al (see @ref doc_write / @ref doc_read())
|
||||
*
|
||||
* And also some modest brag is in order: these functions are really
|
||||
* fast: faster even than C++17 `std::to_chars()` and
|
||||
@@ -241,7 +233,7 @@ struct is_fixed_length
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
# pragma warning(push)
|
||||
#elif defined(__clang__)
|
||||
# pragma clang diagnostic push
|
||||
@@ -377,7 +369,7 @@ template<> struct charconv_digits_<4u, false> // uint32_t
|
||||
static constexpr csubstr max_value_dec() noexcept { return csubstr("4294967295"); }
|
||||
static constexpr bool is_oct_overflow(csubstr str) noexcept { return !((str.len < 11) || (str.len == 11 && str[0] <= '3')); }
|
||||
};
|
||||
template<> struct charconv_digits_<8u, true> // int32_t
|
||||
template<> struct charconv_digits_<8u, true> // int64_t
|
||||
{
|
||||
enum : size_t {
|
||||
maxdigits_bin = 1 + 2 + 64, // len=67: -9223372036854775808 -0b1000000000000000000000000000000000000000000000000000000000000000
|
||||
@@ -396,7 +388,7 @@ template<> struct charconv_digits_<8u, true> // int32_t
|
||||
static constexpr csubstr max_value_dec() noexcept { return csubstr("9223372036854775807"); }
|
||||
static constexpr bool is_oct_overflow(csubstr str) noexcept { return !((str.len < 22)); }
|
||||
};
|
||||
template<> struct charconv_digits_<8u, false>
|
||||
template<> struct charconv_digits_<8u, false> // uint64_t
|
||||
{
|
||||
enum : size_t {
|
||||
maxdigits_bin = 2 + 64, // len=66: 18446744073709551615 0b1111111111111111111111111111111111111111111111111111111111111111
|
||||
@@ -545,24 +537,25 @@ C4_CONSTEXPR14 C4_ALWAYS_INLINE unsigned digits_oct(T v_) noexcept
|
||||
// TODO: is there a better way?
|
||||
C4_STATIC_ASSERT(std::is_integral<T>::value);
|
||||
C4_ASSERT(v_ >= 0);
|
||||
using U = typename
|
||||
std::conditional<sizeof(T) <= sizeof(unsigned),
|
||||
unsigned,
|
||||
typename std::make_unsigned<T>::type>::type;
|
||||
U v = (U) v_; // safe because we require v_ >= 0
|
||||
unsigned __n = 1;
|
||||
const unsigned __b2 = 64u;
|
||||
const unsigned __b3 = __b2 * 8u;
|
||||
const unsigned long __b4 = __b3 * 8u;
|
||||
using U = typename std::conditional<sizeof(T) <= sizeof(unsigned),
|
||||
unsigned,
|
||||
typename std::make_unsigned<T>::type>::type;
|
||||
U v = (U) v_; // safe because we require v_ >= 0 // NOLINT
|
||||
uint32_t __n = 1;
|
||||
enum : U {
|
||||
__b2 = 64u,
|
||||
__b3 = 64u * 8u,
|
||||
__b4 = 64u * 8u * 8u,
|
||||
};
|
||||
while(true)
|
||||
{
|
||||
if(v < 8u)
|
||||
return __n;
|
||||
if(v < __b2)
|
||||
else if(v < __b2)
|
||||
return __n + 1;
|
||||
if(v < __b3)
|
||||
else if(v < __b3)
|
||||
return __n + 2;
|
||||
if(v < __b4)
|
||||
else if(v < __b4)
|
||||
return __n + 3;
|
||||
v /= (U) __b4;
|
||||
__n += 4;
|
||||
@@ -617,7 +610,7 @@ void write_dec_unchecked(substr buf, T v, unsigned digits_v) noexcept
|
||||
{
|
||||
T quo = v;
|
||||
quo /= T(100);
|
||||
const auto num = (v - quo * T(100)) << 1u;
|
||||
const auto num = (v - quo * T(100)) << 1u; // NOLINT
|
||||
v = quo;
|
||||
buf.str[--digits_v] = detail::digits0099[num + 1];
|
||||
buf.str[--digits_v] = detail::digits0099[num];
|
||||
@@ -782,15 +775,18 @@ template<class T, NumberWriter<T> writer>
|
||||
size_t write_num_digits(substr buf, T v, size_t num_digits) noexcept
|
||||
{
|
||||
C4_STATIC_ASSERT(std::is_integral<T>::value);
|
||||
size_t ret = writer(buf, v);
|
||||
const size_t ret = writer(buf, v);
|
||||
if(ret >= num_digits)
|
||||
return ret;
|
||||
else if(ret >= buf.len || num_digits > buf.len)
|
||||
return num_digits;
|
||||
C4_ASSERT(num_digits >= ret);
|
||||
size_t delta = static_cast<size_t>(num_digits - ret);
|
||||
memmove(buf.str + delta, buf.str, ret);
|
||||
memset(buf.str, '0', delta);
|
||||
const size_t delta = static_cast<size_t>(num_digits - ret); // NOLINT
|
||||
C4_ASSERT(ret + delta <= buf.len);
|
||||
if(ret)
|
||||
memmove(buf.str + delta, buf.str, ret);
|
||||
if(delta)
|
||||
memset(buf.str, '0', delta);
|
||||
return num_digits;
|
||||
}
|
||||
} // namespace detail
|
||||
@@ -985,7 +981,9 @@ C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wswitch-default")
|
||||
namespace detail {
|
||||
inline size_t _itoa2buf(substr buf, size_t pos, csubstr val) noexcept
|
||||
{
|
||||
C4_ASSERT(pos < buf.len);
|
||||
C4_ASSERT(pos + val.len <= buf.len);
|
||||
C4_ASSERT(val.len > 0);
|
||||
memcpy(buf.str + pos, val.str, val.len);
|
||||
return pos + val.len;
|
||||
}
|
||||
@@ -1013,7 +1011,7 @@ C4_NO_INLINE size_t _itoa2buf(substr buf, I radix) noexcept
|
||||
size_t pos = 0;
|
||||
if(C4_LIKELY(buf.len > 0))
|
||||
buf.str[pos++] = '-';
|
||||
switch(radix)
|
||||
switch(radix) // NOLINT(hicpp-multiway-paths-covered)
|
||||
{
|
||||
case I(10):
|
||||
if(C4_UNLIKELY(buf.len < digits_type::maxdigits_dec))
|
||||
@@ -1052,7 +1050,7 @@ C4_NO_INLINE size_t _itoa2buf(substr buf, I radix, size_t num_digits) noexcept
|
||||
size_t needed_digits = 0;
|
||||
if(C4_LIKELY(buf.len > 0))
|
||||
buf.str[pos++] = '-';
|
||||
switch(radix)
|
||||
switch(radix) // NOLINT(hicpp-multiway-paths-covered)
|
||||
{
|
||||
case I(10):
|
||||
// add 1 to account for -
|
||||
@@ -1117,7 +1115,7 @@ C4_ALWAYS_INLINE size_t itoa(substr buf, T v) noexcept
|
||||
}
|
||||
// when T is the min value (eg i8: -128), negating it
|
||||
// will overflow, so treat the min as a special case
|
||||
else if(C4_LIKELY(v != std::numeric_limits<T>::min()))
|
||||
if(C4_LIKELY(v != std::numeric_limits<T>::min()))
|
||||
{
|
||||
v = -v;
|
||||
unsigned digits = digits_dec(v);
|
||||
@@ -1160,7 +1158,7 @@ C4_ALWAYS_INLINE size_t itoa(substr buf, T v, T radix) noexcept
|
||||
++pos;
|
||||
}
|
||||
unsigned digits = 0;
|
||||
switch(radix)
|
||||
switch(radix) // NOLINT(hicpp-multiway-paths-covered)
|
||||
{
|
||||
case T(10):
|
||||
digits = digits_dec(v);
|
||||
@@ -1237,7 +1235,7 @@ C4_ALWAYS_INLINE size_t itoa(substr buf, T v, T radix, size_t num_digits) noexce
|
||||
++pos;
|
||||
}
|
||||
unsigned total_digits = 0;
|
||||
switch(radix)
|
||||
switch(radix) // NOLINT(hicpp-multiway-paths-covered)
|
||||
{
|
||||
case T(10):
|
||||
total_digits = digits_dec(v);
|
||||
@@ -1322,7 +1320,7 @@ C4_ALWAYS_INLINE size_t utoa(substr buf, T v, T radix) noexcept
|
||||
C4_STATIC_ASSERT(std::is_unsigned<T>::value);
|
||||
C4_ASSERT(radix == 10 || radix == 16 || radix == 2 || radix == 8);
|
||||
unsigned digits = 0;
|
||||
switch(radix)
|
||||
switch(radix) // NOLINT(hicpp-multiway-paths-covered)
|
||||
{
|
||||
case T(10):
|
||||
digits = digits_dec(v);
|
||||
@@ -1377,7 +1375,7 @@ C4_ALWAYS_INLINE size_t utoa(substr buf, T v, T radix, size_t num_digits) noexce
|
||||
C4_STATIC_ASSERT(std::is_unsigned<T>::value);
|
||||
C4_ASSERT(radix == 10 || radix == 16 || radix == 2 || radix == 8);
|
||||
unsigned total_digits = 0;
|
||||
switch(radix)
|
||||
switch(radix) // NOLINT(hicpp-multiway-paths-covered)
|
||||
{
|
||||
case T(10):
|
||||
total_digits = digits_dec(v);
|
||||
@@ -1601,7 +1599,7 @@ C4_ALWAYS_INLINE size_t atou_first(csubstr str, T *v)
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
# pragma warning(pop)
|
||||
#elif defined(__clang__)
|
||||
# pragma clang diagnostic pop
|
||||
@@ -1618,19 +1616,16 @@ C4_ALWAYS_INLINE size_t atou_first(csubstr str, T *v)
|
||||
namespace detail {
|
||||
inline bool check_overflow(csubstr str, csubstr limit) noexcept
|
||||
{
|
||||
if(str.len == limit.len)
|
||||
{
|
||||
for(size_t i = 0; i < limit.len; ++i)
|
||||
{
|
||||
if(str[i] < limit[i])
|
||||
return false;
|
||||
else if(str[i] > limit[i])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
if(str.len != limit.len)
|
||||
return str.len > limit.len;
|
||||
for(size_t i = 0; i < limit.len; ++i)
|
||||
{
|
||||
if(str[i] < limit[i])
|
||||
return false;
|
||||
else if(str[i] > limit[i])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace detail
|
||||
/** @endcond */
|
||||
@@ -1714,7 +1709,7 @@ auto overflows(csubstr str) noexcept
|
||||
* @see doc_overflow_checked for format specifiers to enforce no-overflow reads
|
||||
*/
|
||||
template<class T>
|
||||
auto overflows(csubstr str)
|
||||
auto overflows(csubstr str) noexcept
|
||||
-> typename std::enable_if<std::is_signed<T>::value, bool>::type
|
||||
{
|
||||
C4_STATIC_ASSERT(std::is_integral<T>::value);
|
||||
@@ -1762,7 +1757,9 @@ auto overflows(csubstr str)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return detail::check_overflow(str.sub(1), detail::charconv_digits<T>::min_value_dec());
|
||||
}
|
||||
}
|
||||
else if(str.str[0] == '0')
|
||||
{
|
||||
@@ -1805,7 +1802,9 @@ auto overflows(csubstr str)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return detail::check_overflow(str, detail::charconv_digits<T>::max_value_dec());
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
||||
@@ -1989,7 +1988,7 @@ C4_ALWAYS_INLINE bool scan_rhex(csubstr s, T *C4_RESTRICT val) noexcept
|
||||
else if(c == 'p' || c == 'P')
|
||||
{
|
||||
++pos;
|
||||
goto power; // no mantissa given, jump to power
|
||||
goto power; // no mantissa given, jump to power // NOLINT
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1999,7 +1998,7 @@ C4_ALWAYS_INLINE bool scan_rhex(csubstr s, T *C4_RESTRICT val) noexcept
|
||||
// mantissa
|
||||
{
|
||||
// 0.0625 == 1/16 == value of first digit after the comma
|
||||
for(T digit = T(0.0625); pos < s.len; ++pos, digit /= T(16))
|
||||
for(T digit = T(0.0625); pos < s.len; ++pos, digit /= T(16)) // NOLINT
|
||||
{
|
||||
const char c = s.str[pos];
|
||||
if(c >= '0' && c <= '9')
|
||||
@@ -2011,7 +2010,7 @@ C4_ALWAYS_INLINE bool scan_rhex(csubstr s, T *C4_RESTRICT val) noexcept
|
||||
else if(c == 'p' || c == 'P')
|
||||
{
|
||||
++pos;
|
||||
goto power; // mantissa finished, jump to power
|
||||
goto power; // mantissa finished, jump to power // NOLINT
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2172,6 +2171,7 @@ inline size_t atof_first(csubstr str, float * C4_RESTRICT v) noexcept
|
||||
*/
|
||||
C4_ALWAYS_INLINE bool atod(csubstr str, double * C4_RESTRICT v) noexcept
|
||||
{
|
||||
C4_ASSERT(str.len > 0);
|
||||
C4_ASSERT(str.triml(" \r\t\n").len == str.len);
|
||||
#if C4CORE_HAVE_FAST_FLOAT
|
||||
// fastfloat cannot parse hexadecimal floats
|
||||
@@ -2228,8 +2228,8 @@ inline size_t atod_first(csubstr str, double * C4_RESTRICT v) noexcept
|
||||
/** @cond dev */
|
||||
// on some platforms, (unsigned) int and (unsigned) long
|
||||
// are not any of the fixed length types above
|
||||
#define _C4_IF_NOT_FIXED_LENGTH_I(T, ty) C4_ALWAYS_INLINE typename std::enable_if<std:: is_signed<T>::value && !is_fixed_length<T>::value_i, ty>
|
||||
#define _C4_IF_NOT_FIXED_LENGTH_U(T, ty) C4_ALWAYS_INLINE typename std::enable_if<std::is_unsigned<T>::value && !is_fixed_length<T>::value_u, ty>
|
||||
#define _C4_IF_NOT_FIXED_LENGTH_I(T, ty) typename std::enable_if<std:: is_signed<T>::value && !is_fixed_length<T>::value_i, ty>
|
||||
#define _C4_IF_NOT_FIXED_LENGTH_U(T, ty) typename std::enable_if<std::is_unsigned<T>::value && !is_fixed_length<T>::value_u, ty>
|
||||
/** @endcond*/
|
||||
|
||||
|
||||
@@ -2271,8 +2271,8 @@ C4_ALWAYS_INLINE size_t xtoa(substr s, int64_t v, int64_t radix, size_t num_di
|
||||
C4_ALWAYS_INLINE size_t xtoa(substr s, float v, int precision, RealFormat_e formatting=FTOA_FLEX) noexcept { return ftoa(s, v, precision, formatting); }
|
||||
C4_ALWAYS_INLINE size_t xtoa(substr s, double v, int precision, RealFormat_e formatting=FTOA_FLEX) noexcept { return dtoa(s, v, precision, formatting); }
|
||||
|
||||
template <class T> _C4_IF_NOT_FIXED_LENGTH_I(T, size_t)::type xtoa(substr buf, T v) noexcept { return itoa(buf, v); }
|
||||
template <class T> _C4_IF_NOT_FIXED_LENGTH_U(T, size_t)::type xtoa(substr buf, T v) noexcept { return write_dec(buf, v); }
|
||||
template <class T> C4_ALWAYS_INLINE auto xtoa(substr buf, T v) noexcept -> _C4_IF_NOT_FIXED_LENGTH_I(T, size_t)::type { return itoa(buf, v); }
|
||||
template <class T> C4_ALWAYS_INLINE auto xtoa(substr buf, T v) noexcept -> _C4_IF_NOT_FIXED_LENGTH_U(T, size_t)::type { return write_dec(buf, v); }
|
||||
template <class T>
|
||||
C4_ALWAYS_INLINE size_t xtoa(substr s, T *v) noexcept { return itoa(s, (intptr_t)v, (intptr_t)16); }
|
||||
|
||||
@@ -2296,8 +2296,8 @@ C4_ALWAYS_INLINE bool atox(csubstr s, int64_t *C4_RESTRICT v) noexcept { return
|
||||
C4_ALWAYS_INLINE bool atox(csubstr s, float *C4_RESTRICT v) noexcept { return atof(s, v); }
|
||||
C4_ALWAYS_INLINE bool atox(csubstr s, double *C4_RESTRICT v) noexcept { return atod(s, v); }
|
||||
|
||||
template <class T> _C4_IF_NOT_FIXED_LENGTH_I(T, bool )::type atox(csubstr buf, T *C4_RESTRICT v) noexcept { return atoi(buf, v); }
|
||||
template <class T> _C4_IF_NOT_FIXED_LENGTH_U(T, bool )::type atox(csubstr buf, T *C4_RESTRICT v) noexcept { return atou(buf, v); }
|
||||
template <class T> C4_ALWAYS_INLINE auto atox(csubstr buf, T *C4_RESTRICT v) noexcept -> _C4_IF_NOT_FIXED_LENGTH_I(T, bool)::type { return atoi(buf, v); }
|
||||
template <class T> C4_ALWAYS_INLINE auto atox(csubstr buf, T *C4_RESTRICT v) noexcept -> _C4_IF_NOT_FIXED_LENGTH_U(T, bool)::type { return atou(buf, v); }
|
||||
template <class T>
|
||||
C4_ALWAYS_INLINE bool atox(csubstr s, T **v) noexcept { intptr_t tmp; bool ret = atox(s, &tmp); if(ret) { *v = (T*)tmp; } return ret; }
|
||||
|
||||
@@ -2336,8 +2336,8 @@ C4_ALWAYS_INLINE size_t to_chars(substr buf, int64_t v) noexcept { return itoa(
|
||||
C4_ALWAYS_INLINE size_t to_chars(substr buf, float v) noexcept { return ftoa(buf, v); }
|
||||
C4_ALWAYS_INLINE size_t to_chars(substr buf, double v) noexcept { return dtoa(buf, v); }
|
||||
|
||||
template <class T> _C4_IF_NOT_FIXED_LENGTH_I(T, size_t)::type to_chars(substr buf, T v) noexcept { return itoa(buf, v); }
|
||||
template <class T> _C4_IF_NOT_FIXED_LENGTH_U(T, size_t)::type to_chars(substr buf, T v) noexcept { return write_dec(buf, v); }
|
||||
template <class T> C4_ALWAYS_INLINE auto to_chars(substr buf, T v) noexcept -> _C4_IF_NOT_FIXED_LENGTH_I(T, size_t)::type { return itoa(buf, v); }
|
||||
template <class T> C4_ALWAYS_INLINE auto to_chars(substr buf, T v) noexcept -> _C4_IF_NOT_FIXED_LENGTH_U(T, size_t)::type { return write_dec(buf, v); }
|
||||
template <class T>
|
||||
C4_ALWAYS_INLINE size_t to_chars(substr s, T *v) noexcept { return itoa(s, (intptr_t)v, (intptr_t)16); }
|
||||
|
||||
@@ -2371,8 +2371,8 @@ C4_ALWAYS_INLINE bool from_chars(csubstr buf, int64_t *C4_RESTRICT v) noexcept
|
||||
C4_ALWAYS_INLINE bool from_chars(csubstr buf, float *C4_RESTRICT v) noexcept { return atof(buf, v); }
|
||||
C4_ALWAYS_INLINE bool from_chars(csubstr buf, double *C4_RESTRICT v) noexcept { return atod(buf, v); }
|
||||
|
||||
template <class T> _C4_IF_NOT_FIXED_LENGTH_I(T, bool )::type from_chars(csubstr buf, T *C4_RESTRICT v) noexcept { return atoi(buf, v); }
|
||||
template <class T> _C4_IF_NOT_FIXED_LENGTH_U(T, bool )::type from_chars(csubstr buf, T *C4_RESTRICT v) noexcept { return atou(buf, v); }
|
||||
template <class T> C4_ALWAYS_INLINE auto from_chars(csubstr buf, T *C4_RESTRICT v) noexcept -> _C4_IF_NOT_FIXED_LENGTH_I(T, bool)::type { return atoi(buf, v); }
|
||||
template <class T> C4_ALWAYS_INLINE auto from_chars(csubstr buf, T *C4_RESTRICT v) noexcept -> _C4_IF_NOT_FIXED_LENGTH_U(T, bool)::type { return atou(buf, v); }
|
||||
template <class T>
|
||||
C4_ALWAYS_INLINE bool from_chars(csubstr buf, T **v) noexcept { intptr_t tmp; bool ret = from_chars(buf, &tmp); if(ret) { *v = (T*)tmp; } return ret; }
|
||||
|
||||
@@ -2399,8 +2399,8 @@ C4_ALWAYS_INLINE size_t from_chars_first(csubstr buf, int64_t *C4_RESTRICT v) n
|
||||
C4_ALWAYS_INLINE size_t from_chars_first(csubstr buf, float *C4_RESTRICT v) noexcept { return atof_first(buf, v); }
|
||||
C4_ALWAYS_INLINE size_t from_chars_first(csubstr buf, double *C4_RESTRICT v) noexcept { return atod_first(buf, v); }
|
||||
|
||||
template <class T> _C4_IF_NOT_FIXED_LENGTH_I(T, size_t)::type from_chars_first(csubstr buf, T *C4_RESTRICT v) noexcept { return atoi_first(buf, v); }
|
||||
template <class T> _C4_IF_NOT_FIXED_LENGTH_U(T, size_t)::type from_chars_first(csubstr buf, T *C4_RESTRICT v) noexcept { return atou_first(buf, v); }
|
||||
template <class T> C4_ALWAYS_INLINE auto from_chars_first(csubstr buf, T *C4_RESTRICT v) noexcept -> _C4_IF_NOT_FIXED_LENGTH_I(T, size_t)::type { return atoi_first(buf, v); }
|
||||
template <class T> C4_ALWAYS_INLINE auto from_chars_first(csubstr buf, T *C4_RESTRICT v) noexcept -> _C4_IF_NOT_FIXED_LENGTH_U(T, size_t)::type { return atou_first(buf, v); }
|
||||
template <class T>
|
||||
C4_ALWAYS_INLINE size_t from_chars_first(csubstr buf, T **v) noexcept { intptr_t tmp; bool ret = from_chars_first(buf, &tmp); if(ret) { *v = (T*)tmp; } return ret; }
|
||||
|
||||
@@ -2657,11 +2657,11 @@ inline size_t to_chars(substr buf, const char * C4_RESTRICT v) noexcept
|
||||
|
||||
} // namespace c4
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
// NOLINTEND(hicpp-signed-bitwise)
|
||||
|
||||
#if defined(__clang__)
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
# pragma warning(pop)
|
||||
#elif defined(__clang__)
|
||||
# pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
# pragma GCC diagnostic pop
|
||||
|
||||
5
3rdparty/rapidyaml/include/c4/compiler.hpp
vendored
5
3rdparty/rapidyaml/include/c4/compiler.hpp
vendored
@@ -24,7 +24,7 @@
|
||||
/** @see http://sourceforge.net/p/predef/wiki/Compilers/ for a list of compiler identifier macros */
|
||||
/** @see https://msdn.microsoft.com/en-us/library/b0084kay.aspx for VS2013 predefined macros */
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#if defined(_MSC_VER)
|
||||
# define C4_MSVC
|
||||
# define C4_MSVC_VERSION_2022 17
|
||||
# define C4_MSVC_VERSION_2019 16
|
||||
@@ -93,6 +93,9 @@
|
||||
# define C4_CLANG_VERSION __apple_build_version__
|
||||
# endif
|
||||
# elif defined(__GNUC__)
|
||||
# ifdef __MINGW32__
|
||||
# define C4_MINGW
|
||||
# endif
|
||||
# define C4_GCC
|
||||
# if defined(__GNUC_PATCHLEVEL__)
|
||||
# define C4_GCC_VERSION C4_VERSION_ENCODED(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
|
||||
|
||||
54
3rdparty/rapidyaml/include/c4/cpu.hpp
vendored
54
3rdparty/rapidyaml/include/c4/cpu.hpp
vendored
@@ -7,7 +7,7 @@
|
||||
// see also https://sourceforge.net/p/predef/wiki/Architectures/
|
||||
// see also https://sourceforge.net/p/predef/wiki/Endianness/
|
||||
// see also https://github.com/googlesamples/android-ndk/blob/android-mk/hello-jni/jni/hello-jni.c
|
||||
// see http://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/global/qprocessordetection.h
|
||||
// see also http://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/global/qprocessordetection.h
|
||||
|
||||
#ifdef __ORDER_LITTLE_ENDIAN__
|
||||
# define _C4EL __ORDER_LITTLE_ENDIAN__
|
||||
@@ -22,7 +22,11 @@
|
||||
#endif
|
||||
|
||||
// mixed byte order (eg, PowerPC or ia64)
|
||||
#define _C4EM 1111
|
||||
#define _C4EM 1111 // NOLINT
|
||||
|
||||
|
||||
// NOTE: to find defined macros in a platform,
|
||||
// g++ <flags> -dM -E - </dev/null | sort
|
||||
|
||||
#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64)
|
||||
# define C4_CPU_X86_64
|
||||
@@ -60,11 +64,15 @@
|
||||
|| defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_6KZ__) \
|
||||
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM >= 6)
|
||||
# define C4_CPU_ARMV6
|
||||
# elif defined(__ARM_ARCH_5TEJ__) \
|
||||
# elif (defined(__ARM_ARCH) && __ARM_ARCH == 5) \
|
||||
|| defined(__ARM_ARCH_5TEJ__) \
|
||||
|| defined(__ARM_ARCH_5TE__) \
|
||||
|| defined(__ARM_ARCH_5T__) \
|
||||
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM >= 5)
|
||||
# define C4_CPU_ARMV5
|
||||
# elif defined(__ARM_ARCH_4T__) \
|
||||
# elif (defined(__ARM_ARCH) && __ARM_ARCH == 4) \
|
||||
|| defined(__ARM_ARCH_4T__) \
|
||||
|| defined(__ARM_ARCH_4__) \
|
||||
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM >= 4)
|
||||
# define C4_CPU_ARMV4
|
||||
# else
|
||||
@@ -145,6 +153,44 @@
|
||||
# endif
|
||||
# define C4_BYTE_ORDER _C4EL
|
||||
|
||||
#elif defined(__mips__) || defined(_mips) || defined(mips)
|
||||
# if defined(__mips)
|
||||
# if __mips == 64
|
||||
# define C4_CPU_MIPS64
|
||||
# define C4_WORDSIZE 8
|
||||
# elif __mips == 32
|
||||
# define C4_CPU_MIPS32
|
||||
# define C4_WORDSIZE 4
|
||||
# endif
|
||||
# elif defined(__arch64__) || (defined(__SIZE_WIDTH__) && __SIZE_WIDTH__ == 64) || (defined(__LP64__) && __LP64__)
|
||||
# define C4_CPU_MIPS64
|
||||
# define C4_WORDSIZE 8
|
||||
# elif defined(__arch32__) || (defined(__SIZE_WIDTH__) && __SIZE_WIDTH__ == 32) || (defined(__LP32__) && __LP32__)
|
||||
# define C4_CPU_MIPS32
|
||||
# define C4_WORDSIZE 4
|
||||
# else
|
||||
# error "unknown mips architecture"
|
||||
# endif
|
||||
# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
# define C4_BYTE_ORDER _C4EB
|
||||
# elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
# define C4_BYTE_ORDER _C4EL
|
||||
# else
|
||||
# error "unknown mips endianness"
|
||||
# endif
|
||||
|
||||
#elif defined(__sparc__) || defined(__sparc) || defined(sparc)
|
||||
# if defined(__arch64__) || (defined(__SIZE_WIDTH__) && __SIZE_WIDTH__ == 64) || (defined(__LP64__) && __LP64__)
|
||||
# define C4_CPU_SPARC64
|
||||
# define C4_WORDSIZE 8
|
||||
# elif defined(__arch32__) || (defined(__SIZE_WIDTH__) && __SIZE_WIDTH__ == 32) || (defined(__LP32__) && __LP32__)
|
||||
# define C4_CPU_SPARC32
|
||||
# define C4_WORDSIZE 4
|
||||
# else
|
||||
# error "unknown sparc architecture"
|
||||
# endif
|
||||
# define C4_BYTE_ORDER _C4EB
|
||||
|
||||
#elif defined(SWIG)
|
||||
# error "please define CPU architecture macros when compiling with swig"
|
||||
|
||||
|
||||
809
3rdparty/rapidyaml/include/c4/dump.hpp
vendored
809
3rdparty/rapidyaml/include/c4/dump.hpp
vendored
File diff suppressed because it is too large
Load Diff
19
3rdparty/rapidyaml/include/c4/error.hpp
vendored
19
3rdparty/rapidyaml/include/c4/error.hpp
vendored
@@ -63,6 +63,7 @@ struct fail_type__ {};
|
||||
#else
|
||||
# ifdef __clang__
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wundef"
|
||||
# if !defined(__APPLE_CC__)
|
||||
# if __clang_major__ >= 10
|
||||
# pragma clang diagnostic ignored "-Wgnu-inline-cpp-without-extern" // debugbreak/debugbreak.h:50:16: error: 'gnu_inline' attribute without 'extern' in C++ treated as externally available, this changed in Clang 10 [-Werror,-Wgnu-inline-cpp-without-extern]
|
||||
@@ -73,12 +74,15 @@ struct fail_type__ {};
|
||||
# endif
|
||||
# endif
|
||||
# elif defined(__GNUC__)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wundef"
|
||||
# endif
|
||||
# include <c4/ext/debugbreak/debugbreak.h>
|
||||
# define C4_DEBUG_BREAK() if(c4::is_debugger_attached()) { ::debug_break(); }
|
||||
# ifdef __clang__
|
||||
# pragma clang diagnostic pop
|
||||
# elif defined(__GNUC__)
|
||||
# pragma GCC diagnostic pop
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@@ -114,17 +118,17 @@ namespace c4 {
|
||||
typedef enum : uint32_t {
|
||||
/** when an error happens and the debugger is attached, call C4_DEBUG_BREAK().
|
||||
* Without effect otherwise. */
|
||||
ON_ERROR_DEBUGBREAK = 0x01 << 0,
|
||||
ON_ERROR_DEBUGBREAK = 0x01u << 0u,
|
||||
/** when an error happens log a message. */
|
||||
ON_ERROR_LOG = 0x01 << 1,
|
||||
ON_ERROR_LOG = 0x01u << 1u,
|
||||
/** when an error happens invoke a callback if it was set with
|
||||
* set_error_callback(). */
|
||||
ON_ERROR_CALLBACK = 0x01 << 2,
|
||||
ON_ERROR_CALLBACK = 0x01u << 2u,
|
||||
/** when an error happens call std::terminate(). */
|
||||
ON_ERROR_ABORT = 0x01 << 3,
|
||||
ON_ERROR_ABORT = 0x01u << 3u,
|
||||
/** when an error happens and exceptions are enabled throw an exception.
|
||||
* Without effect otherwise. */
|
||||
ON_ERROR_THROW = 0x01 << 4,
|
||||
ON_ERROR_THROW = 0x01u << 4u,
|
||||
/** the default flags. */
|
||||
ON_ERROR_DEFAULTS = ON_ERROR_DEBUGBREAK|ON_ERROR_LOG|ON_ERROR_CALLBACK|ON_ERROR_ABORT
|
||||
} ErrorFlags_e;
|
||||
@@ -140,7 +144,7 @@ C4CORE_EXPORT error_callback_type get_error_callback();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** RAII class controling the error settings inside a scope. */
|
||||
struct ScopedErrorSettings
|
||||
struct ScopedErrorSettings // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
|
||||
{
|
||||
error_flags m_flags;
|
||||
error_callback_type m_callback;
|
||||
@@ -177,7 +181,8 @@ struct ScopedErrorSettings
|
||||
/** source location */
|
||||
struct srcloc;
|
||||
|
||||
C4CORE_EXPORT void handle_error(srcloc s, const char *fmt, ...);
|
||||
// watchout: for VS the [[noreturn]] needs to come before other annotations like C4CORE_EXPORT
|
||||
[[noreturn]] C4CORE_EXPORT void handle_error(srcloc s, const char *fmt, ...);
|
||||
C4CORE_EXPORT void handle_warning(srcloc s, const char *fmt, ...);
|
||||
|
||||
|
||||
|
||||
17
3rdparty/rapidyaml/include/c4/format.hpp
vendored
17
3rdparty/rapidyaml/include/c4/format.hpp
vendored
@@ -8,7 +8,7 @@
|
||||
#include "c4/blob.hpp"
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
# pragma warning(push)
|
||||
# if C4_MSVC_VERSION != C4_MSVC_VERSION_2017
|
||||
# pragma warning(disable: 4800) // forcing value to bool 'true' or 'false' (performance warning)
|
||||
@@ -20,6 +20,7 @@
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wuseless-cast"
|
||||
#endif
|
||||
// NOLINTBEGIN(cppcoreguidelines-pro-type-reinterpret-cast,*avoid-goto*)
|
||||
|
||||
/** @defgroup doc_format_utils Format utilities
|
||||
*
|
||||
@@ -323,7 +324,7 @@ to_chars(substr buf, fmt::integral_padded_<T> fmt)
|
||||
return utoa(buf, fmt.val, fmt.radix, fmt.num_digits);
|
||||
}
|
||||
|
||||
/** read an format an integer unsigned type
|
||||
/** read an integer type, detecting overflow (returns false on overflow)
|
||||
* @ingroup doc_from_chars */
|
||||
template<class T>
|
||||
C4_ALWAYS_INLINE bool from_chars(csubstr s, fmt::overflow_checked_<T> wrapper)
|
||||
@@ -332,6 +333,15 @@ C4_ALWAYS_INLINE bool from_chars(csubstr s, fmt::overflow_checked_<T> wrapper)
|
||||
return atox(s, wrapper.val);
|
||||
return false;
|
||||
}
|
||||
/** read an integer type, detecting overflow (returns false on overflow)
|
||||
* @ingroup doc_from_chars */
|
||||
template<class T>
|
||||
C4_ALWAYS_INLINE bool from_chars(csubstr s, fmt::overflow_checked_<T> *wrapper)
|
||||
{
|
||||
if(C4_LIKELY(!overflows<T>(s)))
|
||||
return atox(s, wrapper->val);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -967,7 +977,6 @@ inline CharOwningContainer catseprs(Sep const& C4_RESTRICT sep, Args const& C4_R
|
||||
* the result. The buffer is appended to.
|
||||
*
|
||||
* @return a csubstr of the appended part
|
||||
* @ingroup formatting_functions
|
||||
* @ingroup doc_catsep */
|
||||
template<class CharOwningContainer, class Sep, class... Args>
|
||||
inline csubstr catseprs_append(CharOwningContainer * C4_RESTRICT cont, Sep const& C4_RESTRICT sep, Args const& C4_RESTRICT ...args)
|
||||
@@ -1019,7 +1028,6 @@ inline CharOwningContainer formatrs(csubstr fmt, Args const& C4_RESTRICT ...args
|
||||
* arguments, resizing the container as needed to contain the
|
||||
* result. The buffer is appended to.
|
||||
* @return the region newly appended to the original container
|
||||
* @ingroup formatting_functions
|
||||
* @ingroup doc_format */
|
||||
template<class CharOwningContainer, class... Args>
|
||||
inline csubstr formatrs_append(CharOwningContainer * C4_RESTRICT cont, csubstr fmt, Args const& C4_RESTRICT ...args)
|
||||
@@ -1038,6 +1046,7 @@ retry:
|
||||
|
||||
} // namespace c4
|
||||
|
||||
// NOLINTEND(cppcoreguidelines-pro-type-reinterpret-cast,*avoid-goto*)
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#elif defined(__clang__)
|
||||
|
||||
2
3rdparty/rapidyaml/include/c4/language.hpp
vendored
2
3rdparty/rapidyaml/include/c4/language.hpp
vendored
@@ -333,7 +333,7 @@ namespace detail {
|
||||
#ifdef __GNUC__
|
||||
# define C4_DONT_OPTIMIZE(var) c4::detail::dont_optimize(var)
|
||||
template< class T >
|
||||
C4_ALWAYS_INLINE void dont_optimize(T const& value) { asm volatile("" : : "g"(value) : "memory"); }
|
||||
C4_ALWAYS_INLINE void dont_optimize(T const& value) { asm volatile("" : : "g"(value) : "memory"); } // NOLINT
|
||||
#else
|
||||
# define C4_DONT_OPTIMIZE(var) c4::detail::use_char_pointer(reinterpret_cast< const char* >(&var))
|
||||
void use_char_pointer(char const volatile*);
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
/** @file memory_util.hpp Some memory utilities. */
|
||||
|
||||
// NOLINTBEGIN(google-runtime-int)
|
||||
|
||||
namespace c4 {
|
||||
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wold-style-cast")
|
||||
@@ -696,8 +698,8 @@ struct tight_pair<First, Second, tpc_same_empty> : public First
|
||||
|
||||
C4_ALWAYS_INLINE C4_CONSTEXPR14 First & first () { return static_cast<First &>(*this); }
|
||||
C4_ALWAYS_INLINE C4_CONSTEXPR14 First const& first () const { return static_cast<First const&>(*this); }
|
||||
C4_ALWAYS_INLINE C4_CONSTEXPR14 Second & second() { return reinterpret_cast<Second &>(*this); }
|
||||
C4_ALWAYS_INLINE C4_CONSTEXPR14 Second const& second() const { return reinterpret_cast<Second const&>(*this); }
|
||||
C4_ALWAYS_INLINE C4_CONSTEXPR14 Second & second() { return reinterpret_cast<Second &>(*this); } // NOLINT
|
||||
C4_ALWAYS_INLINE C4_CONSTEXPR14 Second const& second() const { return reinterpret_cast<Second const&>(*this); } // NOLINT
|
||||
};
|
||||
|
||||
template<class First, class Second>
|
||||
@@ -775,4 +777,6 @@ C4_SUPPRESS_WARNING_GCC_CLANG_POP
|
||||
|
||||
} // namespace c4
|
||||
|
||||
// NOLINTEND(google-runtime-int)
|
||||
|
||||
#endif /* _C4_MEMORY_UTIL_HPP_ */
|
||||
|
||||
47
3rdparty/rapidyaml/include/c4/substr.hpp
vendored
47
3rdparty/rapidyaml/include/c4/substr.hpp
vendored
@@ -67,12 +67,9 @@ static inline void _do_reverse(C *C4_RESTRICT first, C *C4_RESTRICT last)
|
||||
* @see a [quickstart
|
||||
* sample](https://rapidyaml.readthedocs.io/latest/doxygen/group__doc__quickstart.html#ga43e253da0692c13967019446809c1113)
|
||||
* in rapidyaml's documentation.
|
||||
*
|
||||
* @see @ref substr and @ref to_substr()
|
||||
* @see @ref csubstr and @ref to_csubstr()
|
||||
*/
|
||||
template<class C>
|
||||
struct C4CORE_EXPORT basic_substring
|
||||
struct C4CORE_EXPORT basic_substring // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -530,11 +527,11 @@ public:
|
||||
/** @name Lookup methods */
|
||||
/** @{ */
|
||||
|
||||
inline size_t find(const C c, size_t start_pos=0) const
|
||||
size_t find(const C c, size_t start_pos=0) const
|
||||
{
|
||||
return first_of(c, start_pos);
|
||||
}
|
||||
inline size_t find(ro_substr pattern, size_t start_pos=0) const
|
||||
size_t find(ro_substr pattern, size_t start_pos=0) const
|
||||
{
|
||||
C4_ASSERT(start_pos == npos || (start_pos >= 0 && start_pos <= len));
|
||||
if(len < pattern.len) return npos;
|
||||
@@ -561,7 +558,7 @@ public:
|
||||
public:
|
||||
|
||||
/** count the number of occurrences of c */
|
||||
inline size_t count(const C c, size_t pos=0) const
|
||||
size_t count(const C c, size_t pos=0) const
|
||||
{
|
||||
C4_ASSERT(pos >= 0 && pos <= len);
|
||||
size_t num = 0;
|
||||
@@ -575,7 +572,7 @@ public:
|
||||
}
|
||||
|
||||
/** count the number of occurrences of s */
|
||||
inline size_t count(ro_substr c, size_t pos=0) const
|
||||
size_t count(ro_substr c, size_t pos=0) const
|
||||
{
|
||||
C4_ASSERT(pos >= 0 && pos <= len);
|
||||
size_t num = 0;
|
||||
@@ -589,14 +586,14 @@ public:
|
||||
}
|
||||
|
||||
/** get the substr consisting of the first occurrence of @p c after @p pos, or an empty substr if none occurs */
|
||||
inline basic_substring select(const C c, size_t pos=0) const
|
||||
basic_substring select(const C c, size_t pos=0) const
|
||||
{
|
||||
pos = find(c, pos);
|
||||
return pos != npos ? sub(pos, 1) : basic_substring();
|
||||
}
|
||||
|
||||
/** get the substr consisting of the first occurrence of @p pattern after @p pos, or an empty substr if none occurs */
|
||||
inline basic_substring select(ro_substr pattern, size_t pos=0) const
|
||||
basic_substring select(ro_substr pattern, size_t pos=0) const
|
||||
{
|
||||
pos = find(pattern, pos);
|
||||
return pos != npos ? sub(pos, pattern.len) : basic_substring();
|
||||
@@ -608,7 +605,7 @@ public:
|
||||
{
|
||||
size_t which;
|
||||
size_t pos;
|
||||
inline operator bool() const { return which != NONE && pos != npos; }
|
||||
operator bool() const { return which != NONE && pos != npos; }
|
||||
};
|
||||
|
||||
first_of_any_result first_of_any(ro_substr s0, ro_substr s1) const
|
||||
@@ -1307,12 +1304,12 @@ public:
|
||||
else if(c == '.')
|
||||
{
|
||||
++pos;
|
||||
goto fractional_part_dec;
|
||||
goto fractional_part_dec; // NOLINT
|
||||
}
|
||||
else if(c == 'e' || c == 'E')
|
||||
{
|
||||
++pos;
|
||||
goto power_part_dec;
|
||||
goto power_part_dec; // NOLINT
|
||||
}
|
||||
else if(_is_delim_char(c))
|
||||
{
|
||||
@@ -1341,7 +1338,7 @@ public:
|
||||
else if(c == 'e' || c == 'E')
|
||||
{
|
||||
++pos;
|
||||
goto power_part_dec;
|
||||
goto power_part_dec; // NOLINT
|
||||
}
|
||||
else if(_is_delim_char(c))
|
||||
{
|
||||
@@ -1394,12 +1391,12 @@ public:
|
||||
else if(c == '.')
|
||||
{
|
||||
++pos;
|
||||
goto fractional_part_hex;
|
||||
goto fractional_part_hex; // NOLINT
|
||||
}
|
||||
else if(c == 'p' || c == 'P')
|
||||
{
|
||||
++pos;
|
||||
goto power_part_hex;
|
||||
goto power_part_hex; // NOLINT
|
||||
}
|
||||
else if(_is_delim_char(c))
|
||||
{
|
||||
@@ -1428,7 +1425,7 @@ public:
|
||||
else if(c == 'p' || c == 'P')
|
||||
{
|
||||
++pos;
|
||||
goto power_part_hex;
|
||||
goto power_part_hex; // NOLINT
|
||||
}
|
||||
else if(_is_delim_char(c))
|
||||
{
|
||||
@@ -1484,12 +1481,12 @@ public:
|
||||
else if(c == '.')
|
||||
{
|
||||
++pos;
|
||||
goto fractional_part_bin;
|
||||
goto fractional_part_bin; // NOLINT
|
||||
}
|
||||
else if(c == 'p' || c == 'P')
|
||||
{
|
||||
++pos;
|
||||
goto power_part_bin;
|
||||
goto power_part_bin; // NOLINT
|
||||
}
|
||||
else if(_is_delim_char(c))
|
||||
{
|
||||
@@ -1518,7 +1515,7 @@ public:
|
||||
else if(c == 'p' || c == 'P')
|
||||
{
|
||||
++pos;
|
||||
goto power_part_bin;
|
||||
goto power_part_bin; // NOLINT
|
||||
}
|
||||
else if(_is_delim_char(c))
|
||||
{
|
||||
@@ -1574,12 +1571,12 @@ public:
|
||||
else if(c == '.')
|
||||
{
|
||||
++pos;
|
||||
goto fractional_part_oct;
|
||||
goto fractional_part_oct; // NOLINT
|
||||
}
|
||||
else if(c == 'p' || c == 'P')
|
||||
{
|
||||
++pos;
|
||||
goto power_part_oct;
|
||||
goto power_part_oct; // NOLINT
|
||||
}
|
||||
else if(_is_delim_char(c))
|
||||
{
|
||||
@@ -1608,7 +1605,7 @@ public:
|
||||
else if(c == 'p' || c == 'P')
|
||||
{
|
||||
++pos;
|
||||
goto power_part_oct;
|
||||
goto power_part_oct; // NOLINT
|
||||
}
|
||||
else if(_is_delim_char(c))
|
||||
{
|
||||
@@ -1714,7 +1711,7 @@ private:
|
||||
}
|
||||
|
||||
split_iterator_impl& operator++ () { _tick(); return *this; }
|
||||
split_iterator_impl operator++ (int) { split_iterator_impl it = *this; _tick(); return it; }
|
||||
split_iterator_impl operator++ (int) { split_iterator_impl it = *this; _tick(); return it; } // NOLINT
|
||||
|
||||
basic_substring& operator* () { return m_str; }
|
||||
basic_substring* operator-> () { return &m_str; }
|
||||
@@ -2069,7 +2066,7 @@ public:
|
||||
C4_REQUIRE_RW(basic_substring) erase_range(size_t first, size_t last)
|
||||
{
|
||||
C4_ASSERT(first <= last);
|
||||
return erase(first, static_cast<size_t>(last-first));
|
||||
return erase(first, static_cast<size_t>(last-first)); // NOLINT
|
||||
}
|
||||
|
||||
/** erase a part of the string.
|
||||
|
||||
2
3rdparty/rapidyaml/include/c4/szconv.hpp
vendored
2
3rdparty/rapidyaml/include/c4/szconv.hpp
vendored
@@ -53,7 +53,7 @@ szconv(SizeIn sz) noexcept
|
||||
template<class SizeOut, class SizeIn>
|
||||
C4_ALWAYS_INLINE
|
||||
typename std::enable_if<is_narrower_size<SizeOut, SizeIn>::value, SizeOut>::type
|
||||
szconv(SizeIn sz) C4_NOEXCEPT_X
|
||||
szconv(SizeIn sz)
|
||||
{
|
||||
C4_XASSERT(sz >= 0);
|
||||
C4_XASSERT_MSG((SizeIn)sz <= (SizeIn)std::numeric_limits<SizeOut>::max(), "size conversion overflow: in=%zu", (size_t)sz);
|
||||
|
||||
16
3rdparty/rapidyaml/include/c4/types.hpp
vendored
16
3rdparty/rapidyaml/include/c4/types.hpp
vendored
@@ -17,6 +17,8 @@
|
||||
|
||||
/** @defgroup types Type utilities */
|
||||
|
||||
// NOLINTBEGIN(bugprone-macro-parentheses)
|
||||
|
||||
namespace c4 {
|
||||
|
||||
/** @defgroup intrinsic_types Intrinsic types
|
||||
@@ -114,17 +116,17 @@ using fastcref = typename std::conditional<c4::cref_uses_val<T>::value, T, T con
|
||||
//--------------------------------------------------
|
||||
|
||||
/** Just what its name says. Useful sometimes as a default empty policy class. */
|
||||
struct EmptyStruct
|
||||
struct EmptyStruct // NOLINT
|
||||
{
|
||||
template<class... T> EmptyStruct(T && ...){}
|
||||
template<class... T> EmptyStruct(T && ...){} // NOLINT
|
||||
};
|
||||
|
||||
/** Just what its name says. Useful sometimes as a default policy class to
|
||||
* be inherited from. */
|
||||
struct EmptyStructVirtual
|
||||
struct EmptyStructVirtual // NOLINT
|
||||
{
|
||||
virtual ~EmptyStructVirtual() = default;
|
||||
template<class... T> EmptyStructVirtual(T && ...){}
|
||||
template<class... T> EmptyStructVirtual(T && ...){} // NOLINT
|
||||
};
|
||||
|
||||
|
||||
@@ -159,7 +161,7 @@ struct Padded : public T
|
||||
using T::T;
|
||||
using T::operator=;
|
||||
Padded(T const& val) : T(val) {}
|
||||
Padded(T && val) : T(val) {}
|
||||
Padded(T && val) : T(std::forward<T>(val)) {} // NOLINT
|
||||
char ___c4padspace___[BytesToPadAtEnd];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
@@ -170,7 +172,7 @@ struct Padded<T, 0> : public T
|
||||
using T::T;
|
||||
using T::operator=;
|
||||
Padded(T const& val) : T(val) {}
|
||||
Padded(T && val) : T(val) {}
|
||||
Padded(T && val) : T(std::forward<T>(val)) {} // NOLINT
|
||||
};
|
||||
|
||||
/** make T have a size which is at least Min bytes */
|
||||
@@ -500,4 +502,6 @@ using index_sequence_for = make_index_sequence<sizeof...(_Tp)>;
|
||||
|
||||
} // namespace c4
|
||||
|
||||
// NOLINTEND(bugprone-macro-parentheses)
|
||||
|
||||
#endif /* _C4_TYPES_HPP_ */
|
||||
|
||||
61
3rdparty/rapidyaml/include/c4/utf.hpp
vendored
61
3rdparty/rapidyaml/include/c4/utf.hpp
vendored
@@ -6,10 +6,67 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/** @file utf.hpp utilities for UTF and Byte Order Mark */
|
||||
|
||||
namespace c4 {
|
||||
|
||||
substr decode_code_point(substr out, csubstr code_point);
|
||||
size_t decode_code_point(uint8_t *C4_RESTRICT buf, size_t buflen, const uint32_t code);
|
||||
/** @defgroup doc_utf UTF utilities
|
||||
* @{ */
|
||||
|
||||
|
||||
/** skip the Byte Order Mark, or get the full string if there is Byte Order Mark.
|
||||
* @see Implements the Byte Order Marks as described in https://en.wikipedia.org/wiki/Byte_order_mark#Byte-order_marks_by_encoding */
|
||||
C4CORE_EXPORT substr skip_bom(substr s);
|
||||
/** skip the Byte Order Mark, or get the full string if there is Byte Order Mark
|
||||
* @see Implements the Byte Order Marks as described in https://en.wikipedia.org/wiki/Byte_order_mark#Byte-order_marks_by_encoding */
|
||||
C4CORE_EXPORT csubstr skip_bom(csubstr s);
|
||||
|
||||
|
||||
/** get the Byte Order Mark, or an empty string if there is no Byte Order Mark
|
||||
* @see Implements the Byte Order Marks as described in https://en.wikipedia.org/wiki/Byte_order_mark#Byte-order_marks_by_encoding */
|
||||
C4CORE_EXPORT substr get_bom(substr s);
|
||||
/** get the Byte Order Mark, or an empty string if there is no Byte Order Mark
|
||||
* @see Implements the Byte Order Marks as described in https://en.wikipedia.org/wiki/Byte_order_mark#Byte-order_marks_by_encoding */
|
||||
C4CORE_EXPORT csubstr get_bom(csubstr s);
|
||||
|
||||
|
||||
/** return the position of the first character not belonging to the
|
||||
* Byte Order Mark, or 0 if there is no Byte Order Mark.
|
||||
* @see Implements the Byte Order Marks as described in https://en.wikipedia.org/wiki/Byte_order_mark#Byte-order_marks_by_encoding */
|
||||
C4CORE_EXPORT size_t first_non_bom(csubstr s);
|
||||
|
||||
|
||||
/** decode the given @p code_point, writing into the output string in
|
||||
* @p out.
|
||||
*
|
||||
* @param out the output string. must have at least 4 bytes (this is
|
||||
* asserted), and must not have a null string.
|
||||
*
|
||||
* @param code_point: must have length in ]0,8], and must not begin
|
||||
* with any of `U+`,`\\x`,`\\u,`\\U`,`0` (asserted)
|
||||
*
|
||||
* @return the part of @p out that was written, which will always be
|
||||
* at most 4 bytes.
|
||||
*/
|
||||
C4CORE_EXPORT substr decode_code_point(substr out, csubstr code_point);
|
||||
|
||||
/** decode the given @p code point, writing into the output string @p
|
||||
* buf, of size @p buflen
|
||||
*
|
||||
* @param buf the output string. must have at least 4 bytes (this is
|
||||
* asserted), and must not be null
|
||||
*
|
||||
* @param buflen the length of the output string. must be at least 4
|
||||
*
|
||||
* @param code: the code point must have length in ]0,8], and must not begin
|
||||
* with any of `U+`,`\\x`,`\\u,`\\U`,`0` (asserted)
|
||||
*
|
||||
* @return the part of @p out that was written, which will always be
|
||||
* at most 4 bytes.
|
||||
*/
|
||||
size_t decode_code_point(uint8_t *C4_RESTRICT buf, size_t buflen, uint32_t code);
|
||||
|
||||
/** @} */
|
||||
|
||||
} // namespace c4
|
||||
|
||||
|
||||
272
3rdparty/rapidyaml/include/c4/yml/common.hpp
vendored
272
3rdparty/rapidyaml/include/c4/yml/common.hpp
vendored
@@ -5,8 +5,50 @@
|
||||
|
||||
#include <cstddef>
|
||||
#include <c4/substr.hpp>
|
||||
#include <c4/charconv.hpp>
|
||||
#include <c4/dump.hpp>
|
||||
#include <c4/yml/export.hpp>
|
||||
|
||||
#if defined(C4_MSVC) || defined(C4_MINGW)
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef RYML_ERRMSG_SIZE
|
||||
/// size for the error message buffer
|
||||
#define RYML_ERRMSG_SIZE (1024)
|
||||
#endif
|
||||
|
||||
#ifndef RYML_LOGBUF_SIZE
|
||||
/// size for the buffer used to format individual values to string
|
||||
/// while preparing an error message. This is only used for formatting
|
||||
/// individual values in the message; final messages will be larger
|
||||
/// than this value (see @ref RYML_ERRMSG_SIZE). This is also used for
|
||||
/// the detailed debug log messages when RYML_DBG is defined.
|
||||
#define RYML_LOGBUF_SIZE (256)
|
||||
#endif
|
||||
|
||||
#ifndef RYML_LOGBUF_SIZE_MAX
|
||||
/// size for the fallback larger log buffer. When @ref
|
||||
/// RYML_LOGBUF_SIZE is not large enough to convert a value to string,
|
||||
/// then temporary stack memory is allocated up to
|
||||
/// RYML_LOGBUF_SIZE_MAX. This limit is in place to prevent a stack
|
||||
/// overflow. If the printed value requires more than
|
||||
/// RYML_LOGBUF_SIZE_MAX, the value is silently skipped.
|
||||
#define RYML_LOGBUF_SIZE_MAX (1024)
|
||||
#endif
|
||||
|
||||
#ifndef RYML_LOCATIONS_SMALL_THRESHOLD
|
||||
/// threshold at which a location search will revert from linear to
|
||||
/// binary search.
|
||||
#define RYML_LOCATIONS_SMALL_THRESHOLD (30)
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Specify groups to have a predefined topic order in doxygen:
|
||||
@@ -83,6 +125,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/** @defgroup doc_ref_utils Anchor/Reference utilities
|
||||
*
|
||||
* @see sample::sample_anchors_and_aliases
|
||||
* */
|
||||
|
||||
/** @defgroup doc_tag_utils Tag utilities
|
||||
* @see sample::sample_tags
|
||||
*/
|
||||
@@ -134,11 +181,13 @@
|
||||
# define RYML_ASSERT(cond) RYML_CHECK(cond)
|
||||
# define RYML_ASSERT_MSG(cond, msg) RYML_CHECK_MSG(cond, msg)
|
||||
# define _RYML_CB_ASSERT(cb, cond) _RYML_CB_CHECK((cb), (cond))
|
||||
# define _RYML_CB_ASSERT_(cb, cond, loc) _RYML_CB_CHECK((cb), (cond), (loc))
|
||||
# define RYML_NOEXCEPT
|
||||
#else
|
||||
# define RYML_ASSERT(cond)
|
||||
# define RYML_ASSERT_MSG(cond, msg)
|
||||
# define _RYML_CB_ASSERT(cb, cond)
|
||||
# define _RYML_CB_ASSERT_(cb, cond, loc)
|
||||
# define RYML_NOEXCEPT noexcept
|
||||
#endif
|
||||
|
||||
@@ -148,7 +197,7 @@
|
||||
do { \
|
||||
if(C4_UNLIKELY(!(cond))) \
|
||||
{ \
|
||||
RYML_DEBUG_BREAK() \
|
||||
RYML_DEBUG_BREAK(); \
|
||||
c4::yml::error("check failed: " #cond, c4::yml::Location(__FILE__, __LINE__, 0)); \
|
||||
C4_UNREACHABLE_AFTER_ERR(); \
|
||||
} \
|
||||
@@ -159,7 +208,7 @@
|
||||
{ \
|
||||
if(C4_UNLIKELY(!(cond))) \
|
||||
{ \
|
||||
RYML_DEBUG_BREAK() \
|
||||
RYML_DEBUG_BREAK(); \
|
||||
c4::yml::error(msg ": check failed: " #cond, c4::yml::Location(__FILE__, __LINE__, 0)); \
|
||||
C4_UNREACHABLE_AFTER_ERR(); \
|
||||
} \
|
||||
@@ -167,17 +216,16 @@
|
||||
|
||||
#if defined(RYML_DBG) && !defined(NDEBUG) && !defined(C4_NO_DEBUG_BREAK)
|
||||
# define RYML_DEBUG_BREAK() \
|
||||
{ \
|
||||
do { \
|
||||
if(c4::get_error_flags() & c4::ON_ERROR_DEBUGBREAK) \
|
||||
{ \
|
||||
C4_DEBUG_BREAK(); \
|
||||
} \
|
||||
}
|
||||
} while(0)
|
||||
#else
|
||||
# define RYML_DEBUG_BREAK()
|
||||
#endif
|
||||
|
||||
|
||||
/** @endcond */
|
||||
|
||||
|
||||
@@ -190,11 +238,33 @@ namespace yml {
|
||||
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wold-style-cast")
|
||||
|
||||
enum : size_t {
|
||||
/** a null position */
|
||||
npos = size_t(-1),
|
||||
|
||||
#ifndef RYML_ID_TYPE
|
||||
/** The type of a node id in the YAML tree. In the future, the default
|
||||
* will likely change to int32_t, which was observed to be faster.
|
||||
* @see id_type */
|
||||
#define RYML_ID_TYPE size_t
|
||||
#endif
|
||||
|
||||
|
||||
/** The type of a node id in the YAML tree; to override the default
|
||||
* type, define the macro @ref RYML_ID_TYPE to a suitable integer
|
||||
* type. */
|
||||
using id_type = RYML_ID_TYPE;
|
||||
static_assert(std::is_integral<id_type>::value, "id_type must be an integer type");
|
||||
|
||||
|
||||
C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wuseless-cast")
|
||||
enum : id_type {
|
||||
/** an index to none */
|
||||
NONE = size_t(-1)
|
||||
NONE = id_type(-1),
|
||||
};
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_POP
|
||||
|
||||
|
||||
enum : size_t {
|
||||
/** a null string position */
|
||||
npos = size_t(-1)
|
||||
};
|
||||
|
||||
|
||||
@@ -212,28 +282,40 @@ struct RYML_EXPORT LineCol
|
||||
//! column
|
||||
size_t col;
|
||||
|
||||
LineCol() : offset(), line(), col() {}
|
||||
LineCol() = default;
|
||||
//! construct from line and column
|
||||
LineCol(size_t l, size_t c) : offset(0), line(l), col(c) {}
|
||||
//! construct from offset, line and column
|
||||
LineCol(size_t o, size_t l, size_t c) : offset(o), line(l), col(c) {}
|
||||
};
|
||||
static_assert(std::is_trivial<LineCol>::value, "LineCol not trivial");
|
||||
static_assert(std::is_standard_layout<LineCol>::value, "Location not trivial");
|
||||
|
||||
|
||||
//! a source file position
|
||||
struct RYML_EXPORT Location : public LineCol
|
||||
struct RYML_EXPORT Location
|
||||
{
|
||||
//! number of bytes from the beginning of the source buffer
|
||||
size_t offset;
|
||||
//! line
|
||||
size_t line;
|
||||
//! column
|
||||
size_t col;
|
||||
//! file name
|
||||
csubstr name;
|
||||
|
||||
operator bool () const { return !name.empty() || line != 0 || offset != 0; }
|
||||
operator bool () const { return !name.empty() || line != 0 || offset != 0 || col != 0; }
|
||||
operator LineCol const& () const { return reinterpret_cast<LineCol const&>(*this); } // NOLINT
|
||||
|
||||
Location() : LineCol(), name() {}
|
||||
Location( size_t l, size_t c) : LineCol{ l, c}, name( ) {}
|
||||
Location( csubstr n, size_t l, size_t c) : LineCol{ l, c}, name(n) {}
|
||||
Location( csubstr n, size_t b, size_t l, size_t c) : LineCol{b, l, c}, name(n) {}
|
||||
Location(const char *n, size_t l, size_t c) : LineCol{ l, c}, name(to_csubstr(n)) {}
|
||||
Location(const char *n, size_t b, size_t l, size_t c) : LineCol{b, l, c}, name(to_csubstr(n)) {}
|
||||
Location() = default;
|
||||
Location( size_t l, size_t c) : offset( ), line(l), col(c), name( ) {}
|
||||
Location( size_t b, size_t l, size_t c) : offset(b), line(l), col(c), name( ) {}
|
||||
Location( csubstr n, size_t l, size_t c) : offset( ), line(l), col(c), name(n) {}
|
||||
Location( csubstr n, size_t b, size_t l, size_t c) : offset(b), line(l), col(c), name(n) {}
|
||||
Location(const char *n, size_t l, size_t c) : offset( ), line(l), col(c), name(to_csubstr(n)) {}
|
||||
Location(const char *n, size_t b, size_t l, size_t c) : offset(b), line(l), col(c), name(to_csubstr(n)) {}
|
||||
};
|
||||
static_assert(std::is_standard_layout<Location>::value, "Location not trivial");
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -300,7 +382,7 @@ struct RYML_EXPORT Callbacks
|
||||
/** Construct an object with the default callbacks. If
|
||||
* @ref RYML_NO_DEFAULT_CALLBACKS is defined, the object will have null
|
||||
* members.*/
|
||||
Callbacks();
|
||||
Callbacks() noexcept;
|
||||
|
||||
/** Construct an object with the given callbacks.
|
||||
*
|
||||
@@ -338,6 +420,20 @@ struct RYML_EXPORT Callbacks
|
||||
/** @} */
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
typedef enum {
|
||||
NOBOM,
|
||||
UTF8,
|
||||
UTF16LE,
|
||||
UTF16BE,
|
||||
UTF32LE,
|
||||
UTF32BE,
|
||||
} Encoding_e;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -364,30 +460,30 @@ template<size_t N>
|
||||
}
|
||||
|
||||
#define _RYML_CB_ERR(cb, msg_literal) \
|
||||
_RYML_CB_ERR_(cb, msg_literal, c4::yml::Location(__FILE__, 0, __LINE__, 0))
|
||||
#define _RYML_CB_CHECK(cb, cond) \
|
||||
_RYML_CB_CHECK_(cb, cond, c4::yml::Location(__FILE__, 0, __LINE__, 0))
|
||||
#define _RYML_CB_ERR_(cb, msg_literal, loc) \
|
||||
do \
|
||||
{ \
|
||||
const char msg[] = msg_literal; \
|
||||
RYML_DEBUG_BREAK() \
|
||||
c4::yml::error((cb), \
|
||||
msg, sizeof(msg), \
|
||||
c4::yml::Location(__FILE__, 0, __LINE__, 0)); \
|
||||
RYML_DEBUG_BREAK(); \
|
||||
c4::yml::error((cb), msg, sizeof(msg)-1, loc); \
|
||||
C4_UNREACHABLE_AFTER_ERR(); \
|
||||
} while(0)
|
||||
#define _RYML_CB_CHECK(cb, cond) \
|
||||
#define _RYML_CB_CHECK_(cb, cond, loc) \
|
||||
do \
|
||||
{ \
|
||||
if(!(cond)) \
|
||||
if(C4_UNLIKELY(!(cond))) \
|
||||
{ \
|
||||
const char msg[] = "check failed: " #cond; \
|
||||
RYML_DEBUG_BREAK() \
|
||||
c4::yml::error((cb), \
|
||||
msg, sizeof(msg), \
|
||||
c4::yml::Location(__FILE__, 0, __LINE__, 0)); \
|
||||
RYML_DEBUG_BREAK(); \
|
||||
c4::yml::error((cb), msg, sizeof(msg)-1, loc); \
|
||||
C4_UNREACHABLE_AFTER_ERR(); \
|
||||
} \
|
||||
} while(0)
|
||||
#define _RYML_CB_ALLOC_HINT(cb, T, num, hint) (T*) (cb).m_allocate((num) * sizeof(T), (hint), (cb).m_user_data)
|
||||
#define _RYML_CB_ALLOC(cb, T, num) _RYML_CB_ALLOC_HINT((cb), (T), (num), nullptr)
|
||||
#define _RYML_CB_ALLOC(cb, T, num) _RYML_CB_ALLOC_HINT((cb), T, (num), nullptr)
|
||||
#define _RYML_CB_FREE(cb, buf, T, num) \
|
||||
do { \
|
||||
(cb).m_free((buf), (num) * sizeof(T), (cb).m_user_data); \
|
||||
@@ -395,11 +491,54 @@ do \
|
||||
} while(0)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
typedef enum {
|
||||
BLOCK_LITERAL, //!< keep newlines (|)
|
||||
BLOCK_FOLD //!< replace newline with single space (>)
|
||||
} BlockStyle_e;
|
||||
|
||||
typedef enum {
|
||||
CHOMP_CLIP, //!< single newline at end (default)
|
||||
CHOMP_STRIP, //!< no newline at end (-)
|
||||
CHOMP_KEEP //!< all newlines from end (+)
|
||||
} BlockChomp_e;
|
||||
|
||||
|
||||
/** Abstracts the fact that a scalar filter result may not fit in the
|
||||
* intended memory. */
|
||||
struct FilterResult
|
||||
{
|
||||
C4_ALWAYS_INLINE bool valid() const noexcept { return str.str != nullptr; }
|
||||
C4_ALWAYS_INLINE size_t required_len() const noexcept { return str.len; }
|
||||
C4_ALWAYS_INLINE csubstr get() const { RYML_ASSERT(valid()); return str; }
|
||||
csubstr str;
|
||||
};
|
||||
/** Abstracts the fact that a scalar filter result may not fit in the
|
||||
* intended memory. */
|
||||
struct FilterResultExtending
|
||||
{
|
||||
C4_ALWAYS_INLINE bool valid() const noexcept { return str.str != nullptr; }
|
||||
C4_ALWAYS_INLINE size_t required_len() const noexcept { return reqlen; }
|
||||
C4_ALWAYS_INLINE csubstr get() const { RYML_ASSERT(valid()); return str; }
|
||||
csubstr str;
|
||||
size_t reqlen;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace detail {
|
||||
// is there a better way to do this?
|
||||
template<int8_t signedval, uint8_t unsignedval>
|
||||
struct _charconstant_t
|
||||
: public std::conditional<std::is_signed<char>::value,
|
||||
std::integral_constant<int8_t, signedval>,
|
||||
std::integral_constant<int8_t, static_cast<int8_t>(unsignedval)>,
|
||||
std::integral_constant<uint8_t, unsignedval>>::type
|
||||
{};
|
||||
#define _RYML_CHCONST(signedval, unsignedval) ::c4::yml::detail::_charconstant_t<INT8_C(signedval), UINT8_C(unsignedval)>::value
|
||||
@@ -411,10 +550,11 @@ struct _SubstrWriter
|
||||
{
|
||||
substr buf;
|
||||
size_t pos;
|
||||
_SubstrWriter(substr buf_, size_t pos_=0) : buf(buf_), pos(pos_) {}
|
||||
_SubstrWriter(substr buf_, size_t pos_=0) : buf(buf_), pos(pos_) { C4_ASSERT(buf.str); }
|
||||
void append(csubstr s)
|
||||
{
|
||||
C4_ASSERT(!s.overlaps(buf));
|
||||
C4_ASSERT(s.str || !s.len);
|
||||
if(s.len && pos + s.len <= buf.len)
|
||||
{
|
||||
C4_ASSERT(s.str);
|
||||
@@ -424,12 +564,14 @@ struct _SubstrWriter
|
||||
}
|
||||
void append(char c)
|
||||
{
|
||||
C4_ASSERT(buf.str);
|
||||
if(pos < buf.len)
|
||||
buf.str[pos] = c;
|
||||
++pos;
|
||||
}
|
||||
void append_n(char c, size_t numtimes)
|
||||
{
|
||||
C4_ASSERT(buf.str);
|
||||
if(numtimes && pos + numtimes < buf.len)
|
||||
memset(buf.str + pos, c, numtimes);
|
||||
pos += numtimes;
|
||||
@@ -439,15 +581,77 @@ struct _SubstrWriter
|
||||
//! get the part written so far
|
||||
csubstr curr() const { return pos <= buf.len ? buf.first(pos) : buf; }
|
||||
//! get the part that is still free to write to (the remainder)
|
||||
substr rem() { return pos < buf.len ? buf.sub(pos) : buf.last(0); }
|
||||
substr rem() const { return pos < buf.len ? buf.sub(pos) : buf.last(0); }
|
||||
|
||||
size_t advance(size_t more) { pos += more; return pos; }
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
|
||||
namespace detail {
|
||||
// dumpfn is a function abstracting prints to terminal (or to string).
|
||||
template<class DumpFn, class ...Args>
|
||||
C4_NO_INLINE void _dump(DumpFn &&dumpfn, csubstr fmt, Args&& ...args)
|
||||
{
|
||||
DumpResults results;
|
||||
// try writing everything:
|
||||
{
|
||||
// buffer for converting individual arguments. it is defined
|
||||
// in a child scope to free it in case the buffer is too small
|
||||
// for any of the arguments.
|
||||
char writebuf[RYML_LOGBUF_SIZE];
|
||||
results = format_dump_resume(std::forward<DumpFn>(dumpfn), writebuf, fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
// if any of the arguments failed to fit the buffer, allocate a
|
||||
// larger buffer (up to a limit) and resume writing.
|
||||
//
|
||||
// results.bufsize is set to the size of the largest element
|
||||
// serialized. Eg int(1) will require 1 byte.
|
||||
if(C4_UNLIKELY(results.bufsize > RYML_LOGBUF_SIZE))
|
||||
{
|
||||
const size_t bufsize = results.bufsize <= RYML_LOGBUF_SIZE_MAX ? results.bufsize : RYML_LOGBUF_SIZE_MAX;
|
||||
#ifdef C4_MSVC
|
||||
substr largerbuf = {static_cast<char*>(_alloca(bufsize)), bufsize};
|
||||
#else
|
||||
substr largerbuf = {static_cast<char*>(alloca(bufsize)), bufsize};
|
||||
#endif
|
||||
results = format_dump_resume(std::forward<DumpFn>(dumpfn), results, largerbuf, fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
template<class ...Args>
|
||||
C4_NORETURN C4_NO_INLINE void _report_err(Callbacks const& C4_RESTRICT callbacks, csubstr fmt, Args const& C4_RESTRICT ...args)
|
||||
{
|
||||
char errmsg[RYML_ERRMSG_SIZE] = {0};
|
||||
detail::_SubstrWriter writer(errmsg);
|
||||
auto dumpfn = [&writer](csubstr s){ writer.append(s); };
|
||||
_dump(dumpfn, fmt, args...);
|
||||
writer.append('\n');
|
||||
const size_t len = writer.pos < RYML_ERRMSG_SIZE ? writer.pos : RYML_ERRMSG_SIZE;
|
||||
callbacks.m_error(errmsg, len, {}, callbacks.m_user_data);
|
||||
C4_UNREACHABLE_AFTER_ERR();
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
|
||||
inline csubstr _c4prc(const char &C4_RESTRICT c) // pass by reference!
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case '\n': return csubstr("\\n");
|
||||
case '\t': return csubstr("\\t");
|
||||
case '\0': return csubstr("\\0");
|
||||
case '\r': return csubstr("\\r");
|
||||
case '\f': return csubstr("\\f");
|
||||
case '\b': return csubstr("\\b");
|
||||
case '\v': return csubstr("\\v");
|
||||
case '\a': return csubstr("\\a");
|
||||
default: return csubstr(&c, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_POP
|
||||
C4_SUPPRESS_WARNING_GCC_POP
|
||||
|
||||
} // namespace yml
|
||||
} // namespace c4
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
|
||||
void check_invariants(Tree const& t, size_t node=NONE);
|
||||
void check_invariants(Tree const& t, id_type node=NONE);
|
||||
void check_free_list(Tree const& t);
|
||||
void check_arena(Tree const& t);
|
||||
|
||||
@@ -26,16 +26,16 @@ void check_arena(Tree const& t);
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline void check_invariants(Tree const& t, size_t node)
|
||||
inline void check_invariants(Tree const& t, id_type node)
|
||||
{
|
||||
if(node == NONE)
|
||||
{
|
||||
if(t.size() == 0) return;
|
||||
if(t.empty()) return;
|
||||
node = t.root_id();
|
||||
}
|
||||
|
||||
auto const& n = *t._p(node);
|
||||
#ifdef RYML_DBG
|
||||
NodeData const& n = *t._p(node);
|
||||
#if defined(RYML_DBG) && 0
|
||||
if(n.m_first_child != NONE || n.m_last_child != NONE)
|
||||
{
|
||||
printf("check(%zu): fc=%zu lc=%zu\n", node, n.m_first_child, n.m_last_child);
|
||||
@@ -100,10 +100,10 @@ inline void check_invariants(Tree const& t, size_t node)
|
||||
C4_CHECK(t._p(n.m_next_sibling)->m_next_sibling != node);
|
||||
}
|
||||
|
||||
size_t count = 0;
|
||||
for(size_t i = n.m_first_child; i != NONE; i = t.next_sibling(i))
|
||||
id_type count = 0;
|
||||
for(id_type i = n.m_first_child; i != NONE; i = t.next_sibling(i))
|
||||
{
|
||||
#ifdef RYML_DBG
|
||||
#if defined(RYML_DBG) && 0
|
||||
printf("check(%zu): descend to child[%zu]=%zu\n", node, count, i);
|
||||
#endif
|
||||
auto const& ch = *t._p(i);
|
||||
@@ -131,7 +131,7 @@ inline void check_invariants(Tree const& t, size_t node)
|
||||
check_arena(t);
|
||||
}
|
||||
|
||||
for(size_t i = t.first_child(node); i != NONE; i = t.next_sibling(i))
|
||||
for(id_type i = t.first_child(node); i != NONE; i = t.next_sibling(i))
|
||||
{
|
||||
check_invariants(t, i);
|
||||
}
|
||||
@@ -159,8 +159,8 @@ inline void check_free_list(Tree const& t)
|
||||
//C4_CHECK(head.m_prev_sibling == NONE);
|
||||
//C4_CHECK(tail.m_next_sibling == NONE);
|
||||
|
||||
size_t count = 0;
|
||||
for(size_t i = t.m_free_head, prev = NONE; i != NONE; i = t._p(i)->m_next_sibling)
|
||||
id_type count = 0;
|
||||
for(id_type i = t.m_free_head, prev = NONE; i != NONE; i = t._p(i)->m_next_sibling)
|
||||
{
|
||||
auto const& elm = *t._p(i);
|
||||
if(&elm != &head)
|
||||
|
||||
@@ -4,135 +4,144 @@
|
||||
#ifndef _C4_YML_COMMON_HPP_
|
||||
#include "../common.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef RYML_DBG
|
||||
#include <cstdio>
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// some debugging scaffolds
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4068/*unknown pragma*/)
|
||||
#endif
|
||||
// NOLINTBEGIN(*)
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_PUSH
|
||||
C4_SUPPRESS_WARNING_MSVC_PUSH
|
||||
C4_SUPPRESS_WARNING_MSVC(4068/*unknown pragma*/)
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
|
||||
//#pragma GCC diagnostic ignored "-Wpragma-system-header-outside-header"
|
||||
#pragma GCC system_header
|
||||
C4_SUPPRESS_WARNING_GCC("-Wunknown-pragmas")
|
||||
C4_SUPPRESS_WARNING_CLANG("-Wgnu-zero-variadic-macro-arguments")
|
||||
// NOLINTEND(*)
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Werror"
|
||||
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
|
||||
|
||||
// some debugging scaffolds
|
||||
#ifdef RYML_DBG
|
||||
#include <c4/dump.hpp>
|
||||
namespace c4 {
|
||||
inline void _dbg_dumper(csubstr s) { fwrite(s.str, 1, s.len, stdout); };
|
||||
template<class ...Args>
|
||||
void _dbg_printf(c4::csubstr fmt, Args&& ...args)
|
||||
{
|
||||
static char writebuf[256];
|
||||
auto results = c4::format_dump_resume<&_dbg_dumper>(writebuf, fmt, std::forward<Args>(args)...);
|
||||
// resume writing if the results failed to fit the buffer
|
||||
if(C4_UNLIKELY(results.bufsize > sizeof(writebuf))) // bufsize will be that of the largest element serialized. Eg int(1), will require 1 byte.
|
||||
{
|
||||
results = format_dump_resume<&_dbg_dumper>(results, writebuf, fmt, std::forward<Args>(args)...);
|
||||
if(C4_UNLIKELY(results.bufsize > sizeof(writebuf)))
|
||||
{
|
||||
results = format_dump_resume<&_dbg_dumper>(results, writebuf, fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace c4
|
||||
|
||||
# define _c4dbgt(fmt, ...) this->_dbg ("{}:{}: " fmt , __FILE__, __LINE__, ## __VA_ARGS__)
|
||||
# define _c4dbgpf(fmt, ...) _dbg_printf("{}:{}: " fmt "\n", __FILE__, __LINE__, ## __VA_ARGS__)
|
||||
# define _c4dbgp(msg) _dbg_printf("{}:{}: " msg "\n", __FILE__, __LINE__ )
|
||||
# define _c4dbgq(msg) _dbg_printf(msg "\n")
|
||||
#ifndef RYML_DBG
|
||||
# define _c4err(fmt, ...) \
|
||||
do { if(c4::is_debugger_attached()) { C4_DEBUG_BREAK(); } \
|
||||
this->_err("ERROR:\n" "{}:{}: " fmt, __FILE__, __LINE__, ## __VA_ARGS__); } while(0)
|
||||
#else
|
||||
this->_err("ERROR: " fmt, ## __VA_ARGS__)
|
||||
# define _c4dbgt(fmt, ...)
|
||||
# define _c4dbgpf(fmt, ...)
|
||||
# define _c4dbgpf_(fmt, ...)
|
||||
# define _c4dbgp(msg)
|
||||
# define _c4dbgp_(msg)
|
||||
# define _c4dbgq(msg)
|
||||
# define _c4presc(...)
|
||||
# define _c4prscalar(msg, scalar, keep_newlines)
|
||||
#else
|
||||
# define _c4err(fmt, ...) \
|
||||
do { if(c4::is_debugger_attached()) { C4_DEBUG_BREAK(); } \
|
||||
this->_err("ERROR: " fmt, ## __VA_ARGS__); } while(0)
|
||||
#endif
|
||||
do { RYML_DEBUG_BREAK(); this->_err("ERROR:\n" "{}:{}: " fmt, __FILE__, __LINE__, ## __VA_ARGS__); } while(0)
|
||||
# define _c4dbgt(fmt, ...) do { if(_dbg_enabled()) { \
|
||||
this->_dbg ("{}:{}: " fmt , __FILE__, __LINE__, ## __VA_ARGS__); } } while(0)
|
||||
# define _c4dbgpf(fmt, ...) _dbg_printf("{}:{}: " fmt "\n", __FILE__, __LINE__, ## __VA_ARGS__)
|
||||
# define _c4dbgpf_(fmt, ...) _dbg_printf("{}:{}: " fmt , __FILE__, __LINE__, ## __VA_ARGS__)
|
||||
# define _c4dbgp(msg) _dbg_printf("{}:{}: " msg "\n", __FILE__, __LINE__ )
|
||||
# define _c4dbgp_(msg) _dbg_printf("{}:{}: " msg , __FILE__, __LINE__ )
|
||||
# define _c4dbgq(msg) _dbg_printf(msg "\n")
|
||||
# define _c4presc(...) do { if(_dbg_enabled()) __c4presc(__VA_ARGS__); } while(0)
|
||||
# define _c4prscalar(msg, scalar, keep_newlines) \
|
||||
do { \
|
||||
_c4dbgpf_("{}: [{}]~~~", msg, scalar.len); \
|
||||
if(_dbg_enabled()) { \
|
||||
__c4presc((scalar).str, (scalar).len, (keep_newlines)); \
|
||||
} \
|
||||
_c4dbgq("~~~"); \
|
||||
} while(0)
|
||||
#endif // RYML_DBG
|
||||
|
||||
#define _c4prsp(sp) sp
|
||||
#define _c4presc(s) __c4presc(s.str, s.len)
|
||||
inline c4::csubstr _c4prc(const char &C4_RESTRICT c)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef RYML_DBG
|
||||
|
||||
#include <c4/dump.hpp>
|
||||
namespace c4 {
|
||||
inline bool& _dbg_enabled() { static bool enabled = true; return enabled; }
|
||||
inline void _dbg_set_enabled(bool yes) { _dbg_enabled() = yes; }
|
||||
inline void _dbg_dumper(csubstr s)
|
||||
{
|
||||
switch(c)
|
||||
if(s.str)
|
||||
fwrite(s.str, 1, s.len, stdout);
|
||||
}
|
||||
inline substr _dbg_buf() noexcept
|
||||
{
|
||||
static char writebuf[2048];
|
||||
return substr{writebuf, sizeof(writebuf)}; // g++-5 has trouble with return writebuf;
|
||||
}
|
||||
template<class ...Args>
|
||||
C4_NO_INLINE void _dbg_printf(c4::csubstr fmt, Args const& ...args)
|
||||
{
|
||||
if(_dbg_enabled())
|
||||
{
|
||||
case '\n': return c4::csubstr("\\n");
|
||||
case '\t': return c4::csubstr("\\t");
|
||||
case '\0': return c4::csubstr("\\0");
|
||||
case '\r': return c4::csubstr("\\r");
|
||||
case '\f': return c4::csubstr("\\f");
|
||||
case '\b': return c4::csubstr("\\b");
|
||||
case '\v': return c4::csubstr("\\v");
|
||||
case '\a': return c4::csubstr("\\a");
|
||||
default: return c4::csubstr(&c, 1);
|
||||
substr buf = _dbg_buf();
|
||||
const size_t needed_size = c4::format_dump(&_dbg_dumper, buf, fmt, args...);
|
||||
C4_CHECK(needed_size <= buf.len);
|
||||
}
|
||||
}
|
||||
inline void __c4presc(const char *s, size_t len)
|
||||
inline C4_NO_INLINE void __c4presc(const char *s, size_t len, bool keep_newlines=false)
|
||||
{
|
||||
RYML_ASSERT(s || !len);
|
||||
size_t prev = 0;
|
||||
for(size_t i = 0; i < len; ++i)
|
||||
{
|
||||
switch(s[i])
|
||||
{
|
||||
case '\n' : if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('n'); putchar('\n'); prev = i+1; break;
|
||||
case '\t' : if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('t'); prev = i+1; break;
|
||||
case '\0' : if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('0'); prev = i+1; break;
|
||||
case '\r' : if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('r'); prev = i+1; break;
|
||||
case '\f' : if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('f'); prev = i+1; break;
|
||||
case '\b' : if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('b'); prev = i+1; break;
|
||||
case '\v' : if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('v'); prev = i+1; break;
|
||||
case '\a' : if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('a'); prev = i+1; break;
|
||||
case '\x1b': if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('e'); prev = i+1; break;
|
||||
case '\n' : _dbg_printf("{}{}{}", csubstr(s+prev, i-prev), csubstr("\\n"), csubstr(keep_newlines ? "\n":"")); prev = i+1; break;
|
||||
case '\t' : _dbg_printf("{}{}", csubstr(s+prev, i-prev), csubstr("\\t")); prev = i+1; break;
|
||||
case '\0' : _dbg_printf("{}{}", csubstr(s+prev, i-prev), csubstr("\\0")); prev = i+1; break;
|
||||
case '\r' : _dbg_printf("{}{}", csubstr(s+prev, i-prev), csubstr("\\r")); prev = i+1; break;
|
||||
case '\f' : _dbg_printf("{}{}", csubstr(s+prev, i-prev), csubstr("\\f")); prev = i+1; break;
|
||||
case '\b' : _dbg_printf("{}{}", csubstr(s+prev, i-prev), csubstr("\\b")); prev = i+1; break;
|
||||
case '\v' : _dbg_printf("{}{}", csubstr(s+prev, i-prev), csubstr("\\v")); prev = i+1; break;
|
||||
case '\a' : _dbg_printf("{}{}", csubstr(s+prev, i-prev), csubstr("\\a")); prev = i+1; break;
|
||||
case '\x1b': _dbg_printf("{}{}", csubstr(s+prev, i-prev), csubstr("\\x1b")); prev = i+1; break;
|
||||
case -0x3e/*0xc2u*/:
|
||||
if(i+1 < len)
|
||||
{
|
||||
if(s[i+1] == -0x60/*0xa0u*/)
|
||||
{
|
||||
if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('_'); prev = i+2; ++i;
|
||||
_dbg_printf("{}{}", csubstr(s+prev, i-prev), csubstr("\\_")); prev = i+1;
|
||||
}
|
||||
else if(s[i+1] == -0x7b/*0x85u*/)
|
||||
{
|
||||
if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('N'); prev = i+2; ++i;
|
||||
_dbg_printf("{}{}", csubstr(s+prev, i-prev), csubstr("\\N")); prev = i+1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case -0x1e/*0xe2u*/:
|
||||
if(i+2 < len && s[i+1] == -0x80/*0x80u*/)
|
||||
{
|
||||
if(s[i+2] == -0x58/*0xa8u*/)
|
||||
{
|
||||
if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('L'); prev = i+3; i += 2;
|
||||
_dbg_printf("{}{}", csubstr(s+prev, i-prev), csubstr("\\L")); prev = i+1;
|
||||
}
|
||||
else if(s[i+2] == -0x57/*0xa9u*/)
|
||||
{
|
||||
if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('P'); prev = i+3; i += 2;
|
||||
_dbg_printf("{}{}", csubstr(s+prev, i-prev), csubstr("\\P")); prev = i+1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(len > prev)
|
||||
fwrite(s + prev, 1, len - prev, stdout);
|
||||
_dbg_printf("{}", csubstr(s+prev, len-prev));
|
||||
}
|
||||
inline void __c4presc(csubstr s, bool keep_newlines=false)
|
||||
{
|
||||
__c4presc(s.str, s.len, keep_newlines);
|
||||
}
|
||||
} // namespace c4
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
#endif // RYML_DBG
|
||||
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_POP
|
||||
C4_SUPPRESS_WARNING_MSVC_POP
|
||||
|
||||
#endif /* _C4_YML_DETAIL_PARSER_DBG_HPP_ */
|
||||
|
||||
152
3rdparty/rapidyaml/include/c4/yml/detail/print.hpp
vendored
152
3rdparty/rapidyaml/include/c4/yml/detail/print.hpp
vendored
@@ -4,20 +4,76 @@
|
||||
#include "c4/yml/tree.hpp"
|
||||
#include "c4/yml/node.hpp"
|
||||
|
||||
#ifdef RYML_DBG
|
||||
#define _c4dbg_tree(...) print_tree(__VA_ARGS__)
|
||||
#define _c4dbg_node(...) print_tree(__VA_ARGS__)
|
||||
#else
|
||||
#define _c4dbg_tree(...)
|
||||
#define _c4dbg_node(...)
|
||||
#endif
|
||||
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wold-style-cast")
|
||||
C4_SUPPRESS_WARNING_GCC("-Wuseless-cast")
|
||||
|
||||
inline size_t print_node(Tree const& p, size_t node, int level, size_t count, bool print_children)
|
||||
inline const char* _container_style_code(Tree const& p, id_type node)
|
||||
{
|
||||
printf("[%zd]%*s[%zd] %p", count, (2*level), "", node, (void const*)p.get(node));
|
||||
if(p.is_container(node))
|
||||
{
|
||||
if(p._p(node)->m_type & (FLOW_SL|FLOW_ML))
|
||||
{
|
||||
return "[FLOW]";
|
||||
}
|
||||
if(p._p(node)->m_type & (BLOCK))
|
||||
{
|
||||
return "[BLCK]";
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
inline char _scalar_code(NodeType masked)
|
||||
{
|
||||
if(masked & (KEY_LITERAL|VAL_LITERAL))
|
||||
return '|';
|
||||
if(masked & (KEY_FOLDED|VAL_FOLDED))
|
||||
return '>';
|
||||
if(masked & (KEY_SQUO|VAL_SQUO))
|
||||
return '\'';
|
||||
if(masked & (KEY_DQUO|VAL_DQUO))
|
||||
return '"';
|
||||
if(masked & (KEY_PLAIN|VAL_PLAIN))
|
||||
return '~';
|
||||
return '@';
|
||||
}
|
||||
inline char _scalar_code_key(NodeType t)
|
||||
{
|
||||
return _scalar_code(t & KEY_STYLE);
|
||||
}
|
||||
inline char _scalar_code_val(NodeType t)
|
||||
{
|
||||
return _scalar_code(t & VAL_STYLE);
|
||||
}
|
||||
inline char _scalar_code_key(Tree const& p, id_type node)
|
||||
{
|
||||
return _scalar_code_key(p._p(node)->m_type);
|
||||
}
|
||||
inline char _scalar_code_val(Tree const& p, id_type node)
|
||||
{
|
||||
return _scalar_code_key(p._p(node)->m_type);
|
||||
}
|
||||
inline id_type print_node(Tree const& p, id_type node, int level, id_type count, bool print_children)
|
||||
{
|
||||
printf("[%zu]%*s[%zu] %p", (size_t)count, (2*level), "", (size_t)node, (void const*)p.get(node));
|
||||
if(p.is_root(node))
|
||||
{
|
||||
printf(" [ROOT]");
|
||||
}
|
||||
printf(" %s:", p.type_str(node));
|
||||
char typebuf[128];
|
||||
csubstr typestr = p.type(node).type_str(typebuf);
|
||||
RYML_CHECK(typestr.str);
|
||||
printf(" %.*s", (int)typestr.len, typestr.str);
|
||||
if(p.has_key(node))
|
||||
{
|
||||
if(p.has_key_anchor(node))
|
||||
@@ -28,65 +84,47 @@ inline size_t print_node(Tree const& p, size_t node, int level, size_t count, bo
|
||||
if(p.has_key_tag(node))
|
||||
{
|
||||
csubstr kt = p.key_tag(node);
|
||||
csubstr k = p.key(node);
|
||||
printf(" %.*s '%.*s'", (int)kt.len, kt.str, (int)k.len, k.str);
|
||||
}
|
||||
else
|
||||
{
|
||||
csubstr k = p.key(node);
|
||||
printf(" '%.*s'", (int)k.len, k.str);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RYML_ASSERT( ! p.has_key_tag(node));
|
||||
}
|
||||
if(p.has_val(node))
|
||||
{
|
||||
if(p.has_val_tag(node))
|
||||
{
|
||||
csubstr vt = p.val_tag(node);
|
||||
csubstr v = p.val(node);
|
||||
printf(" %.*s '%.*s'", (int)vt.len, vt.str, (int)v.len, v.str);
|
||||
}
|
||||
else
|
||||
{
|
||||
csubstr v = p.val(node);
|
||||
printf(" '%.*s'", (int)v.len, v.str);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(p.has_val_tag(node))
|
||||
{
|
||||
csubstr vt = p.val_tag(node);
|
||||
printf(" %.*s", (int)vt.len, vt.str);
|
||||
printf(" <%.*s>", (int)kt.len, kt.str);
|
||||
}
|
||||
const char code = _scalar_code_key(p, node);
|
||||
csubstr k = p.key(node);
|
||||
printf(" %c%.*s%c :", code, (int)k.len, k.str, code);
|
||||
}
|
||||
if(p.has_val_anchor(node))
|
||||
{
|
||||
auto &a = p.val_anchor(node);
|
||||
printf(" valanchor='&%.*s'", (int)a.len, a.str);
|
||||
csubstr a = p.val_anchor(node);
|
||||
printf(" &%.*s'", (int)a.len, a.str);
|
||||
}
|
||||
printf(" (%zd sibs)", p.num_siblings(node));
|
||||
if(p.has_val_tag(node))
|
||||
{
|
||||
csubstr vt = p.val_tag(node);
|
||||
printf(" <%.*s>", (int)vt.len, vt.str);
|
||||
}
|
||||
if(p.has_val(node))
|
||||
{
|
||||
const char code = _scalar_code_val(p, node);
|
||||
csubstr v = p.val(node);
|
||||
printf(" %c%.*s%c", code, (int)v.len, v.str, code);
|
||||
}
|
||||
printf(" (%zu sibs)", (size_t)p.num_siblings(node));
|
||||
|
||||
++count;
|
||||
|
||||
if(p.is_container(node))
|
||||
if(!p.is_container(node))
|
||||
{
|
||||
printf(" %zd children:\n", p.num_children(node));
|
||||
printf("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" (%zu children)\n", (size_t)p.num_children(node));
|
||||
if(print_children)
|
||||
{
|
||||
for(size_t i = p.first_child(node); i != NONE; i = p.next_sibling(i))
|
||||
for(id_type i = p.first_child(node); i != NONE; i = p.next_sibling(i))
|
||||
{
|
||||
count = print_node(p, i, level+1, count, print_children);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
@@ -106,21 +144,37 @@ inline void print_node(ConstNodeRef const& p, int level=0)
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline size_t print_tree(Tree const& p, size_t node=NONE)
|
||||
inline id_type print_tree(const char *message, Tree const& p, id_type node=NONE)
|
||||
{
|
||||
printf("--------------------------------------\n");
|
||||
size_t ret = 0;
|
||||
if(message != nullptr)
|
||||
printf("%s:\n", message);
|
||||
id_type ret = 0;
|
||||
if(!p.empty())
|
||||
{
|
||||
if(node == NONE)
|
||||
node = p.root_id();
|
||||
ret = print_node(p, node, 0, 0, true);
|
||||
}
|
||||
printf("#nodes=%zd vs #printed=%zd\n", p.size(), ret);
|
||||
printf("#nodes=%zu vs #printed=%zu\n", (size_t)p.size(), (size_t)ret);
|
||||
printf("--------------------------------------\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline id_type print_tree(Tree const& p, id_type node=NONE)
|
||||
{
|
||||
return print_tree(nullptr, p, node);
|
||||
}
|
||||
|
||||
inline void print_tree(ConstNodeRef const& p, int level)
|
||||
{
|
||||
print_node(p, level);
|
||||
for(ConstNodeRef ch : p.children())
|
||||
{
|
||||
print_tree(ch, level+1);
|
||||
}
|
||||
}
|
||||
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_POP
|
||||
|
||||
} /* namespace yml */
|
||||
|
||||
115
3rdparty/rapidyaml/include/c4/yml/detail/stack.hpp
vendored
115
3rdparty/rapidyaml/include/c4/yml/detail/stack.hpp
vendored
@@ -18,22 +18,27 @@ C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wold-style-cast")
|
||||
|
||||
namespace detail {
|
||||
|
||||
/** A lightweight contiguous stack with SSO. This avoids a dependency on std. */
|
||||
template<class T, size_t N=16>
|
||||
/** A lightweight contiguous stack with Small Storage
|
||||
* Optimization. This is required because std::vector can throw
|
||||
* exceptions, and we don't want to enforce any particular error
|
||||
* mechanism. */
|
||||
template<class T, id_type N=16>
|
||||
class stack
|
||||
{
|
||||
static_assert(std::is_trivially_copyable<T>::value, "T must be trivially copyable");
|
||||
static_assert(std::is_trivially_destructible<T>::value, "T must be trivially destructible");
|
||||
|
||||
enum : size_t { sso_size = N };
|
||||
public:
|
||||
|
||||
enum : id_type { sso_size = N };
|
||||
|
||||
public:
|
||||
|
||||
T m_buf[N];
|
||||
T * m_stack;
|
||||
size_t m_size;
|
||||
size_t m_capacity;
|
||||
Callbacks m_callbacks;
|
||||
T m_buf[size_t(N)];
|
||||
T *C4_RESTRICT m_stack;
|
||||
id_type m_size;
|
||||
id_type m_capacity;
|
||||
Callbacks m_callbacks;
|
||||
|
||||
public:
|
||||
|
||||
@@ -64,9 +69,12 @@ public:
|
||||
|
||||
stack& operator= (stack const& that) RYML_NOEXCEPT
|
||||
{
|
||||
_cb(that.m_callbacks);
|
||||
resize(that.m_size);
|
||||
_cp(&that);
|
||||
if(&that != this)
|
||||
{
|
||||
_cb(that.m_callbacks);
|
||||
resize(that.m_size);
|
||||
_cp(&that);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -79,29 +87,29 @@ public:
|
||||
|
||||
public:
|
||||
|
||||
size_t size() const { return m_size; }
|
||||
size_t empty() const { return m_size == 0; }
|
||||
size_t capacity() const { return m_capacity; }
|
||||
id_type size() const { return m_size; }
|
||||
id_type empty() const { return m_size == 0; }
|
||||
id_type capacity() const { return m_capacity; }
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
void resize(size_t sz)
|
||||
void resize(id_type sz)
|
||||
{
|
||||
reserve(sz);
|
||||
m_size = sz;
|
||||
}
|
||||
|
||||
void reserve(size_t sz);
|
||||
void reserve(id_type sz);
|
||||
|
||||
void push(T const& C4_RESTRICT n)
|
||||
{
|
||||
RYML_ASSERT((const char*)&n + sizeof(T) < (const char*)m_stack || &n > m_stack + m_capacity);
|
||||
_RYML_CB_ASSERT(m_callbacks, (const char*)&n + sizeof(T) < (const char*)m_stack || &n > m_stack + m_capacity);
|
||||
if(m_size == m_capacity)
|
||||
{
|
||||
size_t cap = m_capacity == 0 ? N : 2 * m_capacity;
|
||||
id_type cap = m_capacity == 0 ? N : 2 * m_capacity;
|
||||
reserve(cap);
|
||||
}
|
||||
m_stack[m_size] = n;
|
||||
@@ -110,10 +118,10 @@ public:
|
||||
|
||||
void push_top()
|
||||
{
|
||||
RYML_ASSERT(m_size > 0);
|
||||
_RYML_CB_ASSERT(m_callbacks, m_size > 0);
|
||||
if(m_size == m_capacity)
|
||||
{
|
||||
size_t cap = m_capacity == 0 ? N : 2 * m_capacity;
|
||||
id_type cap = m_capacity == 0 ? N : 2 * m_capacity;
|
||||
reserve(cap);
|
||||
}
|
||||
m_stack[m_size] = m_stack[m_size - 1];
|
||||
@@ -122,25 +130,25 @@ public:
|
||||
|
||||
T const& C4_RESTRICT pop()
|
||||
{
|
||||
RYML_ASSERT(m_size > 0);
|
||||
_RYML_CB_ASSERT(m_callbacks, m_size > 0);
|
||||
--m_size;
|
||||
return m_stack[m_size];
|
||||
}
|
||||
|
||||
C4_ALWAYS_INLINE T const& C4_RESTRICT top() const { RYML_ASSERT(m_size > 0); return m_stack[m_size - 1]; }
|
||||
C4_ALWAYS_INLINE T & C4_RESTRICT top() { RYML_ASSERT(m_size > 0); return m_stack[m_size - 1]; }
|
||||
C4_ALWAYS_INLINE T const& C4_RESTRICT top() const { _RYML_CB_ASSERT(m_callbacks, m_size > 0); return m_stack[m_size - 1]; }
|
||||
C4_ALWAYS_INLINE T & C4_RESTRICT top() { _RYML_CB_ASSERT(m_callbacks, m_size > 0); return m_stack[m_size - 1]; }
|
||||
|
||||
C4_ALWAYS_INLINE T const& C4_RESTRICT bottom() const { RYML_ASSERT(m_size > 0); return m_stack[0]; }
|
||||
C4_ALWAYS_INLINE T & C4_RESTRICT bottom() { RYML_ASSERT(m_size > 0); return m_stack[0]; }
|
||||
C4_ALWAYS_INLINE T const& C4_RESTRICT bottom() const { _RYML_CB_ASSERT(m_callbacks, m_size > 0); return m_stack[0]; }
|
||||
C4_ALWAYS_INLINE T & C4_RESTRICT bottom() { _RYML_CB_ASSERT(m_callbacks, m_size > 0); return m_stack[0]; }
|
||||
|
||||
C4_ALWAYS_INLINE T const& C4_RESTRICT top(size_t i) const { RYML_ASSERT(i < m_size); return m_stack[m_size - 1 - i]; }
|
||||
C4_ALWAYS_INLINE T & C4_RESTRICT top(size_t i) { RYML_ASSERT(i < m_size); return m_stack[m_size - 1 - i]; }
|
||||
C4_ALWAYS_INLINE T const& C4_RESTRICT top(id_type i) const { _RYML_CB_ASSERT(m_callbacks, i < m_size); return m_stack[m_size - 1 - i]; }
|
||||
C4_ALWAYS_INLINE T & C4_RESTRICT top(id_type i) { _RYML_CB_ASSERT(m_callbacks, i < m_size); return m_stack[m_size - 1 - i]; }
|
||||
|
||||
C4_ALWAYS_INLINE T const& C4_RESTRICT bottom(size_t i) const { RYML_ASSERT(i < m_size); return m_stack[i]; }
|
||||
C4_ALWAYS_INLINE T & C4_RESTRICT bottom(size_t i) { RYML_ASSERT(i < m_size); return m_stack[i]; }
|
||||
C4_ALWAYS_INLINE T const& C4_RESTRICT bottom(id_type i) const { _RYML_CB_ASSERT(m_callbacks, i < m_size); return m_stack[i]; }
|
||||
C4_ALWAYS_INLINE T & C4_RESTRICT bottom(id_type i) { _RYML_CB_ASSERT(m_callbacks, i < m_size); return m_stack[i]; }
|
||||
|
||||
C4_ALWAYS_INLINE T const& C4_RESTRICT operator[](size_t i) const { RYML_ASSERT(i < m_size); return m_stack[i]; }
|
||||
C4_ALWAYS_INLINE T & C4_RESTRICT operator[](size_t i) { RYML_ASSERT(i < m_size); return m_stack[i]; }
|
||||
C4_ALWAYS_INLINE T const& C4_RESTRICT operator[](id_type i) const { _RYML_CB_ASSERT(m_callbacks, i < m_size); return m_stack[i]; }
|
||||
C4_ALWAYS_INLINE T & C4_RESTRICT operator[](id_type i) { _RYML_CB_ASSERT(m_callbacks, i < m_size); return m_stack[i]; }
|
||||
|
||||
public:
|
||||
|
||||
@@ -154,10 +162,12 @@ public:
|
||||
const_iterator end () const { return (const_iterator)m_stack + m_size; }
|
||||
|
||||
public:
|
||||
|
||||
void _free();
|
||||
void _cp(stack const* C4_RESTRICT that);
|
||||
void _mv(stack * that);
|
||||
void _cb(Callbacks const& cb);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -165,8 +175,8 @@ public:
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template<class T, size_t N>
|
||||
void stack<T, N>::reserve(size_t sz)
|
||||
template<class T, id_type N>
|
||||
void stack<T, N>::reserve(id_type sz)
|
||||
{
|
||||
if(sz <= m_size)
|
||||
return;
|
||||
@@ -176,11 +186,12 @@ void stack<T, N>::reserve(size_t sz)
|
||||
m_capacity = N;
|
||||
return;
|
||||
}
|
||||
T *buf = (T*) m_callbacks.m_allocate(sz * sizeof(T), m_stack, m_callbacks.m_user_data);
|
||||
memcpy(buf, m_stack, m_size * sizeof(T));
|
||||
T *buf = (T*) m_callbacks.m_allocate((size_t)sz * sizeof(T), m_stack, m_callbacks.m_user_data);
|
||||
_RYML_CB_ASSERT(m_callbacks, ((uintptr_t)buf % alignof(T)) == 0u);
|
||||
memcpy(buf, m_stack, (size_t)m_size * sizeof(T));
|
||||
if(m_stack != m_buf)
|
||||
{
|
||||
m_callbacks.m_free(m_stack, m_capacity * sizeof(T), m_callbacks.m_user_data);
|
||||
m_callbacks.m_free(m_stack, (size_t)m_capacity * sizeof(T), m_callbacks.m_user_data);
|
||||
}
|
||||
m_stack = buf;
|
||||
m_capacity = sz;
|
||||
@@ -189,38 +200,38 @@ void stack<T, N>::reserve(size_t sz)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template<class T, size_t N>
|
||||
template<class T, id_type N>
|
||||
void stack<T, N>::_free()
|
||||
{
|
||||
RYML_ASSERT(m_stack != nullptr); // this structure cannot be memset() to zero
|
||||
_RYML_CB_ASSERT(m_callbacks, m_stack != nullptr); // this structure cannot be memset() to zero
|
||||
if(m_stack != m_buf)
|
||||
{
|
||||
m_callbacks.m_free(m_stack, m_capacity * sizeof(T), m_callbacks.m_user_data);
|
||||
m_callbacks.m_free(m_stack, (size_t)m_capacity * sizeof(T), m_callbacks.m_user_data);
|
||||
m_stack = m_buf;
|
||||
m_size = N;
|
||||
m_capacity = N;
|
||||
}
|
||||
else
|
||||
{
|
||||
RYML_ASSERT(m_capacity == N);
|
||||
_RYML_CB_ASSERT(m_callbacks, m_capacity == N);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template<class T, size_t N>
|
||||
template<class T, id_type N>
|
||||
void stack<T, N>::_cp(stack const* C4_RESTRICT that)
|
||||
{
|
||||
if(that->m_stack != that->m_buf)
|
||||
{
|
||||
RYML_ASSERT(that->m_capacity > N);
|
||||
RYML_ASSERT(that->m_size <= that->m_capacity);
|
||||
_RYML_CB_ASSERT(m_callbacks, that->m_capacity > N);
|
||||
_RYML_CB_ASSERT(m_callbacks, that->m_size <= that->m_capacity);
|
||||
}
|
||||
else
|
||||
{
|
||||
RYML_ASSERT(that->m_capacity <= N);
|
||||
RYML_ASSERT(that->m_size <= that->m_capacity);
|
||||
_RYML_CB_ASSERT(m_callbacks, that->m_capacity <= N);
|
||||
_RYML_CB_ASSERT(m_callbacks, that->m_size <= that->m_capacity);
|
||||
}
|
||||
memcpy(m_stack, that->m_stack, that->m_size * sizeof(T));
|
||||
m_size = that->m_size;
|
||||
@@ -231,19 +242,19 @@ void stack<T, N>::_cp(stack const* C4_RESTRICT that)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template<class T, size_t N>
|
||||
template<class T, id_type N>
|
||||
void stack<T, N>::_mv(stack * that)
|
||||
{
|
||||
if(that->m_stack != that->m_buf)
|
||||
{
|
||||
RYML_ASSERT(that->m_capacity > N);
|
||||
RYML_ASSERT(that->m_size <= that->m_capacity);
|
||||
_RYML_CB_ASSERT(m_callbacks, that->m_capacity > N);
|
||||
_RYML_CB_ASSERT(m_callbacks, that->m_size <= that->m_capacity);
|
||||
m_stack = that->m_stack;
|
||||
}
|
||||
else
|
||||
{
|
||||
RYML_ASSERT(that->m_capacity <= N);
|
||||
RYML_ASSERT(that->m_size <= that->m_capacity);
|
||||
_RYML_CB_ASSERT(m_callbacks, that->m_capacity <= N);
|
||||
_RYML_CB_ASSERT(m_callbacks, that->m_size <= that->m_capacity);
|
||||
memcpy(m_buf, that->m_buf, that->m_size * sizeof(T));
|
||||
m_stack = m_buf;
|
||||
}
|
||||
@@ -251,7 +262,7 @@ void stack<T, N>::_mv(stack * that)
|
||||
m_capacity = that->m_capacity;
|
||||
m_callbacks = that->m_callbacks;
|
||||
// make sure no deallocation happens on destruction
|
||||
RYML_ASSERT(that->m_stack != m_buf);
|
||||
_RYML_CB_ASSERT(m_callbacks, that->m_stack != m_buf);
|
||||
that->m_stack = that->m_buf;
|
||||
that->m_capacity = N;
|
||||
that->m_size = 0;
|
||||
@@ -260,7 +271,7 @@ void stack<T, N>::_mv(stack * that)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template<class T, size_t N>
|
||||
template<class T, id_type N>
|
||||
void stack<T, N>::_cb(Callbacks const& cb)
|
||||
{
|
||||
if(cb != m_callbacks)
|
||||
|
||||
916
3rdparty/rapidyaml/include/c4/yml/emit.def.hpp
vendored
916
3rdparty/rapidyaml/include/c4/yml/emit.def.hpp
vendored
File diff suppressed because it is too large
Load Diff
681
3rdparty/rapidyaml/include/c4/yml/emit.hpp
vendored
681
3rdparty/rapidyaml/include/c4/yml/emit.hpp
vendored
@@ -15,13 +15,8 @@
|
||||
#include "./node.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef emit
|
||||
#error "emit is defined, likely from a Qt include. This will cause a compilation error. See https://github.com/biojppm/rapidyaml/issues/120"
|
||||
#endif
|
||||
#define RYML_DEPRECATE_EMIT \
|
||||
RYML_DEPRECATED("use emit_yaml() instead. See https://github.com/biojppm/rapidyaml/issues/120")
|
||||
#define RYML_DEPRECATE_EMITRS \
|
||||
RYML_DEPRECATED("use emitrs_yaml() instead. See https://github.com/biojppm/rapidyaml/issues/120")
|
||||
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wold-style-cast")
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -43,6 +38,15 @@ using EmitterOStream = Emitter<WriterOStream<OStream>>;
|
||||
using EmitterFile = Emitter<WriterFile>;
|
||||
using EmitterBuf = Emitter<WriterBuf>;
|
||||
|
||||
namespace detail {
|
||||
inline bool is_set_(ConstNodeRef n) { return n.tree() && (n.id() != NONE); }
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** Specifies the type of content to emit */
|
||||
typedef enum {
|
||||
EMIT_YAML = 0, ///< emit YAML
|
||||
@@ -50,6 +54,59 @@ typedef enum {
|
||||
} EmitType_e;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** A lightweight object containing options to be used when emitting. */
|
||||
struct EmitOptions
|
||||
{
|
||||
typedef enum : uint32_t {
|
||||
DEFAULT_FLAGS = 0u,
|
||||
JSON_ERR_ON_TAG = 1u << 0u,
|
||||
JSON_ERR_ON_ANCHOR = 1u << 1u,
|
||||
_JSON_ERR_MASK = JSON_ERR_ON_TAG|JSON_ERR_ON_ANCHOR,
|
||||
} EmitOptionFlags_e;
|
||||
|
||||
public:
|
||||
|
||||
/** @name option flags
|
||||
*
|
||||
* @{ */
|
||||
C4_ALWAYS_INLINE EmitOptionFlags_e json_error_flags() const noexcept { return m_option_flags; }
|
||||
EmitOptions& json_error_flags(EmitOptionFlags_e d) noexcept { m_option_flags = (EmitOptionFlags_e)(d & _JSON_ERR_MASK); return *this; }
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
|
||||
/** @name max depth for the emitted tree
|
||||
*
|
||||
* This makes the emitter fail when emitting trees exceeding the
|
||||
* max_depth.
|
||||
*
|
||||
* @{ */
|
||||
C4_ALWAYS_INLINE id_type max_depth() const noexcept { return m_max_depth; }
|
||||
EmitOptions& max_depth(id_type d) noexcept { m_max_depth = d; return *this; }
|
||||
static constexpr const id_type max_depth_default = 64;
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
|
||||
bool operator== (const EmitOptions& that) const noexcept
|
||||
{
|
||||
return m_max_depth == that.m_max_depth &&
|
||||
m_option_flags == that.m_option_flags;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/** @cond dev */
|
||||
id_type m_max_depth{max_depth_default};
|
||||
EmitOptionFlags_e m_option_flags{DEFAULT_FLAGS};
|
||||
/** @endcond */
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -61,12 +118,21 @@ class Emitter : public Writer
|
||||
{
|
||||
public:
|
||||
|
||||
/** Construct the emitter and its internal Writer state. Every
|
||||
* parameter is forwarded to the constructor of the writer. */
|
||||
/** Construct the emitter and its internal Writer state, using default emit options.
|
||||
* @param args arguments to be forwarded to the constructor of the writer.
|
||||
* */
|
||||
template<class ...Args>
|
||||
Emitter(Args &&...args) : Writer(std::forward<Args>(args)...), m_tree() {}
|
||||
/** emit!
|
||||
Emitter(Args &&...args) : Writer(std::forward<Args>(args)...), m_tree(), m_opts(), m_flow(false) {}
|
||||
|
||||
/** Construct the emitter and its internal Writer state.
|
||||
*
|
||||
* @param opts EmitOptions
|
||||
* @param args arguments to be forwarded to the constructor of the writer.
|
||||
* */
|
||||
template<class ...Args>
|
||||
Emitter(EmitOptions const& opts, Args &&...args) : Writer(std::forward<Args>(args)...), m_tree(), m_opts(opts), m_flow(false) {}
|
||||
|
||||
/** emit!
|
||||
*
|
||||
* When writing to a buffer, returns a substr of the emitted YAML.
|
||||
* If the given buffer has insufficient space, the returned substr
|
||||
@@ -83,36 +149,63 @@ public:
|
||||
* @param error_on_excess when true, an error is raised when the
|
||||
* output buffer is too small for the emitted YAML/JSON
|
||||
* */
|
||||
substr emit_as(EmitType_e type, Tree const& t, size_t id, bool error_on_excess);
|
||||
substr emit_as(EmitType_e type, Tree const& t, id_type id, bool error_on_excess);
|
||||
/** emit starting at the root node */
|
||||
substr emit_as(EmitType_e type, Tree const& t, bool error_on_excess=true);
|
||||
/** emit the given node */
|
||||
substr emit_as(EmitType_e type, ConstNodeRef const& n, bool error_on_excess=true);
|
||||
substr emit_as(EmitType_e type, Tree const& t, bool error_on_excess=true)
|
||||
{
|
||||
if(t.empty())
|
||||
return {};
|
||||
return this->emit_as(type, t, t.root_id(), error_on_excess);
|
||||
}
|
||||
/** emit starting at the given node */
|
||||
substr emit_as(EmitType_e type, ConstNodeRef const& n, bool error_on_excess=true)
|
||||
{
|
||||
if(!detail::is_set_(n))
|
||||
return {};
|
||||
_RYML_CB_CHECK(n.tree()->callbacks(), n.readable());
|
||||
return this->emit_as(type, *n.tree(), n.id(), error_on_excess);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/** get the emit options for this object */
|
||||
EmitOptions const& options() const noexcept { return m_opts; }
|
||||
|
||||
/** set the max depth for emitted trees (to prevent a stack overflow) */
|
||||
void max_depth(id_type max_depth) noexcept { m_opts.max_depth(max_depth); }
|
||||
/** get the max depth for emitted trees (to prevent a stack overflow) */
|
||||
id_type max_depth() const noexcept { return m_opts.max_depth(); }
|
||||
|
||||
private:
|
||||
|
||||
Tree const* C4_RESTRICT m_tree;
|
||||
|
||||
void _emit_yaml(size_t id);
|
||||
void _do_visit_flow_sl(size_t id, size_t ilevel=0);
|
||||
void _do_visit_flow_ml(size_t id, size_t ilevel=0, size_t do_indent=1);
|
||||
void _do_visit_block(size_t id, size_t ilevel=0, size_t do_indent=1);
|
||||
void _do_visit_block_container(size_t id, size_t next_level, size_t do_indent);
|
||||
void _do_visit_json(size_t id);
|
||||
EmitOptions m_opts;
|
||||
bool m_flow;
|
||||
|
||||
private:
|
||||
|
||||
void _write(NodeScalar const& C4_RESTRICT sc, NodeType flags, size_t level);
|
||||
void _emit_yaml(id_type id);
|
||||
void _do_visit_flow_sl(id_type id, id_type depth, id_type ilevel=0);
|
||||
void _do_visit_flow_ml(id_type id, id_type depth, id_type ilevel=0, id_type do_indent=1);
|
||||
void _do_visit_block(id_type id, id_type depth, id_type ilevel=0, id_type do_indent=1);
|
||||
void _do_visit_block_container(id_type id, id_type depth, id_type next_level, bool do_indent);
|
||||
void _do_visit_json(id_type id, id_type depth);
|
||||
|
||||
private:
|
||||
|
||||
void _write(NodeScalar const& C4_RESTRICT sc, NodeType flags, id_type level);
|
||||
void _write_json(NodeScalar const& C4_RESTRICT sc, NodeType flags);
|
||||
|
||||
void _write_doc(size_t id);
|
||||
void _write_scalar(csubstr s, bool was_quoted);
|
||||
void _write_scalar_json(csubstr s, bool as_key, bool was_quoted);
|
||||
void _write_scalar_literal(csubstr s, size_t level, bool as_key, bool explicit_indentation=false);
|
||||
void _write_scalar_folded(csubstr s, size_t level, bool as_key);
|
||||
void _write_scalar_squo(csubstr s, size_t level);
|
||||
void _write_scalar_dquo(csubstr s, size_t level);
|
||||
void _write_scalar_plain(csubstr s, size_t level);
|
||||
void _write_doc(id_type id);
|
||||
void _write_scalar_json_dquo(csubstr s);
|
||||
void _write_scalar_literal(csubstr s, id_type level, bool as_key);
|
||||
void _write_scalar_folded(csubstr s, id_type level, bool as_key);
|
||||
void _write_scalar_squo(csubstr s, id_type level);
|
||||
void _write_scalar_dquo(csubstr s, id_type level);
|
||||
void _write_scalar_plain(csubstr s, id_type level);
|
||||
|
||||
size_t _write_escaped_newlines(csubstr s, size_t i);
|
||||
size_t _write_indented_block(csubstr s, size_t i, id_type level);
|
||||
|
||||
void _write_tag(csubstr tag)
|
||||
{
|
||||
@@ -122,18 +215,28 @@ private:
|
||||
}
|
||||
|
||||
enum : type_bits {
|
||||
_keysc = (KEY|KEYREF|KEYANCH|KEYQUO|_WIP_KEY_STYLE) | ~(VAL|VALREF|VALANCH|VALQUO|_WIP_VAL_STYLE),
|
||||
_valsc = ~(KEY|KEYREF|KEYANCH|KEYQUO|_WIP_KEY_STYLE) | (VAL|VALREF|VALANCH|VALQUO|_WIP_VAL_STYLE),
|
||||
_keysc = (KEY|KEYREF|KEYANCH|KEYQUO|KEY_STYLE) | ~(VAL|VALREF|VALANCH|VALQUO|VAL_STYLE) | CONTAINER_STYLE,
|
||||
_valsc = ~(KEY|KEYREF|KEYANCH|KEYQUO|KEY_STYLE) | (VAL|VALREF|VALANCH|VALQUO|VAL_STYLE) | CONTAINER_STYLE,
|
||||
_keysc_json = (KEY) | ~(VAL),
|
||||
_valsc_json = ~(KEY) | (VAL),
|
||||
};
|
||||
|
||||
C4_ALWAYS_INLINE void _writek(size_t id, size_t level) { _write(m_tree->keysc(id), m_tree->_p(id)->m_type.type & ~_valsc, level); }
|
||||
C4_ALWAYS_INLINE void _writev(size_t id, size_t level) { _write(m_tree->valsc(id), m_tree->_p(id)->m_type.type & ~_keysc, level); }
|
||||
C4_ALWAYS_INLINE void _writek(id_type id, id_type level) { _write(m_tree->keysc(id), (m_tree->_p(id)->m_type.type & ~_valsc), level); }
|
||||
C4_ALWAYS_INLINE void _writev(id_type id, id_type level) { _write(m_tree->valsc(id), (m_tree->_p(id)->m_type.type & ~_keysc), level); }
|
||||
|
||||
C4_ALWAYS_INLINE void _writek_json(size_t id) { _write_json(m_tree->keysc(id), m_tree->_p(id)->m_type.type & ~(VAL)); }
|
||||
C4_ALWAYS_INLINE void _writev_json(size_t id) { _write_json(m_tree->valsc(id), m_tree->_p(id)->m_type.type & ~(KEY)); }
|
||||
C4_ALWAYS_INLINE void _writek_json(id_type id) { _write_json(m_tree->keysc(id), m_tree->_p(id)->m_type.type & ~(VAL)); }
|
||||
C4_ALWAYS_INLINE void _writev_json(id_type id) { _write_json(m_tree->valsc(id), m_tree->_p(id)->m_type.type & ~(KEY)); }
|
||||
|
||||
void _indent(id_type level, bool enabled)
|
||||
{
|
||||
if(enabled)
|
||||
this->Writer::_do_write(' ', 2u * (size_t)level);
|
||||
}
|
||||
void _indent(id_type level)
|
||||
{
|
||||
if(!m_flow)
|
||||
this->Writer::_do_write(' ', 2u * (size_t)level);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -147,33 +250,59 @@ private:
|
||||
*/
|
||||
|
||||
|
||||
/** emit YAML to the given file. A null file defaults to stdout.
|
||||
* Return the number of bytes written. */
|
||||
inline size_t emit_yaml(Tree const& t, size_t id, FILE *f)
|
||||
// emit from tree and node id -----------------------
|
||||
|
||||
/** (1) emit YAML to the given file, starting at the given node. A null
|
||||
* file defaults to stdout. Return the number of bytes written. */
|
||||
inline size_t emit_yaml(Tree const& t, id_type id, EmitOptions const& opts, FILE *f)
|
||||
{
|
||||
EmitterFile em(opts, f);
|
||||
return em.emit_as(EMIT_YAML, t, id, /*error_on_excess*/true).len;
|
||||
}
|
||||
/** (2) like (1), but use default emit options */
|
||||
inline size_t emit_yaml(Tree const& t, id_type id, FILE *f)
|
||||
{
|
||||
EmitterFile em(f);
|
||||
return em.emit_as(EMIT_YAML, t, id, /*error_on_excess*/true).len;
|
||||
}
|
||||
/** emit JSON to the given file. A null file defaults to stdout.
|
||||
* Return the number of bytes written. */
|
||||
inline size_t emit_json(Tree const& t, size_t id, FILE *f)
|
||||
/** (1) emit JSON to the given file, starting at the given node. A null
|
||||
* file defaults to stdout. Return the number of bytes written. */
|
||||
inline size_t emit_json(Tree const& t, id_type id, EmitOptions const& opts, FILE *f)
|
||||
{
|
||||
EmitterFile em(opts, f);
|
||||
return em.emit_as(EMIT_JSON, t, id, /*error_on_excess*/true).len;
|
||||
}
|
||||
/** (2) like (1), but use default emit options */
|
||||
inline size_t emit_json(Tree const& t, id_type id, FILE *f)
|
||||
{
|
||||
EmitterFile em(f);
|
||||
return em.emit_as(EMIT_JSON, t, id, /*error_on_excess*/true).len;
|
||||
}
|
||||
|
||||
|
||||
/** emit YAML to the given file. A null file defaults to stdout.
|
||||
* Return the number of bytes written.
|
||||
* @overload */
|
||||
// emit from root -------------------------
|
||||
|
||||
/** (1) emit YAML to the given file, starting at the root node. A null file defaults to stdout.
|
||||
* Return the number of bytes written. */
|
||||
inline size_t emit_yaml(Tree const& t, EmitOptions const& opts, FILE *f=nullptr)
|
||||
{
|
||||
EmitterFile em(opts, f);
|
||||
return em.emit_as(EMIT_YAML, t, /*error_on_excess*/true).len;
|
||||
}
|
||||
/** (2) like (1), but use default emit options */
|
||||
inline size_t emit_yaml(Tree const& t, FILE *f=nullptr)
|
||||
{
|
||||
EmitterFile em(f);
|
||||
return em.emit_as(EMIT_YAML, t, /*error_on_excess*/true).len;
|
||||
}
|
||||
/** emit JSON to the given file. A null file defaults to stdout.
|
||||
* Return the number of bytes written.
|
||||
* @overload */
|
||||
/** (1) emit JSON to the given file. A null file defaults to stdout.
|
||||
* Return the number of bytes written. */
|
||||
inline size_t emit_json(Tree const& t, EmitOptions const& opts, FILE *f=nullptr)
|
||||
{
|
||||
EmitterFile em(opts, f);
|
||||
return em.emit_as(EMIT_JSON, t, /*error_on_excess*/true).len;
|
||||
}
|
||||
/** (2) like (1), but use default emit options */
|
||||
inline size_t emit_json(Tree const& t, FILE *f=nullptr)
|
||||
{
|
||||
EmitterFile em(f);
|
||||
@@ -181,19 +310,39 @@ inline size_t emit_json(Tree const& t, FILE *f=nullptr)
|
||||
}
|
||||
|
||||
|
||||
/** emit YAML to the given file. A null file defaults to stdout.
|
||||
* Return the number of bytes written.
|
||||
* @overload */
|
||||
// emit from ConstNodeRef ------------------------
|
||||
|
||||
/** (1) emit YAML to the given file. A null file defaults to stdout.
|
||||
* Return the number of bytes written. */
|
||||
inline size_t emit_yaml(ConstNodeRef const& r, EmitOptions const& opts, FILE *f=nullptr)
|
||||
{
|
||||
if(!detail::is_set_(r))
|
||||
return {};
|
||||
EmitterFile em(opts, f);
|
||||
return em.emit_as(EMIT_YAML, r, /*error_on_excess*/true).len;
|
||||
}
|
||||
/** (2) like (1), but use default emit options */
|
||||
inline size_t emit_yaml(ConstNodeRef const& r, FILE *f=nullptr)
|
||||
{
|
||||
if(!detail::is_set_(r))
|
||||
return {};
|
||||
EmitterFile em(f);
|
||||
return em.emit_as(EMIT_YAML, r, /*error_on_excess*/true).len;
|
||||
}
|
||||
/** emit JSON to the given file. A null file defaults to stdout.
|
||||
* Return the number of bytes written.
|
||||
* @overload */
|
||||
/** (1) emit JSON to the given file. A null file defaults to stdout.
|
||||
* Return the number of bytes written. */
|
||||
inline size_t emit_json(ConstNodeRef const& r, EmitOptions const& opts, FILE *f=nullptr)
|
||||
{
|
||||
if(!detail::is_set_(r))
|
||||
return {};
|
||||
EmitterFile em(opts, f);
|
||||
return em.emit_as(EMIT_JSON, r, /*error_on_excess*/true).len;
|
||||
}
|
||||
/** (2) like (1), but use default emit options */
|
||||
inline size_t emit_json(ConstNodeRef const& r, FILE *f=nullptr)
|
||||
{
|
||||
if(!detail::is_set_(r))
|
||||
return {};
|
||||
EmitterFile em(f);
|
||||
return em.emit_as(EMIT_JSON, r, /*error_on_excess*/true).len;
|
||||
}
|
||||
@@ -208,24 +357,6 @@ inline size_t emit_json(ConstNodeRef const& r, FILE *f=nullptr)
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** mark a tree or node to be emitted as json when using @ref operator<< . For example:
|
||||
*
|
||||
* ```cpp
|
||||
* Tree t = parse_in_arena("{foo: bar}");
|
||||
* std::cout << t; // emits YAML
|
||||
* std::cout << as_json(t); // emits JSON
|
||||
* ```
|
||||
*
|
||||
* @see @ref operator<< */
|
||||
struct as_json
|
||||
{
|
||||
Tree const* tree;
|
||||
size_t node;
|
||||
as_json(Tree const& t) : tree(&t), node(t.empty() ? NONE : t.root_id()) {}
|
||||
as_json(Tree const& t, size_t id) : tree(&t), node(id) {}
|
||||
as_json(ConstNodeRef const& n) : tree(n.tree()), node(n.id()) {}
|
||||
};
|
||||
|
||||
/** emit YAML to an STL-like ostream */
|
||||
template<class OStream>
|
||||
inline OStream& operator<< (OStream& s, Tree const& t)
|
||||
@@ -240,20 +371,77 @@ inline OStream& operator<< (OStream& s, Tree const& t)
|
||||
template<class OStream>
|
||||
inline OStream& operator<< (OStream& s, ConstNodeRef const& n)
|
||||
{
|
||||
if(!detail::is_set_(n))
|
||||
return s;
|
||||
EmitterOStream<OStream> em(s);
|
||||
em.emit_as(EMIT_YAML, n);
|
||||
return s;
|
||||
}
|
||||
|
||||
/** mark a tree or node to be emitted as yaml when using @ref
|
||||
* operator<<, with options. For example:
|
||||
*
|
||||
* ```cpp
|
||||
* Tree t = parse_in_arena("{foo: bar}");
|
||||
* std::cout << t; // emits YAML
|
||||
* std::cout << as_yaml(t); // emits YAML, same as above
|
||||
* std::cout << as_yaml(t, EmitOptions().max_depth(10)); // emits JSON with a max tree depth
|
||||
* ```
|
||||
*
|
||||
* @see @ref operator<< */
|
||||
struct as_json
|
||||
{
|
||||
Tree const* tree;
|
||||
size_t node;
|
||||
EmitOptions options;
|
||||
as_json(Tree const& t, EmitOptions const& opts={}) : tree(&t), node(t.empty() ? NONE : t.root_id()), options(opts) {}
|
||||
as_json(Tree const& t, size_t id, EmitOptions const& opts={}) : tree(&t), node(id), options(opts) {}
|
||||
as_json(ConstNodeRef const& n, EmitOptions const& opts={}) : tree(n.tree()), node(n.id()), options(opts) {}
|
||||
};
|
||||
|
||||
/** mark a tree or node to be emitted as yaml when using @ref
|
||||
* operator<< . For example:
|
||||
*
|
||||
* ```cpp
|
||||
* Tree t = parse_in_arena("{foo: bar}");
|
||||
* std::cout << t; // emits YAML
|
||||
* std::cout << as_json(t); // emits JSON
|
||||
* std::cout << as_json(t, EmitOptions().max_depth(10)); // emits JSON with a max tree depth
|
||||
* ```
|
||||
*
|
||||
* @see @ref operator<< */
|
||||
struct as_yaml
|
||||
{
|
||||
Tree const* tree;
|
||||
size_t node;
|
||||
EmitOptions options;
|
||||
as_yaml(Tree const& t, EmitOptions const& opts={}) : tree(&t), node(t.empty() ? NONE : t.root_id()), options(opts) {}
|
||||
as_yaml(Tree const& t, size_t id, EmitOptions const& opts={}) : tree(&t), node(id), options(opts) {}
|
||||
as_yaml(ConstNodeRef const& n, EmitOptions const& opts={}) : tree(n.tree()), node(n.id()), options(opts) {}
|
||||
};
|
||||
|
||||
/** emit json to an STL-like stream */
|
||||
template<class OStream>
|
||||
inline OStream& operator<< (OStream& s, as_json const& j)
|
||||
{
|
||||
EmitterOStream<OStream> em(s);
|
||||
if(!j.tree || j.node == NONE)
|
||||
return s;
|
||||
EmitterOStream<OStream> em(j.options, s);
|
||||
em.emit_as(EMIT_JSON, *j.tree, j.node, true);
|
||||
return s;
|
||||
}
|
||||
|
||||
/** emit yaml to an STL-like stream */
|
||||
template<class OStream>
|
||||
inline OStream& operator<< (OStream& s, as_yaml const& y)
|
||||
{
|
||||
if(!y.tree || y.node == NONE)
|
||||
return s;
|
||||
EmitterOStream<OStream> em(y.options, s);
|
||||
em.emit_as(EMIT_YAML, *y.tree, y.node, true);
|
||||
return s;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
@@ -264,35 +452,85 @@ inline OStream& operator<< (OStream& s, as_json const& j)
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** emit YAML to the given buffer. Return a substr trimmed to the emitted YAML.
|
||||
// emit from tree and node id -----------------------
|
||||
|
||||
/** (1) emit YAML to the given buffer. Return a substr trimmed to the emitted YAML.
|
||||
* @param t the tree to emit.
|
||||
* @param id the node where to start emitting.
|
||||
* @param opts emit options.
|
||||
* @param buf the output buffer.
|
||||
* @param error_on_excess Raise an error if the space in the buffer is insufficient.
|
||||
* @overload */
|
||||
inline substr emit_yaml(Tree const& t, size_t id, substr buf, bool error_on_excess=true)
|
||||
* @return a substr trimmed to the result in the output buffer. If the buffer is
|
||||
* insufficient (when error_on_excess is false), the string pointer of the
|
||||
* result will be set to null, and the length will report the required buffer size. */
|
||||
inline substr emit_yaml(Tree const& t, id_type id, EmitOptions const& opts, substr buf, bool error_on_excess=true)
|
||||
{
|
||||
EmitterBuf em(opts, buf);
|
||||
return em.emit_as(EMIT_YAML, t, id, error_on_excess);
|
||||
}
|
||||
/** (2) like (1), but use default emit options */
|
||||
inline substr emit_yaml(Tree const& t, id_type id, substr buf, bool error_on_excess=true)
|
||||
{
|
||||
EmitterBuf em(buf);
|
||||
return em.emit_as(EMIT_YAML, t, id, error_on_excess);
|
||||
}
|
||||
/** emit JSON to the given buffer. Return a substr trimmed to the emitted JSON.
|
||||
/** (1) emit JSON to the given buffer. Return a substr trimmed to the emitted JSON.
|
||||
* @param t the tree to emit.
|
||||
* @param id the node where to start emitting.
|
||||
* @param opts emit options.
|
||||
* @param buf the output buffer.
|
||||
* @param error_on_excess Raise an error if the space in the buffer is insufficient.
|
||||
* @overload */
|
||||
inline substr emit_json(Tree const& t, size_t id, substr buf, bool error_on_excess=true)
|
||||
* @return a substr trimmed to the result in the output buffer. If the buffer is
|
||||
* insufficient (when error_on_excess is false), the string pointer of the
|
||||
* result will be set to null, and the length will report the required buffer size. */
|
||||
inline substr emit_json(Tree const& t, id_type id, EmitOptions const& opts, substr buf, bool error_on_excess=true)
|
||||
{
|
||||
EmitterBuf em(opts, buf);
|
||||
return em.emit_as(EMIT_JSON, t, id, error_on_excess);
|
||||
}
|
||||
/** (2) like (1), but use default emit options */
|
||||
inline substr emit_json(Tree const& t, id_type id, substr buf, bool error_on_excess=true)
|
||||
{
|
||||
EmitterBuf em(buf);
|
||||
return em.emit_as(EMIT_JSON, t, id, error_on_excess);
|
||||
}
|
||||
|
||||
|
||||
/** emit YAML to the given buffer. Return a substr trimmed to the emitted YAML.
|
||||
// emit from root -------------------------
|
||||
|
||||
/** (1) emit YAML to the given buffer. Return a substr trimmed to the emitted YAML.
|
||||
* @param t the tree; will be emitted from the root node.
|
||||
* @param opts emit options.
|
||||
* @param buf the output buffer.
|
||||
* @param error_on_excess Raise an error if the space in the buffer is insufficient.
|
||||
* @overload */
|
||||
* @return a substr trimmed to the result in the output buffer. If the buffer is
|
||||
* insufficient (when error_on_excess is false), the string pointer of the
|
||||
* result will be set to null, and the length will report the required buffer size. */
|
||||
inline substr emit_yaml(Tree const& t, EmitOptions const& opts, substr buf, bool error_on_excess=true)
|
||||
{
|
||||
EmitterBuf em(opts, buf);
|
||||
return em.emit_as(EMIT_YAML, t, error_on_excess);
|
||||
}
|
||||
/** (2) like (1), but use default emit options */
|
||||
inline substr emit_yaml(Tree const& t, substr buf, bool error_on_excess=true)
|
||||
{
|
||||
EmitterBuf em(buf);
|
||||
return em.emit_as(EMIT_YAML, t, error_on_excess);
|
||||
}
|
||||
/** emit JSON to the given buffer. Return a substr trimmed to the emitted JSON.
|
||||
/** (1) emit JSON to the given buffer. Return a substr trimmed to the emitted JSON.
|
||||
* @param t the tree; will be emitted from the root node.
|
||||
* @param opts emit options.
|
||||
* @param buf the output buffer.
|
||||
* @param error_on_excess Raise an error if the space in the buffer is insufficient.
|
||||
* @overload */
|
||||
* @return a substr trimmed to the result in the output buffer. If the buffer is
|
||||
* insufficient (when error_on_excess is false), the string pointer of the
|
||||
* result will be set to null, and the length will report the required buffer size. */
|
||||
inline substr emit_json(Tree const& t, EmitOptions const& opts, substr buf, bool error_on_excess=true)
|
||||
{
|
||||
EmitterBuf em(opts, buf);
|
||||
return em.emit_as(EMIT_JSON, t, error_on_excess);
|
||||
}
|
||||
/** (2) like (1), but use default emit options */
|
||||
inline substr emit_json(Tree const& t, substr buf, bool error_on_excess=true)
|
||||
{
|
||||
EmitterBuf em(buf);
|
||||
@@ -300,21 +538,51 @@ inline substr emit_json(Tree const& t, substr buf, bool error_on_excess=true)
|
||||
}
|
||||
|
||||
|
||||
/** emit YAML to the given buffer. Return a substr trimmed to the emitted YAML.
|
||||
// emit from ConstNodeRef ------------------------
|
||||
|
||||
/** (1) emit YAML to the given buffer. Return a substr trimmed to the emitted YAML.
|
||||
* @param r the starting node.
|
||||
* @param buf the output buffer.
|
||||
* @param opts emit options.
|
||||
* @param error_on_excess Raise an error if the space in the buffer is insufficient.
|
||||
* @overload
|
||||
*/
|
||||
* @return a substr trimmed to the result in the output buffer. If the buffer is
|
||||
* insufficient (when error_on_excess is false), the string pointer of the
|
||||
* result will be set to null, and the length will report the required buffer size. */
|
||||
inline substr emit_yaml(ConstNodeRef const& r, EmitOptions const& opts, substr buf, bool error_on_excess=true)
|
||||
{
|
||||
if(!detail::is_set_(r))
|
||||
return {};
|
||||
EmitterBuf em(opts, buf);
|
||||
return em.emit_as(EMIT_YAML, r, error_on_excess);
|
||||
}
|
||||
/** (2) like (1), but use default emit options */
|
||||
inline substr emit_yaml(ConstNodeRef const& r, substr buf, bool error_on_excess=true)
|
||||
{
|
||||
if(!detail::is_set_(r))
|
||||
return {};
|
||||
EmitterBuf em(buf);
|
||||
return em.emit_as(EMIT_YAML, r, error_on_excess);
|
||||
}
|
||||
/** emit JSON to the given buffer. Return a substr trimmed to the emitted JSON.
|
||||
/** (1) emit JSON to the given buffer. Return a substr trimmed to the emitted JSON.
|
||||
* @param r the starting node.
|
||||
* @param buf the output buffer.
|
||||
* @param opts emit options.
|
||||
* @param error_on_excess Raise an error if the space in the buffer is insufficient.
|
||||
* @overload
|
||||
*/
|
||||
* @return a substr trimmed to the result in the output buffer. If the buffer is
|
||||
* insufficient (when error_on_excess is false), the string pointer of the
|
||||
* result will be set to null, and the length will report the required buffer size. */
|
||||
inline substr emit_json(ConstNodeRef const& r, EmitOptions const& opts, substr buf, bool error_on_excess=true)
|
||||
{
|
||||
if(!detail::is_set_(r))
|
||||
return {};
|
||||
EmitterBuf em(opts, buf);
|
||||
return em.emit_as(EMIT_JSON, r, error_on_excess);
|
||||
}
|
||||
/** (2) like (1), but use default emit options */
|
||||
inline substr emit_json(ConstNodeRef const& r, substr buf, bool error_on_excess=true)
|
||||
{
|
||||
if(!detail::is_set_(r))
|
||||
return {};
|
||||
EmitterBuf em(buf);
|
||||
return em.emit_as(EMIT_JSON, r, error_on_excess);
|
||||
}
|
||||
@@ -322,141 +590,225 @@ inline substr emit_json(ConstNodeRef const& r, substr buf, bool error_on_excess=
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** emit+resize: emit YAML to the given `std::string`/`std::vector`-like
|
||||
* container, resizing it as needed to fit the emitted YAML. */
|
||||
/** @defgroup doc_emit_to_container Emit to resizeable container
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
// emit from tree and node id ---------------------------
|
||||
|
||||
/** (1) emit+resize: emit YAML to the given `std::string`/`std::vector`-like
|
||||
* container, resizing it as needed to fit the emitted YAML. If @p append is
|
||||
* set to true, the emitted YAML is appended at the end of the container.
|
||||
*
|
||||
* @return a substr trimmed to the emitted YAML (excluding the initial contents, when appending) */
|
||||
template<class CharOwningContainer>
|
||||
substr emitrs_yaml(Tree const& t, size_t id, CharOwningContainer * cont)
|
||||
substr emitrs_yaml(Tree const& t, id_type id, EmitOptions const& opts, CharOwningContainer * cont, bool append=false)
|
||||
{
|
||||
substr buf = to_substr(*cont);
|
||||
substr ret = emit_yaml(t, id, buf, /*error_on_excess*/false);
|
||||
size_t startpos = append ? cont->size() : 0u;
|
||||
cont->resize(cont->capacity()); // otherwise the first emit would be certain to fail
|
||||
substr buf = to_substr(*cont).sub(startpos);
|
||||
substr ret = emit_yaml(t, id, opts, buf, /*error_on_excess*/false);
|
||||
if(ret.str == nullptr && ret.len > 0)
|
||||
{
|
||||
cont->resize(ret.len);
|
||||
buf = to_substr(*cont);
|
||||
ret = emit_yaml(t, id, buf, /*error_on_excess*/true);
|
||||
cont->resize(startpos + ret.len);
|
||||
buf = to_substr(*cont).sub(startpos);
|
||||
ret = emit_yaml(t, id, opts, buf, /*error_on_excess*/true);
|
||||
}
|
||||
else
|
||||
{
|
||||
cont->resize(startpos + ret.len);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
/** emit+resize: emit JSON to the given `std::string`/`std::vector`-like
|
||||
* container, resizing it as needed to fit the emitted JSON. */
|
||||
/** (2) like (1), but use default emit options */
|
||||
template<class CharOwningContainer>
|
||||
substr emitrs_json(Tree const& t, size_t id, CharOwningContainer * cont)
|
||||
substr emitrs_yaml(Tree const& t, id_type id, CharOwningContainer * cont, bool append=false)
|
||||
{
|
||||
substr buf = to_substr(*cont);
|
||||
substr ret = emit_json(t, id, buf, /*error_on_excess*/false);
|
||||
return emitrs_yaml(t, id, EmitOptions{}, cont, append);
|
||||
}
|
||||
/** (1) emit+resize: emit JSON to the given `std::string`/`std::vector`-like
|
||||
* container, resizing it as needed to fit the emitted JSON. If @p append is
|
||||
* set to true, the emitted YAML is appended at the end of the container.
|
||||
*
|
||||
* @return a substr trimmed to the emitted JSON (excluding the initial contents, when appending) */
|
||||
template<class CharOwningContainer>
|
||||
substr emitrs_json(Tree const& t, id_type id, EmitOptions const& opts, CharOwningContainer * cont, bool append=false)
|
||||
{
|
||||
const size_t startpos = append ? cont->size() : 0u;
|
||||
cont->resize(cont->capacity()); // otherwise the first emit would be certain to fail
|
||||
substr buf = to_substr(*cont).sub(startpos);
|
||||
EmitterBuf em(opts, buf);
|
||||
substr ret = emit_json(t, id, opts, buf, /*error_on_excess*/false);
|
||||
if(ret.str == nullptr && ret.len > 0)
|
||||
{
|
||||
cont->resize(ret.len);
|
||||
buf = to_substr(*cont);
|
||||
ret = emit_json(t, id, buf, /*error_on_excess*/true);
|
||||
cont->resize(startpos + ret.len);
|
||||
buf = to_substr(*cont).sub(startpos);
|
||||
ret = emit_json(t, id, opts, buf, /*error_on_excess*/true);
|
||||
}
|
||||
else
|
||||
{
|
||||
cont->resize(startpos + ret.len);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** emit+resize: emit YAML to the given `std::string`/`std::vector`-like
|
||||
* container, resizing it as needed to fit the emitted YAML. */
|
||||
/** (2) like (1), but use default emit options */
|
||||
template<class CharOwningContainer>
|
||||
CharOwningContainer emitrs_yaml(Tree const& t, size_t id)
|
||||
substr emitrs_json(Tree const& t, id_type id, CharOwningContainer * cont, bool append=false)
|
||||
{
|
||||
return emitrs_json(t, id, EmitOptions{}, cont, append);
|
||||
}
|
||||
|
||||
|
||||
/** (3) emit+resize: YAML to a newly-created `std::string`/`std::vector`-like container. */
|
||||
template<class CharOwningContainer>
|
||||
CharOwningContainer emitrs_yaml(Tree const& t, id_type id, EmitOptions const& opts={})
|
||||
{
|
||||
CharOwningContainer c;
|
||||
emitrs_yaml(t, id, &c);
|
||||
emitrs_yaml(t, id, opts, &c);
|
||||
return c;
|
||||
}
|
||||
/** emit+resize: emit JSON to the given `std::string`/`std::vector`-like
|
||||
* container, resizing it as needed to fit the emitted JSON. */
|
||||
/** (3) emit+resize: JSON to a newly-created `std::string`/`std::vector`-like container. */
|
||||
template<class CharOwningContainer>
|
||||
CharOwningContainer emitrs_json(Tree const& t, size_t id)
|
||||
CharOwningContainer emitrs_json(Tree const& t, id_type id, EmitOptions const& opts={})
|
||||
{
|
||||
CharOwningContainer c;
|
||||
emitrs_json(t, id, &c);
|
||||
emitrs_json(t, id, opts, &c);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/** emit+resize: YAML to the given `std::string`/`std::vector`-like
|
||||
* container, resizing it as needed to fit the emitted YAML. */
|
||||
// emit from root -------------------------
|
||||
|
||||
/** (1) emit+resize: YAML to the given `std::string`/`std::vector`-like
|
||||
* container, resizing it as needed to fit the emitted YAML.
|
||||
* @return a substr trimmed to the new emitted contents. */
|
||||
template<class CharOwningContainer>
|
||||
substr emitrs_yaml(Tree const& t, CharOwningContainer * cont)
|
||||
substr emitrs_yaml(Tree const& t, EmitOptions const& opts, CharOwningContainer * cont, bool append=false)
|
||||
{
|
||||
if(t.empty())
|
||||
return {};
|
||||
return emitrs_yaml(t, t.root_id(), cont);
|
||||
return emitrs_yaml(t, t.root_id(), opts, cont, append);
|
||||
}
|
||||
/** emit+resize: JSON to the given `std::string`/`std::vector`-like
|
||||
* container, resizing it as needed to fit the emitted JSON. */
|
||||
/** (2) like (1), but use default emit options */
|
||||
template<class CharOwningContainer>
|
||||
substr emitrs_json(Tree const& t, CharOwningContainer * cont)
|
||||
substr emitrs_yaml(Tree const& t, CharOwningContainer * cont, bool append=false)
|
||||
{
|
||||
if(t.empty())
|
||||
return {};
|
||||
return emitrs_json(t, t.root_id(), cont);
|
||||
return emitrs_yaml(t, t.root_id(), EmitOptions{}, cont, append);
|
||||
}
|
||||
/** (1) emit+resize: JSON to the given `std::string`/`std::vector`-like
|
||||
* container, resizing it as needed to fit the emitted JSON.
|
||||
* @return a substr trimmed to the new emitted contents. */
|
||||
template<class CharOwningContainer>
|
||||
substr emitrs_json(Tree const& t, EmitOptions const& opts, CharOwningContainer * cont, bool append=false)
|
||||
{
|
||||
if(t.empty())
|
||||
return {};
|
||||
return emitrs_json(t, t.root_id(), opts, cont, append);
|
||||
}
|
||||
/** (2) like (1), but use default emit options */
|
||||
template<class CharOwningContainer>
|
||||
substr emitrs_json(Tree const& t, CharOwningContainer * cont, bool append=false)
|
||||
{
|
||||
if(t.empty())
|
||||
return {};
|
||||
return emitrs_json(t, t.root_id(), EmitOptions{}, cont, append);
|
||||
}
|
||||
|
||||
|
||||
/** emit+resize: YAML to the given `std::string`/`std::vector`-like container,
|
||||
* resizing it as needed to fit the emitted YAML. */
|
||||
/** (3) emit+resize: YAML to a newly-created `std::string`/`std::vector`-like container. */
|
||||
template<class CharOwningContainer>
|
||||
CharOwningContainer emitrs_yaml(Tree const& t)
|
||||
CharOwningContainer emitrs_yaml(Tree const& t, EmitOptions const& opts={})
|
||||
{
|
||||
CharOwningContainer c;
|
||||
if(t.empty())
|
||||
return c;
|
||||
emitrs_yaml(t, t.root_id(), &c);
|
||||
emitrs_yaml(t, t.root_id(), opts, &c);
|
||||
return c;
|
||||
}
|
||||
/** emit+resize: JSON to the given `std::string`/`std::vector`-like container,
|
||||
* resizing it as needed to fit the emitted JSON. */
|
||||
/** (3) emit+resize: JSON to a newly-created `std::string`/`std::vector`-like container. */
|
||||
template<class CharOwningContainer>
|
||||
CharOwningContainer emitrs_json(Tree const& t)
|
||||
CharOwningContainer emitrs_json(Tree const& t, EmitOptions const& opts={})
|
||||
{
|
||||
CharOwningContainer c;
|
||||
if(t.empty())
|
||||
return c;
|
||||
emitrs_json(t, t.root_id(), &c);
|
||||
emitrs_json(t, t.root_id(), opts, &c);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/** emit+resize: YAML to the given `std::string`/`std::vector`-like container,
|
||||
* resizing it as needed to fit the emitted YAML. */
|
||||
// emit from ConstNodeRef ------------------------
|
||||
|
||||
|
||||
/** (1) emit+resize: YAML to the given `std::string`/`std::vector`-like container,
|
||||
* resizing it as needed to fit the emitted YAML.
|
||||
* @return a substr trimmed to the new emitted contents */
|
||||
template<class CharOwningContainer>
|
||||
substr emitrs_yaml(ConstNodeRef const& n, CharOwningContainer * cont)
|
||||
substr emitrs_yaml(ConstNodeRef const& n, EmitOptions const& opts, CharOwningContainer * cont, bool append=false)
|
||||
{
|
||||
if(!detail::is_set_(n))
|
||||
return {};
|
||||
_RYML_CB_CHECK(n.tree()->callbacks(), n.readable());
|
||||
return emitrs_yaml(*n.tree(), n.id(), cont);
|
||||
return emitrs_yaml(*n.tree(), n.id(), opts, cont, append);
|
||||
}
|
||||
/** emit+resize: JSON to the given `std::string`/`std::vector`-like container,
|
||||
* resizing it as needed to fit the emitted JSON. */
|
||||
/** (2) like (1), but use default emit options */
|
||||
template<class CharOwningContainer>
|
||||
substr emitrs_json(ConstNodeRef const& n, CharOwningContainer * cont)
|
||||
substr emitrs_yaml(ConstNodeRef const& n, CharOwningContainer * cont, bool append=false)
|
||||
{
|
||||
if(!detail::is_set_(n))
|
||||
return {};
|
||||
_RYML_CB_CHECK(n.tree()->callbacks(), n.readable());
|
||||
return emitrs_json(*n.tree(), n.id(), cont);
|
||||
return emitrs_yaml(*n.tree(), n.id(), EmitOptions{}, cont, append);
|
||||
}
|
||||
/** (1) emit+resize: JSON to the given `std::string`/`std::vector`-like container,
|
||||
* resizing it as needed to fit the emitted JSON.
|
||||
* @return a substr trimmed to the new emitted contents */
|
||||
template<class CharOwningContainer>
|
||||
substr emitrs_json(ConstNodeRef const& n, EmitOptions const& opts, CharOwningContainer * cont, bool append=false)
|
||||
{
|
||||
if(!detail::is_set_(n))
|
||||
return {};
|
||||
_RYML_CB_CHECK(n.tree()->callbacks(), n.readable());
|
||||
return emitrs_json(*n.tree(), n.id(), opts, cont, append);
|
||||
}
|
||||
/** (2) like (1), but use default emit options */
|
||||
template<class CharOwningContainer>
|
||||
substr emitrs_json(ConstNodeRef const& n, CharOwningContainer * cont, bool append=false)
|
||||
{
|
||||
if(!detail::is_set_(n))
|
||||
return {};
|
||||
_RYML_CB_CHECK(n.tree()->callbacks(), n.readable());
|
||||
return emitrs_json(*n.tree(), n.id(), EmitOptions{}, cont, append);
|
||||
}
|
||||
|
||||
|
||||
/** emit+resize: YAML to the given `std::string`/`std::vector`-like container,
|
||||
* resizing it as needed to fit the emitted YAML. */
|
||||
/** (3) emit+resize: YAML to a newly-created `std::string`/`std::vector`-like container. */
|
||||
template<class CharOwningContainer>
|
||||
CharOwningContainer emitrs_yaml(ConstNodeRef const& n)
|
||||
CharOwningContainer emitrs_yaml(ConstNodeRef const& n, EmitOptions const& opts={})
|
||||
{
|
||||
if(!detail::is_set_(n))
|
||||
return {};
|
||||
_RYML_CB_CHECK(n.tree()->callbacks(), n.readable());
|
||||
CharOwningContainer c;
|
||||
emitrs_yaml(*n.tree(), n.id(), &c);
|
||||
emitrs_yaml(*n.tree(), n.id(), opts, &c);
|
||||
return c;
|
||||
}
|
||||
/** emit+resize: JSON to the given `std::string`/`std::vector`-like container,
|
||||
* resizing it as needed to fit the emitted JSON. */
|
||||
/** (3) emit+resize: JSON to a newly-created `std::string`/`std::vector`-like container. */
|
||||
template<class CharOwningContainer>
|
||||
CharOwningContainer emitrs_json(ConstNodeRef const& n)
|
||||
CharOwningContainer emitrs_json(ConstNodeRef const& n, EmitOptions const& opts={})
|
||||
{
|
||||
if(!detail::is_set_(n))
|
||||
return {};
|
||||
_RYML_CB_CHECK(n.tree()->callbacks(), n.readable());
|
||||
CharOwningContainer c;
|
||||
emitrs_json(*n.tree(), n.id(), &c);
|
||||
emitrs_json(*n.tree(), n.id(), opts, &c);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
@@ -464,7 +816,22 @@ CharOwningContainer emitrs_json(ConstNodeRef const& n)
|
||||
|
||||
/** @cond dev */
|
||||
|
||||
RYML_DEPRECATE_EMIT inline size_t emit(Tree const& t, size_t id, FILE *f)
|
||||
#define RYML_DEPRECATE_EMIT \
|
||||
RYML_DEPRECATED("use emit_yaml() instead. " \
|
||||
"See https://github.com/biojppm/rapidyaml/issues/120")
|
||||
#define RYML_DEPRECATE_EMITRS \
|
||||
RYML_DEPRECATED("use emitrs_yaml() instead. " \
|
||||
"See https://github.com/biojppm/rapidyaml/issues/120")
|
||||
|
||||
// workaround for Qt emit which is a macro;
|
||||
// see https://github.com/biojppm/rapidyaml/issues/120.
|
||||
// emit is defined in qobjectdefs.h (as an empty define).
|
||||
#ifdef emit
|
||||
#define RYML_TMP_EMIT_
|
||||
#undef emit
|
||||
#endif
|
||||
|
||||
RYML_DEPRECATE_EMIT inline size_t emit(Tree const& t, id_type id, FILE *f)
|
||||
{
|
||||
return emit_yaml(t, id, f);
|
||||
}
|
||||
@@ -477,7 +844,7 @@ RYML_DEPRECATE_EMIT inline size_t emit(ConstNodeRef const& r, FILE *f=nullptr)
|
||||
return emit_yaml(r, f);
|
||||
}
|
||||
|
||||
RYML_DEPRECATE_EMIT inline substr emit(Tree const& t, size_t id, substr buf, bool error_on_excess=true)
|
||||
RYML_DEPRECATE_EMIT inline substr emit(Tree const& t, id_type id, substr buf, bool error_on_excess=true)
|
||||
{
|
||||
return emit_yaml(t, id, buf, error_on_excess);
|
||||
}
|
||||
@@ -490,13 +857,18 @@ RYML_DEPRECATE_EMIT inline substr emit(ConstNodeRef const& r, substr buf, bool e
|
||||
return emit_yaml(r, buf, error_on_excess);
|
||||
}
|
||||
|
||||
#ifdef RYML_TMP_EMIT_
|
||||
#define emit
|
||||
#undef RYML_TMP_EMIT_
|
||||
#endif
|
||||
|
||||
template<class CharOwningContainer>
|
||||
RYML_DEPRECATE_EMITRS substr emitrs(Tree const& t, size_t id, CharOwningContainer * cont)
|
||||
RYML_DEPRECATE_EMITRS substr emitrs(Tree const& t, id_type id, CharOwningContainer * cont)
|
||||
{
|
||||
return emitrs_yaml(t, id, cont);
|
||||
}
|
||||
template<class CharOwningContainer>
|
||||
RYML_DEPRECATE_EMITRS CharOwningContainer emitrs(Tree const& t, size_t id)
|
||||
RYML_DEPRECATE_EMITRS CharOwningContainer emitrs(Tree const& t, id_type id)
|
||||
{
|
||||
return emitrs_yaml<CharOwningContainer>(t, id);
|
||||
}
|
||||
@@ -520,15 +892,18 @@ RYML_DEPRECATE_EMITRS CharOwningContainer emitrs(ConstNodeRef const& n)
|
||||
{
|
||||
return emitrs_yaml<CharOwningContainer>(n);
|
||||
}
|
||||
|
||||
/** @endcond */
|
||||
|
||||
|
||||
} // namespace yml
|
||||
} // namespace c4
|
||||
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_POP
|
||||
|
||||
#undef RYML_DEPRECATE_EMIT
|
||||
#undef RYML_DEPRECATE_EMITRS
|
||||
|
||||
#include "c4/yml/emit.def.hpp"
|
||||
#include "c4/yml/emit.def.hpp" // NOLINT
|
||||
|
||||
#endif /* _C4_YML_EMIT_HPP_ */
|
||||
|
||||
194
3rdparty/rapidyaml/include/c4/yml/event_handler_stack.hpp
vendored
Normal file
194
3rdparty/rapidyaml/include/c4/yml/event_handler_stack.hpp
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
#ifndef _C4_YML_EVENT_HANDLER_STACK_HPP_
|
||||
#define _C4_YML_EVENT_HANDLER_STACK_HPP_
|
||||
|
||||
#ifndef _C4_YML_DETAIL_STACK_HPP_
|
||||
#include "c4/yml/detail/stack.hpp"
|
||||
#endif
|
||||
|
||||
#ifndef _C4_YML_NODE_TYPE_HPP_
|
||||
#include "c4/yml/node_type.hpp"
|
||||
#endif
|
||||
|
||||
#ifndef _C4_YML_DETAIL_PARSER_DBG_HPP_
|
||||
#include "c4/yml/detail/parser_dbg.hpp"
|
||||
#endif
|
||||
|
||||
#ifndef _C4_YML_PARSER_STATE_HPP_
|
||||
#include "c4/yml/parser_state.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef RYML_DBG
|
||||
#ifndef _C4_YML_DETAIL_PRINT_HPP_
|
||||
#include "c4/yml/detail/print.hpp"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// NOLINTBEGIN(hicpp-signed-bitwise)
|
||||
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
/** @addtogroup doc_event_handlers
|
||||
* @{ */
|
||||
|
||||
namespace detail {
|
||||
using pfn_relocate_arena = void (*)(void*, csubstr prev_arena, substr next_arena);
|
||||
} // detail
|
||||
|
||||
/** Use this class a base of implementations of event handler to
|
||||
* simplify the stack logic. */
|
||||
template<class HandlerImpl, class HandlerState>
|
||||
struct EventHandlerStack
|
||||
{
|
||||
static_assert(std::is_base_of<ParserState, HandlerState>::value,
|
||||
"ParserState must be a base of HandlerState");
|
||||
|
||||
using state = HandlerState;
|
||||
using pfn_relocate_arena = detail::pfn_relocate_arena;
|
||||
|
||||
public:
|
||||
|
||||
detail::stack<state> m_stack;
|
||||
state *C4_RESTRICT m_curr; ///< current stack level: top of the stack. cached here for easier access.
|
||||
state *C4_RESTRICT m_parent; ///< parent of the current stack level.
|
||||
pfn_relocate_arena m_relocate_arena; ///< callback when the arena gets relocated
|
||||
void * m_relocate_arena_data;
|
||||
|
||||
protected:
|
||||
|
||||
EventHandlerStack() : m_stack(), m_curr(), m_parent(), m_relocate_arena(), m_relocate_arena_data() {}
|
||||
EventHandlerStack(Callbacks const& cb) : m_stack(cb), m_curr(), m_parent(), m_relocate_arena(), m_relocate_arena_data() {}
|
||||
|
||||
protected:
|
||||
|
||||
void _stack_start_parse(const char *filename, pfn_relocate_arena relocate_arena, void *relocate_arena_data)
|
||||
{
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_curr != nullptr);
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, relocate_arena != nullptr);
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, relocate_arena_data != nullptr);
|
||||
m_curr->start_parse(filename, m_curr->node_id);
|
||||
m_relocate_arena = relocate_arena;
|
||||
m_relocate_arena_data = relocate_arena_data;
|
||||
}
|
||||
|
||||
void _stack_finish_parse()
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void _stack_reset_root()
|
||||
{
|
||||
m_stack.clear();
|
||||
m_stack.push({});
|
||||
m_parent = nullptr;
|
||||
m_curr = &m_stack.top();
|
||||
}
|
||||
|
||||
void _stack_reset_non_root()
|
||||
{
|
||||
m_stack.clear();
|
||||
m_stack.push({}); // parent
|
||||
m_stack.push({}); // node
|
||||
m_parent = &m_stack.top(1);
|
||||
m_curr = &m_stack.top();
|
||||
}
|
||||
|
||||
void _stack_push()
|
||||
{
|
||||
m_stack.push_top();
|
||||
m_parent = &m_stack.top(1); // don't use m_curr. watch out for relocations inside the prev push
|
||||
m_curr = &m_stack.top();
|
||||
m_curr->reset_after_push();
|
||||
}
|
||||
|
||||
void _stack_pop()
|
||||
{
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_parent);
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_stack.size() > 1);
|
||||
m_parent->reset_before_pop(*m_curr);
|
||||
m_stack.pop();
|
||||
m_parent = m_stack.size() > 1 ? &m_stack.top(1) : nullptr;
|
||||
m_curr = &m_stack.top();
|
||||
#ifdef RYML_DBG
|
||||
if(m_parent)
|
||||
_c4dbgpf("popped! top is now node={} (parent={})", m_curr->node_id, m_parent->node_id);
|
||||
else
|
||||
_c4dbgpf("popped! top is now node={} @ ROOT", m_curr->node_id);
|
||||
#endif
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// undefined at the end
|
||||
#define _has_any_(bits) (static_cast<HandlerImpl const* C4_RESTRICT>(this)->template _has_any__<bits>())
|
||||
|
||||
bool _stack_should_push_on_begin_doc() const
|
||||
{
|
||||
const bool is_root = (m_stack.size() == 1u);
|
||||
return is_root && (_has_any_(DOC|VAL|MAP|SEQ) || m_curr->has_children);
|
||||
}
|
||||
|
||||
bool _stack_should_pop_on_end_doc() const
|
||||
{
|
||||
const bool is_root = (m_stack.size() == 1u);
|
||||
return !is_root && _has_any_(DOC);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void _stack_relocate_to_new_arena(csubstr prev, substr curr)
|
||||
{
|
||||
for(state &st : m_stack)
|
||||
{
|
||||
if(st.line_contents.rem.is_sub(prev))
|
||||
st.line_contents.rem = _stack_relocate_to_new_arena(st.line_contents.rem, prev, curr);
|
||||
if(st.line_contents.full.is_sub(prev))
|
||||
st.line_contents.full = _stack_relocate_to_new_arena(st.line_contents.full, prev, curr);
|
||||
if(st.line_contents.stripped.is_sub(prev))
|
||||
st.line_contents.stripped = _stack_relocate_to_new_arena(st.line_contents.stripped, prev, curr);
|
||||
}
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_relocate_arena != nullptr);
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_relocate_arena_data != nullptr);
|
||||
m_relocate_arena(m_relocate_arena_data, prev, curr);
|
||||
}
|
||||
|
||||
substr _stack_relocate_to_new_arena(csubstr s, csubstr prev, substr curr)
|
||||
{
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, prev.is_super(s));
|
||||
auto pos = s.str - prev.str;
|
||||
substr out = {curr.str + pos, s.len};
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, curr.is_super(out));
|
||||
return out;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/** Check whether the current parse tokens are trailing on the
|
||||
* previous doc, and raise an error if they are. This function is
|
||||
* called by the parse engine (not the event handler) before a doc
|
||||
* is started. */
|
||||
void check_trailing_doc_token() const
|
||||
{
|
||||
const bool is_root = (m_stack.size() == 1u);
|
||||
const bool isndoc = (m_curr->flags & NDOC) != 0;
|
||||
const bool suspicious = _has_any_(MAP|SEQ|VAL);
|
||||
_c4dbgpf("target={} isroot={} suspicious={} ndoc={}", m_curr->node_id, is_root, suspicious, isndoc);
|
||||
if((is_root || _has_any_(DOC)) && suspicious && !isndoc)
|
||||
_RYML_CB_ERR_(m_stack.m_callbacks, "parse error", m_curr->pos);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
#undef _has_any_
|
||||
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
} // namespace yml
|
||||
} // namespace c4
|
||||
|
||||
// NOLINTEND(hicpp-signed-bitwise)
|
||||
|
||||
#endif /* _C4_YML_EVENT_HANDLER_STACK_HPP_ */
|
||||
769
3rdparty/rapidyaml/include/c4/yml/event_handler_tree.hpp
vendored
Normal file
769
3rdparty/rapidyaml/include/c4/yml/event_handler_tree.hpp
vendored
Normal file
@@ -0,0 +1,769 @@
|
||||
#ifndef _C4_YML_EVENT_HANDLER_TREE_HPP_
|
||||
#define _C4_YML_EVENT_HANDLER_TREE_HPP_
|
||||
|
||||
#ifndef _C4_YML_TREE_HPP_
|
||||
#include "c4/yml/tree.hpp"
|
||||
#endif
|
||||
|
||||
#ifndef _C4_YML_EVENT_HANDLER_STACK_HPP_
|
||||
#include "c4/yml/event_handler_stack.hpp"
|
||||
#endif
|
||||
|
||||
C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4702) // unreachable code
|
||||
// NOLINTBEGIN(hicpp-signed-bitwise)
|
||||
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
/** @addtogroup doc_event_handlers
|
||||
* @{ */
|
||||
|
||||
|
||||
/** The stack state needed specifically by @ref EventHandlerTree */
|
||||
struct EventHandlerTreeState : public ParserState
|
||||
{
|
||||
NodeData *tr_data;
|
||||
};
|
||||
|
||||
|
||||
/** The event handler to create a ryml @ref Tree. See the
|
||||
* documentation for @ref doc_event_handlers, which has important
|
||||
* notes about the event model used by rapidyaml. */
|
||||
struct EventHandlerTree : public EventHandlerStack<EventHandlerTree, EventHandlerTreeState>
|
||||
{
|
||||
|
||||
/** @name types
|
||||
* @{ */
|
||||
|
||||
using state = EventHandlerTreeState;
|
||||
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
|
||||
/** @cond dev */
|
||||
Tree *C4_RESTRICT m_tree;
|
||||
id_type m_id;
|
||||
size_t m_num_directives;
|
||||
bool m_yaml_directive;
|
||||
|
||||
#ifdef RYML_DBG
|
||||
#define _enable_(bits) _enable__<bits>(); _c4dbgpf("node[{}]: enable {}", m_curr->node_id, #bits)
|
||||
#define _disable_(bits) _disable__<bits>(); _c4dbgpf("node[{}]: disable {}", m_curr->node_id, #bits)
|
||||
#else
|
||||
#define _enable_(bits) _enable__<bits>()
|
||||
#define _disable_(bits) _disable__<bits>()
|
||||
#endif
|
||||
#define _has_any_(bits) _has_any__<bits>()
|
||||
/** @endcond */
|
||||
|
||||
public:
|
||||
|
||||
/** @name construction and resetting
|
||||
* @{ */
|
||||
|
||||
EventHandlerTree() : EventHandlerStack(), m_tree(), m_id(NONE), m_num_directives(), m_yaml_directive() {}
|
||||
EventHandlerTree(Callbacks const& cb) : EventHandlerStack(cb), m_tree(), m_id(NONE), m_num_directives(), m_yaml_directive() {}
|
||||
EventHandlerTree(Tree *tree, id_type id) : EventHandlerStack(tree->callbacks()), m_tree(tree), m_id(id), m_num_directives(), m_yaml_directive()
|
||||
{
|
||||
reset(tree, id);
|
||||
}
|
||||
|
||||
void reset(Tree *tree, id_type id)
|
||||
{
|
||||
if(C4_UNLIKELY(!tree))
|
||||
_RYML_CB_ERR(m_stack.m_callbacks, "null tree");
|
||||
if(C4_UNLIKELY(id >= tree->capacity()))
|
||||
_RYML_CB_ERR(tree->callbacks(), "invalid node");
|
||||
if(C4_UNLIKELY(!tree->is_root(id)))
|
||||
if(C4_UNLIKELY(tree->is_map(tree->parent(id))))
|
||||
if(C4_UNLIKELY(!tree->has_key(id)))
|
||||
_RYML_CB_ERR(tree->callbacks(), "destination node belongs to a map and has no key");
|
||||
m_tree = tree;
|
||||
m_id = id;
|
||||
if(m_tree->is_root(id))
|
||||
{
|
||||
_stack_reset_root();
|
||||
_reset_parser_state(m_curr, id, m_tree->root_id());
|
||||
}
|
||||
else
|
||||
{
|
||||
_stack_reset_non_root();
|
||||
_reset_parser_state(m_parent, id, m_tree->parent(id));
|
||||
_reset_parser_state(m_curr, id, id);
|
||||
}
|
||||
m_num_directives = 0;
|
||||
m_yaml_directive = false;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
|
||||
/** @name parse events
|
||||
* @{ */
|
||||
|
||||
void start_parse(const char* filename, detail::pfn_relocate_arena relocate_arena, void *relocate_arena_data)
|
||||
{
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_tree != nullptr);
|
||||
this->_stack_start_parse(filename, relocate_arena, relocate_arena_data);
|
||||
}
|
||||
|
||||
void finish_parse()
|
||||
{
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_tree != nullptr);
|
||||
if(m_num_directives && !m_tree->is_stream(m_tree->root_id()))
|
||||
_RYML_CB_ERR_(m_stack.m_callbacks, "directives cannot be used without a document", {});
|
||||
this->_stack_finish_parse();
|
||||
/* This pointer is temporary. Remember that:
|
||||
*
|
||||
* - this handler object may be held by the user
|
||||
* - it may be used with a temporary tree inside the parse function
|
||||
* - when the parse function returns the temporary tree, its address
|
||||
* will change
|
||||
*
|
||||
* As a result, the user could try to read the tree from m_tree, and
|
||||
* end up reading the stale temporary object.
|
||||
*
|
||||
* So it is better to clear it here; then the user will get an obvious
|
||||
* segfault if reading from m_tree. */
|
||||
m_tree = nullptr;
|
||||
}
|
||||
|
||||
void cancel_parse()
|
||||
{
|
||||
m_tree = nullptr;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
|
||||
/** @name YAML stream events */
|
||||
/** @{ */
|
||||
|
||||
C4_ALWAYS_INLINE void begin_stream() const noexcept { /*nothing to do*/ }
|
||||
|
||||
C4_ALWAYS_INLINE void end_stream() const noexcept { /*nothing to do*/ }
|
||||
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
|
||||
/** @name YAML document events */
|
||||
/** @{ */
|
||||
|
||||
/** implicit doc start (without ---) */
|
||||
void begin_doc()
|
||||
{
|
||||
_c4dbgp("begin_doc");
|
||||
if(_stack_should_push_on_begin_doc())
|
||||
{
|
||||
_c4dbgp("push!");
|
||||
_set_root_as_stream();
|
||||
_push();
|
||||
_enable_(DOC);
|
||||
}
|
||||
}
|
||||
/** implicit doc end (without ...) */
|
||||
void end_doc()
|
||||
{
|
||||
_c4dbgp("end_doc");
|
||||
if(_stack_should_pop_on_end_doc())
|
||||
{
|
||||
_remove_speculative();
|
||||
_c4dbgp("pop!");
|
||||
_pop();
|
||||
}
|
||||
}
|
||||
|
||||
/** explicit doc start, with --- */
|
||||
void begin_doc_expl()
|
||||
{
|
||||
_c4dbgp("begin_doc_expl");
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_tree->root_id() == m_curr->node_id);
|
||||
if(!m_tree->is_stream(m_tree->root_id())) //if(_should_push_on_begin_doc())
|
||||
{
|
||||
_c4dbgp("ensure stream");
|
||||
_set_root_as_stream();
|
||||
id_type first = m_tree->first_child(m_tree->root_id());
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_tree->is_stream(m_tree->root_id()));
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_tree->num_children(m_tree->root_id()) == 1u);
|
||||
if(m_tree->has_children(first) || m_tree->is_val(first))
|
||||
{
|
||||
_c4dbgp("push!");
|
||||
_push();
|
||||
}
|
||||
else
|
||||
{
|
||||
_c4dbgp("tweak");
|
||||
_push();
|
||||
_remove_speculative();
|
||||
m_curr->node_id = m_tree->last_child(m_tree->root_id());
|
||||
m_curr->tr_data = m_tree->_p(m_curr->node_id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_c4dbgp("push!");
|
||||
_push();
|
||||
}
|
||||
_enable_(DOC);
|
||||
}
|
||||
/** explicit doc end, with ... */
|
||||
void end_doc_expl()
|
||||
{
|
||||
_c4dbgp("end_doc_expl");
|
||||
_remove_speculative();
|
||||
if(_stack_should_pop_on_end_doc())
|
||||
{
|
||||
_c4dbgp("pop!");
|
||||
_pop();
|
||||
}
|
||||
m_yaml_directive = false;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
|
||||
/** @name YAML map events */
|
||||
/** @{ */
|
||||
|
||||
void begin_map_key_flow()
|
||||
{
|
||||
_RYML_CB_ERR_(m_stack.m_callbacks, "ryml trees cannot handle containers as keys", m_curr->pos);
|
||||
}
|
||||
void begin_map_key_block()
|
||||
{
|
||||
_RYML_CB_ERR_(m_stack.m_callbacks, "ryml trees cannot handle containers as keys", m_curr->pos);
|
||||
}
|
||||
|
||||
void begin_map_val_flow()
|
||||
{
|
||||
_c4dbgpf("node[{}]: begin_map_val_flow", m_curr->node_id);
|
||||
_RYML_CB_CHECK(m_stack.m_callbacks, !_has_any_(VAL));
|
||||
_enable_(MAP|FLOW_SL);
|
||||
_save_loc();
|
||||
_push();
|
||||
}
|
||||
void begin_map_val_block()
|
||||
{
|
||||
_c4dbgpf("node[{}]: begin_map_val_block", m_curr->node_id);
|
||||
_RYML_CB_CHECK(m_stack.m_callbacks, !_has_any_(VAL));
|
||||
_enable_(MAP|BLOCK);
|
||||
_save_loc();
|
||||
_push();
|
||||
}
|
||||
|
||||
void end_map()
|
||||
{
|
||||
_pop();
|
||||
_c4dbgpf("node[{}]: end_map_val", m_curr->node_id);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
|
||||
/** @name YAML seq events */
|
||||
/** @{ */
|
||||
|
||||
void begin_seq_key_flow()
|
||||
{
|
||||
_RYML_CB_ERR_(m_stack.m_callbacks, "ryml trees cannot handle containers as keys", m_curr->pos);
|
||||
}
|
||||
void begin_seq_key_block()
|
||||
{
|
||||
_RYML_CB_ERR_(m_stack.m_callbacks, "ryml trees cannot handle containers as keys", m_curr->pos);
|
||||
}
|
||||
|
||||
void begin_seq_val_flow()
|
||||
{
|
||||
_c4dbgpf("node[{}]: begin_seq_val_flow", m_curr->node_id);
|
||||
_RYML_CB_CHECK(m_stack.m_callbacks, !_has_any_(VAL));
|
||||
_enable_(SEQ|FLOW_SL);
|
||||
_save_loc();
|
||||
_push();
|
||||
}
|
||||
void begin_seq_val_block()
|
||||
{
|
||||
_c4dbgpf("node[{}]: begin_seq_val_block", m_curr->node_id);
|
||||
_RYML_CB_CHECK(m_stack.m_callbacks, !_has_any_(VAL));
|
||||
_enable_(SEQ|BLOCK);
|
||||
_save_loc();
|
||||
_push();
|
||||
}
|
||||
|
||||
void end_seq()
|
||||
{
|
||||
_pop();
|
||||
_c4dbgpf("node[{}]: end_seq_val", m_curr->node_id);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
|
||||
/** @name YAML structure events */
|
||||
/** @{ */
|
||||
|
||||
void add_sibling()
|
||||
{
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_parent);
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_tree->has_children(m_parent->node_id));
|
||||
NodeData const* prev = m_tree->m_buf; // watchout against relocation of the tree nodes
|
||||
_set_state_(m_curr, m_tree->_append_child__unprotected(m_parent->node_id));
|
||||
if(prev != m_tree->m_buf)
|
||||
_refresh_after_relocation();
|
||||
_c4dbgpf("node[{}]: added sibling={} prev={}", m_parent->node_id, m_curr->node_id, m_tree->prev_sibling(m_curr->node_id));
|
||||
}
|
||||
|
||||
/** set the previous val as the first key of a new map, with flow style.
|
||||
*
|
||||
* See the documentation for @ref doc_event_handlers, which has
|
||||
* important notes about this event.
|
||||
*/
|
||||
void actually_val_is_first_key_of_new_map_flow()
|
||||
{
|
||||
if(C4_UNLIKELY(m_tree->is_container(m_curr->node_id)))
|
||||
_RYML_CB_ERR_(m_stack.m_callbacks, "ryml trees cannot handle containers as keys", m_curr->pos);
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_parent);
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_tree->is_seq(m_parent->node_id));
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, !m_tree->is_container(m_curr->node_id));
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, !m_tree->has_key(m_curr->node_id));
|
||||
const NodeData tmp = _val2key_(*m_curr->tr_data);
|
||||
_disable_(_VALMASK|VAL_STYLE);
|
||||
m_curr->tr_data->m_val = {};
|
||||
begin_map_val_flow();
|
||||
m_curr->tr_data->m_type = tmp.m_type;
|
||||
m_curr->tr_data->m_key = tmp.m_key;
|
||||
}
|
||||
|
||||
/** like its flow counterpart, but this function can only be
|
||||
* called after the end of a flow-val at root or doc level.
|
||||
*
|
||||
* See the documentation for @ref doc_event_handlers, which has
|
||||
* important notes about this event.
|
||||
*/
|
||||
void actually_val_is_first_key_of_new_map_block()
|
||||
{
|
||||
_RYML_CB_ERR_(m_stack.m_callbacks, "ryml trees cannot handle containers as keys", m_curr->pos);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
|
||||
/** @name YAML scalar events */
|
||||
/** @{ */
|
||||
|
||||
|
||||
C4_ALWAYS_INLINE void set_key_scalar_plain_empty() noexcept
|
||||
{
|
||||
_c4dbgpf("node[{}]: set key scalar plain as empty", m_curr->node_id);
|
||||
m_curr->tr_data->m_key.scalar = {};
|
||||
_enable_(KEY|KEY_PLAIN|KEYNIL);
|
||||
}
|
||||
C4_ALWAYS_INLINE void set_val_scalar_plain_empty() noexcept
|
||||
{
|
||||
_c4dbgpf("node[{}]: set val scalar plain as empty", m_curr->node_id);
|
||||
m_curr->tr_data->m_val.scalar = {};
|
||||
_enable_(VAL|VAL_PLAIN|VALNIL);
|
||||
}
|
||||
|
||||
C4_ALWAYS_INLINE void set_key_scalar_plain(csubstr scalar) noexcept
|
||||
{
|
||||
_c4dbgpf("node[{}]: set key scalar plain: [{}]~~~{}~~~", m_curr->node_id, scalar.len, scalar);
|
||||
m_curr->tr_data->m_key.scalar = scalar;
|
||||
_enable_(KEY|KEY_PLAIN);
|
||||
}
|
||||
C4_ALWAYS_INLINE void set_val_scalar_plain(csubstr scalar) noexcept
|
||||
{
|
||||
_c4dbgpf("node[{}]: set val scalar plain: [{}]~~~{}~~~", m_curr->node_id, scalar.len, scalar);
|
||||
m_curr->tr_data->m_val.scalar = scalar;
|
||||
_enable_(VAL|VAL_PLAIN);
|
||||
}
|
||||
|
||||
|
||||
C4_ALWAYS_INLINE void set_key_scalar_dquoted(csubstr scalar) noexcept
|
||||
{
|
||||
_c4dbgpf("node[{}]: set key scalar dquot: [{}]~~~{}~~~", m_curr->node_id, scalar.len, scalar);
|
||||
m_curr->tr_data->m_key.scalar = scalar;
|
||||
_enable_(KEY|KEY_DQUO);
|
||||
}
|
||||
C4_ALWAYS_INLINE void set_val_scalar_dquoted(csubstr scalar) noexcept
|
||||
{
|
||||
_c4dbgpf("node[{}]: set val scalar dquot: [{}]~~~{}~~~", m_curr->node_id, scalar.len, scalar);
|
||||
m_curr->tr_data->m_val.scalar = scalar;
|
||||
_enable_(VAL|VAL_DQUO);
|
||||
}
|
||||
|
||||
|
||||
C4_ALWAYS_INLINE void set_key_scalar_squoted(csubstr scalar) noexcept
|
||||
{
|
||||
_c4dbgpf("node[{}]: set key scalar squot: [{}]~~~{}~~~", m_curr->node_id, scalar.len, scalar);
|
||||
m_curr->tr_data->m_key.scalar = scalar;
|
||||
_enable_(KEY|KEY_SQUO);
|
||||
}
|
||||
C4_ALWAYS_INLINE void set_val_scalar_squoted(csubstr scalar) noexcept
|
||||
{
|
||||
_c4dbgpf("node[{}]: set val scalar squot: [{}]~~~{}~~~", m_curr->node_id, scalar.len, scalar);
|
||||
m_curr->tr_data->m_val.scalar = scalar;
|
||||
_enable_(VAL|VAL_SQUO);
|
||||
}
|
||||
|
||||
|
||||
C4_ALWAYS_INLINE void set_key_scalar_literal(csubstr scalar) noexcept
|
||||
{
|
||||
_c4dbgpf("node[{}]: set key scalar literal: [{}]~~~{}~~~", m_curr->node_id, scalar.len, scalar);
|
||||
m_curr->tr_data->m_key.scalar = scalar;
|
||||
_enable_(KEY|KEY_LITERAL);
|
||||
}
|
||||
C4_ALWAYS_INLINE void set_val_scalar_literal(csubstr scalar) noexcept
|
||||
{
|
||||
_c4dbgpf("node[{}]: set val scalar literal: [{}]~~~{}~~~", m_curr->node_id, scalar.len, scalar);
|
||||
m_curr->tr_data->m_val.scalar = scalar;
|
||||
_enable_(VAL|VAL_LITERAL);
|
||||
}
|
||||
|
||||
|
||||
C4_ALWAYS_INLINE void set_key_scalar_folded(csubstr scalar) noexcept
|
||||
{
|
||||
_c4dbgpf("node[{}]: set key scalar folded: [{}]~~~{}~~~", m_curr->node_id, scalar.len, scalar);
|
||||
m_curr->tr_data->m_key.scalar = scalar;
|
||||
_enable_(KEY|KEY_FOLDED);
|
||||
}
|
||||
C4_ALWAYS_INLINE void set_val_scalar_folded(csubstr scalar) noexcept
|
||||
{
|
||||
_c4dbgpf("node[{}]: set val scalar folded: [{}]~~~{}~~~", m_curr->node_id, scalar.len, scalar);
|
||||
m_curr->tr_data->m_val.scalar = scalar;
|
||||
_enable_(VAL|VAL_FOLDED);
|
||||
}
|
||||
|
||||
|
||||
C4_ALWAYS_INLINE void mark_key_scalar_unfiltered() noexcept
|
||||
{
|
||||
_enable_(KEY_UNFILT);
|
||||
}
|
||||
C4_ALWAYS_INLINE void mark_val_scalar_unfiltered() noexcept
|
||||
{
|
||||
_enable_(VAL_UNFILT);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
|
||||
/** @name YAML anchor/reference events */
|
||||
/** @{ */
|
||||
|
||||
void set_key_anchor(csubstr anchor)
|
||||
{
|
||||
_c4dbgpf("node[{}]: set key anchor: [{}]~~~{}~~~", m_curr->node_id, anchor.len, anchor);
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);
|
||||
if(C4_UNLIKELY(_has_any_(KEYREF)))
|
||||
_RYML_CB_ERR_(m_tree->callbacks(), "key cannot have both anchor and ref", m_curr->pos);
|
||||
_RYML_CB_ASSERT(m_tree->callbacks(), !anchor.begins_with('&'));
|
||||
_enable_(KEYANCH);
|
||||
m_curr->tr_data->m_key.anchor = anchor;
|
||||
}
|
||||
void set_val_anchor(csubstr anchor)
|
||||
{
|
||||
_c4dbgpf("node[{}]: set val anchor: [{}]~~~{}~~~", m_curr->node_id, anchor.len, anchor);
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);
|
||||
if(C4_UNLIKELY(_has_any_(VALREF)))
|
||||
_RYML_CB_ERR_(m_tree->callbacks(), "val cannot have both anchor and ref", m_curr->pos);
|
||||
_RYML_CB_ASSERT(m_tree->callbacks(), !anchor.begins_with('&'));
|
||||
_enable_(VALANCH);
|
||||
m_curr->tr_data->m_val.anchor = anchor;
|
||||
}
|
||||
|
||||
void set_key_ref(csubstr ref)
|
||||
{
|
||||
_c4dbgpf("node[{}]: set key ref: [{}]~~~{}~~~", m_curr->node_id, ref.len, ref);
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);
|
||||
if(C4_UNLIKELY(_has_any_(KEYANCH)))
|
||||
_RYML_CB_ERR_(m_tree->callbacks(), "key cannot have both anchor and ref", m_curr->pos);
|
||||
_RYML_CB_ASSERT(m_tree->callbacks(), ref.begins_with('*'));
|
||||
_enable_(KEY|KEYREF);
|
||||
m_curr->tr_data->m_key.anchor = ref.sub(1);
|
||||
m_curr->tr_data->m_key.scalar = ref;
|
||||
}
|
||||
void set_val_ref(csubstr ref)
|
||||
{
|
||||
_c4dbgpf("node[{}]: set val ref: [{}]~~~{}~~~", m_curr->node_id, ref.len, ref);
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);
|
||||
if(C4_UNLIKELY(_has_any_(VALANCH)))
|
||||
_RYML_CB_ERR_(m_tree->callbacks(), "val cannot have both anchor and ref", m_curr->pos);
|
||||
_RYML_CB_ASSERT(m_tree->callbacks(), ref.begins_with('*'));
|
||||
_enable_(VAL|VALREF);
|
||||
m_curr->tr_data->m_val.anchor = ref.sub(1);
|
||||
m_curr->tr_data->m_val.scalar = ref;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
|
||||
/** @name YAML tag events */
|
||||
/** @{ */
|
||||
|
||||
void set_key_tag(csubstr tag) noexcept
|
||||
{
|
||||
_c4dbgpf("node[{}]: set key tag: [{}]~~~{}~~~", m_curr->node_id, tag.len, tag);
|
||||
_enable_(KEYTAG);
|
||||
m_curr->tr_data->m_key.tag = tag;
|
||||
}
|
||||
void set_val_tag(csubstr tag) noexcept
|
||||
{
|
||||
_c4dbgpf("node[{}]: set val tag: [{}]~~~{}~~~", m_curr->node_id, tag.len, tag);
|
||||
_enable_(VALTAG);
|
||||
m_curr->tr_data->m_val.tag = tag;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
|
||||
/** @name YAML directive events */
|
||||
/** @{ */
|
||||
|
||||
C4_NO_INLINE void add_directive(csubstr directive)
|
||||
{
|
||||
_c4dbgpf("% directive! {}", directive);
|
||||
_RYML_CB_ASSERT(m_tree->callbacks(), directive.begins_with('%'));
|
||||
if(directive.begins_with("%TAG"))
|
||||
{
|
||||
if(C4_UNLIKELY(!m_tree->add_tag_directive(directive)))
|
||||
_RYML_CB_ERR_(m_stack.m_callbacks, "failed to add directive", m_curr->pos);
|
||||
}
|
||||
else if(directive.begins_with("%YAML"))
|
||||
{
|
||||
_c4dbgpf("%YAML directive! ignoring...: {}", directive);
|
||||
if(C4_UNLIKELY(m_yaml_directive))
|
||||
_RYML_CB_ERR_(m_stack.m_callbacks, "multiple yaml directives", m_curr->pos);
|
||||
m_yaml_directive = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_c4dbgpf("unknown directive! ignoring... {}", directive);
|
||||
}
|
||||
++m_num_directives;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
|
||||
/** @name arena functions */
|
||||
/** @{ */
|
||||
|
||||
substr alloc_arena(size_t len)
|
||||
{
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);
|
||||
csubstr prev = m_tree->arena();
|
||||
substr out = m_tree->alloc_arena(len);
|
||||
substr curr = m_tree->arena();
|
||||
if(curr.str != prev.str)
|
||||
_stack_relocate_to_new_arena(prev, curr);
|
||||
return out;
|
||||
}
|
||||
|
||||
substr alloc_arena(size_t len, substr *relocated)
|
||||
{
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);
|
||||
csubstr prev = m_tree->arena();
|
||||
if(!prev.is_super(*relocated))
|
||||
return alloc_arena(len);
|
||||
substr out = alloc_arena(len);
|
||||
substr curr = m_tree->arena();
|
||||
if(curr.str != prev.str)
|
||||
*relocated = _stack_relocate_to_new_arena(*relocated, prev, curr);
|
||||
return out;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
|
||||
/** @cond dev */
|
||||
void _reset_parser_state(state* st, id_type parse_root, id_type node)
|
||||
{
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);
|
||||
_set_state_(st, node);
|
||||
const NodeType type = m_tree->type(node);
|
||||
#ifdef RYML_DBG
|
||||
char flagbuf[80];
|
||||
_c4dbgpf("resetting state: initial flags={}", detail::_parser_flags_to_str(flagbuf, st->flags));
|
||||
#endif
|
||||
if(type == NOTYPE)
|
||||
{
|
||||
_c4dbgpf("node[{}] is notype", node);
|
||||
if(m_tree->is_root(parse_root))
|
||||
{
|
||||
_c4dbgpf("node[{}] is root", node);
|
||||
st->flags |= RUNK|RTOP;
|
||||
}
|
||||
else
|
||||
{
|
||||
_c4dbgpf("node[{}] is not root. setting USTY", node);
|
||||
st->flags |= USTY;
|
||||
}
|
||||
}
|
||||
else if(type.is_map())
|
||||
{
|
||||
_c4dbgpf("node[{}] is map", node);
|
||||
st->flags |= RMAP|USTY;
|
||||
}
|
||||
else if(type.is_seq())
|
||||
{
|
||||
_c4dbgpf("node[{}] is map", node);
|
||||
st->flags |= RSEQ|USTY;
|
||||
}
|
||||
else if(type.has_key())
|
||||
{
|
||||
_c4dbgpf("node[{}] has key. setting USTY", node);
|
||||
st->flags |= USTY;
|
||||
}
|
||||
else
|
||||
{
|
||||
_RYML_CB_ERR(m_tree->callbacks(), "cannot append to node");
|
||||
}
|
||||
if(type.is_doc())
|
||||
{
|
||||
_c4dbgpf("node[{}] is doc", node);
|
||||
st->flags |= RDOC;
|
||||
}
|
||||
#ifdef RYML_DBG
|
||||
_c4dbgpf("resetting state: final flags={}", detail::_parser_flags_to_str(flagbuf, st->flags));
|
||||
#endif
|
||||
}
|
||||
|
||||
/** push a new parent, add a child to the new parent, and set the
|
||||
* child as the current node */
|
||||
void _push()
|
||||
{
|
||||
_stack_push();
|
||||
NodeData const* prev = m_tree->m_buf; // watch out against relocation of the tree nodes
|
||||
m_curr->node_id = m_tree->_append_child__unprotected(m_parent->node_id);
|
||||
m_curr->tr_data = m_tree->_p(m_curr->node_id);
|
||||
if(prev != m_tree->m_buf)
|
||||
_refresh_after_relocation();
|
||||
_c4dbgpf("pushed! level={}. top is now node={} (parent={})", m_curr->level, m_curr->node_id, m_parent ? m_parent->node_id : NONE);
|
||||
}
|
||||
/** end the current scope */
|
||||
void _pop()
|
||||
{
|
||||
_remove_speculative_with_parent();
|
||||
_stack_pop();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
template<type_bits bits> C4_HOT C4_ALWAYS_INLINE void _enable__() noexcept
|
||||
{
|
||||
m_curr->tr_data->m_type.type = static_cast<NodeType_e>(m_curr->tr_data->m_type.type | bits);
|
||||
}
|
||||
template<type_bits bits> C4_HOT C4_ALWAYS_INLINE void _disable__() noexcept
|
||||
{
|
||||
m_curr->tr_data->m_type.type = static_cast<NodeType_e>(m_curr->tr_data->m_type.type & (~bits));
|
||||
}
|
||||
template<type_bits bits> C4_HOT C4_ALWAYS_INLINE bool _has_any__() const noexcept
|
||||
{
|
||||
return (m_curr->tr_data->m_type.type & bits) != 0;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
C4_ALWAYS_INLINE void _set_state_(state *C4_RESTRICT s, id_type id) const noexcept
|
||||
{
|
||||
s->node_id = id;
|
||||
s->tr_data = m_tree->_p(id);
|
||||
}
|
||||
void _refresh_after_relocation()
|
||||
{
|
||||
_c4dbgp("tree: refreshing stack data after tree data relocation");
|
||||
for(auto &st : m_stack)
|
||||
st.tr_data = m_tree->_p(st.node_id);
|
||||
}
|
||||
|
||||
void _set_root_as_stream()
|
||||
{
|
||||
_c4dbgp("set root as stream");
|
||||
_RYML_CB_ASSERT(m_tree->callbacks(), m_tree->root_id() == 0u);
|
||||
_RYML_CB_ASSERT(m_tree->callbacks(), m_curr->node_id == 0u);
|
||||
const bool hack = !m_tree->has_children(m_curr->node_id) && !m_tree->is_val(m_curr->node_id);
|
||||
if(hack)
|
||||
m_tree->_p(m_tree->root_id())->m_type.add(VAL);
|
||||
m_tree->set_root_as_stream();
|
||||
_RYML_CB_ASSERT(m_tree->callbacks(), m_tree->is_stream(m_tree->root_id()));
|
||||
_RYML_CB_ASSERT(m_tree->callbacks(), m_tree->has_children(m_tree->root_id()));
|
||||
_RYML_CB_ASSERT(m_tree->callbacks(), m_tree->is_doc(m_tree->first_child(m_tree->root_id())));
|
||||
if(hack)
|
||||
m_tree->_p(m_tree->first_child(m_tree->root_id()))->m_type.rem(VAL);
|
||||
_set_state_(m_curr, m_tree->root_id());
|
||||
}
|
||||
|
||||
static NodeData _val2key_(NodeData const& C4_RESTRICT d) noexcept
|
||||
{
|
||||
NodeData r = d;
|
||||
r.m_key = d.m_val;
|
||||
r.m_val = {};
|
||||
r.m_type = d.m_type;
|
||||
static_assert((_VALMASK >> 1u) == _KEYMASK, "required for this function to work");
|
||||
static_assert((VAL_STYLE >> 1u) == KEY_STYLE, "required for this function to work");
|
||||
r.m_type.type = ((d.m_type.type & (_VALMASK|VAL_STYLE)) >> 1u);
|
||||
r.m_type.type = (r.m_type.type & ~(_VALMASK|VAL_STYLE));
|
||||
r.m_type.type = (r.m_type.type | KEY);
|
||||
return r;
|
||||
}
|
||||
|
||||
void _remove_speculative()
|
||||
{
|
||||
_c4dbgp("remove speculative node");
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);
|
||||
_RYML_CB_ASSERT(m_tree->callbacks(), !m_tree->empty());
|
||||
const id_type last_added = m_tree->size() - 1;
|
||||
if(m_tree->has_parent(last_added))
|
||||
if(m_tree->_p(last_added)->m_type == NOTYPE)
|
||||
m_tree->remove(last_added);
|
||||
}
|
||||
|
||||
void _remove_speculative_with_parent()
|
||||
{
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);
|
||||
_RYML_CB_ASSERT(m_tree->callbacks(), !m_tree->empty());
|
||||
const id_type last_added = m_tree->size() - 1;
|
||||
_RYML_CB_ASSERT(m_tree->callbacks(), m_tree->has_parent(last_added));
|
||||
if(m_tree->_p(last_added)->m_type == NOTYPE)
|
||||
{
|
||||
_c4dbgpf("remove speculative node with parent. parent={} node={} parent(node)={}", m_parent->node_id, last_added, m_tree->parent(last_added));
|
||||
m_tree->remove(last_added);
|
||||
}
|
||||
}
|
||||
|
||||
C4_ALWAYS_INLINE void _save_loc()
|
||||
{
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_tree);
|
||||
_RYML_CB_ASSERT(m_tree->callbacks(), m_tree->_p(m_curr->node_id)->m_val.scalar.len == 0);
|
||||
m_tree->_p(m_curr->node_id)->m_val.scalar.str = m_curr->line_contents.rem.str;
|
||||
}
|
||||
|
||||
#undef _enable_
|
||||
#undef _disable_
|
||||
#undef _has_any_
|
||||
|
||||
/** @endcond */
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
} // namespace yml
|
||||
} // namespace c4
|
||||
|
||||
// NOLINTEND(hicpp-signed-bitwise)
|
||||
C4_SUPPRESS_WARNING_MSVC_POP
|
||||
|
||||
#endif /* _C4_YML_EVENT_HANDLER_TREE_HPP_ */
|
||||
512
3rdparty/rapidyaml/include/c4/yml/filter_processor.hpp
vendored
Normal file
512
3rdparty/rapidyaml/include/c4/yml/filter_processor.hpp
vendored
Normal file
@@ -0,0 +1,512 @@
|
||||
#ifndef _C4_YML_FILTER_PROCESSOR_HPP_
|
||||
#define _C4_YML_FILTER_PROCESSOR_HPP_
|
||||
|
||||
#include "c4/yml/common.hpp"
|
||||
|
||||
#ifdef RYML_DBG
|
||||
#include "c4/charconv.hpp"
|
||||
#include "c4/yml/detail/parser_dbg.hpp"
|
||||
#endif
|
||||
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
/** @defgroup doc_filter_processors Scalar filter processors
|
||||
*
|
||||
* These are internal classes used by @ref ParseEngine to parse the
|
||||
* scalars; normally there is no reason for a user to be manually
|
||||
* using these classes.
|
||||
*
|
||||
* @ingroup doc_parse */
|
||||
/** @{ */
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** Filters an input string into a different output string */
|
||||
struct FilterProcessorSrcDst
|
||||
{
|
||||
csubstr src;
|
||||
substr dst;
|
||||
size_t rpos; ///< read position
|
||||
size_t wpos; ///< write position
|
||||
|
||||
C4_ALWAYS_INLINE FilterProcessorSrcDst(csubstr src_, substr dst_) noexcept
|
||||
: src(src_)
|
||||
, dst(dst_)
|
||||
, rpos(0)
|
||||
, wpos(0)
|
||||
{
|
||||
RYML_ASSERT(!dst.overlaps(src));
|
||||
}
|
||||
|
||||
C4_ALWAYS_INLINE void setwpos(size_t wpos_) noexcept { wpos = wpos_; }
|
||||
C4_ALWAYS_INLINE void setpos(size_t rpos_, size_t wpos_) noexcept { rpos = rpos_; wpos = wpos_; }
|
||||
C4_ALWAYS_INLINE void set_at_end() noexcept { skip(src.len - rpos); }
|
||||
|
||||
C4_ALWAYS_INLINE bool has_more_chars() const noexcept { return rpos < src.len; }
|
||||
C4_ALWAYS_INLINE bool has_more_chars(size_t maxpos) const noexcept { RYML_ASSERT(maxpos <= src.len); return rpos < maxpos; }
|
||||
|
||||
C4_ALWAYS_INLINE csubstr rem() const noexcept { return src.sub(rpos); }
|
||||
C4_ALWAYS_INLINE csubstr sofar() const noexcept { return csubstr(dst.str, wpos <= dst.len ? wpos : dst.len); }
|
||||
C4_ALWAYS_INLINE FilterResult result() const noexcept
|
||||
{
|
||||
FilterResult ret;
|
||||
ret.str.str = wpos <= dst.len ? dst.str : nullptr;
|
||||
ret.str.len = wpos;
|
||||
return ret;
|
||||
}
|
||||
|
||||
C4_ALWAYS_INLINE char curr() const noexcept { RYML_ASSERT(rpos < src.len); return src[rpos]; }
|
||||
C4_ALWAYS_INLINE char next() const noexcept { return rpos+1 < src.len ? src[rpos+1] : '\0'; }
|
||||
C4_ALWAYS_INLINE bool skipped_chars() const noexcept { return wpos != rpos; }
|
||||
|
||||
C4_ALWAYS_INLINE void skip() noexcept { ++rpos; }
|
||||
C4_ALWAYS_INLINE void skip(size_t num) noexcept { rpos += num; }
|
||||
|
||||
C4_ALWAYS_INLINE void set_at(size_t pos, char c) noexcept // NOLINT(readability-make-member-function-const)
|
||||
{
|
||||
RYML_ASSERT(pos < wpos);
|
||||
dst.str[pos] = c;
|
||||
}
|
||||
C4_ALWAYS_INLINE void set(char c) noexcept
|
||||
{
|
||||
if(wpos < dst.len)
|
||||
dst.str[wpos] = c;
|
||||
++wpos;
|
||||
}
|
||||
C4_ALWAYS_INLINE void set(char c, size_t num) noexcept
|
||||
{
|
||||
RYML_ASSERT(num > 0);
|
||||
if(wpos + num <= dst.len)
|
||||
memset(dst.str + wpos, c, num);
|
||||
wpos += num;
|
||||
}
|
||||
|
||||
C4_ALWAYS_INLINE void copy() noexcept
|
||||
{
|
||||
RYML_ASSERT(rpos < src.len);
|
||||
if(wpos < dst.len)
|
||||
dst.str[wpos] = src.str[rpos];
|
||||
++wpos;
|
||||
++rpos;
|
||||
}
|
||||
C4_ALWAYS_INLINE void copy(size_t num) noexcept
|
||||
{
|
||||
RYML_ASSERT(num);
|
||||
RYML_ASSERT(rpos+num <= src.len);
|
||||
if(wpos + num <= dst.len)
|
||||
memcpy(dst.str + wpos, src.str + rpos, num);
|
||||
wpos += num;
|
||||
rpos += num;
|
||||
}
|
||||
|
||||
C4_ALWAYS_INLINE void translate_esc(char c) noexcept
|
||||
{
|
||||
if(wpos < dst.len)
|
||||
dst.str[wpos] = c;
|
||||
++wpos;
|
||||
rpos += 2;
|
||||
}
|
||||
C4_ALWAYS_INLINE void translate_esc_bulk(const char *C4_RESTRICT s, size_t nw, size_t nr) noexcept
|
||||
{
|
||||
RYML_ASSERT(nw > 0);
|
||||
RYML_ASSERT(nr > 0);
|
||||
RYML_ASSERT(rpos+nr <= src.len);
|
||||
if(wpos+nw <= dst.len)
|
||||
memcpy(dst.str + wpos, s, nw);
|
||||
wpos += nw;
|
||||
rpos += 1 + nr;
|
||||
}
|
||||
C4_ALWAYS_INLINE void translate_esc_extending(const char *C4_RESTRICT s, size_t nw, size_t nr) noexcept
|
||||
{
|
||||
translate_esc_bulk(s, nw, nr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// filter in place
|
||||
|
||||
// debugging scaffold
|
||||
/** @cond dev */
|
||||
#if defined(RYML_DBG) && 0
|
||||
#define _c4dbgip(...) _c4dbgpf(__VA_ARGS__)
|
||||
#else
|
||||
#define _c4dbgip(...)
|
||||
#endif
|
||||
/** @endcond */
|
||||
|
||||
/** Filters in place. While the result may be larger than the source,
|
||||
* any extending happens only at the end of the string. Consequently,
|
||||
* it's impossible for characters to be left unfiltered.
|
||||
*
|
||||
* @see FilterProcessorInplaceMidExtending */
|
||||
struct FilterProcessorInplaceEndExtending
|
||||
{
|
||||
substr src; ///< the subject string
|
||||
size_t wcap; ///< write capacity - the capacity of the subject string's buffer
|
||||
size_t rpos; ///< read position
|
||||
size_t wpos; ///< write position
|
||||
|
||||
C4_ALWAYS_INLINE FilterProcessorInplaceEndExtending(substr src_, size_t wcap_) noexcept
|
||||
: src(src_)
|
||||
, wcap(wcap_)
|
||||
, rpos(0)
|
||||
, wpos(0)
|
||||
{
|
||||
RYML_ASSERT(wcap >= src.len);
|
||||
}
|
||||
|
||||
C4_ALWAYS_INLINE void setwpos(size_t wpos_) noexcept { wpos = wpos_; }
|
||||
C4_ALWAYS_INLINE void setpos(size_t rpos_, size_t wpos_) noexcept { rpos = rpos_; wpos = wpos_; }
|
||||
C4_ALWAYS_INLINE void set_at_end() noexcept { skip(src.len - rpos); }
|
||||
|
||||
C4_ALWAYS_INLINE bool has_more_chars() const noexcept { return rpos < src.len; }
|
||||
C4_ALWAYS_INLINE bool has_more_chars(size_t maxpos) const noexcept { RYML_ASSERT(maxpos <= src.len); return rpos < maxpos; }
|
||||
|
||||
C4_ALWAYS_INLINE FilterResult result() const noexcept
|
||||
{
|
||||
_c4dbgip("inplace: wpos={} wcap={} small={}", wpos, wcap, wpos > rpos);
|
||||
FilterResult ret;
|
||||
ret.str.str = (wpos <= wcap) ? src.str : nullptr;
|
||||
ret.str.len = wpos;
|
||||
return ret;
|
||||
}
|
||||
C4_ALWAYS_INLINE csubstr sofar() const noexcept { return csubstr(src.str, wpos <= wcap ? wpos : wcap); }
|
||||
C4_ALWAYS_INLINE csubstr rem() const noexcept { return src.sub(rpos); }
|
||||
|
||||
C4_ALWAYS_INLINE char curr() const noexcept { RYML_ASSERT(rpos < src.len); return src[rpos]; }
|
||||
C4_ALWAYS_INLINE char next() const noexcept { return rpos+1 < src.len ? src[rpos+1] : '\0'; }
|
||||
|
||||
C4_ALWAYS_INLINE void skip() noexcept { ++rpos; }
|
||||
C4_ALWAYS_INLINE void skip(size_t num) noexcept { rpos += num; }
|
||||
|
||||
void set_at(size_t pos, char c) noexcept
|
||||
{
|
||||
RYML_ASSERT(pos < wpos);
|
||||
const size_t save = wpos;
|
||||
wpos = pos;
|
||||
set(c);
|
||||
wpos = save;
|
||||
}
|
||||
void set(char c) noexcept
|
||||
{
|
||||
if(wpos < wcap) // respect write-capacity
|
||||
src.str[wpos] = c;
|
||||
++wpos;
|
||||
}
|
||||
void set(char c, size_t num) noexcept
|
||||
{
|
||||
RYML_ASSERT(num);
|
||||
if(wpos + num <= wcap) // respect write-capacity
|
||||
memset(src.str + wpos, c, num);
|
||||
wpos += num;
|
||||
}
|
||||
|
||||
void copy() noexcept
|
||||
{
|
||||
RYML_ASSERT(wpos <= rpos);
|
||||
RYML_ASSERT(rpos < src.len);
|
||||
if(wpos < wcap) // respect write-capacity
|
||||
src.str[wpos] = src.str[rpos];
|
||||
++rpos;
|
||||
++wpos;
|
||||
}
|
||||
void copy(size_t num) noexcept
|
||||
{
|
||||
RYML_ASSERT(num);
|
||||
RYML_ASSERT(rpos+num <= src.len);
|
||||
RYML_ASSERT(wpos <= rpos);
|
||||
if(wpos + num <= wcap) // respect write-capacity
|
||||
{
|
||||
if(wpos + num <= rpos) // there is no overlap
|
||||
memcpy(src.str + wpos, src.str + rpos, num);
|
||||
else // there is overlap
|
||||
memmove(src.str + wpos, src.str + rpos, num);
|
||||
}
|
||||
rpos += num;
|
||||
wpos += num;
|
||||
}
|
||||
|
||||
void translate_esc(char c) noexcept
|
||||
{
|
||||
RYML_ASSERT(rpos + 2 <= src.len);
|
||||
RYML_ASSERT(wpos <= rpos);
|
||||
if(wpos < wcap) // respect write-capacity
|
||||
src.str[wpos] = c;
|
||||
rpos += 2; // add 1u to account for the escape character
|
||||
++wpos;
|
||||
}
|
||||
|
||||
void translate_esc_bulk(const char *C4_RESTRICT s, size_t nw, size_t nr) noexcept
|
||||
{
|
||||
RYML_ASSERT(nw > 0);
|
||||
RYML_ASSERT(nr > 0);
|
||||
RYML_ASSERT(nw <= nr + 1u);
|
||||
RYML_ASSERT(rpos+nr <= src.len);
|
||||
RYML_ASSERT(wpos <= rpos);
|
||||
const size_t wpos_next = wpos + nw;
|
||||
const size_t rpos_next = rpos + nr + 1u; // add 1u to account for the escape character
|
||||
RYML_ASSERT(wpos_next <= rpos_next);
|
||||
if(wpos_next <= wcap)
|
||||
memcpy(src.str + wpos, s, nw);
|
||||
rpos = rpos_next;
|
||||
wpos = wpos_next;
|
||||
}
|
||||
|
||||
C4_ALWAYS_INLINE void translate_esc_extending(const char *C4_RESTRICT s, size_t nw, size_t nr) noexcept
|
||||
{
|
||||
translate_esc_bulk(s, nw, nr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** Filters in place. The result may be larger than the source, and
|
||||
* extending may happen anywhere. As a result some characters may be
|
||||
* left unfiltered when there is no slack in the buffer and the
|
||||
* write-position would overlap the read-position. Consequently, it's
|
||||
* possible for characters to be left unfiltered. In YAML, this
|
||||
* happens only with double-quoted strings, and only with a small
|
||||
* number of escape sequences such as `\L` which is substituted by three
|
||||
* bytes. These escape sequences cause a call to translate_esc_extending()
|
||||
* which is the only entry point to this unfiltered situation.
|
||||
*
|
||||
* @see FilterProcessorInplaceMidExtending */
|
||||
struct FilterProcessorInplaceMidExtending
|
||||
{
|
||||
substr src; ///< the subject string
|
||||
size_t wcap; ///< write capacity - the capacity of the subject string's buffer
|
||||
size_t rpos; ///< read position
|
||||
size_t wpos; ///< write position
|
||||
size_t maxcap; ///< the max capacity needed for filtering the string. This may be larger than the final string size.
|
||||
bool unfiltered_chars; ///< number of characters that were not added to wpos from lack of capacity
|
||||
|
||||
C4_ALWAYS_INLINE FilterProcessorInplaceMidExtending(substr src_, size_t wcap_) noexcept
|
||||
: src(src_)
|
||||
, wcap(wcap_)
|
||||
, rpos(0)
|
||||
, wpos(0)
|
||||
, maxcap(src.len)
|
||||
, unfiltered_chars(false)
|
||||
{
|
||||
RYML_ASSERT(wcap >= src.len);
|
||||
}
|
||||
|
||||
C4_ALWAYS_INLINE void setwpos(size_t wpos_) noexcept { wpos = wpos_; }
|
||||
C4_ALWAYS_INLINE void setpos(size_t rpos_, size_t wpos_) noexcept { rpos = rpos_; wpos = wpos_; }
|
||||
C4_ALWAYS_INLINE void set_at_end() noexcept { skip(src.len - rpos); }
|
||||
|
||||
C4_ALWAYS_INLINE bool has_more_chars() const noexcept { return rpos < src.len; }
|
||||
C4_ALWAYS_INLINE bool has_more_chars(size_t maxpos) const noexcept { RYML_ASSERT(maxpos <= src.len); return rpos < maxpos; }
|
||||
|
||||
C4_ALWAYS_INLINE FilterResultExtending result() const noexcept
|
||||
{
|
||||
_c4dbgip("inplace: wpos={} wcap={} unfiltered={} maxcap={}", this->wpos, this->wcap, this->unfiltered_chars, this->maxcap);
|
||||
FilterResultExtending ret;
|
||||
ret.str.str = (wpos <= wcap && !unfiltered_chars) ? src.str : nullptr;
|
||||
ret.str.len = wpos;
|
||||
ret.reqlen = maxcap;
|
||||
return ret;
|
||||
}
|
||||
C4_ALWAYS_INLINE csubstr sofar() const noexcept { return csubstr(src.str, wpos <= wcap ? wpos : wcap); }
|
||||
C4_ALWAYS_INLINE csubstr rem() const noexcept { return src.sub(rpos); }
|
||||
|
||||
C4_ALWAYS_INLINE char curr() const noexcept { RYML_ASSERT(rpos < src.len); return src[rpos]; }
|
||||
C4_ALWAYS_INLINE char next() const noexcept { return rpos+1 < src.len ? src[rpos+1] : '\0'; }
|
||||
|
||||
C4_ALWAYS_INLINE void skip() noexcept { ++rpos; }
|
||||
C4_ALWAYS_INLINE void skip(size_t num) noexcept { rpos += num; }
|
||||
|
||||
void set_at(size_t pos, char c) noexcept
|
||||
{
|
||||
RYML_ASSERT(pos < wpos);
|
||||
const size_t save = wpos;
|
||||
wpos = pos;
|
||||
set(c);
|
||||
wpos = save;
|
||||
}
|
||||
void set(char c) noexcept
|
||||
{
|
||||
if(wpos < wcap) // respect write-capacity
|
||||
{
|
||||
if((wpos <= rpos) && !unfiltered_chars)
|
||||
src.str[wpos] = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
_c4dbgip("inplace: add unwritten {}->{} maxcap={}->{}!", unfiltered_chars, true, maxcap, (wpos+1u > maxcap ? wpos+1u : maxcap));
|
||||
unfiltered_chars = true;
|
||||
}
|
||||
++wpos;
|
||||
maxcap = wpos > maxcap ? wpos : maxcap;
|
||||
}
|
||||
void set(char c, size_t num) noexcept
|
||||
{
|
||||
RYML_ASSERT(num);
|
||||
if(wpos + num <= wcap) // respect write-capacity
|
||||
{
|
||||
if((wpos <= rpos) && !unfiltered_chars)
|
||||
memset(src.str + wpos, c, num);
|
||||
}
|
||||
else
|
||||
{
|
||||
_c4dbgip("inplace: add unwritten {}->{} maxcap={}->{}!", unfiltered_chars, true, maxcap, (wpos+num > maxcap ? wpos+num : maxcap));
|
||||
unfiltered_chars = true;
|
||||
}
|
||||
wpos += num;
|
||||
maxcap = wpos > maxcap ? wpos : maxcap;
|
||||
}
|
||||
|
||||
void copy() noexcept
|
||||
{
|
||||
RYML_ASSERT(rpos < src.len);
|
||||
if(wpos < wcap) // respect write-capacity
|
||||
{
|
||||
if((wpos < rpos) && !unfiltered_chars) // write only if wpos is behind rpos
|
||||
src.str[wpos] = src.str[rpos];
|
||||
}
|
||||
else
|
||||
{
|
||||
_c4dbgip("inplace: add unwritten {}->{} (wpos={}!=rpos={})={} (wpos={}<wcap={}) maxcap={}->{}!", unfiltered_chars, true, wpos, rpos, wpos!=rpos, wpos, wcap, wpos<wcap, maxcap, (wpos+1u > maxcap ? wpos+1u : maxcap));
|
||||
unfiltered_chars = true;
|
||||
}
|
||||
++rpos;
|
||||
++wpos;
|
||||
maxcap = wpos > maxcap ? wpos : maxcap;
|
||||
}
|
||||
void copy(size_t num) noexcept
|
||||
{
|
||||
RYML_ASSERT(num);
|
||||
RYML_ASSERT(rpos+num <= src.len);
|
||||
if(wpos + num <= wcap) // respect write-capacity
|
||||
{
|
||||
if((wpos < rpos) && !unfiltered_chars) // write only if wpos is behind rpos
|
||||
{
|
||||
if(wpos + num <= rpos) // there is no overlap
|
||||
memcpy(src.str + wpos, src.str + rpos, num);
|
||||
else // there is overlap
|
||||
memmove(src.str + wpos, src.str + rpos, num);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_c4dbgip("inplace: add unwritten {}->{} (wpos={}!=rpos={})={} (wpos={}<wcap={}) maxcap={}->{}!", unfiltered_chars, true, wpos, rpos, wpos!=rpos, wpos, wcap, wpos<wcap);
|
||||
unfiltered_chars = true;
|
||||
}
|
||||
rpos += num;
|
||||
wpos += num;
|
||||
maxcap = wpos > maxcap ? wpos : maxcap;
|
||||
}
|
||||
|
||||
void translate_esc(char c) noexcept
|
||||
{
|
||||
RYML_ASSERT(rpos + 2 <= src.len);
|
||||
if(wpos < wcap) // respect write-capacity
|
||||
{
|
||||
if((wpos <= rpos) && !unfiltered_chars)
|
||||
src.str[wpos] = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
_c4dbgip("inplace: add unfiltered {}->{} maxcap={}->{}!", unfiltered_chars, true, maxcap, (wpos+1u > maxcap ? wpos+1u : maxcap));
|
||||
unfiltered_chars = true;
|
||||
}
|
||||
rpos += 2;
|
||||
++wpos;
|
||||
maxcap = wpos > maxcap ? wpos : maxcap;
|
||||
}
|
||||
|
||||
C4_NO_INLINE void translate_esc_bulk(const char *C4_RESTRICT s, size_t nw, size_t nr) noexcept
|
||||
{
|
||||
RYML_ASSERT(nw > 0);
|
||||
RYML_ASSERT(nr > 0);
|
||||
RYML_ASSERT(nr+1u >= nw);
|
||||
const size_t wpos_next = wpos + nw;
|
||||
const size_t rpos_next = rpos + nr + 1u; // add 1u to account for the escape character
|
||||
if(wpos_next <= wcap) // respect write-capacity
|
||||
{
|
||||
if((wpos <= rpos) && !unfiltered_chars) // write only if wpos is behind rpos
|
||||
memcpy(src.str + wpos, s, nw);
|
||||
}
|
||||
else
|
||||
{
|
||||
_c4dbgip("inplace: add unwritten {}->{} (wpos={}!=rpos={})={} (wpos={}<wcap={}) maxcap={}->{}!", unfiltered_chars, true, wpos, rpos, wpos!=rpos, wpos, wcap, wpos<wcap);
|
||||
unfiltered_chars = true;
|
||||
}
|
||||
rpos = rpos_next;
|
||||
wpos = wpos_next;
|
||||
maxcap = wpos > maxcap ? wpos : maxcap;
|
||||
}
|
||||
|
||||
C4_NO_INLINE void translate_esc_extending(const char *C4_RESTRICT s, size_t nw, size_t nr) noexcept
|
||||
{
|
||||
RYML_ASSERT(nw > 0);
|
||||
RYML_ASSERT(nr > 0);
|
||||
RYML_ASSERT(rpos+nr <= src.len);
|
||||
const size_t wpos_next = wpos + nw;
|
||||
const size_t rpos_next = rpos + nr + 1u; // add 1u to account for the escape character
|
||||
if(wpos_next <= rpos_next) // read and write do not overlap. just do a vanilla copy.
|
||||
{
|
||||
if((wpos_next <= wcap) && !unfiltered_chars)
|
||||
memcpy(src.str + wpos, s, nw);
|
||||
rpos = rpos_next;
|
||||
wpos = wpos_next;
|
||||
maxcap = wpos > maxcap ? wpos : maxcap;
|
||||
}
|
||||
else // there is overlap. move the (to-be-read) string to the right.
|
||||
{
|
||||
const size_t excess = wpos_next - rpos_next;
|
||||
RYML_ASSERT(wpos_next > rpos_next);
|
||||
if(src.len + excess <= wcap) // ensure we do not go past the end
|
||||
{
|
||||
RYML_ASSERT(rpos+nr+excess <= src.len);
|
||||
if(wpos_next <= wcap)
|
||||
{
|
||||
if(!unfiltered_chars)
|
||||
{
|
||||
memmove(src.str + wpos_next, src.str + rpos_next, src.len - rpos_next);
|
||||
memcpy(src.str + wpos, s, nw);
|
||||
}
|
||||
rpos = wpos_next; // wpos, not rpos
|
||||
}
|
||||
else
|
||||
{
|
||||
rpos = rpos_next;
|
||||
//const size_t unw = nw > (nr + 1u) ? nw - (nr + 1u) : 0;
|
||||
_c4dbgip("inplace: add unfiltered {}->{} maxcap={}->{}!", unfiltered_chars, true);
|
||||
unfiltered_chars = true;
|
||||
}
|
||||
wpos = wpos_next;
|
||||
// extend the string up to capacity
|
||||
src.len += excess;
|
||||
maxcap = wpos > maxcap ? wpos : maxcap;
|
||||
}
|
||||
else
|
||||
{
|
||||
//const size_t unw = nw > (nr + 1u) ? nw - (nr + 1u) : 0;
|
||||
RYML_ASSERT(rpos_next <= src.len);
|
||||
const size_t required_size = wpos_next + (src.len - rpos_next);
|
||||
_c4dbgip("inplace: add unfiltered {}->{} maxcap={}->{}!", unfiltered_chars, true, maxcap, required_size > maxcap ? required_size : maxcap);
|
||||
RYML_ASSERT(required_size > wcap);
|
||||
unfiltered_chars = true;
|
||||
maxcap = required_size > maxcap ? required_size : maxcap;
|
||||
wpos = wpos_next;
|
||||
rpos = rpos_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#undef _c4dbgip
|
||||
|
||||
|
||||
/** @} */
|
||||
|
||||
} // namespace yml
|
||||
} // namespace c4
|
||||
|
||||
#endif /* _C4_YML_FILTER_PROCESSOR_HPP_ */
|
||||
24
3rdparty/rapidyaml/include/c4/yml/fwd.hpp
vendored
Normal file
24
3rdparty/rapidyaml/include/c4/yml/fwd.hpp
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef _C4_YML_FWD_HPP_
|
||||
#define _C4_YML_FWD_HPP_
|
||||
|
||||
/** @file fwd.hpp forward declarations */
|
||||
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
struct NodeScalar;
|
||||
struct NodeInit;
|
||||
struct NodeData;
|
||||
struct NodeType;
|
||||
class NodeRef;
|
||||
class ConstNodeRef;
|
||||
class Tree;
|
||||
struct ReferenceResolver;
|
||||
template<class EventHandler> class ParseEngine;
|
||||
struct EventHandlerTree;
|
||||
using Parser = ParseEngine<EventHandlerTree>;
|
||||
|
||||
} // namespace c4
|
||||
} // namespace yml
|
||||
|
||||
#endif /* _C4_YML_FWD_HPP_ */
|
||||
732
3rdparty/rapidyaml/include/c4/yml/node.hpp
vendored
732
3rdparty/rapidyaml/include/c4/yml/node.hpp
vendored
File diff suppressed because it is too large
Load Diff
275
3rdparty/rapidyaml/include/c4/yml/node_type.hpp
vendored
Normal file
275
3rdparty/rapidyaml/include/c4/yml/node_type.hpp
vendored
Normal file
@@ -0,0 +1,275 @@
|
||||
#ifndef C4_YML_NODE_TYPE_HPP_
|
||||
#define C4_YML_NODE_TYPE_HPP_
|
||||
|
||||
#ifndef _C4_YML_COMMON_HPP_
|
||||
#include "c4/yml/common.hpp"
|
||||
#endif
|
||||
|
||||
C4_SUPPRESS_WARNING_MSVC_PUSH
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_PUSH
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG("-Wold-style-cast")
|
||||
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
/** @addtogroup doc_node_type
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** the integral type necessary to cover all the bits for NodeType_e */
|
||||
using type_bits = uint32_t;
|
||||
|
||||
|
||||
/** a bit mask for marking node types and styles */
|
||||
typedef enum : type_bits {
|
||||
#define __(v) (type_bits(1) << v) // a convenience define, undefined below // NOLINT
|
||||
NOTYPE = 0, ///< no node type or style is set
|
||||
KEY = __(0), ///< is member of a map
|
||||
VAL = __(1), ///< a scalar: has a scalar (ie string) value, possibly empty. must be a leaf node, and cannot be MAP or SEQ
|
||||
MAP = __(2), ///< a map: a parent of KEYVAL/KEYSEQ/KEYMAP nodes
|
||||
SEQ = __(3), ///< a seq: a parent of VAL/SEQ/MAP nodes
|
||||
DOC = __(4), ///< a document
|
||||
STREAM = __(5)|SEQ, ///< a stream: a seq of docs
|
||||
KEYREF = __(6), ///< a *reference: the key references an &anchor
|
||||
VALREF = __(7), ///< a *reference: the val references an &anchor
|
||||
KEYANCH = __(8), ///< the key has an &anchor
|
||||
VALANCH = __(9), ///< the val has an &anchor
|
||||
KEYTAG = __(10), ///< the key has a tag
|
||||
VALTAG = __(11), ///< the val has a tag
|
||||
KEYNIL = __(12), ///< the key is null (eg `{ : b}` results in a null key)
|
||||
VALNIL = __(13), ///< the val is null (eg `{a : }` results in a null val)
|
||||
_TYMASK = __(14)-1, ///< all the bits up to here
|
||||
//
|
||||
// unfiltered flags:
|
||||
//
|
||||
KEY_UNFILT = __(14), ///< the key scalar was left unfiltered; the parser was set not to filter. @see ParserOptions
|
||||
VAL_UNFILT = __(15), ///< the val scalar was left unfiltered; the parser was set not to filter. @see ParserOptions
|
||||
//
|
||||
// style flags:
|
||||
//
|
||||
FLOW_SL = __(16), ///< mark container with single-line flow style (seqs as '[val1,val2], maps as '{key: val,key2: val2}')
|
||||
FLOW_ML = __(17), ///< (NOT IMPLEMENTED, work in progress) mark container with multi-line flow style (seqs as '[\n val1,\n val2\n], maps as '{\n key: val,\n key2: val2\n}')
|
||||
BLOCK = __(18), ///< mark container with block style (seqs as '- val\n', maps as 'key: val')
|
||||
KEY_LITERAL = __(19), ///< mark key scalar as multiline, block literal |
|
||||
VAL_LITERAL = __(20), ///< mark val scalar as multiline, block literal |
|
||||
KEY_FOLDED = __(21), ///< mark key scalar as multiline, block folded >
|
||||
VAL_FOLDED = __(22), ///< mark val scalar as multiline, block folded >
|
||||
KEY_SQUO = __(23), ///< mark key scalar as single quoted '
|
||||
VAL_SQUO = __(24), ///< mark val scalar as single quoted '
|
||||
KEY_DQUO = __(25), ///< mark key scalar as double quoted "
|
||||
VAL_DQUO = __(26), ///< mark val scalar as double quoted "
|
||||
KEY_PLAIN = __(27), ///< mark key scalar as plain scalar (unquoted, even when multiline)
|
||||
VAL_PLAIN = __(28), ///< mark val scalar as plain scalar (unquoted, even when multiline)
|
||||
//
|
||||
// type combination masks:
|
||||
//
|
||||
KEYVAL = KEY|VAL,
|
||||
KEYSEQ = KEY|SEQ,
|
||||
KEYMAP = KEY|MAP,
|
||||
DOCMAP = DOC|MAP,
|
||||
DOCSEQ = DOC|SEQ,
|
||||
DOCVAL = DOC|VAL,
|
||||
//
|
||||
// style combination masks:
|
||||
//
|
||||
SCALAR_LITERAL = KEY_LITERAL|VAL_LITERAL,
|
||||
SCALAR_FOLDED = KEY_FOLDED|VAL_FOLDED,
|
||||
SCALAR_SQUO = KEY_SQUO|VAL_SQUO,
|
||||
SCALAR_DQUO = KEY_DQUO|VAL_DQUO,
|
||||
SCALAR_PLAIN = KEY_PLAIN|VAL_PLAIN,
|
||||
KEYQUO = KEY_SQUO|KEY_DQUO|KEY_FOLDED|KEY_LITERAL, ///< key style is one of ', ", > or |
|
||||
VALQUO = VAL_SQUO|VAL_DQUO|VAL_FOLDED|VAL_LITERAL, ///< val style is one of ', ", > or |
|
||||
KEY_STYLE = KEY_LITERAL|KEY_FOLDED|KEY_SQUO|KEY_DQUO|KEY_PLAIN, ///< mask of all the scalar styles for key (not container styles!)
|
||||
VAL_STYLE = VAL_LITERAL|VAL_FOLDED|VAL_SQUO|VAL_DQUO|VAL_PLAIN, ///< mask of all the scalar styles for val (not container styles!)
|
||||
SCALAR_STYLE = KEY_STYLE|VAL_STYLE,
|
||||
CONTAINER_STYLE_FLOW = FLOW_SL|FLOW_ML,
|
||||
CONTAINER_STYLE_BLOCK = BLOCK,
|
||||
CONTAINER_STYLE = FLOW_SL|FLOW_ML|BLOCK,
|
||||
STYLE = SCALAR_STYLE | CONTAINER_STYLE,
|
||||
//
|
||||
// mixed masks
|
||||
_KEYMASK = KEY | KEYQUO | KEYANCH | KEYREF | KEYTAG,
|
||||
_VALMASK = VAL | VALQUO | VALANCH | VALREF | VALTAG,
|
||||
#undef __
|
||||
} NodeType_e;
|
||||
|
||||
constexpr C4_ALWAYS_INLINE C4_CONST NodeType_e operator| (NodeType_e lhs, NodeType_e rhs) noexcept { return (NodeType_e)(((type_bits)lhs) | ((type_bits)rhs)); }
|
||||
constexpr C4_ALWAYS_INLINE C4_CONST NodeType_e operator& (NodeType_e lhs, NodeType_e rhs) noexcept { return (NodeType_e)(((type_bits)lhs) & ((type_bits)rhs)); }
|
||||
constexpr C4_ALWAYS_INLINE C4_CONST NodeType_e operator>> (NodeType_e bits, uint32_t n) noexcept { return (NodeType_e)(((type_bits)bits) >> n); }
|
||||
constexpr C4_ALWAYS_INLINE C4_CONST NodeType_e operator<< (NodeType_e bits, uint32_t n) noexcept { return (NodeType_e)(((type_bits)bits) << n); }
|
||||
constexpr C4_ALWAYS_INLINE C4_CONST NodeType_e operator~ (NodeType_e bits) noexcept { return (NodeType_e)(~(type_bits)bits); }
|
||||
C4_ALWAYS_INLINE NodeType_e& operator&= (NodeType_e &subject, NodeType_e bits) noexcept { subject = (NodeType_e)((type_bits)subject & (type_bits)bits); return subject; }
|
||||
C4_ALWAYS_INLINE NodeType_e& operator|= (NodeType_e &subject, NodeType_e bits) noexcept { subject = (NodeType_e)((type_bits)subject | (type_bits)bits); return subject; }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** wraps a NodeType_e element with some syntactic sugar and predicates */
|
||||
struct RYML_EXPORT NodeType
|
||||
{
|
||||
public:
|
||||
|
||||
NodeType_e type;
|
||||
|
||||
public:
|
||||
|
||||
C4_ALWAYS_INLINE NodeType() noexcept : type(NOTYPE) {}
|
||||
C4_ALWAYS_INLINE NodeType(NodeType_e t) noexcept : type(t) {}
|
||||
C4_ALWAYS_INLINE NodeType(type_bits t) noexcept : type((NodeType_e)t) {}
|
||||
|
||||
C4_ALWAYS_INLINE bool has_any(NodeType_e t) const noexcept { return (type & t) != 0u; }
|
||||
C4_ALWAYS_INLINE bool has_all(NodeType_e t) const noexcept { return (type & t) == t; }
|
||||
C4_ALWAYS_INLINE bool has_none(NodeType_e t) const noexcept { return (type & t) == 0; }
|
||||
|
||||
C4_ALWAYS_INLINE void set(NodeType_e t) noexcept { type = t; }
|
||||
C4_ALWAYS_INLINE void add(NodeType_e t) noexcept { type = (type|t); }
|
||||
C4_ALWAYS_INLINE void rem(NodeType_e t) noexcept { type = (type & ~t); }
|
||||
C4_ALWAYS_INLINE void addrem(NodeType_e bits_to_add, NodeType_e bits_to_remove) noexcept { type |= bits_to_add; type &= ~bits_to_remove; }
|
||||
|
||||
C4_ALWAYS_INLINE void clear() noexcept { type = NOTYPE; }
|
||||
|
||||
public:
|
||||
|
||||
C4_ALWAYS_INLINE operator NodeType_e & C4_RESTRICT () noexcept { return type; }
|
||||
C4_ALWAYS_INLINE operator NodeType_e const& C4_RESTRICT () const noexcept { return type; }
|
||||
|
||||
public:
|
||||
|
||||
/** @name node type queries
|
||||
* @{ */
|
||||
|
||||
/** return a preset string based on the node type */
|
||||
C4_ALWAYS_INLINE const char *type_str() const noexcept { return type_str(type); }
|
||||
/** return a preset string based on the node type */
|
||||
static const char* type_str(NodeType_e t) noexcept;
|
||||
|
||||
/** fill a string with the node type flags. If the string is small, returns {null, len} */
|
||||
C4_ALWAYS_INLINE csubstr type_str(substr buf) const noexcept { return type_str(buf, type); }
|
||||
/** fill a string with the node type flags. If the string is small, returns {null, len} */
|
||||
static csubstr type_str(substr buf, NodeType_e t) noexcept;
|
||||
|
||||
public:
|
||||
|
||||
/** @name node type queries
|
||||
* @{ */
|
||||
|
||||
C4_ALWAYS_INLINE bool is_notype() const noexcept { return type == NOTYPE; }
|
||||
C4_ALWAYS_INLINE bool is_stream() const noexcept { return ((type & STREAM) == STREAM) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_doc() const noexcept { return (type & DOC) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_container() const noexcept { return (type & (MAP|SEQ|STREAM)) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_map() const noexcept { return (type & MAP) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_seq() const noexcept { return (type & SEQ) != 0; }
|
||||
C4_ALWAYS_INLINE bool has_key() const noexcept { return (type & KEY) != 0; }
|
||||
C4_ALWAYS_INLINE bool has_val() const noexcept { return (type & VAL) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_val() const noexcept { return (type & KEYVAL) == VAL; }
|
||||
C4_ALWAYS_INLINE bool is_keyval() const noexcept { return (type & KEYVAL) == KEYVAL; }
|
||||
C4_ALWAYS_INLINE bool key_is_null() const noexcept { return (type & KEYNIL) != 0; }
|
||||
C4_ALWAYS_INLINE bool val_is_null() const noexcept { return (type & VALNIL) != 0; }
|
||||
C4_ALWAYS_INLINE bool has_key_tag() const noexcept { return (type & KEYTAG) != 0; }
|
||||
C4_ALWAYS_INLINE bool has_val_tag() const noexcept { return (type & VALTAG) != 0; }
|
||||
C4_ALWAYS_INLINE bool has_key_anchor() const noexcept { return (type & KEYANCH) != 0; }
|
||||
C4_ALWAYS_INLINE bool has_val_anchor() const noexcept { return (type & VALANCH) != 0; }
|
||||
C4_ALWAYS_INLINE bool has_anchor() const noexcept { return (type & (KEYANCH|VALANCH)) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_key_ref() const noexcept { return (type & KEYREF) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_val_ref() const noexcept { return (type & VALREF) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_ref() const noexcept { return (type & (KEYREF|VALREF)) != 0; }
|
||||
|
||||
C4_ALWAYS_INLINE bool is_key_unfiltered() const noexcept { return (type & (KEY_UNFILT)) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_val_unfiltered() const noexcept { return (type & (VAL_UNFILT)) != 0; }
|
||||
|
||||
RYML_DEPRECATED("use has_key_anchor()") bool is_key_anchor() const noexcept { return has_key_anchor(); }
|
||||
RYML_DEPRECATED("use has_val_anchor()") bool is_val_anchor() const noexcept { return has_val_anchor(); }
|
||||
RYML_DEPRECATED("use has_anchor()") bool is_anchor() const noexcept { return has_anchor(); }
|
||||
RYML_DEPRECATED("use has_anchor() || is_ref()") bool is_anchor_or_ref() const noexcept { return has_anchor() || is_ref(); }
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
|
||||
/** @name container+scalar style queries
|
||||
* @{ */
|
||||
|
||||
C4_ALWAYS_INLINE bool is_container_styled() const noexcept { return (type & (CONTAINER_STYLE)) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_block() const noexcept { return (type & (BLOCK)) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_flow_sl() const noexcept { return (type & (FLOW_SL)) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_flow_ml() const noexcept { return (type & (FLOW_ML)) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_flow() const noexcept { return (type & (FLOW_ML|FLOW_SL)) != 0; }
|
||||
|
||||
C4_ALWAYS_INLINE bool is_key_styled() const noexcept { return (type & (KEY_STYLE)) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_val_styled() const noexcept { return (type & (VAL_STYLE)) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_key_literal() const noexcept { return (type & (KEY_LITERAL)) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_val_literal() const noexcept { return (type & (VAL_LITERAL)) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_key_folded() const noexcept { return (type & (KEY_FOLDED)) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_val_folded() const noexcept { return (type & (VAL_FOLDED)) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_key_squo() const noexcept { return (type & (KEY_SQUO)) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_val_squo() const noexcept { return (type & (VAL_SQUO)) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_key_dquo() const noexcept { return (type & (KEY_DQUO)) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_val_dquo() const noexcept { return (type & (VAL_DQUO)) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_key_plain() const noexcept { return (type & (KEY_PLAIN)) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_val_plain() const noexcept { return (type & (VAL_PLAIN)) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_key_quoted() const noexcept { return (type & KEYQUO) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_val_quoted() const noexcept { return (type & VALQUO) != 0; }
|
||||
C4_ALWAYS_INLINE bool is_quoted() const noexcept { return (type & (KEYQUO|VALQUO)) != 0; }
|
||||
|
||||
C4_ALWAYS_INLINE void set_container_style(NodeType_e style) noexcept { type = ((style & CONTAINER_STYLE) | (type & ~CONTAINER_STYLE)); }
|
||||
C4_ALWAYS_INLINE void set_key_style(NodeType_e style) noexcept { type = ((style & KEY_STYLE) | (type & ~KEY_STYLE)); }
|
||||
C4_ALWAYS_INLINE void set_val_style(NodeType_e style) noexcept { type = ((style & VAL_STYLE) | (type & ~VAL_STYLE)); }
|
||||
|
||||
/** @} */
|
||||
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @name scalar style helpers
|
||||
* @{ */
|
||||
|
||||
/** choose a YAML emitting style based on the scalar's contents */
|
||||
RYML_EXPORT NodeType_e scalar_style_choose(csubstr scalar) noexcept;
|
||||
|
||||
/** choose a json style based on the scalar's contents */
|
||||
RYML_EXPORT NodeType_e scalar_style_json_choose(csubstr scalar) noexcept;
|
||||
|
||||
/** query whether a scalar can be encoded using single quotes.
|
||||
* It may not be possible, notably when there is leading
|
||||
* whitespace after a newline. */
|
||||
RYML_EXPORT bool scalar_style_query_squo(csubstr s) noexcept;
|
||||
|
||||
/** query whether a scalar can be encoded using plain style (no
|
||||
* quotes, not a literal/folded block scalar). */
|
||||
RYML_EXPORT bool scalar_style_query_plain(csubstr s) noexcept;
|
||||
|
||||
/** YAML-sense query of nullity. returns true if the scalar points
|
||||
* to `nullptr` or is otherwise equal to one of the strings
|
||||
* `"~"`,`"null"`,`"Null"`,`"NULL"` */
|
||||
RYML_EXPORT inline C4_NO_INLINE bool scalar_is_null(csubstr s) noexcept
|
||||
{
|
||||
return s.str == nullptr ||
|
||||
s == "~" ||
|
||||
s == "null" ||
|
||||
s == "Null" ||
|
||||
s == "NULL";
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
/** @} */
|
||||
|
||||
} // namespace yml
|
||||
} // namespace c4
|
||||
|
||||
C4_SUPPRESS_WARNING_MSVC_POP
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_POP
|
||||
|
||||
#endif /* C4_YML_NODE_TYPE_HPP_ */
|
||||
961
3rdparty/rapidyaml/include/c4/yml/parse.hpp
vendored
961
3rdparty/rapidyaml/include/c4/yml/parse.hpp
vendored
File diff suppressed because it is too large
Load Diff
8375
3rdparty/rapidyaml/include/c4/yml/parse_engine.def.hpp
vendored
Normal file
8375
3rdparty/rapidyaml/include/c4/yml/parse_engine.def.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
791
3rdparty/rapidyaml/include/c4/yml/parse_engine.hpp
vendored
Normal file
791
3rdparty/rapidyaml/include/c4/yml/parse_engine.hpp
vendored
Normal file
@@ -0,0 +1,791 @@
|
||||
#ifndef _C4_YML_PARSE_ENGINE_HPP_
|
||||
#define _C4_YML_PARSE_ENGINE_HPP_
|
||||
|
||||
#ifndef _C4_YML_DETAIL_PARSER_DBG_HPP_
|
||||
#include "c4/yml/detail/parser_dbg.hpp"
|
||||
#endif
|
||||
|
||||
#ifndef _C4_YML_PARSER_STATE_HPP_
|
||||
#include "c4/yml/parser_state.hpp"
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4251/*needs to have dll-interface to be used by clients of struct*/)
|
||||
#endif
|
||||
|
||||
// NOLINTBEGIN(hicpp-signed-bitwise)
|
||||
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
/** @addtogroup doc_parse
|
||||
* @{ */
|
||||
|
||||
/** @defgroup doc_event_handlers Event Handlers
|
||||
*
|
||||
* @brief rapidyaml implements its parsing logic with a two-level
|
||||
* model, where a @ref ParseEngine object reads through the YAML
|
||||
* source, and dispatches events to an EventHandler bound to the @ref
|
||||
* ParseEngine. Because @ref ParseEngine is templated on the event
|
||||
* handler, the binding uses static polymorphism, without any virtual
|
||||
* functions. The actual handler object can be changed at run time,
|
||||
* (but of course needs to be the type of the template parameter).
|
||||
* This is thus a very efficient architecture, and further enables the
|
||||
* user to provide his own custom handler if he wishes to bypass the
|
||||
* rapidyaml @ref Tree.
|
||||
*
|
||||
* There are two handlers implemented in this project:
|
||||
*
|
||||
* - @ref EventHandlerTree is the handler responsible for creating the
|
||||
* ryml @ref Tree
|
||||
*
|
||||
* - @ref EventHandlerYamlStd is the handler responsible for emitting
|
||||
* standardized [YAML test suite
|
||||
* events](https://github.com/yaml/yaml-test-suite), used (only) in
|
||||
* the CI of this project.
|
||||
*
|
||||
*
|
||||
* ### Event model
|
||||
*
|
||||
* The event model used by the parse engine and event handlers follows
|
||||
* very closely the event model in the [YAML test
|
||||
* suite](https://github.com/yaml/yaml-test-suite).
|
||||
*
|
||||
* Consider for example this YAML,
|
||||
* ```yaml
|
||||
* {foo: bar,foo2: bar2}
|
||||
* ```
|
||||
* which would produce these events in the test-suite parlance:
|
||||
* ```
|
||||
* +STR
|
||||
* +DOC
|
||||
* +MAP {}
|
||||
* =VAL :foo
|
||||
* =VAL :bar
|
||||
* =VAL :foo2
|
||||
* =VAL :bar2
|
||||
* -MAP
|
||||
* -DOC
|
||||
* -STR
|
||||
* ```
|
||||
*
|
||||
* For reference, the @ref ParseEngine object will produce this
|
||||
* sequence of calls to its bound EventHandler:
|
||||
* ```cpp
|
||||
* handler.begin_stream();
|
||||
* handler.begin_doc();
|
||||
* handler.begin_map_val_flow();
|
||||
* handler.set_key_scalar_plain("foo");
|
||||
* handler.set_val_scalar_plain("bar");
|
||||
* handler.add_sibling();
|
||||
* handler.set_key_scalar_plain("foo2");
|
||||
* handler.set_val_scalar_plain("bar2");
|
||||
* handler.end_map();
|
||||
* handler.end_doc();
|
||||
* handler.end_stream();
|
||||
* ```
|
||||
*
|
||||
* For many other examples of all areas of YAML and how ryml's parse
|
||||
* model corresponds to the YAML standard model, refer to the [unit
|
||||
* tests for the parse
|
||||
* engine](https://github.com/biojppm/rapidyaml/tree/master/test/test_parse_engine.cpp).
|
||||
*
|
||||
*
|
||||
* ### Special events
|
||||
*
|
||||
* Most of the parsing events adopted by rapidyaml in its event model
|
||||
* are fairly obvious, but there are two less-obvious events requiring
|
||||
* some explanation.
|
||||
*
|
||||
* These events exist to make it easier to parse some special YAML
|
||||
* cases. They are called by the parser when a just-handled
|
||||
* value/container is actually the first key of a new map:
|
||||
*
|
||||
* - `actually_val_is_first_key_of_new_map_flow()` (@ref EventHandlerTree::actually_val_is_first_key_of_new_map_flow() "see implementation in EventHandlerTree" / @ref EventHandlerYamlStd::actually_val_is_first_key_of_new_map_flow() "see implementation in EventHandlerYamlStd")
|
||||
* - `actually_val_is_first_key_of_new_map_block()` (@ref EventHandlerTree::actually_val_is_first_key_of_new_map_block() "see implementation in EventHandlerTree" / @ref EventHandlerYamlStd::actually_val_is_first_key_of_new_map_block() "see implementation in EventHandlerYamlStd")
|
||||
*
|
||||
* For example, consider an implicit map inside a seq: `[a: b, c:
|
||||
* d]` which is parsed as `[{a: b}, {c: d}]`. The standard event
|
||||
* sequence for this YAML would be the following:
|
||||
* ```cpp
|
||||
* handler.begin_seq_val_flow();
|
||||
* handler.begin_map_val_flow();
|
||||
* handler.set_key_scalar_plain("a");
|
||||
* handler.set_val_scalar_plain("b");
|
||||
* handler.end_map();
|
||||
* handler.add_sibling();
|
||||
* handler.begin_map_val_flow();
|
||||
* handler.set_key_scalar_plain("c");
|
||||
* handler.set_val_scalar_plain("d");
|
||||
* handler.end_map();
|
||||
* handler.end_seq();
|
||||
* ```
|
||||
* The problem with this event sequence is that it forces the
|
||||
* parser to delay setting the val scalar (in this case "a" and
|
||||
* "c") until it knows whether the scalar is a key or a val. This
|
||||
* would require the parser to store the scalar until this
|
||||
* time. For instance, in the example above, the parser should
|
||||
* delay setting "a" and "c", because they are in fact keys and
|
||||
* not vals. Until then, the parser would have to store "a" and
|
||||
* "c" in its internal state. The downside is that this complexity
|
||||
* cost would apply even if there is no implicit map -- every val
|
||||
* in a seq would have to be delayed until one of the
|
||||
* disambiguating subsequent tokens `,-]:` is found.
|
||||
* By calling this function, the parser can avoid this complexity,
|
||||
* by preemptively setting the scalar as a val. Then a call to
|
||||
* this function will create the map and rearrange the scalar as
|
||||
* key. Now the cost applies only once: when a seqimap starts. So
|
||||
* the following (easier and cheaper) event sequence below has the
|
||||
* same effect as the event sequence above:
|
||||
* ```cpp
|
||||
* handler.begin_seq_val_flow();
|
||||
* handler.set_val_scalar_plain("notmap");
|
||||
* handler.set_val_scalar_plain("a"); // preemptively set "a" as val!
|
||||
* handler.actually_as_new_map_key(); // create a map, move the "a" val as the key of the first child of the new map
|
||||
* handler.set_val_scalar_plain("b"); // now "a" is a key and "b" the val
|
||||
* handler.end_map();
|
||||
* handler.set_val_scalar_plain("c"); // "c" also as val!
|
||||
* handler.actually_as_block_flow(); // likewise
|
||||
* handler.set_val_scalar_plain("d"); // now "c" is a key and "b" the val
|
||||
* handler.end_map();
|
||||
* handler.end_seq();
|
||||
* ```
|
||||
* This also applies to container keys (although ryml's tree
|
||||
* cannot accomodate these): the parser can preemptively set a
|
||||
* container as a val, and call this event to turn that container
|
||||
* into a key. For example, consider this yaml:
|
||||
* ```yaml
|
||||
* [aa, bb]: [cc, dd]
|
||||
* # ^ ^ ^
|
||||
* # | | |
|
||||
* # (2) (1) (3) <- event sequence
|
||||
* ```
|
||||
* The standard event sequence for this YAML would be the
|
||||
* following:
|
||||
* ```cpp
|
||||
* handler.begin_map_val_block(); // (1)
|
||||
* handler.begin_seq_key_flow(); // (2)
|
||||
* handler.set_val_scalar_plain("aa");
|
||||
* handler.add_sibling();
|
||||
* handler.set_val_scalar_plain("bb");
|
||||
* handler.end_seq();
|
||||
* handler.begin_seq_val_flow(); // (3)
|
||||
* handler.set_val_scalar_plain("cc");
|
||||
* handler.add_sibling();
|
||||
* handler.set_val_scalar_plain("dd");
|
||||
* handler.end_seq();
|
||||
* handler.end_map();
|
||||
* ```
|
||||
* The problem with the sequence above is that, reading from
|
||||
* left-to-right, the parser can only detect the proper calls at
|
||||
* (1) and (2) once it reaches (1) in the YAML source. So, the
|
||||
* parser would have to buffer the entire event sequence starting
|
||||
* from the beginning until it reaches (1). Using this function,
|
||||
* the parser can do instead:
|
||||
* ```cpp
|
||||
* handler.begin_seq_val_flow(); // (2) -- preemptively as val!
|
||||
* handler.set_val_scalar_plain("aa");
|
||||
* handler.add_sibling();
|
||||
* handler.set_val_scalar_plain("bb");
|
||||
* handler.end_seq();
|
||||
* handler.actually_as_new_map_key(); // (1) -- adjust when finding that the prev val was actually a key.
|
||||
* handler.begin_seq_val_flow(); // (3) -- go on as before
|
||||
* handler.set_val_scalar_plain("cc");
|
||||
* handler.add_sibling();
|
||||
* handler.set_val_scalar_plain("dd");
|
||||
* handler.end_seq();
|
||||
* handler.end_map();
|
||||
* ```
|
||||
*/
|
||||
|
||||
class Tree;
|
||||
class NodeRef;
|
||||
class ConstNodeRef;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** Options to give to the parser to control its behavior. */
|
||||
struct RYML_EXPORT ParserOptions
|
||||
{
|
||||
private:
|
||||
|
||||
typedef enum : uint32_t {
|
||||
SCALAR_FILTERING = (1u << 0u),
|
||||
LOCATIONS = (1u << 1u),
|
||||
DEFAULTS = SCALAR_FILTERING,
|
||||
} Flags_e;
|
||||
|
||||
uint32_t flags = DEFAULTS;
|
||||
|
||||
public:
|
||||
|
||||
ParserOptions() = default;
|
||||
|
||||
public:
|
||||
|
||||
/** @name source location tracking */
|
||||
/** @{ */
|
||||
|
||||
/** enable/disable source location tracking */
|
||||
ParserOptions& locations(bool enabled) noexcept
|
||||
{
|
||||
if(enabled)
|
||||
flags |= LOCATIONS;
|
||||
else
|
||||
flags &= ~LOCATIONS;
|
||||
return *this;
|
||||
}
|
||||
/** query source location tracking status */
|
||||
C4_ALWAYS_INLINE bool locations() const noexcept { return (flags & LOCATIONS); }
|
||||
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
|
||||
/** @name scalar filtering status (experimental; disable at your discretion) */
|
||||
/** @{ */
|
||||
|
||||
/** enable/disable scalar filtering while parsing */
|
||||
ParserOptions& scalar_filtering(bool enabled) noexcept
|
||||
{
|
||||
if(enabled)
|
||||
flags |= SCALAR_FILTERING;
|
||||
else
|
||||
flags &= ~SCALAR_FILTERING;
|
||||
return *this;
|
||||
}
|
||||
/** query scalar filtering status */
|
||||
C4_ALWAYS_INLINE bool scalar_filtering() const noexcept { return (flags & SCALAR_FILTERING); }
|
||||
|
||||
/** @} */
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** This is the main driver of parsing logic: it scans the YAML or
|
||||
* JSON source for tokens, and emits the appropriate sequence of
|
||||
* parsing events to its event handler. The parse engine itself has no
|
||||
* special limitations, and *can* accomodate containers as keys; it is the
|
||||
* event handler may introduce additional constraints.
|
||||
*
|
||||
* There are two implemented handlers (see @ref doc_event_handlers,
|
||||
* which has important notes about the event model):
|
||||
*
|
||||
* - @ref EventHandlerTree is the handler responsible for creating the
|
||||
* ryml @ref Tree
|
||||
*
|
||||
* - @ref EventHandlerYamlStd is the handler responsible for emitting
|
||||
* standardized [YAML test suite
|
||||
* events](https://github.com/yaml/yaml-test-suite), used (only) in
|
||||
* the CI of this project. This is not part of the library and is
|
||||
* not installed.
|
||||
*/
|
||||
template<class EventHandler>
|
||||
class ParseEngine
|
||||
{
|
||||
public:
|
||||
|
||||
using handler_type = EventHandler;
|
||||
|
||||
public:
|
||||
|
||||
/** @name construction and assignment */
|
||||
/** @{ */
|
||||
|
||||
ParseEngine(EventHandler *evt_handler, ParserOptions opts={});
|
||||
~ParseEngine();
|
||||
|
||||
ParseEngine(ParseEngine &&) noexcept;
|
||||
ParseEngine(ParseEngine const&);
|
||||
ParseEngine& operator=(ParseEngine &&) noexcept;
|
||||
ParseEngine& operator=(ParseEngine const&);
|
||||
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
|
||||
/** @name modifiers */
|
||||
/** @{ */
|
||||
|
||||
/** Reserve a certain capacity for the parsing stack.
|
||||
* This should be larger than the expected depth of the parsed
|
||||
* YAML tree.
|
||||
*
|
||||
* The parsing stack is the only (potential) heap memory used
|
||||
* directly by the parser.
|
||||
*
|
||||
* If the requested capacity is below the default
|
||||
* stack size of 16, the memory is used directly in the parser
|
||||
* object; otherwise it will be allocated from the heap.
|
||||
*
|
||||
* @note this reserves memory only for the parser itself; all the
|
||||
* allocations for the parsed tree will go through the tree's
|
||||
* allocator (when different).
|
||||
*
|
||||
* @note for maximum efficiency, the tree and the arena can (and
|
||||
* should) also be reserved. */
|
||||
void reserve_stack(id_type capacity)
|
||||
{
|
||||
m_evt_handler->m_stack.reserve(capacity);
|
||||
}
|
||||
|
||||
/** Reserve a certain capacity for the array used to track node
|
||||
* locations in the source buffer. */
|
||||
void reserve_locations(size_t num_source_lines)
|
||||
{
|
||||
_resize_locations(num_source_lines);
|
||||
}
|
||||
|
||||
RYML_DEPRECATED("filter arena no longer needed")
|
||||
void reserve_filter_arena(size_t) {}
|
||||
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
|
||||
/** @name getters */
|
||||
/** @{ */
|
||||
|
||||
/** Get the options used to build this parser object. */
|
||||
ParserOptions const& options() const { return m_options; }
|
||||
|
||||
/** Get the current callbacks in the parser. */
|
||||
Callbacks const& callbacks() const { RYML_ASSERT(m_evt_handler); return m_evt_handler->m_stack.m_callbacks; }
|
||||
|
||||
/** Get the name of the latest file parsed by this object. */
|
||||
csubstr filename() const { return m_file; }
|
||||
|
||||
/** Get the latest YAML buffer parsed by this object. */
|
||||
csubstr source() const { return m_buf; }
|
||||
|
||||
/** Get the encoding of the latest YAML buffer parsed by this object.
|
||||
* If no encoding was specified, UTF8 is assumed as per the YAML standard. */
|
||||
Encoding_e encoding() const { return m_encoding != NOBOM ? m_encoding : UTF8; }
|
||||
|
||||
id_type stack_capacity() const { RYML_ASSERT(m_evt_handler); return m_evt_handler->m_stack.capacity(); }
|
||||
size_t locations_capacity() const { return m_newline_offsets_capacity; }
|
||||
|
||||
RYML_DEPRECATED("filter arena no longer needed")
|
||||
size_t filter_arena_capacity() const { return 0u; }
|
||||
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
|
||||
/** @name parse methods */
|
||||
/** @{ */
|
||||
|
||||
/** parse YAML in place, emitting events to the current handler */
|
||||
void parse_in_place_ev(csubstr filename, substr src);
|
||||
|
||||
/** parse JSON in place, emitting events to the current handler */
|
||||
void parse_json_in_place_ev(csubstr filename, substr src);
|
||||
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
|
||||
/** @name deprecated parse methods
|
||||
* @{ */
|
||||
|
||||
/** @cond dev */
|
||||
template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the freestanding function in parse.hpp.") typename std::enable_if<U::is_wtree, void>::type parse_in_place(csubstr filename, substr yaml, Tree *t, size_t node_id);
|
||||
template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the freestanding function in parse.hpp.") typename std::enable_if<U::is_wtree, void>::type parse_in_place( substr yaml, Tree *t, size_t node_id);
|
||||
template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the freestanding function in parse.hpp.") typename std::enable_if<U::is_wtree, void>::type parse_in_place(csubstr filename, substr yaml, Tree *t );
|
||||
template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the freestanding function in parse.hpp.") typename std::enable_if<U::is_wtree, void>::type parse_in_place( substr yaml, Tree *t );
|
||||
template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the freestanding function in parse.hpp.") typename std::enable_if<U::is_wtree, void>::type parse_in_place(csubstr filename, substr yaml, NodeRef node );
|
||||
template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the freestanding function in parse.hpp.") typename std::enable_if<U::is_wtree, void>::type parse_in_place( substr yaml, NodeRef node );
|
||||
template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the freestanding function in parse.hpp.") typename std::enable_if<U::is_wtree, Tree>::type parse_in_place(csubstr filename, substr yaml );
|
||||
template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the freestanding function in parse.hpp.") typename std::enable_if<U::is_wtree, Tree>::type parse_in_place( substr yaml );
|
||||
template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the freestanding function in parse.hpp.") typename std::enable_if<U::is_wtree, void>::type parse_in_arena(csubstr filename, csubstr yaml, Tree *t, size_t node_id);
|
||||
template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the freestanding function in parse.hpp.") typename std::enable_if<U::is_wtree, void>::type parse_in_arena( csubstr yaml, Tree *t, size_t node_id);
|
||||
template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the freestanding function in parse.hpp.") typename std::enable_if<U::is_wtree, void>::type parse_in_arena(csubstr filename, csubstr yaml, Tree *t );
|
||||
template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the freestanding function in parse.hpp.") typename std::enable_if<U::is_wtree, void>::type parse_in_arena( csubstr yaml, Tree *t );
|
||||
template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the freestanding function in parse.hpp.") typename std::enable_if<U::is_wtree, void>::type parse_in_arena(csubstr filename, csubstr yaml, NodeRef node );
|
||||
template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the freestanding function in parse.hpp.") typename std::enable_if<U::is_wtree, void>::type parse_in_arena( csubstr yaml, NodeRef node );
|
||||
template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the freestanding function in parse.hpp.") typename std::enable_if<U::is_wtree, Tree>::type parse_in_arena(csubstr filename, csubstr yaml );
|
||||
template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the freestanding function in parse.hpp.") typename std::enable_if<U::is_wtree, Tree>::type parse_in_arena( csubstr yaml );
|
||||
template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the freestanding csubstr version in parse.hpp.") typename std::enable_if<U::is_wtree, void>::type parse_in_arena(csubstr filename, substr yaml, Tree *t, size_t node_id);
|
||||
template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the freestanding csubstr version in parse.hpp.") typename std::enable_if<U::is_wtree, void>::type parse_in_arena( substr yaml, Tree *t, size_t node_id);
|
||||
template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the freestanding csubstr version in parse.hpp.") typename std::enable_if<U::is_wtree, void>::type parse_in_arena(csubstr filename, substr yaml, Tree *t );
|
||||
template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the freestanding csubstr version in parse.hpp.") typename std::enable_if<U::is_wtree, void>::type parse_in_arena( substr yaml, Tree *t );
|
||||
template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the freestanding csubstr version in parse.hpp.") typename std::enable_if<U::is_wtree, void>::type parse_in_arena(csubstr filename, substr yaml, NodeRef node );
|
||||
template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the freestanding csubstr version in parse.hpp.") typename std::enable_if<U::is_wtree, void>::type parse_in_arena( substr yaml, NodeRef node );
|
||||
template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the freestanding csubstr version in parse.hpp.") typename std::enable_if<U::is_wtree, Tree>::type parse_in_arena(csubstr filename, substr yaml );
|
||||
template<class U=EventHandler> RYML_DEPRECATED("removed, deliberately undefined. use the freestanding csubstr version in parse.hpp.") typename std::enable_if<U::is_wtree, Tree>::type parse_in_arena( substr yaml );
|
||||
/** @endcond */
|
||||
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
|
||||
/** @name locations */
|
||||
/** @{ */
|
||||
|
||||
/** Get the location of a node of the last tree to be parsed by this parser. */
|
||||
Location location(Tree const& tree, id_type node_id) const;
|
||||
/** Get the location of a node of the last tree to be parsed by this parser. */
|
||||
Location location(ConstNodeRef node) const;
|
||||
/** Get the string starting at a particular location, to the end
|
||||
* of the parsed source buffer. */
|
||||
csubstr location_contents(Location const& loc) const;
|
||||
/** Given a pointer to a buffer position, get the location.
|
||||
* @param[in] val must be pointing to somewhere in the source
|
||||
* buffer that was last parsed by this object. */
|
||||
Location val_location(const char *val) const;
|
||||
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
|
||||
/** @name scalar filtering */
|
||||
/** @{*/
|
||||
|
||||
/** filter a plain scalar */
|
||||
FilterResult filter_scalar_plain(csubstr scalar, substr dst, size_t indentation);
|
||||
/** filter a plain scalar in place */
|
||||
FilterResult filter_scalar_plain_in_place(substr scalar, size_t cap, size_t indentation);
|
||||
|
||||
/** filter a single-quoted scalar */
|
||||
FilterResult filter_scalar_squoted(csubstr scalar, substr dst);
|
||||
/** filter a single-quoted scalar in place */
|
||||
FilterResult filter_scalar_squoted_in_place(substr scalar, size_t cap);
|
||||
|
||||
/** filter a double-quoted scalar */
|
||||
FilterResult filter_scalar_dquoted(csubstr scalar, substr dst);
|
||||
/** filter a double-quoted scalar in place */
|
||||
FilterResultExtending filter_scalar_dquoted_in_place(substr scalar, size_t cap);
|
||||
|
||||
/** filter a block-literal scalar */
|
||||
FilterResult filter_scalar_block_literal(csubstr scalar, substr dst, size_t indentation, BlockChomp_e chomp);
|
||||
/** filter a block-literal scalar in place */
|
||||
FilterResult filter_scalar_block_literal_in_place(substr scalar, size_t cap, size_t indentation, BlockChomp_e chomp);
|
||||
|
||||
/** filter a block-folded scalar */
|
||||
FilterResult filter_scalar_block_folded(csubstr scalar, substr dst, size_t indentation, BlockChomp_e chomp);
|
||||
/** filter a block-folded scalar in place */
|
||||
FilterResult filter_scalar_block_folded_in_place(substr scalar, size_t cap, size_t indentation, BlockChomp_e chomp);
|
||||
|
||||
/** @} */
|
||||
|
||||
private:
|
||||
|
||||
struct ScannedScalar
|
||||
{
|
||||
substr scalar;
|
||||
bool needs_filter;
|
||||
};
|
||||
|
||||
struct ScannedBlock
|
||||
{
|
||||
substr scalar;
|
||||
size_t indentation;
|
||||
BlockChomp_e chomp;
|
||||
};
|
||||
|
||||
bool _is_doc_begin(csubstr s);
|
||||
bool _is_doc_end(csubstr s);
|
||||
|
||||
bool _scan_scalar_plain_blck(ScannedScalar *C4_RESTRICT sc, size_t indentation);
|
||||
bool _scan_scalar_plain_seq_flow(ScannedScalar *C4_RESTRICT sc);
|
||||
bool _scan_scalar_plain_seq_blck(ScannedScalar *C4_RESTRICT sc);
|
||||
bool _scan_scalar_plain_map_flow(ScannedScalar *C4_RESTRICT sc);
|
||||
bool _scan_scalar_plain_map_blck(ScannedScalar *C4_RESTRICT sc);
|
||||
bool _scan_scalar_map_json(ScannedScalar *C4_RESTRICT sc);
|
||||
bool _scan_scalar_seq_json(ScannedScalar *C4_RESTRICT sc);
|
||||
bool _scan_scalar_plain_unk(ScannedScalar *C4_RESTRICT sc);
|
||||
bool _is_valid_start_scalar_plain_flow(csubstr s);
|
||||
|
||||
ScannedScalar _scan_scalar_squot();
|
||||
ScannedScalar _scan_scalar_dquot();
|
||||
|
||||
void _scan_block(ScannedBlock *C4_RESTRICT sb, size_t indref);
|
||||
|
||||
csubstr _scan_anchor();
|
||||
csubstr _scan_ref_seq();
|
||||
csubstr _scan_ref_map();
|
||||
csubstr _scan_tag();
|
||||
|
||||
public: // exposed for testing
|
||||
|
||||
/** @cond dev */
|
||||
csubstr _filter_scalar_plain(substr s, size_t indentation);
|
||||
csubstr _filter_scalar_squot(substr s);
|
||||
csubstr _filter_scalar_dquot(substr s);
|
||||
csubstr _filter_scalar_literal(substr s, size_t indentation, BlockChomp_e chomp);
|
||||
csubstr _filter_scalar_folded(substr s, size_t indentation, BlockChomp_e chomp);
|
||||
|
||||
csubstr _maybe_filter_key_scalar_plain(ScannedScalar const& sc, size_t indendation);
|
||||
csubstr _maybe_filter_val_scalar_plain(ScannedScalar const& sc, size_t indendation);
|
||||
csubstr _maybe_filter_key_scalar_squot(ScannedScalar const& sc);
|
||||
csubstr _maybe_filter_val_scalar_squot(ScannedScalar const& sc);
|
||||
csubstr _maybe_filter_key_scalar_dquot(ScannedScalar const& sc);
|
||||
csubstr _maybe_filter_val_scalar_dquot(ScannedScalar const& sc);
|
||||
csubstr _maybe_filter_key_scalar_literal(ScannedBlock const& sb);
|
||||
csubstr _maybe_filter_val_scalar_literal(ScannedBlock const& sb);
|
||||
csubstr _maybe_filter_key_scalar_folded(ScannedBlock const& sb);
|
||||
csubstr _maybe_filter_val_scalar_folded(ScannedBlock const& sb);
|
||||
/** @endcond */
|
||||
|
||||
private:
|
||||
|
||||
void _handle_map_block();
|
||||
void _handle_seq_block();
|
||||
void _handle_map_flow();
|
||||
void _handle_seq_flow();
|
||||
void _handle_seq_imap();
|
||||
void _handle_map_json();
|
||||
void _handle_seq_json();
|
||||
|
||||
void _handle_unk();
|
||||
void _handle_unk_json();
|
||||
void _handle_usty();
|
||||
|
||||
void _handle_flow_skip_whitespace();
|
||||
|
||||
void _end_map_blck();
|
||||
void _end_seq_blck();
|
||||
void _end2_map();
|
||||
void _end2_seq();
|
||||
|
||||
void _begin2_doc();
|
||||
void _begin2_doc_expl();
|
||||
void _end2_doc();
|
||||
void _end2_doc_expl();
|
||||
|
||||
void _maybe_begin_doc();
|
||||
void _maybe_end_doc();
|
||||
|
||||
void _start_doc_suddenly();
|
||||
void _end_doc_suddenly();
|
||||
void _end_doc_suddenly__pop();
|
||||
void _end_stream();
|
||||
|
||||
void _set_indentation(size_t indentation);
|
||||
void _save_indentation();
|
||||
void _handle_indentation_pop_from_block_seq();
|
||||
void _handle_indentation_pop_from_block_map();
|
||||
void _handle_indentation_pop(ParserState const* dst);
|
||||
|
||||
void _maybe_skip_comment();
|
||||
void _skip_comment();
|
||||
void _maybe_skip_whitespace_tokens();
|
||||
void _maybe_skipchars(char c);
|
||||
#ifdef RYML_NO_COVERAGE__TO_BE_DELETED
|
||||
void _maybe_skipchars_up_to(char c, size_t max_to_skip);
|
||||
#endif
|
||||
template<size_t N>
|
||||
void _skipchars(const char (&chars)[N]);
|
||||
bool _maybe_scan_following_colon() noexcept;
|
||||
bool _maybe_scan_following_comma() noexcept;
|
||||
|
||||
public:
|
||||
|
||||
/** @cond dev */
|
||||
template<class FilterProcessor> auto _filter_plain(FilterProcessor &C4_RESTRICT proc, size_t indentation) -> decltype(proc.result());
|
||||
template<class FilterProcessor> auto _filter_squoted(FilterProcessor &C4_RESTRICT proc) -> decltype(proc.result());
|
||||
template<class FilterProcessor> auto _filter_dquoted(FilterProcessor &C4_RESTRICT proc) -> decltype(proc.result());
|
||||
template<class FilterProcessor> auto _filter_block_literal(FilterProcessor &C4_RESTRICT proc, size_t indentation, BlockChomp_e chomp) -> decltype(proc.result());
|
||||
template<class FilterProcessor> auto _filter_block_folded(FilterProcessor &C4_RESTRICT proc, size_t indentation, BlockChomp_e chomp) -> decltype(proc.result());
|
||||
/** @endcond */
|
||||
|
||||
public:
|
||||
|
||||
/** @cond dev */
|
||||
template<class FilterProcessor> void _filter_nl_plain(FilterProcessor &C4_RESTRICT proc, size_t indentation);
|
||||
template<class FilterProcessor> void _filter_nl_squoted(FilterProcessor &C4_RESTRICT proc);
|
||||
template<class FilterProcessor> void _filter_nl_dquoted(FilterProcessor &C4_RESTRICT proc);
|
||||
|
||||
template<class FilterProcessor> bool _filter_ws_handle_to_first_non_space(FilterProcessor &C4_RESTRICT proc);
|
||||
template<class FilterProcessor> void _filter_ws_copy_trailing(FilterProcessor &C4_RESTRICT proc);
|
||||
template<class FilterProcessor> void _filter_ws_skip_trailing(FilterProcessor &C4_RESTRICT proc);
|
||||
|
||||
template<class FilterProcessor> void _filter_dquoted_backslash(FilterProcessor &C4_RESTRICT proc);
|
||||
|
||||
template<class FilterProcessor> void _filter_chomp(FilterProcessor &C4_RESTRICT proc, BlockChomp_e chomp, size_t indentation);
|
||||
template<class FilterProcessor> size_t _handle_all_whitespace(FilterProcessor &C4_RESTRICT proc, BlockChomp_e chomp);
|
||||
template<class FilterProcessor> size_t _extend_to_chomp(FilterProcessor &C4_RESTRICT proc, size_t contents_len);
|
||||
template<class FilterProcessor> void _filter_block_indentation(FilterProcessor &C4_RESTRICT proc, size_t indentation);
|
||||
template<class FilterProcessor> void _filter_block_folded_newlines(FilterProcessor &C4_RESTRICT proc, size_t indentation, size_t len);
|
||||
template<class FilterProcessor> size_t _filter_block_folded_newlines_compress(FilterProcessor &C4_RESTRICT proc, size_t num_newl, size_t wpos_at_first_newl);
|
||||
template<class FilterProcessor> void _filter_block_folded_newlines_leading(FilterProcessor &C4_RESTRICT proc, size_t indentation, size_t len);
|
||||
template<class FilterProcessor> void _filter_block_folded_indented_block(FilterProcessor &C4_RESTRICT proc, size_t indentation, size_t len, size_t curr_indentation) noexcept;
|
||||
|
||||
/** @endcond */
|
||||
|
||||
private:
|
||||
|
||||
void _line_progressed(size_t ahead);
|
||||
void _line_ended();
|
||||
void _line_ended_undo();
|
||||
|
||||
bool _finished_file() const;
|
||||
bool _finished_line() const;
|
||||
|
||||
void _scan_line();
|
||||
substr _peek_next_line(size_t pos=npos) const;
|
||||
|
||||
bool _at_line_begin() const
|
||||
{
|
||||
return m_evt_handler->m_curr->line_contents.rem.begin() == m_evt_handler->m_curr->line_contents.full.begin();
|
||||
}
|
||||
|
||||
void _relocate_arena(csubstr prev_arena, substr next_arena);
|
||||
static void _s_relocate_arena(void*, csubstr prev_arena, substr next_arena);
|
||||
|
||||
private:
|
||||
|
||||
C4_ALWAYS_INLINE bool has_all(ParserFlag_t f) const noexcept { return (m_evt_handler->m_curr->flags & f) == f; }
|
||||
C4_ALWAYS_INLINE bool has_any(ParserFlag_t f) const noexcept { return (m_evt_handler->m_curr->flags & f) != 0; }
|
||||
C4_ALWAYS_INLINE bool has_none(ParserFlag_t f) const noexcept { return (m_evt_handler->m_curr->flags & f) == 0; }
|
||||
static C4_ALWAYS_INLINE bool has_all(ParserFlag_t f, ParserState const* C4_RESTRICT s) noexcept { return (s->flags & f) == f; }
|
||||
static C4_ALWAYS_INLINE bool has_any(ParserFlag_t f, ParserState const* C4_RESTRICT s) noexcept { return (s->flags & f) != 0; }
|
||||
static C4_ALWAYS_INLINE bool has_none(ParserFlag_t f, ParserState const* C4_RESTRICT s) noexcept { return (s->flags & f) == 0; }
|
||||
|
||||
#ifndef RYML_DBG
|
||||
C4_ALWAYS_INLINE static void add_flags(ParserFlag_t on, ParserState *C4_RESTRICT s) noexcept { s->flags |= on; }
|
||||
C4_ALWAYS_INLINE static void addrem_flags(ParserFlag_t on, ParserFlag_t off, ParserState *C4_RESTRICT s) noexcept { s->flags &= ~off; s->flags |= on; }
|
||||
C4_ALWAYS_INLINE static void rem_flags(ParserFlag_t off, ParserState *C4_RESTRICT s) noexcept { s->flags &= ~off; }
|
||||
C4_ALWAYS_INLINE void add_flags(ParserFlag_t on) noexcept { m_evt_handler->m_curr->flags |= on; }
|
||||
C4_ALWAYS_INLINE void addrem_flags(ParserFlag_t on, ParserFlag_t off) noexcept { m_evt_handler->m_curr->flags &= ~off; m_evt_handler->m_curr->flags |= on; }
|
||||
C4_ALWAYS_INLINE void rem_flags(ParserFlag_t off) noexcept { m_evt_handler->m_curr->flags &= ~off; }
|
||||
#else
|
||||
static void add_flags(ParserFlag_t on, ParserState *C4_RESTRICT s);
|
||||
static void addrem_flags(ParserFlag_t on, ParserFlag_t off, ParserState *C4_RESTRICT s);
|
||||
static void rem_flags(ParserFlag_t off, ParserState *C4_RESTRICT s);
|
||||
C4_ALWAYS_INLINE void add_flags(ParserFlag_t on) noexcept { add_flags(on, m_evt_handler->m_curr); }
|
||||
C4_ALWAYS_INLINE void addrem_flags(ParserFlag_t on, ParserFlag_t off) noexcept { addrem_flags(on, off, m_evt_handler->m_curr); }
|
||||
C4_ALWAYS_INLINE void rem_flags(ParserFlag_t off) noexcept { rem_flags(off, m_evt_handler->m_curr); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
void _prepare_locations();
|
||||
void _resize_locations(size_t sz);
|
||||
bool _locations_dirty() const;
|
||||
|
||||
bool _location_from_cont(Tree const& tree, id_type node, Location *C4_RESTRICT loc) const;
|
||||
bool _location_from_node(Tree const& tree, id_type node, Location *C4_RESTRICT loc, id_type level) const;
|
||||
|
||||
private:
|
||||
|
||||
void _reset();
|
||||
void _free();
|
||||
void _clr();
|
||||
|
||||
#ifdef RYML_DBG
|
||||
template<class ...Args> void _dbg(csubstr fmt, Args const& C4_RESTRICT ...args) const;
|
||||
#endif
|
||||
template<class ...Args> void _err(csubstr fmt, Args const& C4_RESTRICT ...args) const;
|
||||
template<class ...Args> void _errloc(csubstr fmt, Location const& loc, Args const& C4_RESTRICT ...args) const;
|
||||
|
||||
template<class DumpFn> void _fmt_msg(DumpFn &&dumpfn) const;
|
||||
|
||||
private:
|
||||
|
||||
/** store pending tag or anchor/ref annotations */
|
||||
struct Annotation
|
||||
{
|
||||
struct Entry
|
||||
{
|
||||
csubstr str;
|
||||
size_t indentation;
|
||||
size_t line;
|
||||
};
|
||||
Entry annotations[2];
|
||||
size_t num_entries;
|
||||
};
|
||||
|
||||
void _handle_colon();
|
||||
void _add_annotation(Annotation *C4_RESTRICT dst, csubstr str, size_t indentation, size_t line);
|
||||
void _clear_annotations(Annotation *C4_RESTRICT dst);
|
||||
bool _has_pending_annotations() const { return m_pending_tags.num_entries || m_pending_anchors.num_entries; }
|
||||
#ifdef RYML_NO_COVERAGE__TO_BE_DELETED
|
||||
bool _handle_indentation_from_annotations();
|
||||
#endif
|
||||
bool _annotations_require_key_container() const;
|
||||
void _handle_annotations_before_blck_key_scalar();
|
||||
void _handle_annotations_before_blck_val_scalar();
|
||||
void _handle_annotations_before_start_mapblck(size_t current_line);
|
||||
void _handle_annotations_before_start_mapblck_as_key();
|
||||
void _handle_annotations_and_indentation_after_start_mapblck(size_t key_indentation, size_t key_line);
|
||||
size_t _select_indentation_from_annotations(size_t val_indentation, size_t val_line);
|
||||
void _handle_directive(csubstr rem);
|
||||
bool _handle_bom();
|
||||
void _handle_bom(Encoding_e enc);
|
||||
|
||||
void _check_tag(csubstr tag);
|
||||
|
||||
private:
|
||||
|
||||
ParserOptions m_options;
|
||||
|
||||
csubstr m_file;
|
||||
substr m_buf;
|
||||
|
||||
public:
|
||||
|
||||
/** @cond dev */
|
||||
EventHandler *C4_RESTRICT m_evt_handler; // NOLINT
|
||||
/** @endcond */
|
||||
|
||||
private:
|
||||
|
||||
Annotation m_pending_anchors;
|
||||
Annotation m_pending_tags;
|
||||
|
||||
bool m_was_inside_qmrk;
|
||||
bool m_doc_empty = true;
|
||||
size_t m_prev_colon = npos;
|
||||
|
||||
Encoding_e m_encoding = UTF8;
|
||||
|
||||
private:
|
||||
|
||||
size_t *m_newline_offsets;
|
||||
size_t m_newline_offsets_size;
|
||||
size_t m_newline_offsets_capacity;
|
||||
csubstr m_newline_offsets_buf;
|
||||
|
||||
};
|
||||
|
||||
/** @cond dev */
|
||||
RYML_EXPORT C4_NO_INLINE size_t _find_last_newline_and_larger_indentation(csubstr s, size_t indentation) noexcept;
|
||||
/** @endcond */
|
||||
|
||||
|
||||
/** Quickly inspect the source to estimate the number of nodes the
|
||||
* resulting tree is likely have. If a tree is empty before
|
||||
* parsing, considerable time will be spent growing it, so calling
|
||||
* this to reserve the tree size prior to parsing is likely to
|
||||
* result in a time gain. We encourage using this method before
|
||||
* parsing, but as always measure its impact in performance to
|
||||
* obtain a good trade-off.
|
||||
*
|
||||
* @note since this method is meant for optimizing performance, it
|
||||
* is approximate. The result may be actually smaller than the
|
||||
* resulting number of nodes, notably if the YAML uses implicit
|
||||
* maps as flow seq members as in `[these: are, individual:
|
||||
* maps]`. */
|
||||
RYML_EXPORT id_type estimate_tree_capacity(csubstr src); // NOLINT(readability-redundant-declaration)
|
||||
|
||||
/** @} */
|
||||
|
||||
} // namespace yml
|
||||
} // namespace c4
|
||||
|
||||
// NOLINTEND(hicpp-signed-bitwise)
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif /* _C4_YML_PARSE_ENGINE_HPP_ */
|
||||
212
3rdparty/rapidyaml/include/c4/yml/parser_state.hpp
vendored
Normal file
212
3rdparty/rapidyaml/include/c4/yml/parser_state.hpp
vendored
Normal file
@@ -0,0 +1,212 @@
|
||||
#ifndef _C4_YML_PARSER_STATE_HPP_
|
||||
#define _C4_YML_PARSER_STATE_HPP_
|
||||
|
||||
#ifndef _C4_YML_COMMON_HPP_
|
||||
#include "c4/yml/common.hpp"
|
||||
#endif
|
||||
|
||||
// NOLINTBEGIN(hicpp-signed-bitwise)
|
||||
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
/** data type for @ref ParserState_e */
|
||||
using ParserFlag_t = int;
|
||||
|
||||
/** Enumeration of the state flags for the parser */
|
||||
typedef enum : ParserFlag_t {
|
||||
RTOP = 0x01 << 0, ///< reading at top level
|
||||
RUNK = 0x01 << 1, ///< reading unknown state (when starting): must determine whether scalar, map or seq
|
||||
RMAP = 0x01 << 2, ///< reading a map
|
||||
RSEQ = 0x01 << 3, ///< reading a seq
|
||||
FLOW = 0x01 << 4, ///< reading is inside explicit flow chars: [] or {}
|
||||
BLCK = 0x01 << 5, ///< reading in block mode
|
||||
QMRK = 0x01 << 6, ///< reading an explicit key (`? key`)
|
||||
RKEY = 0x01 << 7, ///< reading a scalar as key
|
||||
RVAL = 0x01 << 9, ///< reading a scalar as val
|
||||
RKCL = 0x01 << 8, ///< reading the key colon (ie the : after the key in the map)
|
||||
RNXT = 0x01 << 10, ///< read next val or keyval
|
||||
SSCL = 0x01 << 11, ///< there's a stored scalar
|
||||
QSCL = 0x01 << 12, ///< stored scalar was quoted
|
||||
RSET = 0x01 << 13, ///< the (implicit) map being read is a !!set. @see https://yaml.org/type/set.html
|
||||
RDOC = 0x01 << 14, ///< reading a document
|
||||
NDOC = 0x01 << 15, ///< no document mode. a document has ended and another has not started yet.
|
||||
USTY = 0x01 << 16, ///< reading in unknown style mode - must determine FLOW or BLCK
|
||||
//! reading an implicit map nested in an explicit seq.
|
||||
//! eg, {key: [key2: value2, key3: value3]}
|
||||
//! is parsed as {key: [{key2: value2}, {key3: value3}]}
|
||||
RSEQIMAP = 0x01 << 17,
|
||||
} ParserState_e;
|
||||
|
||||
#ifdef RYML_DBG
|
||||
/** @cond dev */
|
||||
namespace detail {
|
||||
csubstr _parser_flags_to_str(substr buf, ParserFlag_t flags);
|
||||
} // namespace
|
||||
/** @endcond */
|
||||
#endif
|
||||
|
||||
|
||||
/** Helper to control the line contents while parsing a buffer */
|
||||
struct LineContents
|
||||
{
|
||||
substr rem; ///< the stripped line remainder; initially starts at the first non-space character
|
||||
size_t indentation; ///< the number of spaces on the beginning of the line
|
||||
substr full; ///< the full line, including newlines on the right
|
||||
substr stripped; ///< the stripped line, excluding newlines on the right
|
||||
|
||||
LineContents() = default;
|
||||
|
||||
void reset_with_next_line(substr buf, size_t offset)
|
||||
{
|
||||
RYML_ASSERT(offset <= buf.len);
|
||||
size_t e = offset;
|
||||
// get the current line stripped of newline chars
|
||||
while(e < buf.len && (buf.str[e] != '\n' && buf.str[e] != '\r'))
|
||||
++e;
|
||||
RYML_ASSERT(e >= offset);
|
||||
const substr stripped_ = buf.range(offset, e);
|
||||
#if defined(__GNUC__) && __GNUC__ == 11
|
||||
C4_DONT_OPTIMIZE(stripped_);
|
||||
#endif
|
||||
// advance pos to include the first line ending
|
||||
if(e < buf.len && buf.str[e] == '\r')
|
||||
++e;
|
||||
if(e < buf.len && buf.str[e] == '\n')
|
||||
++e;
|
||||
const substr full_ = buf.range(offset, e);
|
||||
reset(full_, stripped_);
|
||||
}
|
||||
|
||||
void reset(substr full_, substr stripped_)
|
||||
{
|
||||
rem = stripped_;
|
||||
indentation = stripped_.first_not_of(' '); // find the first column where the character is not a space
|
||||
full = full_;
|
||||
stripped = stripped_;
|
||||
}
|
||||
|
||||
C4_ALWAYS_INLINE size_t current_col() const RYML_NOEXCEPT
|
||||
{
|
||||
// WARNING: gcc x86 release builds were wrong (eg returning 0
|
||||
// when the result should be 4 ) when this function was like
|
||||
// this:
|
||||
//
|
||||
//return current_col(rem);
|
||||
//
|
||||
// (see below for the full definition of the called overload
|
||||
// of current_col())
|
||||
//
|
||||
// ... so we explicitly inline the code in here:
|
||||
RYML_ASSERT(rem.str >= full.str);
|
||||
size_t col = static_cast<size_t>(rem.str - full.str);
|
||||
return col;
|
||||
//
|
||||
// this was happening only on builds specifically with (gcc
|
||||
// AND x86 AND release); no other builds were having the
|
||||
// problem: not in debug, not in x64, not in other
|
||||
// architectures, not in clang, not in visual studio. WTF!?
|
||||
//
|
||||
// Enabling debug prints with RYML_DBG made the problem go
|
||||
// away, so these could not be used to debug the
|
||||
// problem. Adding prints inside the called current_col() also
|
||||
// made the problem go away! WTF!???
|
||||
//
|
||||
// a prize will be offered to anybody able to explain why this
|
||||
// was happening.
|
||||
}
|
||||
|
||||
C4_ALWAYS_INLINE size_t current_col(csubstr s) const RYML_NOEXCEPT
|
||||
{
|
||||
RYML_ASSERT(s.str >= full.str);
|
||||
RYML_ASSERT(full.is_super(s));
|
||||
size_t col = static_cast<size_t>(s.str - full.str);
|
||||
return col;
|
||||
}
|
||||
};
|
||||
static_assert(std::is_standard_layout<LineContents>::value, "LineContents not standard");
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
struct ParserState
|
||||
{
|
||||
LineContents line_contents;
|
||||
Location pos;
|
||||
ParserFlag_t flags;
|
||||
size_t indref; ///< the reference indentation in the current block scope
|
||||
id_type level;
|
||||
id_type node_id; ///< don't hold a pointer to the node as it will be relocated during tree resizes
|
||||
size_t scalar_col; // the column where the scalar (or its quotes) begin
|
||||
bool more_indented;
|
||||
bool has_children;
|
||||
|
||||
ParserState() = default;
|
||||
|
||||
void start_parse(const char *file, id_type node_id_)
|
||||
{
|
||||
level = 0;
|
||||
pos.name = to_csubstr(file);
|
||||
pos.offset = 0;
|
||||
pos.line = 1;
|
||||
pos.col = 1;
|
||||
node_id = node_id_;
|
||||
more_indented = false;
|
||||
scalar_col = 0;
|
||||
indref = 0;
|
||||
has_children = false;
|
||||
}
|
||||
|
||||
void reset_after_push()
|
||||
{
|
||||
node_id = NONE;
|
||||
indref = npos;
|
||||
more_indented = false;
|
||||
++level;
|
||||
has_children = false;
|
||||
}
|
||||
|
||||
C4_ALWAYS_INLINE void reset_before_pop(ParserState const& to_pop)
|
||||
{
|
||||
pos = to_pop.pos;
|
||||
line_contents = to_pop.line_contents;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
C4_ALWAYS_INLINE bool at_line_beginning() const noexcept
|
||||
{
|
||||
return line_contents.rem.str == line_contents.full.str;
|
||||
}
|
||||
C4_ALWAYS_INLINE bool indentation_eq() const noexcept
|
||||
{
|
||||
RYML_ASSERT(indref != npos);
|
||||
return line_contents.indentation != npos && line_contents.indentation == indref;
|
||||
}
|
||||
C4_ALWAYS_INLINE bool indentation_ge() const noexcept
|
||||
{
|
||||
RYML_ASSERT(indref != npos);
|
||||
return line_contents.indentation != npos && line_contents.indentation >= indref;
|
||||
}
|
||||
C4_ALWAYS_INLINE bool indentation_gt() const noexcept
|
||||
{
|
||||
RYML_ASSERT(indref != npos);
|
||||
return line_contents.indentation != npos && line_contents.indentation > indref;
|
||||
}
|
||||
C4_ALWAYS_INLINE bool indentation_lt() const noexcept
|
||||
{
|
||||
RYML_ASSERT(indref != npos);
|
||||
return line_contents.indentation != npos && line_contents.indentation < indref;
|
||||
}
|
||||
};
|
||||
static_assert(std::is_standard_layout<ParserState>::value, "ParserState not standard");
|
||||
|
||||
|
||||
} // namespace yml
|
||||
} // namespace c4
|
||||
|
||||
// NOLINTEND(hicpp-signed-bitwise)
|
||||
|
||||
#endif /* _C4_YML_PARSER_STATE_HPP_ */
|
||||
88
3rdparty/rapidyaml/include/c4/yml/reference_resolver.hpp
vendored
Normal file
88
3rdparty/rapidyaml/include/c4/yml/reference_resolver.hpp
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
#ifndef _C4_YML_REFERENCE_RESOLVER_HPP_
|
||||
#define _C4_YML_REFERENCE_RESOLVER_HPP_
|
||||
|
||||
#include "c4/yml/tree.hpp"
|
||||
#include "c4/yml/detail/stack.hpp"
|
||||
|
||||
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
/** @addtogroup doc_ref_utils
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Reusable object to resolve references/aliases in a @ref Tree. */
|
||||
struct RYML_EXPORT ReferenceResolver
|
||||
{
|
||||
ReferenceResolver() = default;
|
||||
|
||||
/** Resolve references: for each reference, look for a matching
|
||||
* anchor, and copy its contents to the ref node.
|
||||
*
|
||||
* @p tree the subject tree
|
||||
*
|
||||
* @p clear_anchors whether to clear existing anchors after
|
||||
* resolving
|
||||
*
|
||||
* This method first does a full traversal of the tree to gather
|
||||
* all anchors and references in a separate collection, then it
|
||||
* goes through that collection to locate the names, which it does
|
||||
* by obeying the YAML standard diktat that "an alias node refers
|
||||
* to the most recent node in the serialization having the
|
||||
* specified anchor"
|
||||
*
|
||||
* So, depending on the number of anchor/alias nodes, this is a
|
||||
* potentially expensive operation, with a best-case linear
|
||||
* complexity (from the initial traversal). This potential cost is
|
||||
* one of the reasons for requiring an explicit call.
|
||||
*
|
||||
* The @ref Tree has an `Tree::resolve()` overload set forwarding
|
||||
* here. Previously this operation was done there, using a
|
||||
* discarded object; using this separate class offers opportunity
|
||||
* for reuse of the object.
|
||||
*
|
||||
* @warning resolving references opens an attack vector when the
|
||||
* data is malicious or severely malformed, as the tree can expand
|
||||
* exponentially. See for example the [Billion Laughs
|
||||
* Attack](https://en.wikipedia.org/wiki/Billion_laughs_attack).
|
||||
*
|
||||
*/
|
||||
void resolve(Tree *tree, bool clear_anchors=true);
|
||||
|
||||
public:
|
||||
|
||||
/** @cond dev */
|
||||
|
||||
struct RefData
|
||||
{
|
||||
NodeType type;
|
||||
id_type node;
|
||||
id_type prev_anchor;
|
||||
id_type target;
|
||||
id_type parent_ref;
|
||||
id_type parent_ref_sibling;
|
||||
};
|
||||
|
||||
void reset_(Tree *t_);
|
||||
void resolve_();
|
||||
void gather_anchors_and_refs_();
|
||||
void gather_anchors_and_refs__(id_type n);
|
||||
id_type count_anchors_and_refs_(id_type n);
|
||||
|
||||
id_type lookup_(RefData const* C4_RESTRICT ra);
|
||||
|
||||
Tree *C4_RESTRICT m_tree;
|
||||
/** We're using this stack purely as an array. */
|
||||
detail::stack<RefData> m_refs;
|
||||
|
||||
/** @endcond */
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
} // namespace ryml
|
||||
} // namespace c4
|
||||
|
||||
|
||||
#endif // _C4_YML_REFERENCE_RESOLVER_HPP_
|
||||
@@ -25,16 +25,17 @@ void write(c4::yml::NodeRef *n, std::map<K, V, Less, Alloc> const& m)
|
||||
}
|
||||
}
|
||||
|
||||
/** read the node members, assigning into the existing map. If a key
|
||||
* is already present in the map, then its value will be
|
||||
* move-assigned. */
|
||||
template<class K, class V, class Less, class Alloc>
|
||||
bool read(c4::yml::ConstNodeRef const& n, std::map<K, V, Less, Alloc> * m)
|
||||
{
|
||||
K k{};
|
||||
V v{};
|
||||
for(auto const& C4_RESTRICT ch : n)
|
||||
{
|
||||
K k{};
|
||||
ch >> c4::yml::key(k);
|
||||
ch >> v;
|
||||
m->emplace(std::make_pair(std::move(k), std::move(v)));
|
||||
ch >> (*m)[k];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
24
3rdparty/rapidyaml/include/c4/yml/std/vector.hpp
vendored
24
3rdparty/rapidyaml/include/c4/yml/std/vector.hpp
vendored
@@ -17,31 +17,37 @@ template<class V, class Alloc>
|
||||
void write(c4::yml::NodeRef *n, std::vector<V, Alloc> const& vec)
|
||||
{
|
||||
*n |= c4::yml::SEQ;
|
||||
for(auto const& v : vec)
|
||||
for(V const& v : vec)
|
||||
n->append_child() << v;
|
||||
}
|
||||
|
||||
/** read the node members, overwriting existing vector entries. */
|
||||
template<class V, class Alloc>
|
||||
bool read(c4::yml::ConstNodeRef const& n, std::vector<V, Alloc> *vec)
|
||||
{
|
||||
vec->resize(n.num_children());
|
||||
C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wuseless-cast")
|
||||
vec->resize(static_cast<size_t>(n.num_children()));
|
||||
C4_SUPPRESS_WARNING_GCC_POP
|
||||
size_t pos = 0;
|
||||
for(auto const ch : n)
|
||||
ch >> (*vec)[pos++];
|
||||
for(ConstNodeRef const child : n)
|
||||
child >> (*vec)[pos++];
|
||||
return true;
|
||||
}
|
||||
|
||||
/** specialization: std::vector<bool> uses std::vector<bool>::reference as
|
||||
/** read the node members, overwriting existing vector entries.
|
||||
* specialization: std::vector<bool> uses std::vector<bool>::reference as
|
||||
* the return value of its operator[]. */
|
||||
template<class Alloc>
|
||||
bool read(c4::yml::ConstNodeRef const& n, std::vector<bool, Alloc> *vec)
|
||||
{
|
||||
vec->resize(n.num_children());
|
||||
C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wuseless-cast")
|
||||
vec->resize(static_cast<size_t>(n.num_children()));
|
||||
C4_SUPPRESS_WARNING_GCC_POP
|
||||
size_t pos = 0;
|
||||
bool tmp = false;
|
||||
for(auto const ch : n)
|
||||
bool tmp = {};
|
||||
for(ConstNodeRef const child : n)
|
||||
{
|
||||
ch >> tmp;
|
||||
child >> tmp;
|
||||
(*vec)[pos++] = tmp;
|
||||
}
|
||||
return true;
|
||||
|
||||
84
3rdparty/rapidyaml/include/c4/yml/tag.hpp
vendored
Normal file
84
3rdparty/rapidyaml/include/c4/yml/tag.hpp
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
#ifndef _C4_YML_TAG_HPP_
|
||||
#define _C4_YML_TAG_HPP_
|
||||
|
||||
#include <c4/yml/common.hpp>
|
||||
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
class Tree;
|
||||
|
||||
/** @addtogroup doc_tag_utils
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
#ifndef RYML_MAX_TAG_DIRECTIVES
|
||||
/** the maximum number of tag directives in a Tree */
|
||||
#define RYML_MAX_TAG_DIRECTIVES 4
|
||||
#endif
|
||||
|
||||
/** the integral type necessary to cover all the bits marking node tags */
|
||||
using tag_bits = uint16_t;
|
||||
|
||||
/** a bit mask for marking tags for types */
|
||||
typedef enum : tag_bits {
|
||||
TAG_NONE = 0,
|
||||
// container types
|
||||
TAG_MAP = 1, /**< !!map Unordered set of key: value pairs without duplicates. @see https://yaml.org/type/map.html */
|
||||
TAG_OMAP = 2, /**< !!omap Ordered sequence of key: value pairs without duplicates. @see https://yaml.org/type/omap.html */
|
||||
TAG_PAIRS = 3, /**< !!pairs Ordered sequence of key: value pairs allowing duplicates. @see https://yaml.org/type/pairs.html */
|
||||
TAG_SET = 4, /**< !!set Unordered set of non-equal values. @see https://yaml.org/type/set.html */
|
||||
TAG_SEQ = 5, /**< !!seq Sequence of arbitrary values. @see https://yaml.org/type/seq.html */
|
||||
// scalar types
|
||||
TAG_BINARY = 6, /**< !!binary A sequence of zero or more octets (8 bit values). @see https://yaml.org/type/binary.html */
|
||||
TAG_BOOL = 7, /**< !!bool Mathematical Booleans. @see https://yaml.org/type/bool.html */
|
||||
TAG_FLOAT = 8, /**< !!float Floating-point approximation to real numbers. https://yaml.org/type/float.html */
|
||||
TAG_INT = 9, /**< !!float Mathematical integers. https://yaml.org/type/int.html */
|
||||
TAG_MERGE = 10, /**< !!merge Specify one or more mapping to be merged with the current one. https://yaml.org/type/merge.html */
|
||||
TAG_NULL = 11, /**< !!null Devoid of value. https://yaml.org/type/null.html */
|
||||
TAG_STR = 12, /**< !!str A sequence of zero or more Unicode characters. https://yaml.org/type/str.html */
|
||||
TAG_TIMESTAMP = 13, /**< !!timestamp A point in time https://yaml.org/type/timestamp.html */
|
||||
TAG_VALUE = 14, /**< !!value Specify the default value of a mapping https://yaml.org/type/value.html */
|
||||
TAG_YAML = 15, /**< !!yaml Specify the default value of a mapping https://yaml.org/type/yaml.html */
|
||||
} YamlTag_e;
|
||||
|
||||
RYML_EXPORT YamlTag_e to_tag(csubstr tag);
|
||||
RYML_EXPORT csubstr from_tag(YamlTag_e tag);
|
||||
RYML_EXPORT csubstr from_tag_long(YamlTag_e tag);
|
||||
RYML_EXPORT csubstr normalize_tag(csubstr tag);
|
||||
RYML_EXPORT csubstr normalize_tag_long(csubstr tag);
|
||||
RYML_EXPORT csubstr normalize_tag_long(csubstr tag, substr output);
|
||||
|
||||
RYML_EXPORT bool is_custom_tag(csubstr tag);
|
||||
|
||||
|
||||
struct RYML_EXPORT TagDirective
|
||||
{
|
||||
/** Eg <pre>!e!</pre> in <pre>%TAG !e! tag:example.com,2000:app/</pre> */
|
||||
csubstr handle;
|
||||
/** Eg <pre>tag:example.com,2000:app/</pre> in <pre>%TAG !e! tag:example.com,2000:app/</pre> */
|
||||
csubstr prefix;
|
||||
/** The next node to which this tag directive applies */
|
||||
id_type next_node_id;
|
||||
|
||||
bool create_from_str(csubstr directive_); ///< leaves next_node_id unfilled
|
||||
bool create_from_str(csubstr directive_, Tree *tree);
|
||||
size_t transform(csubstr tag, substr output, Callbacks const& callbacks) const;
|
||||
};
|
||||
|
||||
struct RYML_EXPORT TagDirectiveRange
|
||||
{
|
||||
TagDirective const* C4_RESTRICT b;
|
||||
TagDirective const* C4_RESTRICT e;
|
||||
C4_ALWAYS_INLINE TagDirective const* begin() const noexcept { return b; }
|
||||
C4_ALWAYS_INLINE TagDirective const* end() const noexcept { return e; }
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
} // namespace yml
|
||||
} // namespace c4
|
||||
|
||||
#endif /* _C4_YML_TAG_HPP_ */
|
||||
1136
3rdparty/rapidyaml/include/c4/yml/tree.hpp
vendored
1136
3rdparty/rapidyaml/include/c4/yml/tree.hpp
vendored
File diff suppressed because it is too large
Load Diff
25
3rdparty/rapidyaml/include/c4/yml/version.hpp
vendored
Normal file
25
3rdparty/rapidyaml/include/c4/yml/version.hpp
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef _C4_YML_VERSION_HPP_
|
||||
#define _C4_YML_VERSION_HPP_
|
||||
|
||||
/** @file version.hpp */
|
||||
|
||||
#define RYML_VERSION "0.9.0"
|
||||
#define RYML_VERSION_MAJOR 0
|
||||
#define RYML_VERSION_MINOR 9
|
||||
#define RYML_VERSION_PATCH 0
|
||||
|
||||
#include <c4/substr.hpp>
|
||||
#include <c4/yml/export.hpp>
|
||||
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
RYML_EXPORT csubstr version();
|
||||
RYML_EXPORT int version_major();
|
||||
RYML_EXPORT int version_minor();
|
||||
RYML_EXPORT int version_patch();
|
||||
|
||||
} // namespace yml
|
||||
} // namespace c4
|
||||
|
||||
#endif /* _C4_YML_VERSION_HPP_ */
|
||||
135
3rdparty/rapidyaml/include/c4/yml/writer.hpp
vendored
135
3rdparty/rapidyaml/include/c4/yml/writer.hpp
vendored
@@ -23,18 +23,6 @@ namespace yml {
|
||||
*/
|
||||
|
||||
|
||||
/** Repeat-Character: a character to be written a number of times. */
|
||||
struct RepC
|
||||
{
|
||||
char c;
|
||||
size_t num_times;
|
||||
};
|
||||
inline RepC indent_to(size_t num_levels)
|
||||
{
|
||||
return {' ', size_t(2) * num_levels};
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -46,7 +34,7 @@ struct WriterFile
|
||||
|
||||
WriterFile(FILE *f = nullptr) : m_file(f ? f : stdout), m_pos(0) {}
|
||||
|
||||
inline substr _get(bool /*error_on_excess*/)
|
||||
substr _get(bool /*error_on_excess*/) const
|
||||
{
|
||||
substr sp;
|
||||
sp.str = nullptr;
|
||||
@@ -55,44 +43,33 @@ struct WriterFile
|
||||
}
|
||||
|
||||
template<size_t N>
|
||||
inline void _do_write(const char (&a)[N])
|
||||
void _do_write(const char (&a)[N])
|
||||
{
|
||||
fwrite(a, sizeof(char), N - 1, m_file);
|
||||
(void)fwrite(a, sizeof(char), N - 1, m_file);
|
||||
m_pos += N - 1;
|
||||
}
|
||||
|
||||
inline void _do_write(csubstr sp)
|
||||
void _do_write(csubstr sp)
|
||||
{
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#elif defined(__GNUC__)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
if(sp.empty()) return;
|
||||
fwrite(sp.str, sizeof(csubstr::char_type), sp.len, m_file);
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wsign-conversion")
|
||||
if(sp.empty())
|
||||
return;
|
||||
(void)fwrite(sp.str, sizeof(csubstr::char_type), sp.len, m_file);
|
||||
m_pos += sp.len;
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_POP
|
||||
}
|
||||
|
||||
inline void _do_write(const char c)
|
||||
void _do_write(const char c)
|
||||
{
|
||||
fputc(c, m_file);
|
||||
(void)fputc(c, m_file);
|
||||
++m_pos;
|
||||
}
|
||||
|
||||
inline void _do_write(RepC const rc)
|
||||
void _do_write(const char c, size_t num_times)
|
||||
{
|
||||
for(size_t i = 0; i < rc.num_times; ++i)
|
||||
{
|
||||
fputc(rc.c, m_file);
|
||||
}
|
||||
m_pos += rc.num_times;
|
||||
for(size_t i = 0; i < num_times; ++i)
|
||||
(void)fputc(c, m_file);
|
||||
m_pos += num_times;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -104,12 +81,12 @@ struct WriterFile
|
||||
template<class OStream>
|
||||
struct WriterOStream
|
||||
{
|
||||
OStream& m_stream;
|
||||
OStream* m_stream;
|
||||
size_t m_pos;
|
||||
|
||||
WriterOStream(OStream &s) : m_stream(s), m_pos(0) {}
|
||||
WriterOStream(OStream &s) : m_stream(&s), m_pos(0) {}
|
||||
|
||||
inline substr _get(bool /*error_on_excess*/)
|
||||
substr _get(bool /*error_on_excess*/) const
|
||||
{
|
||||
substr sp;
|
||||
sp.str = nullptr;
|
||||
@@ -118,44 +95,33 @@ struct WriterOStream
|
||||
}
|
||||
|
||||
template<size_t N>
|
||||
inline void _do_write(const char (&a)[N])
|
||||
void _do_write(const char (&a)[N])
|
||||
{
|
||||
m_stream.write(a, N - 1);
|
||||
m_stream->write(a, N - 1);
|
||||
m_pos += N - 1;
|
||||
}
|
||||
|
||||
inline void _do_write(csubstr sp)
|
||||
void _do_write(csubstr sp)
|
||||
{
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#elif defined(__GNUC__)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
if(sp.empty()) return;
|
||||
m_stream.write(sp.str, sp.len);
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wsign-conversion")
|
||||
if(sp.empty())
|
||||
return;
|
||||
m_stream->write(sp.str, sp.len);
|
||||
m_pos += sp.len;
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_POP
|
||||
}
|
||||
|
||||
inline void _do_write(const char c)
|
||||
void _do_write(const char c)
|
||||
{
|
||||
m_stream.put(c);
|
||||
m_stream->put(c);
|
||||
++m_pos;
|
||||
}
|
||||
|
||||
inline void _do_write(RepC const rc)
|
||||
void _do_write(const char c, size_t num_times)
|
||||
{
|
||||
for(size_t i = 0; i < rc.num_times; ++i)
|
||||
{
|
||||
m_stream.put(rc.c);
|
||||
}
|
||||
m_pos += rc.num_times;
|
||||
for(size_t i = 0; i < num_times; ++i)
|
||||
m_stream->put(c);
|
||||
m_pos += num_times;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -171,16 +137,12 @@ struct WriterBuf
|
||||
|
||||
WriterBuf(substr sp) : m_buf(sp), m_pos(0) {}
|
||||
|
||||
inline substr _get(bool error_on_excess)
|
||||
substr _get(bool error_on_excess) const
|
||||
{
|
||||
if(m_pos <= m_buf.len)
|
||||
{
|
||||
return m_buf.first(m_pos);
|
||||
}
|
||||
if(error_on_excess)
|
||||
{
|
||||
else if(error_on_excess)
|
||||
c4::yml::error("not enough space in the given buffer");
|
||||
}
|
||||
substr sp;
|
||||
sp.str = nullptr;
|
||||
sp.len = m_pos;
|
||||
@@ -188,46 +150,37 @@ struct WriterBuf
|
||||
}
|
||||
|
||||
template<size_t N>
|
||||
inline void _do_write(const char (&a)[N])
|
||||
void _do_write(const char (&a)[N])
|
||||
{
|
||||
RYML_ASSERT( ! m_buf.overlaps(a));
|
||||
if(m_pos + N-1 <= m_buf.len)
|
||||
{
|
||||
memcpy(&(m_buf[m_pos]), a, N-1);
|
||||
}
|
||||
m_pos += N-1;
|
||||
}
|
||||
|
||||
inline void _do_write(csubstr sp)
|
||||
void _do_write(csubstr sp)
|
||||
{
|
||||
if(sp.empty()) return;
|
||||
if(sp.empty())
|
||||
return;
|
||||
RYML_ASSERT( ! sp.overlaps(m_buf));
|
||||
if(m_pos + sp.len <= m_buf.len)
|
||||
{
|
||||
memcpy(&(m_buf[m_pos]), sp.str, sp.len);
|
||||
}
|
||||
m_pos += sp.len;
|
||||
}
|
||||
|
||||
inline void _do_write(const char c)
|
||||
void _do_write(const char c)
|
||||
{
|
||||
if(m_pos + 1 <= m_buf.len)
|
||||
{
|
||||
m_buf[m_pos] = c;
|
||||
}
|
||||
++m_pos;
|
||||
}
|
||||
|
||||
inline void _do_write(RepC const rc)
|
||||
void _do_write(const char c, size_t num_times)
|
||||
{
|
||||
if(m_pos + rc.num_times <= m_buf.len)
|
||||
{
|
||||
for(size_t i = 0; i < rc.num_times; ++i)
|
||||
{
|
||||
m_buf[m_pos + i] = rc.c;
|
||||
}
|
||||
}
|
||||
m_pos += rc.num_times;
|
||||
if(m_pos + num_times <= m_buf.len)
|
||||
for(size_t i = 0; i < num_times; ++i)
|
||||
m_buf[m_pos + i] = c;
|
||||
m_pos += num_times;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
6
3rdparty/rapidyaml/include/c4/yml/yml.hpp
vendored
6
3rdparty/rapidyaml/include/c4/yml/yml.hpp
vendored
@@ -1,10 +1,16 @@
|
||||
#ifndef _C4_YML_YML_HPP_
|
||||
#define _C4_YML_YML_HPP_
|
||||
|
||||
#include "c4/yml/version.hpp"
|
||||
#include "c4/yml/tree.hpp"
|
||||
#include "c4/yml/node.hpp"
|
||||
#include "c4/yml/emit.hpp"
|
||||
#include "c4/yml/event_handler_tree.hpp"
|
||||
#include "c4/yml/parse_engine.hpp"
|
||||
#include "c4/yml/filter_processor.hpp"
|
||||
#include "c4/yml/parse.hpp"
|
||||
#include "c4/yml/preprocess.hpp"
|
||||
#include "c4/yml/reference_resolver.hpp"
|
||||
#include "c4/yml/tag.hpp"
|
||||
|
||||
#endif // _C4_YML_YML_HPP_
|
||||
|
||||
97
3rdparty/rapidyaml/include/ryml.natvis
vendored
97
3rdparty/rapidyaml/include/ryml.natvis
vendored
@@ -25,12 +25,24 @@ See also:
|
||||
</Type>
|
||||
|
||||
<Type Name="c4::yml::NodeType">
|
||||
<DisplayString>{type}</DisplayString>
|
||||
<DisplayString Condition="((type & c4::yml::KEY ) == c4::yml::KEY) && ((type & c4::yml::VAL) == c4::yml::VAL)">[KEYVAL]</DisplayString>
|
||||
<DisplayString Condition="((type & c4::yml::KEY ) == c4::yml::KEY) && ((type & c4::yml::SEQ) == c4::yml::SEQ)">[KEYSEQ]</DisplayString>
|
||||
<DisplayString Condition="((type & c4::yml::KEY ) == c4::yml::KEY) && ((type & c4::yml::MAP) == c4::yml::MAP)">[KEYMAP]</DisplayString>
|
||||
<DisplayString Condition="((type & c4::yml::DOC ) == c4::yml::DOC) && ((type & c4::yml::VAL) == c4::yml::VAL)">[DOCVAL]</DisplayString>
|
||||
<DisplayString Condition="((type & c4::yml::DOC ) == c4::yml::DOC) && ((type & c4::yml::SEQ) == c4::yml::SEQ)">[DOCSEQ]</DisplayString>
|
||||
<DisplayString Condition="((type & c4::yml::DOC ) == c4::yml::DOC) && ((type & c4::yml::MAP) == c4::yml::MAP)">[DOCMAP]</DisplayString>
|
||||
<DisplayString Condition="(type & c4::yml::VAL ) == c4::yml::VAL" >[VAL]</DisplayString>
|
||||
<DisplayString Condition="(type & c4::yml::KEY ) == c4::yml::KEY" >[KEY]</DisplayString>
|
||||
<DisplayString Condition="(type & c4::yml::SEQ ) == c4::yml::SEQ" >[SEQ]</DisplayString>
|
||||
<DisplayString Condition="(type & c4::yml::MAP ) == c4::yml::MAP" >[MAP]</DisplayString>
|
||||
<DisplayString Condition="(type & c4::yml::DOC ) == c4::yml::DOC" >[DOC]</DisplayString>
|
||||
<DisplayString Condition="(type & c4::yml::STREAM) == c4::yml::STREAM">[STREAM]</DisplayString>
|
||||
<DisplayString Condition="(type & c4::yml::NOTYPE) == c4::yml::NOTYPE">[NOTYPE]</DisplayString>
|
||||
<Expand>
|
||||
<Synthetic Name="[enabled bits]">
|
||||
<Synthetic Name="[type bits]">
|
||||
<Expand>
|
||||
<Item Name="[0]" Condition="(type & c4::yml::VAL) != 0">c4::yml::VAL</Item>
|
||||
<Item Name="[1]" Condition="(type & c4::yml::KEY) != 0">c4::yml::KEY</Item>
|
||||
<Item Name="[0]" Condition="(type & c4::yml::KEY) != 0">c4::yml::KEY</Item>
|
||||
<Item Name="[1]" Condition="(type & c4::yml::VAL) != 0">c4::yml::VAL</Item>
|
||||
<Item Name="[2]" Condition="(type & c4::yml::MAP) != 0">c4::yml::MAP</Item>
|
||||
<Item Name="[3]" Condition="(type & c4::yml::SEQ) != 0">c4::yml::SEQ</Item>
|
||||
<Item Name="[4]" Condition="(type & c4::yml::DOC) != 0">c4::yml::DOC</Item>
|
||||
@@ -41,8 +53,25 @@ See also:
|
||||
<Item Name="[9]" Condition="(type & c4::yml::VALANCH) != 0">c4::yml::VALANCH</Item>
|
||||
<Item Name="[10]" Condition="(type & c4::yml::KEYTAG) != 0">c4::yml::KEYTAG</Item>
|
||||
<Item Name="[11]" Condition="(type & c4::yml::VALTAG) != 0">c4::yml::VALTAG</Item>
|
||||
<Item Name="[12]" Condition="(type & c4::yml::VALQUO) != 0">c4::yml::VALQUO</Item>
|
||||
<Item Name="[13]" Condition="(type & c4::yml::KEYQUO) != 0">c4::yml::KEYQUO</Item>
|
||||
</Expand>
|
||||
</Synthetic>
|
||||
<Synthetic Name="[style bits]">
|
||||
<Expand>
|
||||
<Item Name="[0]" Condition="(type & c4::yml::_WIP_KEY_UNFILT) != 0">c4::yml::_WIP_KEY_UNFILT</Item>
|
||||
<Item Name="[1]" Condition="(type & c4::yml::_WIP_VAL_UNFILT) != 0">c4::yml::_WIP_VAL_UNFILT</Item>
|
||||
<Item Name="[2]" Condition="(type & c4::yml::_WIP_STYLE_FLOW_SL) != 0">c4::yml::_WIP_STYLE_FLOW</Item>
|
||||
<Item Name="[3]" Condition="(type & c4::yml::_WIP_STYLE_FLOW_ML) != 0">c4::yml::_WIP_STYLE_FLOW</Item>
|
||||
<Item Name="[4]" Condition="(type & c4::yml::_WIP_STYLE_BLOCK) != 0">c4::yml::_WIP_STYLE_BLOCK</Item>
|
||||
<Item Name="[5]" Condition="(type & c4::yml::_WIP_KEY_LITERAL) != 0">c4::yml::_WIP_KEY_LITERAL</Item>
|
||||
<Item Name="[6]" Condition="(type & c4::yml::_WIP_VAL_LITERAL) != 0">c4::yml::_WIP_VAL_LITERAL</Item>
|
||||
<Item Name="[7]" Condition="(type & c4::yml::_WIP_KEY_FOLDED) != 0">c4::yml::_WIP_KEY_FOLDED</Item>
|
||||
<Item Name="[8]" Condition="(type & c4::yml::_WIP_VAL_FOLDED) != 0">c4::yml::_WIP_VAL_FOLDED</Item>
|
||||
<Item Name="[9]" Condition="(type & c4::yml::_WIP_KEY_SQUO) != 0">c4::yml::_WIP_KEY_SQUO</Item>
|
||||
<Item Name="[10]" Condition="(type & c4::yml::_WIP_VAL_SQUO) != 0">c4::yml::_WIP_VAL_SQUO</Item>
|
||||
<Item Name="[11]" Condition="(type & c4::yml::_WIP_KEY_DQUO) != 0">c4::yml::_WIP_KEY_DQUO</Item>
|
||||
<Item Name="[12]" Condition="(type & c4::yml::_WIP_VAL_DQUO) != 0">c4::yml::_WIP_VAL_DQUO</Item>
|
||||
<Item Name="[13]" Condition="(type & c4::yml::_WIP_KEY_PLAIN) != 0">c4::yml::_WIP_KEY_PLAIN</Item>
|
||||
<Item Name="[14]" Condition="(type & c4::yml::_WIP_VAL_PLAIN) != 0">c4::yml::_WIP_VAL_PLAIN</Item>
|
||||
</Expand>
|
||||
</Synthetic>
|
||||
</Expand>
|
||||
@@ -216,4 +245,60 @@ See also:
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="c4::yml::detail::FilterProcessorSrcDst">
|
||||
<DisplayString>src={src.str,[rpos]} dst={dst.str,[wpos]}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[src]">src</Item>
|
||||
<Item Name="[dst]">dst</Item>
|
||||
<Item Name="[rpos]">rpos</Item>
|
||||
<Item Name="[wpos]">wpos</Item>
|
||||
<Synthetic Name="[read]">
|
||||
<StringView>src.str,[rpos]</StringView>
|
||||
<Expand>
|
||||
<ArrayItems>
|
||||
<Size>rpos</Size>
|
||||
<ValuePointer>src.str</ValuePointer>
|
||||
</ArrayItems>
|
||||
</Expand>
|
||||
</Synthetic>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="c4::yml::detail::FilterProcessorInplace">
|
||||
<DisplayString>src={src.str,[rpos]} dst={src.str,[wpos]}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[rpos]">rpos</Item>
|
||||
<Item Name="[wpos]">wpos</Item>
|
||||
<Item Name="[wcap]">wcap</Item>
|
||||
<Synthetic Name="[buf]">
|
||||
<StringView>src.str,[wcap]</StringView>
|
||||
<Expand>
|
||||
<ArrayItems>
|
||||
<Size>wcap</Size>
|
||||
<ValuePointer>src.str</ValuePointer>
|
||||
</ArrayItems>
|
||||
</Expand>
|
||||
</Synthetic>
|
||||
<Item Name="[src]">src</Item>
|
||||
<Synthetic Name="[to be read]">
|
||||
<StringView>src.str+rpos,[src.len-rpos]</StringView>
|
||||
<Expand>
|
||||
<ArrayItems><Size>src.len-rpos</Size><ValuePointer>src.str+rpos</ValuePointer></ArrayItems>
|
||||
</Expand>
|
||||
</Synthetic>
|
||||
<Synthetic Name="[read]">
|
||||
<StringView>src.str,[rpos]</StringView>
|
||||
<Expand>
|
||||
<ArrayItems><Size>rpos</Size><ValuePointer>src.str</ValuePointer></ArrayItems>
|
||||
</Expand>
|
||||
</Synthetic>
|
||||
<Synthetic Name="[written]">
|
||||
<StringView>src.str,[wpos]</StringView>
|
||||
<Expand>
|
||||
<ArrayItems><Size>wpos</Size><ValuePointer>src.str</ValuePointer></ArrayItems>
|
||||
</Expand>
|
||||
</Synthetic>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
</AutoVisualizer>
|
||||
|
||||
15
3rdparty/rapidyaml/rapidyaml.vcxproj
vendored
15
3rdparty/rapidyaml/rapidyaml.vcxproj
vendored
@@ -95,8 +95,19 @@
|
||||
<ClInclude Include="include\c4\yml\std\std.hpp" />
|
||||
<ClInclude Include="include\c4\yml\std\string.hpp" />
|
||||
<ClInclude Include="include\c4\yml\std\vector.hpp" />
|
||||
<ClInclude Include="include\c4\yml\tag.hpp" />
|
||||
<ClInclude Include="include\c4\yml\version.hpp" />
|
||||
<ClInclude Include="include\c4\yml\tree.hpp" />
|
||||
<ClInclude Include="include\c4\yml\writer.hpp" />
|
||||
<ClInclude Include="include\c4\yml\event_handler_stack.hpp" />
|
||||
<ClInclude Include="include\c4\yml\event_handler_tree.hpp" />
|
||||
<ClInclude Include="include\c4\yml\filter_processor.hpp" />
|
||||
<ClInclude Include="include\c4\yml\fwd.hpp" />
|
||||
<ClInclude Include="include\c4\yml\node_type.hpp" />
|
||||
<ClInclude Include="include\c4\yml\parse_engine.def.hpp" />
|
||||
<ClInclude Include="include\c4\yml\parse_engine.hpp" />
|
||||
<ClInclude Include="include\c4\yml\parser_state.hpp" />
|
||||
<ClInclude Include="include\c4\yml\reference_resolver.hpp" />
|
||||
<ClInclude Include="include\c4\yml\yml.hpp" />
|
||||
<ClInclude Include="include\ryml.hpp" />
|
||||
<ClInclude Include="include\ryml_std.hpp" />
|
||||
@@ -117,6 +128,10 @@
|
||||
<ClCompile Include="src\c4\yml\parse.cpp" />
|
||||
<ClCompile Include="src\c4\yml\preprocess.cpp" />
|
||||
<ClCompile Include="src\c4\yml\tree.cpp" />
|
||||
<ClCompile Include="src\c4\yml\node_type.cpp" />
|
||||
<ClCompile Include="src\c4\yml\reference_resolver.cpp" />
|
||||
<ClCompile Include="src\c4\yml\tag.cpp" />
|
||||
<ClCompile Include="src\c4\yml\version.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
||||
13
3rdparty/rapidyaml/src/c4/base64.cpp
vendored
13
3rdparty/rapidyaml/src/c4/base64.cpp
vendored
@@ -6,11 +6,14 @@
|
||||
# pragma clang diagnostic ignored "-Wold-style-cast"
|
||||
#elif defined(__GNUC__)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wuseless-cast"
|
||||
# pragma GCC diagnostic ignored "-Wchar-subscripts"
|
||||
# pragma GCC diagnostic ignored "-Wtype-limits"
|
||||
# pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#endif
|
||||
|
||||
// NOLINTBEGIN(bugprone-signed-char-misuse,cert-str34-c,hicpp-signed-bitwise)
|
||||
|
||||
namespace c4 {
|
||||
|
||||
namespace detail {
|
||||
@@ -78,7 +81,7 @@ void base64_test_tables()
|
||||
for(size_t i = 0; i < C4_COUNTOF(detail::base64_sextet_to_char_); ++i)
|
||||
{
|
||||
char s2c = base64_sextet_to_char_[i];
|
||||
char c2s = base64_char_to_sextet_[(int)s2c];
|
||||
char c2s = base64_char_to_sextet_[(unsigned)s2c];
|
||||
C4_CHECK((size_t)c2s == i);
|
||||
}
|
||||
for(size_t i = 0; i < C4_COUNTOF(detail::base64_char_to_sextet_); ++i)
|
||||
@@ -86,7 +89,7 @@ void base64_test_tables()
|
||||
char c2s = base64_char_to_sextet_[i];
|
||||
if(c2s == char(-1))
|
||||
continue;
|
||||
char s2c = base64_sextet_to_char_[(int)c2s];
|
||||
char s2c = base64_sextet_to_char_[(unsigned)c2s];
|
||||
C4_CHECK((size_t)s2c == i);
|
||||
}
|
||||
}
|
||||
@@ -96,7 +99,7 @@ void base64_test_tables()
|
||||
|
||||
bool base64_valid(csubstr encoded)
|
||||
{
|
||||
if(encoded.len & 3u) // (encoded.len % 4u)
|
||||
if((encoded.len & size_t(3u)) != size_t(0)) // (encoded.len % 4u)
|
||||
return false;
|
||||
for(const char c : encoded)
|
||||
{
|
||||
@@ -159,7 +162,7 @@ size_t base64_decode(csubstr encoded, blob data)
|
||||
#define c4append_(c) { if(wpos < data.len) { data.buf[wpos] = static_cast<c4::byte>(c); } ++wpos; }
|
||||
#define c4appendval_(c, shift)\
|
||||
{\
|
||||
C4_XASSERT(c >= 0);\
|
||||
C4_XASSERT((c) >= 0);\
|
||||
C4_XASSERT(size_t(c) < sizeof(detail::base64_char_to_sextet_));\
|
||||
val |= static_cast<uint32_t>(detail::base64_char_to_sextet_[(c)]) << ((shift) * 6);\
|
||||
}
|
||||
@@ -214,6 +217,8 @@ size_t base64_decode(csubstr encoded, blob data)
|
||||
|
||||
} // namespace c4
|
||||
|
||||
// NOLINTEND(bugprone-signed-char-misuse,cert-str34-c,hicpp-signed-bitwise)
|
||||
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
|
||||
80
3rdparty/rapidyaml/src/c4/error.cpp
vendored
80
3rdparty/rapidyaml/src/c4/error.cpp
vendored
@@ -4,9 +4,9 @@
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define C4_LOGF_ERR(...) fprintf(stderr, __VA_ARGS__); fflush(stderr)
|
||||
#define C4_LOGF_WARN(...) fprintf(stderr, __VA_ARGS__); fflush(stderr)
|
||||
#define C4_LOGP(msg, ...) printf(msg)
|
||||
#define C4_LOGF_ERR(...) (void)fprintf(stderr, __VA_ARGS__); (void)fflush(stderr)
|
||||
#define C4_LOGF_WARN(...) (void)fprintf(stderr, __VA_ARGS__); (void)fflush(stderr)
|
||||
#define C4_LOGP(msg, ...) (void)printf(msg)
|
||||
|
||||
#if defined(C4_XBOX) || (defined(C4_WIN) && defined(C4_MSVC))
|
||||
# include "c4/windows.hpp"
|
||||
@@ -41,6 +41,7 @@
|
||||
# pragma GCC diagnostic ignored "-Wformat-nonliteral"
|
||||
# pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#endif
|
||||
// NOLINTBEGIN(*use-anonymous-namespace*,cert-dcl50-cpp)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -49,6 +50,7 @@ namespace c4 {
|
||||
static error_flags s_error_flags = ON_ERROR_DEFAULTS;
|
||||
static error_callback_type s_error_callback = nullptr;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
error_flags get_error_flags()
|
||||
@@ -70,6 +72,7 @@ void set_error_callback(error_callback_type cb)
|
||||
s_error_callback = cb;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void handle_error(srcloc where, const char *fmt, ...)
|
||||
@@ -80,7 +83,7 @@ void handle_error(srcloc where, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
int ilen = vsnprintf(buf, sizeof(buf), fmt, args); // ss.vprintf(fmt, args);
|
||||
int ilen = vsnprintf(buf, sizeof(buf), fmt, args); // NOLINT(clang-analyzer-valist.Uninitialized)
|
||||
va_end(args);
|
||||
msglen = ilen >= 0 && ilen < (int)sizeof(buf) ? static_cast<size_t>(ilen) : sizeof(buf)-1;
|
||||
}
|
||||
@@ -102,23 +105,24 @@ void handle_error(srcloc where, const char *fmt, ...)
|
||||
{
|
||||
if(s_error_callback)
|
||||
{
|
||||
s_error_callback(buf, msglen/*ss.c_strp(), ss.tellp()*/);
|
||||
s_error_callback(buf, msglen);
|
||||
}
|
||||
}
|
||||
|
||||
if(s_error_flags & ON_ERROR_THROW)
|
||||
{
|
||||
#if defined(C4_EXCEPTIONS_ENABLED) && defined(C4_ERROR_THROWS_EXCEPTION)
|
||||
throw std::runtime_error(buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
if(s_error_flags & ON_ERROR_ABORT)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
if(s_error_flags & ON_ERROR_THROW)
|
||||
{
|
||||
#if defined(C4_EXCEPTIONS_ENABLED) && defined(C4_ERROR_THROWS_EXCEPTION)
|
||||
throw std::runtime_error(buf);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
abort(); // abort anyway, in case nothing was set
|
||||
C4_UNREACHABLE_AFTER_ERR();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -126,20 +130,23 @@ void handle_error(srcloc where, const char *fmt, ...)
|
||||
void handle_warning(srcloc where, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buf[1024]; //sstream<c4::string> ss;
|
||||
char buf[1024];
|
||||
va_start(args, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
int ret = vsnprintf(buf, sizeof(buf), fmt, args); // NOLINT(clang-analyzer-valist.Uninitialized)
|
||||
if(ret+1 > (int)sizeof(buf))
|
||||
buf[sizeof(buf) - 1] = '\0'; // truncate
|
||||
else if(ret < 0)
|
||||
buf[0] = '\0'; // output/format error
|
||||
va_end(args);
|
||||
C4_LOGF_WARN("\n");
|
||||
#if defined(C4_ERROR_SHOWS_FILELINE) && defined(C4_ERROR_SHOWS_FUNC)
|
||||
C4_LOGF_WARN("%s:%d: WARNING: %s\n", where.file, where.line, buf/*ss.c_strp()*/);
|
||||
C4_LOGF_WARN("%s:%d: WARNING: %s\n", where.file, where.line, buf);
|
||||
C4_LOGF_WARN("%s:%d: WARNING: here: %s\n", where.file, where.line, where.func);
|
||||
#elif defined(C4_ERROR_SHOWS_FILELINE)
|
||||
C4_LOGF_WARN("%s:%d: WARNING: %s\n", where.file, where.line, buf/*ss.c_strp()*/);
|
||||
C4_LOGF_WARN("%s:%d: WARNING: %s\n", where.file, where.line, buf);
|
||||
#elif ! defined(C4_ERROR_SHOWS_FUNC)
|
||||
C4_LOGF_WARN("WARNING: %s\n", buf/*ss.c_strp()*/);
|
||||
C4_LOGF_WARN("WARNING: %s\n", buf);
|
||||
#endif
|
||||
//c4::log.flush();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -158,30 +165,21 @@ bool is_debugger_attached()
|
||||
//! @see http://stackoverflow.com/questions/3596781/how-to-detect-if-the-current-process-is-being-run-by-gdb
|
||||
//! (this answer: http://stackoverflow.com/a/24969863/3968589 )
|
||||
char buf[1024] = "";
|
||||
int status_fd = open("/proc/self/status", O_RDONLY);
|
||||
int status_fd = open("/proc/self/status", O_RDONLY); // NOLINT
|
||||
if (status_fd == -1)
|
||||
return false;
|
||||
ssize_t num_read = ::read(status_fd, buf, sizeof(buf));
|
||||
if (num_read > 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ssize_t num_read = ::read(status_fd, buf, sizeof(buf));
|
||||
if (num_read > 0)
|
||||
{
|
||||
static const char TracerPid[] = "TracerPid:";
|
||||
char *tracer_pid;
|
||||
if(num_read < 1024)
|
||||
{
|
||||
buf[num_read] = 0;
|
||||
}
|
||||
tracer_pid = strstr(buf, TracerPid);
|
||||
if (tracer_pid)
|
||||
{
|
||||
first_call_result = !!::atoi(tracer_pid + sizeof(TracerPid) - 1);
|
||||
}
|
||||
}
|
||||
close(status_fd);
|
||||
static const char TracerPid[] = "TracerPid:";
|
||||
char *tracer_pid;
|
||||
if(num_read < 1024)
|
||||
buf[num_read] = 0;
|
||||
tracer_pid = strstr(buf, TracerPid);
|
||||
if(tracer_pid)
|
||||
first_call_result = !!::atoi(tracer_pid + sizeof(TracerPid) - 1); // NOLINT
|
||||
}
|
||||
close(status_fd);
|
||||
C4_SUPPRESS_WARNING_GCC_POP
|
||||
}
|
||||
return first_call_result;
|
||||
@@ -216,6 +214,7 @@ bool is_debugger_attached()
|
||||
size = sizeof(info);
|
||||
junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
|
||||
assert(junk == 0);
|
||||
(void)junk;
|
||||
|
||||
// We're being debugged if the P_TRACED flag is set.
|
||||
return ((info.kp_proc.p_flag & P_TRACED) != 0);
|
||||
@@ -226,6 +225,7 @@ bool is_debugger_attached()
|
||||
|
||||
} // namespace c4
|
||||
|
||||
// NOLINTEND(*use-anonymous-namespace*,cert-dcl50-cpp)
|
||||
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic pop
|
||||
|
||||
4
3rdparty/rapidyaml/src/c4/format.cpp
vendored
4
3rdparty/rapidyaml/src/c4/format.cpp
vendored
@@ -19,7 +19,7 @@ size_t to_chars(substr buf, fmt::const_raw_wrapper r)
|
||||
{
|
||||
void * vptr = buf.str;
|
||||
size_t space = buf.len;
|
||||
auto ptr = (decltype(buf.str)) std::align(r.alignment, r.len, vptr, space);
|
||||
char * ptr = (char*) std::align(r.alignment, r.len, vptr, space);
|
||||
if(ptr == nullptr)
|
||||
{
|
||||
// if it was not possible to align, return a conservative estimate
|
||||
@@ -42,7 +42,7 @@ bool from_chars(csubstr buf, fmt::raw_wrapper *r)
|
||||
void * vptr = (void*)buf.str;
|
||||
C4_SUPPRESS_WARNING_GCC_POP
|
||||
size_t space = buf.len;
|
||||
auto ptr = (decltype(buf.str)) std::align(r->alignment, r->len, vptr, space);
|
||||
char * ptr = (char*) std::align(r->alignment, r->len, vptr, space);
|
||||
C4_CHECK(ptr != nullptr);
|
||||
C4_CHECK(ptr >= buf.begin() && ptr <= buf.end());
|
||||
C4_SUPPRESS_WARNING_GCC_PUSH
|
||||
|
||||
2
3rdparty/rapidyaml/src/c4/memory_util.cpp
vendored
2
3rdparty/rapidyaml/src/c4/memory_util.cpp
vendored
@@ -19,7 +19,7 @@ void mem_repeat(void* dest, void const* pattern, size_t pattern_size, size_t num
|
||||
while(begin + 2*n < end)
|
||||
{
|
||||
::memcpy(begin + n, begin, n);
|
||||
n <<= 1; // double n
|
||||
n <<= 1u; // double n
|
||||
}
|
||||
// copy the missing part
|
||||
if(begin + n < end)
|
||||
|
||||
72
3rdparty/rapidyaml/src/c4/utf.cpp
vendored
72
3rdparty/rapidyaml/src/c4/utf.cpp
vendored
@@ -7,8 +7,9 @@ C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wold-style-cast")
|
||||
|
||||
size_t decode_code_point(uint8_t *C4_RESTRICT buf, size_t buflen, const uint32_t code)
|
||||
{
|
||||
C4_UNUSED(buflen);
|
||||
C4_ASSERT(buf);
|
||||
C4_ASSERT(buflen >= 4);
|
||||
C4_UNUSED(buflen);
|
||||
if (code <= UINT32_C(0x7f))
|
||||
{
|
||||
buf[0] = (uint8_t)code;
|
||||
@@ -16,23 +17,23 @@ size_t decode_code_point(uint8_t *C4_RESTRICT buf, size_t buflen, const uint32_t
|
||||
}
|
||||
else if(code <= UINT32_C(0x7ff))
|
||||
{
|
||||
buf[0] = (uint8_t)(UINT32_C(0xc0) | (code >> 6)); /* 110xxxxx */
|
||||
buf[0] = (uint8_t)(UINT32_C(0xc0) | (code >> 6u)); /* 110xxxxx */
|
||||
buf[1] = (uint8_t)(UINT32_C(0x80) | (code & UINT32_C(0x3f))); /* 10xxxxxx */
|
||||
return 2u;
|
||||
}
|
||||
else if(code <= UINT32_C(0xffff))
|
||||
{
|
||||
buf[0] = (uint8_t)(UINT32_C(0xe0) | ((code >> 12))); /* 1110xxxx */
|
||||
buf[1] = (uint8_t)(UINT32_C(0x80) | ((code >> 6) & UINT32_C(0x3f))); /* 10xxxxxx */
|
||||
buf[2] = (uint8_t)(UINT32_C(0x80) | ((code ) & UINT32_C(0x3f))); /* 10xxxxxx */
|
||||
buf[0] = (uint8_t)(UINT32_C(0xe0) | ((code >> 12u))); /* 1110xxxx */
|
||||
buf[1] = (uint8_t)(UINT32_C(0x80) | ((code >> 6u) & UINT32_C(0x3f))); /* 10xxxxxx */
|
||||
buf[2] = (uint8_t)(UINT32_C(0x80) | ((code ) & UINT32_C(0x3f))); /* 10xxxxxx */
|
||||
return 3u;
|
||||
}
|
||||
else if(code <= UINT32_C(0x10ffff))
|
||||
{
|
||||
buf[0] = (uint8_t)(UINT32_C(0xf0) | ((code >> 18))); /* 11110xxx */
|
||||
buf[1] = (uint8_t)(UINT32_C(0x80) | ((code >> 12) & UINT32_C(0x3f))); /* 10xxxxxx */
|
||||
buf[2] = (uint8_t)(UINT32_C(0x80) | ((code >> 6) & UINT32_C(0x3f))); /* 10xxxxxx */
|
||||
buf[3] = (uint8_t)(UINT32_C(0x80) | ((code ) & UINT32_C(0x3f))); /* 10xxxxxx */
|
||||
buf[0] = (uint8_t)(UINT32_C(0xf0) | ((code >> 18u))); /* 11110xxx */
|
||||
buf[1] = (uint8_t)(UINT32_C(0x80) | ((code >> 12u) & UINT32_C(0x3f))); /* 10xxxxxx */
|
||||
buf[2] = (uint8_t)(UINT32_C(0x80) | ((code >> 6u) & UINT32_C(0x3f))); /* 10xxxxxx */
|
||||
buf[3] = (uint8_t)(UINT32_C(0x80) | ((code ) & UINT32_C(0x3f))); /* 10xxxxxx */
|
||||
return 4u;
|
||||
}
|
||||
return 0;
|
||||
@@ -55,6 +56,59 @@ substr decode_code_point(substr out, csubstr code_point)
|
||||
return out.first(ret);
|
||||
}
|
||||
|
||||
size_t first_non_bom(csubstr s)
|
||||
{
|
||||
#define c4check2_(s, c0, c1) ((s).len >= 2) && (((s).str[0] == (c0)) && ((s).str[1] == (c1)))
|
||||
#define c4check3_(s, c0, c1, c2) ((s).len >= 3) && (((s).str[0] == (c0)) && ((s).str[1] == (c1)) && ((s).str[2] == (c2)))
|
||||
#define c4check4_(s, c0, c1, c2, c3) ((s).len >= 4) && (((s).str[0] == (c0)) && ((s).str[1] == (c1)) && ((s).str[2] == (c2)) && ((s).str[3] == (c3)))
|
||||
// see https://en.wikipedia.org/wiki/Byte_order_mark#Byte-order_marks_by_encoding
|
||||
if(s.len < 2u)
|
||||
return false;
|
||||
else if(c4check3_(s, '\xef', '\xbb', '\xbf')) // UTF-8
|
||||
return 3u;
|
||||
else if(c4check4_(s, '\x00', '\x00', '\xfe', '\xff')) // UTF-32BE
|
||||
return 4u;
|
||||
else if(c4check4_(s, '\xff', '\xfe', '\x00', '\x00')) // UTF-32LE
|
||||
return 4u;
|
||||
else if(c4check2_(s, '\xfe', '\xff')) // UTF-16BE
|
||||
return 2u;
|
||||
else if(c4check2_(s, '\xff', '\xfe')) // UTF-16BE
|
||||
return 2u;
|
||||
else if(c4check3_(s, '\x2b', '\x2f', '\x76')) // UTF-7
|
||||
return 3u;
|
||||
else if(c4check3_(s, '\xf7', '\x64', '\x4c')) // UTF-1
|
||||
return 3u;
|
||||
else if(c4check4_(s, '\xdd', '\x73', '\x66', '\x73')) // UTF-EBCDIC
|
||||
return 4u;
|
||||
else if(c4check3_(s, '\x0e', '\xfe', '\xff')) // SCSU
|
||||
return 3u;
|
||||
else if(c4check3_(s, '\xfb', '\xee', '\x28')) // BOCU-1
|
||||
return 3u;
|
||||
else if(c4check4_(s, '\x84', '\x31', '\x95', '\x33')) // GB18030
|
||||
return 4u;
|
||||
return 0u;
|
||||
#undef c4check2_
|
||||
#undef c4check3_
|
||||
#undef c4check4_
|
||||
}
|
||||
|
||||
substr get_bom(substr s)
|
||||
{
|
||||
return s.first(first_non_bom(s));
|
||||
}
|
||||
csubstr get_bom(csubstr s)
|
||||
{
|
||||
return s.first(first_non_bom(s));
|
||||
}
|
||||
substr skip_bom(substr s)
|
||||
{
|
||||
return s.sub(first_non_bom(s));
|
||||
}
|
||||
csubstr skip_bom(csubstr s)
|
||||
{
|
||||
return s.sub(first_non_bom(s));
|
||||
}
|
||||
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_POP
|
||||
|
||||
} // namespace c4
|
||||
|
||||
28
3rdparty/rapidyaml/src/c4/yml/common.cpp
vendored
28
3rdparty/rapidyaml/src/c4/yml/common.cpp
vendored
@@ -28,21 +28,27 @@ void report_error_impl(const char* msg, size_t length, Location loc, FILE *f)
|
||||
{
|
||||
if(!loc.name.empty())
|
||||
{
|
||||
fwrite(loc.name.str, 1, loc.name.len, f);
|
||||
fputc(':', f);
|
||||
// this is more portable than using fprintf("%.*s:") which
|
||||
// is not available in some embedded platforms
|
||||
fwrite(loc.name.str, 1, loc.name.len, f); // NOLINT
|
||||
fputc(':', f); // NOLINT
|
||||
}
|
||||
fprintf(f, "%zu:", loc.line);
|
||||
fprintf(f, "%zu:", loc.line); // NOLINT
|
||||
if(loc.col)
|
||||
fprintf(f, "%zu:", loc.col);
|
||||
fprintf(f, "%zu:", loc.col); // NOLINT
|
||||
if(loc.offset)
|
||||
fprintf(f, " (%zuB):", loc.offset);
|
||||
fprintf(f, " (%zuB):", loc.offset); // NOLINT
|
||||
fputc(' ', f); // NOLINT
|
||||
}
|
||||
fprintf(f, "%.*s\n", (int)length, msg);
|
||||
fflush(f);
|
||||
RYML_ASSERT(!csubstr(msg, length).ends_with('\0'));
|
||||
fwrite(msg, 1, length, f); // NOLINT
|
||||
fputc('\n', f); // NOLINT
|
||||
fflush(f); // NOLINT
|
||||
}
|
||||
|
||||
[[noreturn]] void error_impl(const char* msg, size_t length, Location loc, void * /*user_data*/)
|
||||
{
|
||||
RYML_ASSERT(!csubstr(msg, length).ends_with('\0'));
|
||||
report_error_impl(msg, length, loc, nullptr);
|
||||
#ifdef RYML_DEFAULT_CALLBACK_USES_EXCEPTIONS
|
||||
throw std::runtime_error(std::string(msg, length));
|
||||
@@ -70,7 +76,7 @@ void free_impl(void *mem, size_t /*length*/, void * /*user_data*/)
|
||||
|
||||
|
||||
|
||||
Callbacks::Callbacks()
|
||||
Callbacks::Callbacks() noexcept
|
||||
:
|
||||
m_user_data(nullptr),
|
||||
#ifndef RYML_NO_DEFAULT_CALLBACKS
|
||||
@@ -98,9 +104,9 @@ Callbacks::Callbacks(void *user_data, pfn_allocate alloc_, pfn_free free_, pfn_e
|
||||
m_error(error_)
|
||||
#endif
|
||||
{
|
||||
C4_CHECK(m_allocate);
|
||||
C4_CHECK(m_free);
|
||||
C4_CHECK(m_error);
|
||||
RYML_CHECK(m_allocate);
|
||||
RYML_CHECK(m_free);
|
||||
RYML_CHECK(m_error);
|
||||
}
|
||||
|
||||
|
||||
|
||||
215
3rdparty/rapidyaml/src/c4/yml/node_type.cpp
vendored
Normal file
215
3rdparty/rapidyaml/src/c4/yml/node_type.cpp
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
#include "c4/yml/node_type.hpp"
|
||||
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
const char* NodeType::type_str(NodeType_e ty) noexcept
|
||||
{
|
||||
switch(ty & _TYMASK)
|
||||
{
|
||||
case KEYVAL:
|
||||
return "KEYVAL";
|
||||
case KEY:
|
||||
return "KEY";
|
||||
case VAL:
|
||||
return "VAL";
|
||||
case MAP:
|
||||
return "MAP";
|
||||
case SEQ:
|
||||
return "SEQ";
|
||||
case KEYMAP:
|
||||
return "KEYMAP";
|
||||
case KEYSEQ:
|
||||
return "KEYSEQ";
|
||||
case DOCSEQ:
|
||||
return "DOCSEQ";
|
||||
case DOCMAP:
|
||||
return "DOCMAP";
|
||||
case DOCVAL:
|
||||
return "DOCVAL";
|
||||
case DOC:
|
||||
return "DOC";
|
||||
case STREAM:
|
||||
return "STREAM";
|
||||
case NOTYPE:
|
||||
return "NOTYPE";
|
||||
default:
|
||||
if((ty & KEYVAL) == KEYVAL)
|
||||
return "KEYVAL***";
|
||||
if((ty & KEYMAP) == KEYMAP)
|
||||
return "KEYMAP***";
|
||||
if((ty & KEYSEQ) == KEYSEQ)
|
||||
return "KEYSEQ***";
|
||||
if((ty & DOCSEQ) == DOCSEQ)
|
||||
return "DOCSEQ***";
|
||||
if((ty & DOCMAP) == DOCMAP)
|
||||
return "DOCMAP***";
|
||||
if((ty & DOCVAL) == DOCVAL)
|
||||
return "DOCVAL***";
|
||||
if(ty & KEY)
|
||||
return "KEY***";
|
||||
if(ty & VAL)
|
||||
return "VAL***";
|
||||
if(ty & MAP)
|
||||
return "MAP***";
|
||||
if(ty & SEQ)
|
||||
return "SEQ***";
|
||||
if(ty & DOC)
|
||||
return "DOC***";
|
||||
return "(unk)";
|
||||
}
|
||||
}
|
||||
|
||||
csubstr NodeType::type_str(substr buf, NodeType_e flags) noexcept
|
||||
{
|
||||
size_t pos = 0;
|
||||
bool gotone = false;
|
||||
|
||||
#define _prflag(fl, txt) \
|
||||
do { \
|
||||
if((flags & (fl)) == (fl)) \
|
||||
{ \
|
||||
if(gotone) \
|
||||
{ \
|
||||
if(pos + 1 < buf.len) \
|
||||
buf[pos] = '|'; \
|
||||
++pos; \
|
||||
} \
|
||||
csubstr fltxt = txt; \
|
||||
if(pos + fltxt.len <= buf.len) \
|
||||
memcpy(buf.str + pos, fltxt.str, fltxt.len); \
|
||||
pos += fltxt.len; \
|
||||
gotone = true; \
|
||||
flags = (flags & ~(fl)); /*remove the flag*/ \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
_prflag(STREAM, "STREAM");
|
||||
_prflag(DOC, "DOC");
|
||||
// key properties
|
||||
_prflag(KEY, "KEY");
|
||||
_prflag(KEYNIL, "KNIL");
|
||||
_prflag(KEYTAG, "KTAG");
|
||||
_prflag(KEYANCH, "KANCH");
|
||||
_prflag(KEYREF, "KREF");
|
||||
_prflag(KEY_LITERAL, "KLITERAL");
|
||||
_prflag(KEY_FOLDED, "KFOLDED");
|
||||
_prflag(KEY_SQUO, "KSQUO");
|
||||
_prflag(KEY_DQUO, "KDQUO");
|
||||
_prflag(KEY_PLAIN, "KPLAIN");
|
||||
_prflag(KEY_UNFILT, "KUNFILT");
|
||||
// val properties
|
||||
_prflag(VAL, "VAL");
|
||||
_prflag(VALNIL, "VNIL");
|
||||
_prflag(VALTAG, "VTAG");
|
||||
_prflag(VALANCH, "VANCH");
|
||||
_prflag(VALREF, "VREF");
|
||||
_prflag(VAL_UNFILT, "VUNFILT");
|
||||
_prflag(VAL_LITERAL, "VLITERAL");
|
||||
_prflag(VAL_FOLDED, "VFOLDED");
|
||||
_prflag(VAL_SQUO, "VSQUO");
|
||||
_prflag(VAL_DQUO, "VDQUO");
|
||||
_prflag(VAL_PLAIN, "VPLAIN");
|
||||
_prflag(VAL_UNFILT, "VUNFILT");
|
||||
// container properties
|
||||
_prflag(MAP, "MAP");
|
||||
_prflag(SEQ, "SEQ");
|
||||
_prflag(FLOW_SL, "FLOWSL");
|
||||
_prflag(FLOW_ML, "FLOWML");
|
||||
_prflag(BLOCK, "BLCK");
|
||||
if(pos == 0)
|
||||
_prflag(NOTYPE, "NOTYPE");
|
||||
|
||||
#undef _prflag
|
||||
|
||||
if(pos < buf.len)
|
||||
{
|
||||
buf[pos] = '\0';
|
||||
return buf.first(pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
csubstr failed;
|
||||
failed.len = pos + 1;
|
||||
failed.str = nullptr;
|
||||
return failed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// see https://www.yaml.info/learn/quote.html#noplain
|
||||
bool scalar_style_query_squo(csubstr s) noexcept
|
||||
{
|
||||
return ! s.first_of_any("\n ", "\n\t");
|
||||
}
|
||||
|
||||
// see https://www.yaml.info/learn/quote.html#noplain
|
||||
bool scalar_style_query_plain(csubstr s) noexcept
|
||||
{
|
||||
if(s.begins_with("-."))
|
||||
{
|
||||
if(s == "-.inf" || s == "-.INF")
|
||||
return true;
|
||||
else if(s.sub(2).is_number())
|
||||
return true;
|
||||
}
|
||||
else if(s.begins_with_any("0123456789.-+") && s.is_number())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return s != ':'
|
||||
&& ( ! s.begins_with_any("-:?*&,'\"{}[]|>%#@`\r")) // @ and ` are reserved characters
|
||||
&& ( ! s.ends_with_any(":#"))
|
||||
// make this check in the last place, as it has linear
|
||||
// complexity, while the previous ones are
|
||||
// constant-time
|
||||
&& (s.first_of("\n#:[]{},") == npos);
|
||||
}
|
||||
|
||||
NodeType_e scalar_style_choose(csubstr s) noexcept
|
||||
{
|
||||
if(s.len)
|
||||
{
|
||||
if(s.begins_with_any(" \n\t")
|
||||
||
|
||||
s.ends_with_any(" \n\t"))
|
||||
{
|
||||
return SCALAR_DQUO;
|
||||
}
|
||||
else if( ! scalar_style_query_plain(s))
|
||||
{
|
||||
return scalar_style_query_squo(s) ? SCALAR_SQUO : SCALAR_DQUO;
|
||||
}
|
||||
// nothing remarkable - use plain
|
||||
return SCALAR_PLAIN;
|
||||
}
|
||||
return s.str ? SCALAR_SQUO : SCALAR_PLAIN;
|
||||
}
|
||||
|
||||
NodeType_e scalar_style_json_choose(csubstr s) noexcept
|
||||
{
|
||||
// do not quote special cases
|
||||
bool plain = (
|
||||
(s == "true" || s == "false" || s == "null")
|
||||
||
|
||||
(
|
||||
// do not quote numbers
|
||||
s.is_number()
|
||||
&&
|
||||
(
|
||||
// quote integral numbers if they have a leading 0
|
||||
// https://github.com/biojppm/rapidyaml/issues/291
|
||||
(!(s.len > 1 && s.begins_with('0')))
|
||||
// do not quote reals with leading 0
|
||||
// https://github.com/biojppm/rapidyaml/issues/313
|
||||
|| (s.find('.') != csubstr::npos)
|
||||
)
|
||||
)
|
||||
);
|
||||
return plain ? SCALAR_PLAIN : SCALAR_DQUO;
|
||||
}
|
||||
|
||||
} // namespace yml
|
||||
} // namespace c4
|
||||
5839
3rdparty/rapidyaml/src/c4/yml/parse.cpp
vendored
5839
3rdparty/rapidyaml/src/c4/yml/parse.cpp
vendored
File diff suppressed because it is too large
Load Diff
2
3rdparty/rapidyaml/src/c4/yml/preprocess.cpp
vendored
2
3rdparty/rapidyaml/src/c4/yml/preprocess.cpp
vendored
@@ -21,7 +21,7 @@ C4_ALWAYS_INLINE bool _is_idchar(char c)
|
||||
|| (c == '_' || c == '-' || c == '~' || c == '$');
|
||||
}
|
||||
|
||||
typedef enum { kReadPending = 0, kKeyPending = 1, kValPending = 2 } _ppstate;
|
||||
enum _ppstate : int { kReadPending = 0, kKeyPending = 1, kValPending = 2 };
|
||||
C4_ALWAYS_INLINE _ppstate _next(_ppstate s)
|
||||
{
|
||||
int n = (int)s + 1;
|
||||
|
||||
333
3rdparty/rapidyaml/src/c4/yml/reference_resolver.cpp
vendored
Normal file
333
3rdparty/rapidyaml/src/c4/yml/reference_resolver.cpp
vendored
Normal file
@@ -0,0 +1,333 @@
|
||||
#include "c4/yml/reference_resolver.hpp"
|
||||
#include "c4/yml/common.hpp"
|
||||
#include "c4/yml/detail/parser_dbg.hpp"
|
||||
#ifdef RYML_DBG
|
||||
#include "c4/yml/detail/print.hpp"
|
||||
#else
|
||||
#define _c4dbg_tree(...)
|
||||
#define _c4dbg_node(...)
|
||||
#endif
|
||||
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
/** @cond dev */
|
||||
|
||||
id_type ReferenceResolver::count_anchors_and_refs_(id_type n)
|
||||
{
|
||||
id_type c = 0;
|
||||
c += m_tree->has_key_anchor(n);
|
||||
c += m_tree->has_val_anchor(n);
|
||||
c += m_tree->is_key_ref(n);
|
||||
c += m_tree->is_val_ref(n);
|
||||
c += m_tree->has_key(n) && m_tree->key(n) == "<<";
|
||||
for(id_type ch = m_tree->first_child(n); ch != NONE; ch = m_tree->next_sibling(ch))
|
||||
c += count_anchors_and_refs_(ch);
|
||||
return c;
|
||||
}
|
||||
|
||||
void ReferenceResolver::gather_anchors_and_refs__(id_type n)
|
||||
{
|
||||
// insert key refs BEFORE inserting val refs
|
||||
if(m_tree->has_key(n))
|
||||
{
|
||||
if(m_tree->key(n) == "<<")
|
||||
{
|
||||
_c4dbgpf("node[{}]: key is <<", n);
|
||||
if(m_tree->has_val(n))
|
||||
{
|
||||
if(m_tree->is_val_ref(n))
|
||||
{
|
||||
_c4dbgpf("node[{}]: instance[{}]: val ref, inheriting! '{}'", n, m_refs.size(), m_tree->val_ref(n));
|
||||
m_refs.push({VALREF, n, NONE, NONE, NONE, NONE});
|
||||
//m_refs.push({KEYREF, n, NONE, NONE, NONE, NONE});
|
||||
}
|
||||
else
|
||||
{
|
||||
_c4dbgpf("node[{}]: not ref!", n);
|
||||
}
|
||||
}
|
||||
else if(m_tree->is_seq(n))
|
||||
{
|
||||
// for merging multiple inheritance targets
|
||||
// <<: [ *CENTER, *BIG ]
|
||||
_c4dbgpf("node[{}]: is seq!", n);
|
||||
for(id_type ich = m_tree->first_child(n); ich != NONE; ich = m_tree->next_sibling(ich))
|
||||
{
|
||||
_c4dbgpf("node[{}]: instance [{}]: val ref, inheriting multiple: {} '{}'", n, m_refs.size(), ich, m_tree->val_ref(ich));
|
||||
if(m_tree->is_container(ich))
|
||||
{
|
||||
detail::_report_err(m_tree->m_callbacks, "ERROR: node {} child {}: refs for << cannot be containers.'", n, ich);
|
||||
C4_UNREACHABLE_AFTER_ERR();
|
||||
}
|
||||
m_refs.push({VALREF, ich, NONE, NONE, n, m_tree->next_sibling(n)});
|
||||
}
|
||||
return; // don't descend into the seq
|
||||
}
|
||||
else
|
||||
{
|
||||
detail::_report_err(m_tree->m_callbacks, "ERROR: node {}: refs for << must be either val or seq", n);
|
||||
C4_UNREACHABLE_AFTER_ERR();
|
||||
}
|
||||
}
|
||||
else if(m_tree->is_key_ref(n))
|
||||
{
|
||||
_c4dbgpf("node[{}]: instance[{}]: key ref: '{}', key='{}'", n, m_refs.size(), m_tree->key_ref(n), m_tree->has_key(n) ? m_tree->key(n) : csubstr{"-"});
|
||||
_RYML_CB_ASSERT(m_tree->m_callbacks, m_tree->key(n) != "<<");
|
||||
_RYML_CB_CHECK(m_tree->m_callbacks, (!m_tree->has_key(n)) || m_tree->key(n).ends_with(m_tree->key_ref(n)));
|
||||
m_refs.push({KEYREF, n, NONE, NONE, NONE, NONE});
|
||||
}
|
||||
}
|
||||
// val ref
|
||||
if(m_tree->is_val_ref(n) && (!m_tree->has_key(n) || m_tree->key(n) != "<<"))
|
||||
{
|
||||
_c4dbgpf("node[{}]: instance[{}]: val ref: '{}'", n, m_refs.size(), m_tree->val_ref(n));
|
||||
RYML_CHECK((!m_tree->has_val(n)) || m_tree->val(n).ends_with(m_tree->val_ref(n)));
|
||||
m_refs.push({VALREF, n, NONE, NONE, NONE, NONE});
|
||||
}
|
||||
// anchors
|
||||
if(m_tree->has_key_anchor(n))
|
||||
{
|
||||
_c4dbgpf("node[{}]: instance[{}]: key anchor: '{}'", n, m_refs.size(), m_tree->key_anchor(n));
|
||||
RYML_CHECK(m_tree->has_key(n));
|
||||
m_refs.push({KEYANCH, n, NONE, NONE, NONE, NONE});
|
||||
}
|
||||
if(m_tree->has_val_anchor(n))
|
||||
{
|
||||
_c4dbgpf("node[{}]: instance[{}]: val anchor: '{}'", n, m_refs.size(), m_tree->val_anchor(n));
|
||||
RYML_CHECK(m_tree->has_val(n) || m_tree->is_container(n));
|
||||
m_refs.push({VALANCH, n, NONE, NONE, NONE, NONE});
|
||||
}
|
||||
// recurse
|
||||
for(id_type ch = m_tree->first_child(n); ch != NONE; ch = m_tree->next_sibling(ch))
|
||||
gather_anchors_and_refs__(ch);
|
||||
}
|
||||
|
||||
void ReferenceResolver::gather_anchors_and_refs_()
|
||||
{
|
||||
_c4dbgp("gathering anchors and refs...");
|
||||
|
||||
// minimize (re-)allocations by counting first
|
||||
id_type num_anchors_and_refs = count_anchors_and_refs_(m_tree->root_id());
|
||||
if(!num_anchors_and_refs)
|
||||
return;
|
||||
m_refs.reserve(num_anchors_and_refs);
|
||||
m_refs.clear();
|
||||
|
||||
// now descend through the hierarchy
|
||||
gather_anchors_and_refs__(m_tree->root_id());
|
||||
|
||||
_c4dbgpf("found {} anchors/refs", m_refs.size());
|
||||
|
||||
// finally connect the reference list
|
||||
id_type prev_anchor = NONE;
|
||||
id_type count = 0;
|
||||
for(auto &rd : m_refs)
|
||||
{
|
||||
rd.prev_anchor = prev_anchor;
|
||||
if(rd.type.has_anchor())
|
||||
prev_anchor = count;
|
||||
++count;
|
||||
}
|
||||
_c4dbgp("gathering anchors and refs: finished");
|
||||
}
|
||||
|
||||
id_type ReferenceResolver::lookup_(RefData const* C4_RESTRICT ra)
|
||||
{
|
||||
#ifdef RYML_DBG
|
||||
id_type instance = static_cast<id_type>(ra-m_refs.m_stack);
|
||||
id_type node = ra->node;
|
||||
#endif
|
||||
RYML_ASSERT(ra->type.is_key_ref() || ra->type.is_val_ref());
|
||||
RYML_ASSERT(ra->type.is_key_ref() != ra->type.is_val_ref());
|
||||
csubstr refname;
|
||||
_c4dbgpf("instance[{}:node{}]: lookup from node={}...", instance, node, ra->node);
|
||||
if(ra->type.is_val_ref())
|
||||
{
|
||||
refname = m_tree->val_ref(ra->node);
|
||||
_c4dbgpf("instance[{}:node{}]: valref: '{}'", instance, node, refname);
|
||||
}
|
||||
else
|
||||
{
|
||||
RYML_ASSERT(ra->type.is_key_ref());
|
||||
refname = m_tree->key_ref(ra->node);
|
||||
_c4dbgpf("instance[{}:node{}]: keyref: '{}'", instance, node, refname);
|
||||
}
|
||||
while(ra->prev_anchor != NONE)
|
||||
{
|
||||
ra = &m_refs[ra->prev_anchor];
|
||||
_c4dbgpf("instance[{}:node{}]: lookup '{}' at [{}:node{}]: keyref='{}' valref='{}'", instance, node, refname, ra-m_refs.m_stack, ra->node,
|
||||
(m_tree->has_key_anchor(ra->node) ? m_tree->key_anchor(ra->node) : csubstr("~")),
|
||||
(m_tree->has_val_anchor(ra->node) ? m_tree->val_anchor(ra->node) : csubstr("~")));
|
||||
if(m_tree->has_anchor(ra->node, refname))
|
||||
{
|
||||
_c4dbgpf("instance[{}:node{}]: got it at [{}:node{}]!", instance, node, ra-m_refs.m_stack, ra->node);
|
||||
return ra->node;
|
||||
}
|
||||
}
|
||||
detail::_report_err(m_tree->m_callbacks, "ERROR: anchor not found: '{}'", refname);
|
||||
C4_UNREACHABLE_AFTER_ERR();
|
||||
}
|
||||
|
||||
void ReferenceResolver::reset_(Tree *t_)
|
||||
{
|
||||
if(t_->callbacks() != m_refs.m_callbacks)
|
||||
{
|
||||
m_refs.m_callbacks = t_->callbacks();
|
||||
}
|
||||
m_tree = t_;
|
||||
m_refs.clear();
|
||||
}
|
||||
|
||||
void ReferenceResolver::resolve_()
|
||||
{
|
||||
/* from the specs: "an alias node refers to the most recent
|
||||
* node in the serialization having the specified anchor". So
|
||||
* we need to start looking upward from ref nodes.
|
||||
*
|
||||
* @see http://yaml.org/spec/1.2/spec.html#id2765878 */
|
||||
_c4dbgp("matching anchors/refs...");
|
||||
for(id_type i = 0, e = m_refs.size(); i < e; ++i)
|
||||
{
|
||||
RefData &C4_RESTRICT refdata = m_refs.top(i);
|
||||
if( ! refdata.type.is_ref())
|
||||
continue;
|
||||
refdata.target = lookup_(&refdata);
|
||||
}
|
||||
_c4dbgp("matching anchors/refs: finished");
|
||||
|
||||
// insert the resolved references
|
||||
_c4dbgp("modifying tree...");
|
||||
id_type prev_parent_ref = NONE;
|
||||
id_type prev_parent_ref_after = NONE;
|
||||
for(id_type i = 0, e = m_refs.size(); i < e; ++i)
|
||||
{
|
||||
RefData const& C4_RESTRICT refdata = m_refs[i];
|
||||
_c4dbgpf("instance[{}:node{}]: {}/{}...", i, refdata.node, i+1, e);
|
||||
if( ! refdata.type.is_ref())
|
||||
continue;
|
||||
_c4dbgpf("instance[{}:node{}]: is reference!", i, refdata.node);
|
||||
if(refdata.parent_ref != NONE)
|
||||
{
|
||||
_c4dbgpf("instance[{}:node{}] has parent: {}", i, refdata.node, refdata.parent_ref);
|
||||
_RYML_CB_ASSERT(m_tree->m_callbacks, m_tree->is_seq(refdata.parent_ref));
|
||||
const id_type p = m_tree->parent(refdata.parent_ref);
|
||||
const id_type after = (prev_parent_ref != refdata.parent_ref) ?
|
||||
refdata.parent_ref//prev_sibling(rd.parent_ref_sibling)
|
||||
:
|
||||
prev_parent_ref_after;
|
||||
prev_parent_ref = refdata.parent_ref;
|
||||
prev_parent_ref_after = m_tree->duplicate_children_no_rep(refdata.target, p, after);
|
||||
m_tree->remove(refdata.node);
|
||||
}
|
||||
else
|
||||
{
|
||||
_c4dbgpf("instance[{}:node{}] has no parent", i, refdata.node, refdata.parent_ref);
|
||||
if(m_tree->has_key(refdata.node) && m_tree->key(refdata.node) == "<<")
|
||||
{
|
||||
_c4dbgpf("instance[{}:node{}] is inheriting", i, refdata.node);
|
||||
_RYML_CB_ASSERT(m_tree->m_callbacks, m_tree->is_keyval(refdata.node));
|
||||
const id_type p = m_tree->parent(refdata.node);
|
||||
const id_type after = m_tree->prev_sibling(refdata.node);
|
||||
_c4dbgpf("instance[{}:node{}] p={} after={}", i, refdata.node, p, after);
|
||||
m_tree->duplicate_children_no_rep(refdata.target, p, after);
|
||||
m_tree->remove(refdata.node);
|
||||
}
|
||||
else if(refdata.type.is_key_ref())
|
||||
{
|
||||
_c4dbgpf("instance[{}:node{}] is key ref", i, refdata.node);
|
||||
_RYML_CB_ASSERT(m_tree->m_callbacks, m_tree->is_key_ref(refdata.node));
|
||||
_RYML_CB_ASSERT(m_tree->m_callbacks, m_tree->has_key_anchor(refdata.target) || m_tree->has_val_anchor(refdata.target));
|
||||
if(m_tree->has_val_anchor(refdata.target) && m_tree->val_anchor(refdata.target) == m_tree->key_ref(refdata.node))
|
||||
{
|
||||
_c4dbgpf("instance[{}:node{}] target.anchor==val.anchor=={}", i, refdata.node, m_tree->val_anchor(refdata.target));
|
||||
_RYML_CB_CHECK(m_tree->m_callbacks, !m_tree->is_container(refdata.target));
|
||||
_RYML_CB_CHECK(m_tree->m_callbacks, m_tree->has_val(refdata.target));
|
||||
const type_bits existing_style_flags = VAL_STYLE & m_tree->_p(refdata.target)->m_type.type;
|
||||
static_assert((VAL_STYLE >> 1u) == (KEY_STYLE), "bad flags");
|
||||
m_tree->_p(refdata.node)->m_key.scalar = m_tree->val(refdata.target);
|
||||
m_tree->_add_flags(refdata.node, KEY | (existing_style_flags >> 1u));
|
||||
}
|
||||
else
|
||||
{
|
||||
_c4dbgpf("instance[{}:node{}] don't inherit container flags", i, refdata.node);
|
||||
_RYML_CB_CHECK(m_tree->m_callbacks, m_tree->key_anchor(refdata.target) == m_tree->key_ref(refdata.node));
|
||||
m_tree->_p(refdata.node)->m_key.scalar = m_tree->key(refdata.target);
|
||||
// keys cannot be containers, so don't inherit container flags
|
||||
const type_bits existing_style_flags = KEY_STYLE & m_tree->_p(refdata.target)->m_type.type;
|
||||
m_tree->_add_flags(refdata.node, KEY | existing_style_flags);
|
||||
}
|
||||
}
|
||||
else // val ref
|
||||
{
|
||||
_c4dbgpf("instance[{}:node{}] is val ref", i, refdata.node);
|
||||
_RYML_CB_ASSERT(m_tree->m_callbacks, refdata.type.is_val_ref());
|
||||
if(m_tree->has_key_anchor(refdata.target) && m_tree->key_anchor(refdata.target) == m_tree->val_ref(refdata.node))
|
||||
{
|
||||
_c4dbgpf("instance[{}:node{}] target.anchor==key.anchor=={}", i, refdata.node, m_tree->val_anchor(refdata.target));
|
||||
_RYML_CB_CHECK(m_tree->m_callbacks, !m_tree->is_container(refdata.target));
|
||||
_RYML_CB_CHECK(m_tree->m_callbacks, m_tree->has_val(refdata.target));
|
||||
// keys cannot be containers, so don't inherit container flags
|
||||
const type_bits existing_style_flags = (KEY_STYLE) & m_tree->_p(refdata.target)->m_type.type;
|
||||
static_assert((KEY_STYLE << 1u) == (VAL_STYLE), "bad flags");
|
||||
m_tree->_p(refdata.node)->m_val.scalar = m_tree->key(refdata.target);
|
||||
m_tree->_add_flags(refdata.node, VAL | (existing_style_flags << 1u));
|
||||
}
|
||||
else
|
||||
{
|
||||
_c4dbgpf("instance[{}:node{}] duplicate contents", i, refdata.node);
|
||||
m_tree->duplicate_contents(refdata.target, refdata.node);
|
||||
}
|
||||
}
|
||||
}
|
||||
_c4dbg_tree("after insertion", *m_tree);
|
||||
}
|
||||
}
|
||||
|
||||
void ReferenceResolver::resolve(Tree *t_, bool clear_anchors)
|
||||
{
|
||||
_c4dbgp("resolving references...");
|
||||
|
||||
reset_(t_);
|
||||
|
||||
_c4dbg_tree("unresolved tree", *m_tree);
|
||||
|
||||
gather_anchors_and_refs_();
|
||||
if(m_refs.empty())
|
||||
return;
|
||||
resolve_();
|
||||
_c4dbg_tree("resolved tree", *m_tree);
|
||||
|
||||
// clear anchors and refs
|
||||
if(clear_anchors)
|
||||
{
|
||||
_c4dbgp("clearing anchors/refs");
|
||||
auto clear_ = [this]{
|
||||
for(auto const& C4_RESTRICT ar : m_refs)
|
||||
{
|
||||
m_tree->rem_anchor_ref(ar.node);
|
||||
if(ar.parent_ref != NONE)
|
||||
if(m_tree->type(ar.parent_ref) != NOTYPE)
|
||||
m_tree->remove(ar.parent_ref);
|
||||
}
|
||||
};
|
||||
clear_();
|
||||
// some of the elements injected during the resolution may
|
||||
// have nested anchors; these anchors will have been newly
|
||||
// injected during the resolution; collect again, and clear
|
||||
// again, to ensure those are also cleared:
|
||||
gather_anchors_and_refs_();
|
||||
clear_();
|
||||
_c4dbgp("clearing anchors/refs: finished");
|
||||
}
|
||||
|
||||
_c4dbg_tree("final resolved tree", *m_tree);
|
||||
|
||||
m_tree = nullptr;
|
||||
_c4dbgp("resolving references: finished");
|
||||
}
|
||||
|
||||
/** @endcond */
|
||||
|
||||
} // namespace ryml
|
||||
} // namespace c4
|
||||
323
3rdparty/rapidyaml/src/c4/yml/tag.cpp
vendored
Normal file
323
3rdparty/rapidyaml/src/c4/yml/tag.cpp
vendored
Normal file
@@ -0,0 +1,323 @@
|
||||
#include "c4/yml/tag.hpp"
|
||||
#include "c4/yml/tree.hpp"
|
||||
#include "c4/yml/detail/parser_dbg.hpp"
|
||||
|
||||
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
bool is_custom_tag(csubstr tag)
|
||||
{
|
||||
if((tag.len > 2) && (tag.str[0] == '!'))
|
||||
{
|
||||
size_t pos = tag.find('!', 1);
|
||||
return pos != npos && pos > 1 && tag.str[1] != '<';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
csubstr normalize_tag(csubstr tag)
|
||||
{
|
||||
YamlTag_e t = to_tag(tag);
|
||||
if(t != TAG_NONE)
|
||||
return from_tag(t);
|
||||
if(tag.begins_with("!<"))
|
||||
tag = tag.sub(1);
|
||||
if(tag.begins_with("<!"))
|
||||
return tag;
|
||||
return tag;
|
||||
}
|
||||
|
||||
csubstr normalize_tag_long(csubstr tag)
|
||||
{
|
||||
YamlTag_e t = to_tag(tag);
|
||||
if(t != TAG_NONE)
|
||||
return from_tag_long(t);
|
||||
if(tag.begins_with("!<"))
|
||||
tag = tag.sub(1);
|
||||
if(tag.begins_with("<!"))
|
||||
return tag;
|
||||
return tag;
|
||||
}
|
||||
|
||||
csubstr normalize_tag_long(csubstr tag, substr output)
|
||||
{
|
||||
csubstr result = normalize_tag_long(tag);
|
||||
if(result.begins_with("!!"))
|
||||
{
|
||||
tag = tag.sub(2);
|
||||
const csubstr pfx = "<tag:yaml.org,2002:";
|
||||
const size_t len = pfx.len + tag.len + 1;
|
||||
if(len <= output.len)
|
||||
{
|
||||
memcpy(output.str , pfx.str, pfx.len);
|
||||
memcpy(output.str + pfx.len, tag.str, tag.len);
|
||||
output[pfx.len + tag.len] = '>';
|
||||
result = output.first(len);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.str = nullptr;
|
||||
result.len = len;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
YamlTag_e to_tag(csubstr tag)
|
||||
{
|
||||
if(tag.begins_with("!<"))
|
||||
tag = tag.sub(1);
|
||||
if(tag.begins_with("!!"))
|
||||
tag = tag.sub(2);
|
||||
else if(tag.begins_with('!'))
|
||||
return TAG_NONE;
|
||||
else if(tag.begins_with("tag:yaml.org,2002:"))
|
||||
{
|
||||
RYML_ASSERT(csubstr("tag:yaml.org,2002:").len == 18);
|
||||
tag = tag.sub(18);
|
||||
}
|
||||
else if(tag.begins_with("<tag:yaml.org,2002:"))
|
||||
{
|
||||
RYML_ASSERT(csubstr("<tag:yaml.org,2002:").len == 19);
|
||||
tag = tag.sub(19);
|
||||
if(!tag.len)
|
||||
return TAG_NONE;
|
||||
tag = tag.offs(0, 1);
|
||||
}
|
||||
|
||||
if(tag == "map")
|
||||
return TAG_MAP;
|
||||
else if(tag == "omap")
|
||||
return TAG_OMAP;
|
||||
else if(tag == "pairs")
|
||||
return TAG_PAIRS;
|
||||
else if(tag == "set")
|
||||
return TAG_SET;
|
||||
else if(tag == "seq")
|
||||
return TAG_SEQ;
|
||||
else if(tag == "binary")
|
||||
return TAG_BINARY;
|
||||
else if(tag == "bool")
|
||||
return TAG_BOOL;
|
||||
else if(tag == "float")
|
||||
return TAG_FLOAT;
|
||||
else if(tag == "int")
|
||||
return TAG_INT;
|
||||
else if(tag == "merge")
|
||||
return TAG_MERGE;
|
||||
else if(tag == "null")
|
||||
return TAG_NULL;
|
||||
else if(tag == "str")
|
||||
return TAG_STR;
|
||||
else if(tag == "timestamp")
|
||||
return TAG_TIMESTAMP;
|
||||
else if(tag == "value")
|
||||
return TAG_VALUE;
|
||||
else if(tag == "yaml")
|
||||
return TAG_YAML;
|
||||
|
||||
return TAG_NONE;
|
||||
}
|
||||
|
||||
csubstr from_tag_long(YamlTag_e tag)
|
||||
{
|
||||
switch(tag)
|
||||
{
|
||||
case TAG_MAP:
|
||||
return {"<tag:yaml.org,2002:map>"};
|
||||
case TAG_OMAP:
|
||||
return {"<tag:yaml.org,2002:omap>"};
|
||||
case TAG_PAIRS:
|
||||
return {"<tag:yaml.org,2002:pairs>"};
|
||||
case TAG_SET:
|
||||
return {"<tag:yaml.org,2002:set>"};
|
||||
case TAG_SEQ:
|
||||
return {"<tag:yaml.org,2002:seq>"};
|
||||
case TAG_BINARY:
|
||||
return {"<tag:yaml.org,2002:binary>"};
|
||||
case TAG_BOOL:
|
||||
return {"<tag:yaml.org,2002:bool>"};
|
||||
case TAG_FLOAT:
|
||||
return {"<tag:yaml.org,2002:float>"};
|
||||
case TAG_INT:
|
||||
return {"<tag:yaml.org,2002:int>"};
|
||||
case TAG_MERGE:
|
||||
return {"<tag:yaml.org,2002:merge>"};
|
||||
case TAG_NULL:
|
||||
return {"<tag:yaml.org,2002:null>"};
|
||||
case TAG_STR:
|
||||
return {"<tag:yaml.org,2002:str>"};
|
||||
case TAG_TIMESTAMP:
|
||||
return {"<tag:yaml.org,2002:timestamp>"};
|
||||
case TAG_VALUE:
|
||||
return {"<tag:yaml.org,2002:value>"};
|
||||
case TAG_YAML:
|
||||
return {"<tag:yaml.org,2002:yaml>"};
|
||||
case TAG_NONE:
|
||||
default:
|
||||
return {""};
|
||||
}
|
||||
}
|
||||
|
||||
csubstr from_tag(YamlTag_e tag)
|
||||
{
|
||||
switch(tag)
|
||||
{
|
||||
case TAG_MAP:
|
||||
return {"!!map"};
|
||||
case TAG_OMAP:
|
||||
return {"!!omap"};
|
||||
case TAG_PAIRS:
|
||||
return {"!!pairs"};
|
||||
case TAG_SET:
|
||||
return {"!!set"};
|
||||
case TAG_SEQ:
|
||||
return {"!!seq"};
|
||||
case TAG_BINARY:
|
||||
return {"!!binary"};
|
||||
case TAG_BOOL:
|
||||
return {"!!bool"};
|
||||
case TAG_FLOAT:
|
||||
return {"!!float"};
|
||||
case TAG_INT:
|
||||
return {"!!int"};
|
||||
case TAG_MERGE:
|
||||
return {"!!merge"};
|
||||
case TAG_NULL:
|
||||
return {"!!null"};
|
||||
case TAG_STR:
|
||||
return {"!!str"};
|
||||
case TAG_TIMESTAMP:
|
||||
return {"!!timestamp"};
|
||||
case TAG_VALUE:
|
||||
return {"!!value"};
|
||||
case TAG_YAML:
|
||||
return {"!!yaml"};
|
||||
case TAG_NONE:
|
||||
default:
|
||||
return {""};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool TagDirective::create_from_str(csubstr directive_)
|
||||
{
|
||||
csubstr directive = directive_;
|
||||
directive = directive.sub(4);
|
||||
if(!directive.begins_with(' '))
|
||||
return false;
|
||||
directive = directive.triml(' ');
|
||||
size_t pos = directive.find(' ');
|
||||
if(pos == npos)
|
||||
return false;
|
||||
handle = directive.first(pos);
|
||||
directive = directive.sub(handle.len).triml(' ');
|
||||
pos = directive.find(' ');
|
||||
if(pos != npos)
|
||||
directive = directive.first(pos);
|
||||
prefix = directive;
|
||||
next_node_id = NONE;
|
||||
_c4dbgpf("%TAG: handle={} prefix={}", handle, prefix);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TagDirective::create_from_str(csubstr directive_, Tree *tree)
|
||||
{
|
||||
_RYML_CB_CHECK(tree->callbacks(), directive_.begins_with("%TAG "));
|
||||
if(!create_from_str(directive_))
|
||||
{
|
||||
_RYML_CB_ERR(tree->callbacks(), "invalid tag directive");
|
||||
}
|
||||
next_node_id = tree->size();
|
||||
if(!tree->empty())
|
||||
{
|
||||
const id_type prev = tree->size() - 1;
|
||||
if(tree->is_root(prev) && tree->type(prev) != NOTYPE && !tree->is_stream(prev))
|
||||
++next_node_id;
|
||||
}
|
||||
_c4dbgpf("%TAG: handle={} prefix={} next_node={}", handle, prefix, next_node_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t TagDirective::transform(csubstr tag, substr output, Callbacks const& callbacks) const
|
||||
{
|
||||
_c4dbgpf("%TAG: handle={} prefix={} next_node={}. tag={}", handle, prefix, next_node_id, tag);
|
||||
_RYML_CB_ASSERT(callbacks, tag.len >= handle.len);
|
||||
csubstr rest = tag.sub(handle.len);
|
||||
_c4dbgpf("%TAG: rest={}", rest);
|
||||
if(rest.begins_with('<'))
|
||||
{
|
||||
_c4dbgpf("%TAG: begins with <. rest={}", rest);
|
||||
if(C4_UNLIKELY(!rest.ends_with('>')))
|
||||
_RYML_CB_ERR(callbacks, "malformed tag");
|
||||
rest = rest.offs(1, 1);
|
||||
if(rest.begins_with(prefix))
|
||||
{
|
||||
_c4dbgpf("%TAG: already transformed! actual={}", rest.sub(prefix.len));
|
||||
return 0; // return 0 to signal that the tag is local and cannot be resolved
|
||||
}
|
||||
}
|
||||
size_t len = 1u + prefix.len + rest.len + 1u;
|
||||
size_t numpc = rest.count('%');
|
||||
if(numpc == 0)
|
||||
{
|
||||
if(len <= output.len)
|
||||
{
|
||||
output.str[0] = '<';
|
||||
memcpy(1u + output.str, prefix.str, prefix.len);
|
||||
memcpy(1u + output.str + prefix.len, rest.str, rest.len);
|
||||
output.str[1u + prefix.len + rest.len] = '>';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// need to decode URI % sequences
|
||||
size_t pos = rest.find('%');
|
||||
_RYML_CB_ASSERT(callbacks, pos != npos);
|
||||
do {
|
||||
size_t next = rest.first_not_of("0123456789abcdefABCDEF", pos+1);
|
||||
if(next == npos)
|
||||
next = rest.len;
|
||||
_RYML_CB_CHECK(callbacks, pos+1 < next);
|
||||
_RYML_CB_CHECK(callbacks, pos+1 + 2 <= next);
|
||||
size_t delta = next - (pos+1);
|
||||
len -= delta;
|
||||
pos = rest.find('%', pos+1);
|
||||
} while(pos != npos);
|
||||
if(len <= output.len)
|
||||
{
|
||||
size_t prev = 0, wpos = 0;
|
||||
auto appendstr = [&](csubstr s) { memcpy(output.str + wpos, s.str, s.len); wpos += s.len; };
|
||||
auto appendchar = [&](char c) { output.str[wpos++] = c; };
|
||||
appendchar('<');
|
||||
appendstr(prefix);
|
||||
pos = rest.find('%');
|
||||
_RYML_CB_ASSERT(callbacks, pos != npos);
|
||||
do {
|
||||
size_t next = rest.first_not_of("0123456789abcdefABCDEF", pos+1);
|
||||
if(next == npos)
|
||||
next = rest.len;
|
||||
_RYML_CB_CHECK(callbacks, pos+1 < next);
|
||||
_RYML_CB_CHECK(callbacks, pos+1 + 2 <= next);
|
||||
uint8_t val;
|
||||
if(C4_UNLIKELY(!read_hex(rest.range(pos+1, next), &val) || val > 127))
|
||||
_RYML_CB_ERR(callbacks, "invalid URI character");
|
||||
appendstr(rest.range(prev, pos));
|
||||
appendchar(static_cast<char>(val));
|
||||
prev = next;
|
||||
pos = rest.find('%', pos+1);
|
||||
} while(pos != npos);
|
||||
_RYML_CB_ASSERT(callbacks, pos == npos);
|
||||
_RYML_CB_ASSERT(callbacks, prev > 0);
|
||||
_RYML_CB_ASSERT(callbacks, rest.len >= prev);
|
||||
appendstr(rest.sub(prev));
|
||||
appendchar('>');
|
||||
_RYML_CB_ASSERT(callbacks, wpos == len);
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
} // namespace yml
|
||||
} // namespace c4
|
||||
1069
3rdparty/rapidyaml/src/c4/yml/tree.cpp
vendored
1069
3rdparty/rapidyaml/src/c4/yml/tree.cpp
vendored
File diff suppressed because it is too large
Load Diff
27
3rdparty/rapidyaml/src/c4/yml/version.cpp
vendored
Normal file
27
3rdparty/rapidyaml/src/c4/yml/version.cpp
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
#include "c4/yml/version.hpp"
|
||||
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
csubstr version()
|
||||
{
|
||||
return RYML_VERSION;
|
||||
}
|
||||
|
||||
int version_major()
|
||||
{
|
||||
return RYML_VERSION_MAJOR;
|
||||
}
|
||||
|
||||
int version_minor()
|
||||
{
|
||||
return RYML_VERSION_MINOR;
|
||||
}
|
||||
|
||||
int version_patch()
|
||||
{
|
||||
return RYML_VERSION_PATCH;
|
||||
}
|
||||
|
||||
} // namespace yml
|
||||
} // namespace c4
|
||||
Reference in New Issue
Block a user