From 3d2ecafb01ea51c383c02327b71d348ec0fd4d99 Mon Sep 17 00:00:00 2001 From: SternXD Date: Wed, 26 Nov 2025 14:17:32 -0500 Subject: [PATCH] 3rdparty: Update rapidyaml to v0.10.0 Signed-off-by: SternXD --- 3rdparty/rapidyaml/CMakeLists.txt | 2 +- 3rdparty/rapidyaml/include/c4/compiler.hpp | 2 +- 3rdparty/rapidyaml/include/c4/dump.hpp | 2 +- 3rdparty/rapidyaml/include/c4/std/string.hpp | 6 +- 3rdparty/rapidyaml/include/c4/std/vector.hpp | 2 +- .../rapidyaml/include/c4/std/vector_fwd.hpp | 4 + 3rdparty/rapidyaml/include/c4/utf.hpp | 4 +- 3rdparty/rapidyaml/include/c4/yml/common.hpp | 5 +- .../detail/{parser_dbg.hpp => dbgprint.hpp} | 36 +-- .../rapidyaml/include/c4/yml/emit.def.hpp | 4 +- .../include/c4/yml/event_handler_stack.hpp | 4 +- .../include/c4/yml/event_handler_tree.hpp | 13 +- .../include/c4/yml/filter_processor.hpp | 2 +- 3rdparty/rapidyaml/include/c4/yml/node.hpp | 27 +- .../rapidyaml/include/c4/yml/node_type.hpp | 9 +- .../include/c4/yml/parse_engine.def.hpp | 260 +++++++----------- .../rapidyaml/include/c4/yml/parse_engine.hpp | 54 ++-- 3rdparty/rapidyaml/include/c4/yml/tag.hpp | 3 +- 3rdparty/rapidyaml/include/c4/yml/tree.hpp | 26 ++ 3rdparty/rapidyaml/include/c4/yml/version.hpp | 4 +- 3rdparty/rapidyaml/rapidyaml.vcxproj | 2 +- 3rdparty/rapidyaml/src/c4/yml/parse.cpp | 18 -- 3rdparty/rapidyaml/src/c4/yml/preprocess.cpp | 2 +- .../src/c4/yml/reference_resolver.cpp | 6 +- 3rdparty/rapidyaml/src/c4/yml/tag.cpp | 49 ++-- 3rdparty/rapidyaml/src/c4/yml/tree.cpp | 178 +++++++++++- 26 files changed, 431 insertions(+), 293 deletions(-) rename 3rdparty/rapidyaml/include/c4/yml/detail/{parser_dbg.hpp => dbgprint.hpp} (83%) diff --git a/3rdparty/rapidyaml/CMakeLists.txt b/3rdparty/rapidyaml/CMakeLists.txt index 9d93f03f8e..b2375d8cf8 100644 --- a/3rdparty/rapidyaml/CMakeLists.txt +++ b/3rdparty/rapidyaml/CMakeLists.txt @@ -30,7 +30,7 @@ add_library(pcsx2-rapidyaml include/c4/windows_pop.hpp include/c4/windows_push.hpp include/c4/yml/common.hpp - include/c4/yml/detail/parser_dbg.hpp + include/c4/yml/detail/dbgprint.hpp include/c4/yml/detail/stack.hpp include/c4/yml/emit.def.hpp include/c4/yml/emit.hpp diff --git a/3rdparty/rapidyaml/include/c4/compiler.hpp b/3rdparty/rapidyaml/include/c4/compiler.hpp index 275c65dd45..07c5e91aa3 100644 --- a/3rdparty/rapidyaml/include/c4/compiler.hpp +++ b/3rdparty/rapidyaml/include/c4/compiler.hpp @@ -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) +#if defined(_MSC_VER) && !defined(__clang__) # define C4_MSVC # define C4_MSVC_VERSION_2022 17 # define C4_MSVC_VERSION_2019 16 diff --git a/3rdparty/rapidyaml/include/c4/dump.hpp b/3rdparty/rapidyaml/include/c4/dump.hpp index 6292247ae8..1e3d15d4a3 100644 --- a/3rdparty/rapidyaml/include/c4/dump.hpp +++ b/3rdparty/rapidyaml/include/c4/dump.hpp @@ -561,7 +561,7 @@ template C4_ALWAYS_INLINE auto _format_dump_compute_size(T const& v) -> typename std::enable_if::value, size_t>::type { - return to_chars({}, v); + return to_chars(substr{}, v); } template size_t _format_dump_compute_size(Arg const& a, Args const& ...more) diff --git a/3rdparty/rapidyaml/include/c4/std/string.hpp b/3rdparty/rapidyaml/include/c4/std/string.hpp index 34f5f61b54..bc69347f17 100644 --- a/3rdparty/rapidyaml/include/c4/std/string.hpp +++ b/3rdparty/rapidyaml/include/c4/std/string.hpp @@ -24,7 +24,7 @@ C4_ALWAYS_INLINE c4::substr to_substr(std::string &s) noexcept #error this function will have undefined behavior #endif // since c++11 it is legal to call s[s.size()]. - return c4::substr(&s[0], s.size()); + return c4::substr(&s[0], s.size()); // NOLINT(readability-container-data-pointer) } /** get a readonly view to an existing std::string. @@ -38,7 +38,7 @@ C4_ALWAYS_INLINE c4::csubstr to_csubstr(std::string const& s) noexcept #error this function will have undefined behavior #endif // since c++11 it is legal to call s[s.size()]. - return c4::csubstr(&s[0], s.size()); + return c4::csubstr(&s[0], s.size()); // NOLINT(readability-container-data-pointer) } //----------------------------------------------------------------------------- @@ -87,7 +87,7 @@ inline bool from_chars(c4::csubstr buf, std::string * s) if(buf.len) { C4_ASSERT(buf.str != nullptr); - memcpy(&(*s)[0], buf.str, buf.len); + memcpy(&(*s)[0], buf.str, buf.len); // NOLINT(readability-container-data-pointer) } return true; } diff --git a/3rdparty/rapidyaml/include/c4/std/vector.hpp b/3rdparty/rapidyaml/include/c4/std/vector.hpp index baaa242234..43f4f82e47 100644 --- a/3rdparty/rapidyaml/include/c4/std/vector.hpp +++ b/3rdparty/rapidyaml/include/c4/std/vector.hpp @@ -78,7 +78,7 @@ inline bool from_chars(c4::csubstr buf, std::vector * s) // see https://github.com/biojppm/rapidyaml/pull/264#issuecomment-1262133637 if(buf.len > 0) { - memcpy(&(*s)[0], buf.str, buf.len); + memcpy(&(*s)[0], buf.str, buf.len); // NOLINT(readability-container-data-pointer) } return true; } diff --git a/3rdparty/rapidyaml/include/c4/std/vector_fwd.hpp b/3rdparty/rapidyaml/include/c4/std/vector_fwd.hpp index 55025bd5f3..791e0feeea 100644 --- a/3rdparty/rapidyaml/include/c4/std/vector_fwd.hpp +++ b/3rdparty/rapidyaml/include/c4/std/vector_fwd.hpp @@ -5,6 +5,8 @@ #include +// NOLINTBEGIN(cert-dcl58-cpp) + // forward declarations for std::vector #if defined(__GLIBCXX__) || defined(__GLIBCPP__) || defined(_MSC_VER) #if defined(_MSC_VER) @@ -63,4 +65,6 @@ template bool from_chars(c4::csubstr buf, std::vector } // namespace c4 +// NOLINTEND(cert-dcl58-cpp) + #endif // _C4_STD_VECTOR_FWD_HPP_ diff --git a/3rdparty/rapidyaml/include/c4/utf.hpp b/3rdparty/rapidyaml/include/c4/utf.hpp index 360446cde2..362e3dc85b 100644 --- a/3rdparty/rapidyaml/include/c4/utf.hpp +++ b/3rdparty/rapidyaml/include/c4/utf.hpp @@ -61,10 +61,10 @@ C4CORE_EXPORT substr decode_code_point(substr out, csubstr code_point); * @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 + * @return the number of written characters, which will always be * at most 4 bytes. */ -size_t decode_code_point(uint8_t *C4_RESTRICT buf, size_t buflen, uint32_t code); +C4CORE_EXPORT size_t decode_code_point(uint8_t *C4_RESTRICT buf, size_t buflen, uint32_t code); /** @} */ diff --git a/3rdparty/rapidyaml/include/c4/yml/common.hpp b/3rdparty/rapidyaml/include/c4/yml/common.hpp index c53b393654..c4afa6361e 100644 --- a/3rdparty/rapidyaml/include/c4/yml/common.hpp +++ b/3rdparty/rapidyaml/include/c4/yml/common.hpp @@ -9,7 +9,7 @@ #include #include -#if defined(C4_MSVC) || defined(C4_MINGW) +#if defined(C4_MSVC) || defined(C4_MINGW) || defined(_WIN32) || defined(C4_WIN) #include #else #include @@ -288,7 +288,8 @@ struct RYML_EXPORT LineCol //! 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::value, "LineCol not trivial"); +static_assert(std::is_trivially_copyable::value, "LineCol not trivially copyable"); +static_assert(std::is_trivially_default_constructible::value, "LineCol not trivially default constructible"); static_assert(std::is_standard_layout::value, "Location not trivial"); diff --git a/3rdparty/rapidyaml/include/c4/yml/detail/parser_dbg.hpp b/3rdparty/rapidyaml/include/c4/yml/detail/dbgprint.hpp similarity index 83% rename from 3rdparty/rapidyaml/include/c4/yml/detail/parser_dbg.hpp rename to 3rdparty/rapidyaml/include/c4/yml/detail/dbgprint.hpp index 0b97f1ec8c..3423787a2b 100644 --- a/3rdparty/rapidyaml/include/c4/yml/detail/parser_dbg.hpp +++ b/3rdparty/rapidyaml/include/c4/yml/detail/dbgprint.hpp @@ -1,5 +1,5 @@ -#ifndef _C4_YML_DETAIL_PARSER_DBG_HPP_ -#define _C4_YML_DETAIL_PARSER_DBG_HPP_ +#ifndef _C4_YML_DETAIL_DBGPRINT_HPP_ +#define _C4_YML_DETAIL_DBGPRINT_HPP_ #ifndef _C4_YML_COMMON_HPP_ #include "../common.hpp" @@ -11,22 +11,9 @@ //----------------------------------------------------------------------------- -// some debugging scaffolds - -// NOLINTBEGIN(*) -C4_SUPPRESS_WARNING_GCC_CLANG_PUSH -C4_SUPPRESS_WARNING_MSVC_PUSH -C4_SUPPRESS_WARNING_MSVC(4068/*unknown pragma*/) - -#pragma GCC system_header -C4_SUPPRESS_WARNING_GCC("-Wunknown-pragmas") -C4_SUPPRESS_WARNING_CLANG("-Wgnu-zero-variadic-macro-arguments") -// NOLINTEND(*) - +// debug prints #ifndef RYML_DBG -# define _c4err(fmt, ...) \ - this->_err("ERROR: " fmt, ## __VA_ARGS__) # define _c4dbgt(fmt, ...) # define _c4dbgpf(fmt, ...) # define _c4dbgpf_(fmt, ...) @@ -36,14 +23,12 @@ C4_SUPPRESS_WARNING_CLANG("-Wgnu-zero-variadic-macro-arguments") # define _c4presc(...) # define _c4prscalar(msg, scalar, keep_newlines) #else -# define _c4err(fmt, ...) \ - 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__ ) + 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) \ @@ -141,7 +126,4 @@ inline void __c4presc(csubstr s, bool keep_newlines=false) #endif // RYML_DBG -C4_SUPPRESS_WARNING_GCC_CLANG_POP -C4_SUPPRESS_WARNING_MSVC_POP - -#endif /* _C4_YML_DETAIL_PARSER_DBG_HPP_ */ +#endif /* _C4_YML_DETAIL_DBGPRINT_HPP_ */ diff --git a/3rdparty/rapidyaml/include/c4/yml/emit.def.hpp b/3rdparty/rapidyaml/include/c4/yml/emit.def.hpp index 48d8cd9ea5..7257e82b34 100644 --- a/3rdparty/rapidyaml/include/c4/yml/emit.def.hpp +++ b/3rdparty/rapidyaml/include/c4/yml/emit.def.hpp @@ -6,8 +6,8 @@ #endif /** @file emit.def.hpp Definitions for emit functions. */ -#ifndef _C4_YML_DETAIL_PARSER_DBG_HPP_ -#include "c4/yml/detail/parser_dbg.hpp" +#ifndef _C4_YML_DETAIL_DBGPRINT_HPP_ +#include "c4/yml/detail/dbgprint.hpp" #endif namespace c4 { diff --git a/3rdparty/rapidyaml/include/c4/yml/event_handler_stack.hpp b/3rdparty/rapidyaml/include/c4/yml/event_handler_stack.hpp index 3d2723dc59..65960d3009 100644 --- a/3rdparty/rapidyaml/include/c4/yml/event_handler_stack.hpp +++ b/3rdparty/rapidyaml/include/c4/yml/event_handler_stack.hpp @@ -9,8 +9,8 @@ #include "c4/yml/node_type.hpp" #endif -#ifndef _C4_YML_DETAIL_PARSER_DBG_HPP_ -#include "c4/yml/detail/parser_dbg.hpp" +#ifndef _C4_YML_DETAIL_DBGPRINT_HPP_ +#include "c4/yml/detail/dbgprint.hpp" #endif #ifndef _C4_YML_PARSER_STATE_HPP_ diff --git a/3rdparty/rapidyaml/include/c4/yml/event_handler_tree.hpp b/3rdparty/rapidyaml/include/c4/yml/event_handler_tree.hpp index db7f15541e..6b35adabb1 100644 --- a/3rdparty/rapidyaml/include/c4/yml/event_handler_tree.hpp +++ b/3rdparty/rapidyaml/include/c4/yml/event_handler_tree.hpp @@ -19,11 +19,12 @@ namespace yml { * @{ */ -/** The stack state needed specifically by @ref EventHandlerTree */ +/** @cond dev */ struct EventHandlerTreeState : public ParserState { NodeData *tr_data; }; +/** @endcond */ /** The event handler to create a ryml @ref Tree. See the @@ -463,9 +464,8 @@ public: { _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('&')); + _RYML_CB_ASSERT(m_stack.m_callbacks, !_has_any_(KEYREF)); + _RYML_CB_ASSERT(m_stack.m_callbacks, !anchor.begins_with('&')); _enable_(KEYANCH); m_curr->tr_data->m_key.anchor = anchor; } @@ -473,9 +473,8 @@ public: { _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('&')); + _RYML_CB_ASSERT(m_stack.m_callbacks, !_has_any_(VALREF)); + _RYML_CB_ASSERT(m_stack.m_callbacks, !anchor.begins_with('&')); _enable_(VALANCH); m_curr->tr_data->m_val.anchor = anchor; } diff --git a/3rdparty/rapidyaml/include/c4/yml/filter_processor.hpp b/3rdparty/rapidyaml/include/c4/yml/filter_processor.hpp index 194099bbe6..2dc3810d35 100644 --- a/3rdparty/rapidyaml/include/c4/yml/filter_processor.hpp +++ b/3rdparty/rapidyaml/include/c4/yml/filter_processor.hpp @@ -5,7 +5,7 @@ #ifdef RYML_DBG #include "c4/charconv.hpp" -#include "c4/yml/detail/parser_dbg.hpp" +#include "c4/yml/detail/dbgprint.hpp" #endif namespace c4 { diff --git a/3rdparty/rapidyaml/include/c4/yml/node.hpp b/3rdparty/rapidyaml/include/c4/yml/node.hpp index 252959db56..4d74dd3d4f 100644 --- a/3rdparty/rapidyaml/include/c4/yml/node.hpp +++ b/3rdparty/rapidyaml/include/c4/yml/node.hpp @@ -260,7 +260,7 @@ public: public: - /** @name node container+scalar style predicates */ + /** @name style predicates */ /** @{ */ // documentation to the right --> @@ -269,6 +269,9 @@ public: C4_ALWAYS_INLINE bool type_has_all(NodeType_e bits) const RYML_NOEXCEPT { _C4RR(); return tree_->type_has_all(id_, bits); } /**< Forward to @ref Tree::type_has_all(). Node must be readable. */ C4_ALWAYS_INLINE bool type_has_none(NodeType_e bits) const RYML_NOEXCEPT { _C4RR(); return tree_->type_has_none(id_, bits); } /**< Forward to @ref Tree::type_has_none(). Node must be readable. */ + C4_ALWAYS_INLINE NodeType key_style() const RYML_NOEXCEPT { _C4RR(); return tree_->key_style(id_); } /**< Forward to @ref Tree::key_style(). Node must be readable. */ + C4_ALWAYS_INLINE NodeType val_style() const RYML_NOEXCEPT { _C4RR(); return tree_->val_style(id_); } /**< Forward to @ref Tree::val_style(). Node must be readable. */ + C4_ALWAYS_INLINE bool is_container_styled() const RYML_NOEXCEPT { _C4RR(); return tree_->is_container_styled(id_); } /**< Forward to @ref Tree::is_container_styled(). Node must be readable. */ C4_ALWAYS_INLINE bool is_block() const RYML_NOEXCEPT { _C4RR(); return tree_->is_block(id_); } /**< Forward to @ref Tree::is_block(). Node must be readable. */ C4_ALWAYS_INLINE bool is_flow_sl() const RYML_NOEXCEPT { _C4RR(); return tree_->is_flow_sl(id_); } /**< Forward to @ref Tree::is_flow_sl(). Node must be readable. */ @@ -608,6 +611,19 @@ public: /** @} */ +public: + + /** @name locations */ + /** @{ */ + + Location location(Parser const& parser) const + { + _C4RR(); + return tree_->location(parser, id_); + } + + /** @} */ + public: /** @name deserialization */ @@ -881,7 +897,6 @@ public: ConstNodeRef& operator= (NodeRef const&) noexcept; ConstNodeRef& operator= (NodeRef &&) noexcept; - /** @} */ public: @@ -1128,6 +1143,14 @@ public: void set_container_style(NodeType_e style) { _C4RR(); m_tree->set_container_style(m_id, style); } void set_key_style(NodeType_e style) { _C4RR(); m_tree->set_key_style(m_id, style); } void set_val_style(NodeType_e style) { _C4RR(); m_tree->set_val_style(m_id, style); } + void clear_style(bool recurse=false) { _C4RR(); m_tree->clear_style(m_id, recurse); } + void set_style_conditionally(NodeType type_mask, + NodeType rem_style_flags, + NodeType add_style_flags, + bool recurse=false) + { + _C4RR(); m_tree->set_style_conditionally(m_id, type_mask, rem_style_flags, add_style_flags, recurse); + } public: diff --git a/3rdparty/rapidyaml/include/c4/yml/node_type.hpp b/3rdparty/rapidyaml/include/c4/yml/node_type.hpp index 03e428c3fb..4ee79fdfaa 100644 --- a/3rdparty/rapidyaml/include/c4/yml/node_type.hpp +++ b/3rdparty/rapidyaml/include/c4/yml/node_type.hpp @@ -8,6 +8,9 @@ C4_SUPPRESS_WARNING_MSVC_PUSH C4_SUPPRESS_WARNING_GCC_CLANG_PUSH C4_SUPPRESS_WARNING_GCC_CLANG("-Wold-style-cast") +#if __GNUC__ >= 6 +C4_SUPPRESS_WARNING_GCC("-Wnull-dereference") +#endif namespace c4 { namespace yml { @@ -193,7 +196,7 @@ public: public: - /** @name container+scalar style queries + /** @name style functions * @{ */ C4_ALWAYS_INLINE bool is_container_styled() const noexcept { return (type & (CONTAINER_STYLE)) != 0; } @@ -218,9 +221,13 @@ public: 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 NodeType key_style() const noexcept { return (type & (KEY_STYLE)); } + C4_ALWAYS_INLINE NodeType val_style() const noexcept { return (type & (VAL_STYLE)); } + 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)); } + C4_ALWAYS_INLINE void clear_style() noexcept { type &= ~STYLE; } /** @} */ diff --git a/3rdparty/rapidyaml/include/c4/yml/parse_engine.def.hpp b/3rdparty/rapidyaml/include/c4/yml/parse_engine.def.hpp index cf90de22a2..2aebaa3c7f 100644 --- a/3rdparty/rapidyaml/include/c4/yml/parse_engine.def.hpp +++ b/3rdparty/rapidyaml/include/c4/yml/parse_engine.def.hpp @@ -8,11 +8,16 @@ #include -#include "c4/yml/detail/parser_dbg.hpp" +#include "c4/yml/detail/dbgprint.hpp" #include "c4/yml/filter_processor.hpp" #ifdef RYML_DBG #include #include "c4/yml/detail/print.hpp" +#define _c4err_(fmt, ...) do { RYML_DEBUG_BREAK(); this->_err("ERROR:\n" "{}:{}: " fmt, __FILE__, __LINE__, __VA_ARGS__); } while(0) +#define _c4err(fmt) do { RYML_DEBUG_BREAK(); this->_err("ERROR:\n" "{}:{}: " fmt, __FILE__, __LINE__); } while(0) +#else +#define _c4err_(fmt, ...) this->_err("ERROR: " fmt, __VA_ARGS__) +#define _c4err(fmt) this->_err("ERROR: {}", fmt) #endif @@ -796,7 +801,7 @@ bool ParseEngine::_is_valid_start_scalar_plain_flow(csubstr s) case '{': case '[': //_RYML_WITHOUT_TAB_TOKENS(case '\t'): - _c4err("invalid token \":{}\"", _c4prc(s.str[1])); + _c4err_("invalid token \":{}\"", _c4prc(s.str[1])); break; case ' ': case '}': @@ -831,7 +836,7 @@ bool ParseEngine::_is_valid_start_scalar_plain_flow(csubstr s) case '}': case '[': case ']': - _c4err("invalid token \"?{}\"", _c4prc(s.str[1])); + _c4err_("invalid token \"?{}\"", _c4prc(s.str[1])); break; default: break; @@ -945,7 +950,7 @@ bool ParseEngine::_scan_scalar_plain_seq_flow(ScannedScalar *C4_RE case '{': case '}': _line_progressed(i); - _c4err("invalid character: '{}'", c); // noreturn + _c4err_("invalid character: '{}'", c); // noreturn default: ; } @@ -1021,14 +1026,14 @@ bool ParseEngine::_scan_scalar_plain_map_flow(ScannedScalar *C4_RE case '{': case '[': _line_progressed(i); - _c4err("invalid character: '{}'", c); // noreturn + _c4err_("invalid character: '{}'", c); // noreturn break; case ']': _line_progressed(i); if(has_any(RSEQIMAP)) goto ended_scalar; else - _c4err("invalid character: '{}'", c); // noreturn + _c4err_("invalid character: '{}'", c); // noreturn break; case '#': if(!i || s.str[i-1] == ' ' _RYML_WITH_TAB_TOKENS(|| s.str[i-1] == '\t')) @@ -2661,45 +2666,50 @@ void ParseEngine::_filter_dquoted_backslash(FilterProcessor &C4_RE { proc.translate_esc('\\'); } - else if(next == 'x') // UTF8 + else if(next == 'x') // 2-digit Unicode escape (\xXX), code point 0x00–0xFF { if(C4_UNLIKELY(proc.rpos + 1u + 2u >= proc.src.len)) - _c4err("\\x requires 2 hex digits. scalar pos={}", proc.rpos); + _c4err_("\\x requires 2 hex digits. scalar pos={}", proc.rpos); + char readbuf[8]; csubstr codepoint = proc.src.sub(proc.rpos + 2u, 2u); _c4dbgfdq("utf8 ~~~{}~~~ rpos={} rem=~~~{}~~~", codepoint, proc.rpos, proc.src.sub(proc.rpos)); - uint8_t byteval = {}; - if(C4_UNLIKELY(!read_hex(codepoint, &byteval))) - _c4err("failed to read \\x codepoint. scalar pos={}", proc.rpos); - proc.translate_esc_bulk((const char*)&byteval, 1u, /*nread*/3u); + uint32_t codepoint_val = {}; + if(C4_UNLIKELY(!read_hex(codepoint, &codepoint_val))) + _c4err_("failed to read \\x codepoint. scalar pos={}", proc.rpos); + const size_t numbytes = decode_code_point((uint8_t*)readbuf, sizeof(readbuf), codepoint_val); + if(C4_UNLIKELY(numbytes == 0)) + _c4err_("failed to decode code point={}", proc.rpos); + _RYML_CB_ASSERT(callbacks(), numbytes <= 4); + proc.translate_esc_bulk(readbuf, numbytes, /*nread*/3u); _c4dbgfdq("utf8 after rpos={} rem=~~~{}~~~", proc.rpos, proc.src.sub(proc.rpos)); } - else if(next == 'u') // UTF16 + else if(next == 'u') // 4-digit Unicode escape (\uXXXX), code point 0x0000–0xFFFF { if(C4_UNLIKELY(proc.rpos + 1u + 4u >= proc.src.len)) - _c4err("\\u requires 4 hex digits. scalar pos={}", proc.rpos); + _c4err_("\\u requires 4 hex digits. scalar pos={}", proc.rpos); char readbuf[8]; csubstr codepoint = proc.src.sub(proc.rpos + 2u, 4u); uint32_t codepoint_val = {}; if(C4_UNLIKELY(!read_hex(codepoint, &codepoint_val))) - _c4err("failed to parse \\u codepoint. scalar pos={}", proc.rpos); + _c4err_("failed to parse \\u codepoint. scalar pos={}", proc.rpos); const size_t numbytes = decode_code_point((uint8_t*)readbuf, sizeof(readbuf), codepoint_val); if(C4_UNLIKELY(numbytes == 0)) - _c4err("failed to decode code point={}", proc.rpos); + _c4err_("failed to decode code point={}", proc.rpos); _RYML_CB_ASSERT(callbacks(), numbytes <= 4); proc.translate_esc_bulk(readbuf, numbytes, /*nread*/5u); } - else if(next == 'U') // UTF32 + else if(next == 'U') // 8-digit Unicode escape (\UXXXXXXXX), full 32-bit code point { if(C4_UNLIKELY(proc.rpos + 1u + 8u >= proc.src.len)) - _c4err("\\U requires 8 hex digits. scalar pos={}", proc.rpos); + _c4err_("\\U requires 8 hex digits. scalar pos={}", proc.rpos); char readbuf[8]; csubstr codepoint = proc.src.sub(proc.rpos + 2u, 8u); uint32_t codepoint_val = {}; if(C4_UNLIKELY(!read_hex(codepoint, &codepoint_val))) - _c4err("failed to parse \\U codepoint. scalar pos={}", proc.rpos); + _c4err_("failed to parse \\U codepoint. scalar pos={}", proc.rpos); const size_t numbytes = decode_code_point((uint8_t*)readbuf, sizeof(readbuf), codepoint_val); if(C4_UNLIKELY(numbytes == 0)) - _c4err("failed to decode code point={}", proc.rpos); + _c4err_("failed to decode code point={}", proc.rpos); _RYML_CB_ASSERT(callbacks(), numbytes <= 4); proc.translate_esc_bulk(readbuf, numbytes, /*nread*/9u); } @@ -2772,7 +2782,7 @@ void ParseEngine::_filter_dquoted_backslash(FilterProcessor &C4_RE } else { - _c4err("unknown character '{}' after '\\' pos={}", _c4prc(next), proc.rpos); + _c4err_("unknown character '{}' after '\\' pos={}", _c4prc(next), proc.rpos); } _c4dbgfdq("backslash...sofar=[{}]~~~{}~~~", proc.wpos, proc.sofar()); } @@ -2849,6 +2859,24 @@ FilterResultExtending ParseEngine::filter_scalar_dquoted_in_place( //----------------------------------------------------------------------------- // block filtering helpers +C4_NO_INLINE inline size_t _find_last_newline_and_larger_indentation(csubstr s, size_t indentation) noexcept +{ + if(indentation + 1 > s.len) + return npos; + for(size_t i = s.len-indentation-1; i != size_t(-1); --i) + { + if(s.str[i] == '\n') + { + csubstr rem = s.sub(i + 1); + size_t first = rem.first_not_of(' '); + first = (first != npos) ? first : rem.len; + if(first > indentation) + return i; + } + } + return npos; +} + template template void ParseEngine::_filter_chomp(FilterProcessor &C4_RESTRICT proc, BlockChomp_e chomp, size_t indentation) @@ -3506,37 +3534,67 @@ csubstr ParseEngine::_filter_scalar_dquot(substr s) _c4dbgpf("filtering dquo scalar: not enough space: needs {}, have {}", len, s.len); substr dst = m_evt_handler->alloc_arena(len, &s); _c4dbgpf("filtering dquo scalar: dst.len={}", dst.len); - _RYML_CB_ASSERT(this->callbacks(), dst.len == len); - FilterResult rsd = this->filter_scalar_dquoted(s, dst); - _c4dbgpf("filtering dquo scalar: ... result now needs {} was {}", rsd.required_len(), len); - _RYML_CB_ASSERT(this->callbacks(), rsd.required_len() <= len); // may be smaller! - _RYML_CB_CHECK(m_evt_handler->m_stack.m_callbacks, rsd.valid()); - _c4dbgpf("filtering dquo scalar: success! s=[{}]~~~{}~~~", rsd.get().len, rsd.get()); - return rsd.get(); + if(dst.str) + { + _RYML_CB_ASSERT(this->callbacks(), dst.len == len); + FilterResult rsd = this->filter_scalar_dquoted(s, dst); + _c4dbgpf("filtering dquo scalar: ... result now needs {} was {}", rsd.required_len(), len); + _RYML_CB_ASSERT(this->callbacks(), rsd.required_len() <= len); // may be smaller! + _RYML_CB_CHECK(m_evt_handler->m_stack.m_callbacks, rsd.valid()); + _c4dbgpf("filtering dquo scalar: success! s=[{}]~~~{}~~~", rsd.get().len, rsd.get()); + return rsd.get(); + } + return dst; } } //----------------------------------------------------------------------------- + +template +csubstr ParseEngine::_move_scalar_left_and_add_newline(substr s) +{ + if(s.is_sub(m_buf)) + { + _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, s.str > m_buf.str); + _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, s.str-1 >= m_buf.str); + if(s.len) + memmove(s.str - 1, s.str, s.len); + --s.str; + s.str[s.len] = '\n'; + ++s.len; + return s; + } + else + { + substr dst = m_evt_handler->alloc_arena(s.len + 1); + if(s.len) + memcpy(dst.str, s.str, s.len); + dst[s.len] = '\n'; + return dst; + } +} + template csubstr ParseEngine::_filter_scalar_literal(substr s, size_t indentation, BlockChomp_e chomp) { _c4dbgpf("filtering block literal scalar: s=[{}]~~~{}~~~", s.len, s); FilterResult r = this->filter_scalar_block_literal_in_place(s, s.len, indentation, chomp); + csubstr result; if(C4_LIKELY(r.valid())) { - _c4dbgpf("filtering block literal scalar: success! s=[{}]~~~{}~~~", r.get().len, r.get()); - return r.get(); + result = r.get(); } else { _c4dbgpf("filtering block literal scalar: not enough space: needs {}, have {}", r.required_len(), s.len); - substr dst = m_evt_handler->alloc_arena(r.required_len(), &s); - FilterResult rsd = this->filter_scalar_block_literal(s, dst, indentation, chomp); - _RYML_CB_CHECK(m_evt_handler->m_stack.m_callbacks, rsd.valid()); - _c4dbgpf("filtering block literal scalar: success! s=[{}]~~~{}~~~", rsd.get().len, rsd.get()); - return rsd.get(); + _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, r.required_len() == s.len + 1); + // this can only happen when adding a single newline in clip mode. + // so we shift left the scalar by one place + result = _move_scalar_left_and_add_newline(s); } + _c4dbgpf("filtering block literal scalar: success! s=[{}]~~~{}~~~", result.len, result); + return result; } @@ -3546,20 +3604,21 @@ csubstr ParseEngine::_filter_scalar_folded(substr s, size_t indent { _c4dbgpf("filtering block folded scalar: s=[{}]~~~{}~~~", s.len, s); FilterResult r = this->filter_scalar_block_folded_in_place(s, s.len, indentation, chomp); + csubstr result; if(C4_LIKELY(r.valid())) { - _c4dbgpf("filtering block folded scalar: success! s=[{}]~~~{}~~~", r.get().len, r.get()); - return r.get(); + result = r.get(); } else { _c4dbgpf("filtering block folded scalar: not enough space: needs {}, have {}", r.required_len(), s.len); - substr dst = m_evt_handler->alloc_arena(r.required_len(), &s); - FilterResult rsd = this->filter_scalar_block_folded(s, dst, indentation, chomp); - _RYML_CB_CHECK(m_evt_handler->m_stack.m_callbacks, rsd.valid()); - _c4dbgpf("filtering block folded scalar: success! s=[{}]~~~{}~~~", rsd.get().len, rsd.get()); - return rsd.get(); + _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, r.required_len() == s.len + 1); + // this can only happen when adding a single newline in clip mode. + // so we shift left the scalar by one place + result = _move_scalar_left_and_add_newline(s); } + _c4dbgpf("filtering block folded scalar: success! s=[{}]~~~{}~~~", result.len, result); + return result; } @@ -3876,119 +3935,6 @@ csubstr ParseEngine::location_contents(Location const& loc) const return m_buf.sub(loc.offset); } -template -Location ParseEngine::location(ConstNodeRef node) const -{ - _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, node.readable()); - return location(*node.tree(), node.id()); -} - -template -Location ParseEngine::location(Tree const& tree, id_type node) const -{ - // try hard to avoid getting the location from a null string. - Location loc; - if(_location_from_node(tree, node, &loc, 0)) - return loc; - return val_location(m_buf.str); -} - -template -bool ParseEngine::_location_from_node(Tree const& tree, id_type node, Location *C4_RESTRICT loc, id_type level) const -{ - if(tree.has_key(node)) - { - csubstr k = tree.key(node); - if(C4_LIKELY(k.str != nullptr)) - { - _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, k.is_sub(m_buf)); - _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_buf.is_super(k)); - *loc = val_location(k.str); - return true; - } - } - - if(tree.has_val(node)) - { - csubstr v = tree.val(node); - if(C4_LIKELY(v.str != nullptr)) - { - _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, v.is_sub(m_buf)); - _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, m_buf.is_super(v)); - *loc = val_location(v.str); - return true; - } - } - - if(tree.is_container(node)) - { - if(_location_from_cont(tree, node, loc)) - return true; - } - - if(tree.type(node) != NOTYPE && level == 0) - { - // try the prev sibling - { - const id_type prev = tree.prev_sibling(node); - if(prev != NONE) - { - if(_location_from_node(tree, prev, loc, level+1)) - return true; - } - } - // try the next sibling - { - const id_type next = tree.next_sibling(node); - if(next != NONE) - { - if(_location_from_node(tree, next, loc, level+1)) - return true; - } - } - // try the parent - { - const id_type parent = tree.parent(node); - if(parent != NONE) - { - if(_location_from_node(tree, parent, loc, level+1)) - return true; - } - } - } - - return false; -} - -template -bool ParseEngine::_location_from_cont(Tree const& tree, id_type node, Location *C4_RESTRICT loc) const -{ - _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, tree.is_container(node)); - if(!tree.is_stream(node)) - { - const char *node_start = tree._p(node)->m_val.scalar.str; // this was stored in the container - if(tree.has_children(node)) - { - id_type child = tree.first_child(node); - if(tree.has_key(child)) - { - // when a map starts, the container was set after the key - csubstr k = tree.key(child); - if(k.str && node_start > k.str) - node_start = k.str; - } - } - *loc = val_location(node_start); - return true; - } - else // it's a stream - { - *loc = val_location(m_buf.str); // just return the front of the buffer - } - return true; -} - - template Location ParseEngine::val_location(const char *val) const { @@ -6563,7 +6509,6 @@ mapblck_start: csubstr maybe_filtered = _maybe_filter_key_scalar_squot(sc); // KEY! m_evt_handler->set_key_scalar_squoted(maybe_filtered); _maybe_skip_whitespace_tokens(); - _set_indentation(m_evt_handler->m_curr->line_contents.indentation); // keep the child state on RVAL addrem_flags(RVAL, RNXT); } @@ -6604,7 +6549,6 @@ mapblck_start: csubstr maybe_filtered = _maybe_filter_key_scalar_dquot(sc); // KEY! m_evt_handler->set_key_scalar_dquoted(maybe_filtered); _maybe_skip_whitespace_tokens(); - _set_indentation(m_evt_handler->m_curr->line_contents.indentation); // keep the child state on RVAL addrem_flags(RVAL, RNXT); } @@ -6666,7 +6610,6 @@ mapblck_start: csubstr maybe_filtered = _maybe_filter_key_scalar_plain(sc, m_evt_handler->m_curr->indref); // KEY! m_evt_handler->set_key_scalar_plain(maybe_filtered); _maybe_skip_whitespace_tokens(); - _set_indentation(m_evt_handler->m_curr->line_contents.indentation); // keep the child state on RVAL addrem_flags(RVAL, RNXT); } @@ -6846,7 +6789,6 @@ mapblck_start: m_evt_handler->begin_map_val_block(); _handle_annotations_and_indentation_after_start_mapblck(startindent, startline); m_evt_handler->set_key_scalar_plain_empty(); - _set_indentation(m_evt_handler->m_curr->line_contents.indentation); // keep the child state on RVAL addrem_flags(RVAL, RNXT); } diff --git a/3rdparty/rapidyaml/include/c4/yml/parse_engine.hpp b/3rdparty/rapidyaml/include/c4/yml/parse_engine.hpp index 8080c8fc5d..656b87ea5d 100644 --- a/3rdparty/rapidyaml/include/c4/yml/parse_engine.hpp +++ b/3rdparty/rapidyaml/include/c4/yml/parse_engine.hpp @@ -1,10 +1,6 @@ #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 @@ -41,7 +37,10 @@ namespace yml { * - @ref EventHandlerTree is the handler responsible for creating the * ryml @ref Tree * - * - @ref EventHandlerYamlStd is the handler responsible for emitting + * - @ref extra::EventHandlerInts parses YAML into an integer array + representation of the tree and scalars. + * + * - @ref extra::EventHandlerTestSuite 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. @@ -103,8 +102,8 @@ namespace yml { * 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") + * - `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 EventHandlerTestSuite::actually_val_is_first_key_of_new_map_flow() "see implementation in EventHandlerTestSuite") + * - `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 EventHandlerTestSuite::actually_val_is_first_key_of_new_map_block() "see implementation in EventHandlerTestSuite") * * For example, consider an implicit map inside a seq: `[a: b, c: * d]` which is parsed as `[{a: b}, {c: d}]`. The standard event @@ -282,11 +281,20 @@ public: * - @ref EventHandlerTree is the handler responsible for creating the * ryml @ref Tree * - * - @ref EventHandlerYamlStd is the handler responsible for emitting + * - @ref extra::EventHandlerTestSuite is a 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. + * + * - @ref extra::EventHandlerInts is the handler responsible for + * emitting integer-coded events. It is intended for implementing + * fully-conformant parsing in other programming languages + * (integration is currently under work for + * [YamlScript](https://github.com/yaml/yamlscript) and + * [go-yaml](https://github.com/yaml/go-yaml/)). It is not part of + * the library and is not installed. + * */ template class ParseEngine @@ -393,8 +401,7 @@ public: public: - /** @name deprecated parse methods - * @{ */ + // deprecated parse methods /** @cond dev */ template RYML_DEPRECATED("removed, deliberately undefined. use the freestanding function in parse.hpp.") typename std::enable_if::type parse_in_place(csubstr filename, substr yaml, Tree *t, size_t node_id); @@ -423,20 +430,15 @@ public: template RYML_DEPRECATED("removed, deliberately undefined. use the freestanding csubstr version in parse.hpp.") typename std::enable_if::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. */ @@ -444,6 +446,18 @@ public: /** @} */ +public: + + /** @cond dev */ + template + RYML_DEPRECATED("moved to Tree::location(Parser const&). deliberately undefined here.") + auto location(Tree const&, id_type node) const -> typename std::enable_if::type; + + template + RYML_DEPRECATED("moved to ConstNodeRef::location(Parser const&), deliberately undefined here.") + auto location(ConstNodeRef const&) const -> typename std::enable_if::type; + /** @endcond */ + public: /** @name scalar filtering */ @@ -522,6 +536,7 @@ public: // exposed for testing 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 _move_scalar_left_and_add_newline(substr s); csubstr _maybe_filter_key_scalar_plain(ScannedScalar const& sc, size_t indendation); csubstr _maybe_filter_val_scalar_plain(ScannedScalar const& sc, size_t indendation); @@ -672,9 +687,6 @@ private: 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(); @@ -757,10 +769,6 @@ private: }; -/** @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 diff --git a/3rdparty/rapidyaml/include/c4/yml/tag.hpp b/3rdparty/rapidyaml/include/c4/yml/tag.hpp index 4a644ed0b2..1915b3ba67 100644 --- a/3rdparty/rapidyaml/include/c4/yml/tag.hpp +++ b/3rdparty/rapidyaml/include/c4/yml/tag.hpp @@ -64,8 +64,7 @@ struct RYML_EXPORT TagDirective 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; + size_t transform(csubstr tag, substr output, Callbacks const& callbacks, bool with_brackets=true) const; }; struct RYML_EXPORT TagDirectiveRange diff --git a/3rdparty/rapidyaml/include/c4/yml/tree.hpp b/3rdparty/rapidyaml/include/c4/yml/tree.hpp index 662bfc3aa1..2d93dd7b04 100644 --- a/3rdparty/rapidyaml/include/c4/yml/tree.hpp +++ b/3rdparty/rapidyaml/include/c4/yml/tree.hpp @@ -512,10 +512,19 @@ public: C4_ALWAYS_INLINE bool is_val_quoted(id_type node) const { return _p(node)->m_type.is_val_quoted(); } C4_ALWAYS_INLINE bool is_quoted(id_type node) const { return _p(node)->m_type.is_quoted(); } + C4_ALWAYS_INLINE NodeType key_style(id_type node) const { _RYML_CB_ASSERT(m_callbacks, has_key(node)); return _p(node)->m_type.key_style(); } + C4_ALWAYS_INLINE NodeType val_style(id_type node) const { _RYML_CB_ASSERT(m_callbacks, has_val(node) || is_root(node)); return _p(node)->m_type.val_style(); } + C4_ALWAYS_INLINE void set_container_style(id_type node, NodeType_e style) { _RYML_CB_ASSERT(m_callbacks, is_container(node)); _p(node)->m_type.set_container_style(style); } C4_ALWAYS_INLINE void set_key_style(id_type node, NodeType_e style) { _RYML_CB_ASSERT(m_callbacks, has_key(node)); _p(node)->m_type.set_key_style(style); } C4_ALWAYS_INLINE void set_val_style(id_type node, NodeType_e style) { _RYML_CB_ASSERT(m_callbacks, has_val(node)); _p(node)->m_type.set_val_style(style); } + void clear_style(id_type node, bool recurse=false); + void set_style_conditionally(id_type node, + NodeType type_mask, + NodeType rem_style_flags, + NodeType add_style_flags, + bool recurse=false); /** @} */ public: @@ -580,6 +589,8 @@ public: * uses a throwaway resolver object. */ void resolve(bool clear_anchors=true); + /** @} */ + public: /** @name tag directives */ @@ -766,6 +777,21 @@ public: /** @} */ +public: + + /** @name locations */ + /** @{ */ + + /** Get the location of a node from the parse used to parse this tree. */ + Location location(Parser const& p, id_type node) const; + +private: + + bool _location_from_node(Parser const& p, id_type node, Location *C4_RESTRICT loc, id_type level) const; + bool _location_from_cont(Parser const& p, id_type node, Location *C4_RESTRICT loc) const; + + /** @} */ + public: /** @name internal string arena */ diff --git a/3rdparty/rapidyaml/include/c4/yml/version.hpp b/3rdparty/rapidyaml/include/c4/yml/version.hpp index b15c5be981..a6c3df310e 100644 --- a/3rdparty/rapidyaml/include/c4/yml/version.hpp +++ b/3rdparty/rapidyaml/include/c4/yml/version.hpp @@ -3,9 +3,9 @@ /** @file version.hpp */ -#define RYML_VERSION "0.9.0" +#define RYML_VERSION "0.10.0" #define RYML_VERSION_MAJOR 0 -#define RYML_VERSION_MINOR 9 +#define RYML_VERSION_MINOR 10 #define RYML_VERSION_PATCH 0 #include diff --git a/3rdparty/rapidyaml/rapidyaml.vcxproj b/3rdparty/rapidyaml/rapidyaml.vcxproj index 4157810665..502da175e3 100644 --- a/3rdparty/rapidyaml/rapidyaml.vcxproj +++ b/3rdparty/rapidyaml/rapidyaml.vcxproj @@ -82,7 +82,7 @@ - + diff --git a/3rdparty/rapidyaml/src/c4/yml/parse.cpp b/3rdparty/rapidyaml/src/c4/yml/parse.cpp index c6f347bdc1..4f5622ff6f 100644 --- a/3rdparty/rapidyaml/src/c4/yml/parse.cpp +++ b/3rdparty/rapidyaml/src/c4/yml/parse.cpp @@ -129,24 +129,6 @@ Tree parse_json_in_arena(csubstr filename, csubstr json Tree parse_json_in_arena( csubstr json ) { Parser::handler_type event_handler; Parser parser(&event_handler); Tree tree(parser.callbacks()); substr src = tree.copy_to_arena(json); parse_json_in_place(&parser, {} , src, &tree, tree.root_id()); return tree; } -RYML_EXPORT C4_NO_INLINE size_t _find_last_newline_and_larger_indentation(csubstr s, size_t indentation) noexcept -{ - if(indentation + 1 > s.len) - return npos; - for(size_t i = s.len-indentation-1; i != size_t(-1); --i) - { - if(s.str[i] == '\n') - { - csubstr rem = s.sub(i + 1); - size_t first = rem.first_not_of(' '); - first = (first != npos) ? first : rem.len; - if(first > indentation) - return i; - } - } - return npos; -} - //----------------------------------------------------------------------------- RYML_EXPORT id_type estimate_tree_capacity(csubstr src) diff --git a/3rdparty/rapidyaml/src/c4/yml/preprocess.cpp b/3rdparty/rapidyaml/src/c4/yml/preprocess.cpp index 42cf2d59b8..e45abb8569 100644 --- a/3rdparty/rapidyaml/src/c4/yml/preprocess.cpp +++ b/3rdparty/rapidyaml/src/c4/yml/preprocess.cpp @@ -1,5 +1,5 @@ #include "c4/yml/preprocess.hpp" -#include "c4/yml/detail/parser_dbg.hpp" +#include "c4/yml/detail/dbgprint.hpp" /** @file preprocess.hpp Functions for preprocessing YAML prior to parsing. */ diff --git a/3rdparty/rapidyaml/src/c4/yml/reference_resolver.cpp b/3rdparty/rapidyaml/src/c4/yml/reference_resolver.cpp index 93e52eb096..9ce9c57d70 100644 --- a/3rdparty/rapidyaml/src/c4/yml/reference_resolver.cpp +++ b/3rdparty/rapidyaml/src/c4/yml/reference_resolver.cpp @@ -1,6 +1,6 @@ #include "c4/yml/reference_resolver.hpp" #include "c4/yml/common.hpp" -#include "c4/yml/detail/parser_dbg.hpp" +#include "c4/yml/detail/dbgprint.hpp" #ifdef RYML_DBG #include "c4/yml/detail/print.hpp" #else @@ -31,7 +31,7 @@ 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) == "<<") + if(!m_tree->is_key_quoted(n) && m_tree->key(n) == "<<") { _c4dbgpf("node[{}]: key is <<", n); if(m_tree->has_val(n)) @@ -264,7 +264,7 @@ void ReferenceResolver::resolve_() _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)); + _c4dbgpf("instance[{}:node{}] target.anchor==key.anchor=={}", i, refdata.node, m_tree->key_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 diff --git a/3rdparty/rapidyaml/src/c4/yml/tag.cpp b/3rdparty/rapidyaml/src/c4/yml/tag.cpp index a2f54fc270..ba5dbf14a4 100644 --- a/3rdparty/rapidyaml/src/c4/yml/tag.cpp +++ b/3rdparty/rapidyaml/src/c4/yml/tag.cpp @@ -1,6 +1,5 @@ #include "c4/yml/tag.hpp" -#include "c4/yml/tree.hpp" -#include "c4/yml/detail/parser_dbg.hpp" +#include "c4/yml/detail/dbgprint.hpp" namespace c4 { @@ -222,25 +221,7 @@ bool TagDirective::create_from_str(csubstr directive_) 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 +size_t TagDirective::transform(csubstr tag, substr output, Callbacks const& callbacks, bool with_brackets) const { _c4dbgpf("%TAG: handle={} prefix={} next_node={}. tag={}", handle, prefix, next_node_id, tag); _RYML_CB_ASSERT(callbacks, tag.len >= handle.len); @@ -258,16 +239,26 @@ size_t TagDirective::transform(csubstr tag, substr output, Callbacks const& call 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 len = prefix.len + rest.len; + if(with_brackets) + len += 2; 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] = '>'; + if(with_brackets) + { + 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 + { + memcpy(output.str, prefix.str, prefix.len); + memcpy(output.str + prefix.len, rest.str, rest.len); + } } } else @@ -290,7 +281,8 @@ size_t TagDirective::transform(csubstr tag, substr output, Callbacks const& call 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('<'); + if(with_brackets) + appendchar('<'); appendstr(prefix); pos = rest.find('%'); _RYML_CB_ASSERT(callbacks, pos != npos); @@ -312,7 +304,8 @@ size_t TagDirective::transform(csubstr tag, substr output, Callbacks const& call _RYML_CB_ASSERT(callbacks, prev > 0); _RYML_CB_ASSERT(callbacks, rest.len >= prev); appendstr(rest.sub(prev)); - appendchar('>'); + if(with_brackets) + appendchar('>'); _RYML_CB_ASSERT(callbacks, wpos == len); } } diff --git a/3rdparty/rapidyaml/src/c4/yml/tree.cpp b/3rdparty/rapidyaml/src/c4/yml/tree.cpp index 1b2360aefe..fb2e58bcc2 100644 --- a/3rdparty/rapidyaml/src/c4/yml/tree.cpp +++ b/3rdparty/rapidyaml/src/c4/yml/tree.cpp @@ -1,5 +1,5 @@ #include "c4/yml/tree.hpp" -#include "c4/yml/detail/parser_dbg.hpp" +#include "c4/yml/detail/dbgprint.hpp" #include "c4/yml/node.hpp" #include "c4/yml/reference_resolver.hpp" @@ -857,7 +857,13 @@ void Tree::set_root_as_stream() void Tree::remove_children(id_type node) { _RYML_CB_ASSERT(m_callbacks, get(node) != nullptr); + #if __GNUC__ >= 6 + C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wnull-dereference") + #endif id_type ich = get(node)->m_first_child; + #if __GNUC__ >= 6 + C4_SUPPRESS_WARNING_GCC_POP + #endif while(ich != NONE) { remove_children(ich); @@ -1178,7 +1184,6 @@ id_type Tree::child_pos(id_type node, id_type ch) const #if defined(__clang__) # pragma clang diagnostic push -# pragma GCC diagnostic ignored "-Wnull-dereference" #elif defined(__GNUC__) # pragma GCC diagnostic push # if __GNUC__ >= 6 @@ -1336,6 +1341,37 @@ void Tree::to_stream(id_type node, type_bits more_flags) } +//----------------------------------------------------------------------------- + +void Tree::clear_style(id_type node, bool recurse) +{ + NodeData *C4_RESTRICT d = _p(node); + d->m_type.clear_style(); + if(!recurse) + return; + for(id_type child = d->m_first_child; child != NONE; child = next_sibling(child)) + clear_style(child, recurse); +} + +void Tree::set_style_conditionally(id_type node, + NodeType type_mask, + NodeType rem_style_flags, + NodeType add_style_flags, + bool recurse) +{ + NodeData *C4_RESTRICT d = _p(node); + if((d->m_type & type_mask) == type_mask) + { + d->m_type &= ~(NodeType)rem_style_flags; + d->m_type |= (NodeType)add_style_flags; + } + if(!recurse) + return; + for(id_type child = d->m_first_child; child != NONE; child = next_sibling(child)) + set_style_conditionally(child, type_mask, rem_style_flags, add_style_flags, recurse); +} + + //----------------------------------------------------------------------------- id_type Tree::num_tag_directives() const { @@ -1366,10 +1402,30 @@ id_type Tree::add_tag_directive(TagDirective const& td) return pos; } +namespace { +bool _create_tag_directive_from_str(csubstr directive_, TagDirective *td, Tree *tree) +{ + _RYML_CB_CHECK(tree->callbacks(), directive_.begins_with("%TAG ")); + if(!td->create_from_str(directive_)) + { + _RYML_CB_ERR(tree->callbacks(), "invalid tag directive"); + } + td->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)) + ++td->next_node_id; + } + _c4dbgpf("%TAG: handle={} prefix={} next_node={}", td->handle, td->prefix, td->next_node_id); + return true; +} +} // namespace + bool Tree::add_tag_directive(csubstr directive_) { TagDirective td; - if(td.create_from_str(directive_, this)) + if(_create_tag_directive_from_str(directive_, &td, this)) { add_tag_directive(td); return true; @@ -1802,5 +1858,121 @@ Tree::_lookup_path_token Tree::_next_token(lookup_result *r, _lookup_path_token } // namespace c4 +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +#include "c4/yml/event_handler_tree.hpp" +#include "c4/yml/parse_engine.def.hpp" +#include "c4/yml/parse.hpp" + +namespace c4 { +namespace yml { + +Location Tree::location(Parser const& parser, id_type node) const +{ + // try hard to avoid getting the location from a null string. + Location loc; + if(_location_from_node(parser, node, &loc, 0)) + return loc; + return parser.val_location(parser.source().str); +} + +bool Tree::_location_from_node(Parser const& parser, id_type node, Location *C4_RESTRICT loc, id_type level) const +{ + if(has_key(node)) + { + csubstr k = key(node); + if(C4_LIKELY(k.str != nullptr)) + { + _RYML_CB_ASSERT(m_callbacks, k.is_sub(parser.source())); + _RYML_CB_ASSERT(m_callbacks, parser.source().is_super(k)); + *loc = parser.val_location(k.str); + return true; + } + } + + if(has_val(node)) + { + csubstr v = val(node); + if(C4_LIKELY(v.str != nullptr)) + { + _RYML_CB_ASSERT(m_callbacks, v.is_sub(parser.source())); + _RYML_CB_ASSERT(m_callbacks, parser.source().is_super(v)); + *loc = parser.val_location(v.str); + return true; + } + } + + if(is_container(node)) + { + if(_location_from_cont(parser, node, loc)) + return true; + } + + if(type(node) != NOTYPE && level == 0) + { + // try the prev sibling + { + const id_type prev = prev_sibling(node); + if(prev != NONE) + { + if(_location_from_node(parser, prev, loc, level+1)) + return true; + } + } + // try the next sibling + { + const id_type next = next_sibling(node); + if(next != NONE) + { + if(_location_from_node(parser, next, loc, level+1)) + return true; + } + } + // try the parent + { + const id_type parent = this->parent(node); + if(parent != NONE) + { + if(_location_from_node(parser, parent, loc, level+1)) + return true; + } + } + } + return false; +} + +bool Tree::_location_from_cont(Parser const& parser, id_type node, Location *C4_RESTRICT loc) const +{ + _RYML_CB_ASSERT(m_callbacks, is_container(node)); + if(!is_stream(node)) + { + const char *node_start = _p(node)->m_val.scalar.str; // this was stored in the container + if(has_children(node)) + { + id_type child = first_child(node); + if(has_key(child)) + { + // when a map starts, the container was set after the key + csubstr k = key(child); + if(k.str && node_start > k.str) + node_start = k.str; + } + } + *loc = parser.val_location(node_start); + return true; + } + else // it's a stream + { + *loc = parser.val_location(parser.source().str); // just return the front of the buffer + } + return true; +} + +} // namespace yml +} // namespace c4 + + C4_SUPPRESS_WARNING_GCC_CLANG_POP C4_SUPPRESS_WARNING_MSVC_POP