mirror of
https://github.com/biojppm/rapidyaml.git
synced 2026-01-18 13:31:19 +01:00
Improve error annotations & code docs
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -12,6 +12,7 @@ namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wold-style-cast")
|
||||
C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4702/*unreachable code*/) // on the call to the unreachable macro
|
||||
|
||||
namespace {
|
||||
Callbacks s_default_callbacks;
|
||||
@@ -39,7 +40,7 @@ void report_error_impl(const char* msg, size_t length, Location loc, FILE *f)
|
||||
fflush(f);
|
||||
}
|
||||
|
||||
void error_impl(const char* msg, size_t length, Location loc, void * /*user_data*/)
|
||||
[[noreturn]] void error_impl(const char* msg, size_t length, Location loc, void * /*user_data*/)
|
||||
{
|
||||
report_error_impl(msg, length, loc, nullptr);
|
||||
#ifdef RYML_DEFAULT_CALLBACK_USES_EXCEPTIONS
|
||||
@@ -89,7 +90,7 @@ Callbacks::Callbacks(void *user_data, pfn_allocate alloc_, pfn_free free_, pfn_e
|
||||
#ifndef RYML_NO_DEFAULT_CALLBACKS
|
||||
m_allocate(alloc_ ? alloc_ : allocate_impl),
|
||||
m_free(free_ ? free_ : free_impl),
|
||||
m_error(error_ ? error_ : error_impl)
|
||||
m_error((error_ ? error_ : error_impl))
|
||||
#else
|
||||
m_allocate(alloc_),
|
||||
m_free(free_),
|
||||
@@ -117,11 +118,24 @@ void reset_callbacks()
|
||||
set_callbacks(Callbacks());
|
||||
}
|
||||
|
||||
void error(const char *msg, size_t msg_len, Location loc)
|
||||
// the [[noreturn]] attribute needs to be here as well (UB otherwise)
|
||||
// https://en.cppreference.com/w/cpp/language/attributes/noreturn
|
||||
[[noreturn]] void error(Callbacks const& cb, const char *msg, size_t msg_len, Location loc)
|
||||
{
|
||||
s_default_callbacks.m_error(msg, msg_len, loc, s_default_callbacks.m_user_data);
|
||||
cb.m_error(msg, msg_len, loc, cb.m_user_data);
|
||||
abort(); // call abort in case the error callback didn't interrupt execution
|
||||
C4_UNREACHABLE();
|
||||
}
|
||||
|
||||
// the [[noreturn]] attribute needs to be here as well (UB otherwise)
|
||||
// see https://en.cppreference.com/w/cpp/language/attributes/noreturn
|
||||
[[noreturn]] void error(const char *msg, size_t msg_len, Location loc)
|
||||
{
|
||||
error(s_default_callbacks, msg, msg_len, loc);
|
||||
C4_UNREACHABLE();
|
||||
}
|
||||
|
||||
C4_SUPPRESS_WARNING_MSVC_POP
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_POP
|
||||
|
||||
} // namespace yml
|
||||
|
||||
@@ -1,18 +1,127 @@
|
||||
#ifndef _C4_YML_COMMON_HPP_
|
||||
#define _C4_YML_COMMON_HPP_
|
||||
|
||||
/** @file common.hpp Common utilities and infrastructure used by ryml. */
|
||||
|
||||
#include <cstddef>
|
||||
#include <c4/substr.hpp>
|
||||
#include <c4/yml/export.hpp>
|
||||
|
||||
|
||||
#ifndef RYML_USE_ASSERT
|
||||
/** define this macro with a boolean value to force enable/disable
|
||||
assertions. This causes a slowdown of the code.*/
|
||||
# define RYML_USE_ASSERT C4_USE_ASSERT
|
||||
//-----------------------------------------------------------------------------
|
||||
// Specify groups to have a predefined topic order in doxygen:
|
||||
|
||||
/** @defgroup doc_quickstart Quickstart
|
||||
*
|
||||
* Example code for every feature.
|
||||
*/
|
||||
|
||||
/** @defgroup doc_parse Parse utilities
|
||||
* @see sample::sample_parse_in_place
|
||||
* @see sample::sample_parse_in_arena
|
||||
* @see sample::sample_parse_file
|
||||
* @see sample::sample_parse_reuse_tree
|
||||
* @see sample::sample_parse_reuse_parser
|
||||
* @see sample::sample_parse_reuse_tree_and_parser
|
||||
* @see sample::sample_location_tracking
|
||||
*/
|
||||
|
||||
/** @defgroup doc_emit Emit utilities
|
||||
*
|
||||
* Utilities to emit YAML and JSON, either to a memory buffer or to a
|
||||
* file or ostream-like class.
|
||||
*
|
||||
* @see sample::sample_emit_to_container
|
||||
* @see sample::sample_emit_to_stream
|
||||
* @see sample::sample_emit_to_file
|
||||
* @see sample::sample_emit_nested_node
|
||||
* @see sample::sample_emit_style
|
||||
*/
|
||||
|
||||
/** @defgroup doc_node_type Node types
|
||||
*/
|
||||
|
||||
/** @defgroup doc_tree Tree utilities
|
||||
* @see sample::sample_quick_overview
|
||||
* @see sample::sample_iterate_trees
|
||||
* @see sample::sample_create_trees
|
||||
* @see sample::sample_tree_arena
|
||||
*
|
||||
* @see sample::sample_static_trees
|
||||
* @see sample::sample_location_tracking
|
||||
*
|
||||
* @see sample::sample_docs
|
||||
* @see sample::sample_anchors_and_aliases
|
||||
* @see sample::sample_tags
|
||||
*/
|
||||
|
||||
/** @defgroup doc_node_classes Node classes
|
||||
*
|
||||
* High-level node classes.
|
||||
*
|
||||
* @see sample::sample_quick_overview
|
||||
* @see sample::sample_iterate_trees
|
||||
* @see sample::sample_create_trees
|
||||
* @see sample::sample_tree_arena
|
||||
*/
|
||||
|
||||
/** @defgroup doc_callbacks Callbacks for errors and allocation
|
||||
*
|
||||
* Functions called by ryml to allocate/free memory and to report
|
||||
* errors.
|
||||
*
|
||||
* @see sample::sample_error_handler
|
||||
* @see sample::sample_global_allocator
|
||||
* @see sample::sample_per_tree_allocator
|
||||
*/
|
||||
|
||||
/** @defgroup doc_tag_utils Tag utilities
|
||||
* @see sample::sample_tags
|
||||
*/
|
||||
|
||||
/** @defgroup doc_preprocessors Preprocessors
|
||||
*
|
||||
* Functions for preprocessing YAML prior to parsing.
|
||||
*/
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// document macros for doxygen
|
||||
#ifdef __DOXYGEN__ // defined in Doxyfile::PREDEFINED
|
||||
|
||||
/** define this macro with a boolean value to enable/disable
|
||||
* assertions to check preconditions and assumptions throughout the
|
||||
* codebase; this causes a slowdown of the code, and larger code
|
||||
* size. By default, this macro is defined unless NDEBUG is defined
|
||||
* (see C4_USE_ASSERT); as a result, by default this macro is truthy
|
||||
* only in debug builds. */
|
||||
# define RYML_USE_ASSERT
|
||||
|
||||
/** (Undefined by default) Define this macro to disable ryml's default
|
||||
* implementation of the callback functions; see @ref c4::yml::Callbacks */
|
||||
# define RYML_NO_DEFAULT_CALLBACKS
|
||||
|
||||
/** (Undefined by default) When this macro is defined (and
|
||||
* @ref RYML_NO_DEFAULT_CALLBACKS is not defined), the default error
|
||||
* handler will throw C++ exceptions of type `std::runtime_error`. */
|
||||
# define RYML_DEFAULT_CALLBACK_USES_EXCEPTIONS
|
||||
|
||||
/** Conditionally expands to `noexcept` when @ref RYML_USE_ASSERT is 0 and
|
||||
* is empty otherwise. The user is unable to override this macro. */
|
||||
# define RYML_NOEXCEPT
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** @cond dev*/
|
||||
#ifndef RYML_USE_ASSERT
|
||||
# define RYML_USE_ASSERT C4_USE_ASSERT
|
||||
#endif
|
||||
|
||||
#if RYML_USE_ASSERT
|
||||
# define RYML_ASSERT(cond) RYML_CHECK(cond)
|
||||
# define RYML_ASSERT_MSG(cond, msg) RYML_CHECK_MSG(cond, msg)
|
||||
@@ -25,6 +134,28 @@
|
||||
# define RYML_NOEXCEPT noexcept
|
||||
#endif
|
||||
|
||||
#define RYML_DEPRECATED(msg) C4_DEPRECATED(msg)
|
||||
|
||||
#define RYML_CHECK(cond) \
|
||||
do { \
|
||||
if(C4_UNLIKELY(!(cond))) \
|
||||
{ \
|
||||
RYML_DEBUG_BREAK() \
|
||||
c4::yml::error("check failed: " #cond, c4::yml::Location(__FILE__, __LINE__, 0)); \
|
||||
C4_UNREACHABLE_AFTER_ERR(); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define RYML_CHECK_MSG(cond, msg) \
|
||||
do \
|
||||
{ \
|
||||
if(C4_UNLIKELY(!(cond))) \
|
||||
{ \
|
||||
RYML_DEBUG_BREAK() \
|
||||
c4::yml::error(msg ": check failed: " #cond, c4::yml::Location(__FILE__, __LINE__, 0)); \
|
||||
C4_UNREACHABLE_AFTER_ERR(); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#if defined(RYML_DBG) && !defined(NDEBUG) && !defined(C4_NO_DEBUG_BREAK)
|
||||
# define RYML_DEBUG_BREAK() \
|
||||
@@ -39,35 +170,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
#define RYML_CHECK(cond) \
|
||||
do { \
|
||||
if(!(cond)) \
|
||||
{ \
|
||||
RYML_DEBUG_BREAK() \
|
||||
c4::yml::error("check failed: " #cond, c4::yml::Location(__FILE__, __LINE__, 0)); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define RYML_CHECK_MSG(cond, msg) \
|
||||
do \
|
||||
{ \
|
||||
if(!(cond)) \
|
||||
{ \
|
||||
RYML_DEBUG_BREAK() \
|
||||
c4::yml::error(msg ": check failed: " #cond, c4::yml::Location(__FILE__, __LINE__, 0)); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
#if C4_CPP >= 14
|
||||
# define RYML_DEPRECATED(msg) [[deprecated(msg)]]
|
||||
#else
|
||||
# if defined(_MSC_VER)
|
||||
# define RYML_DEPRECATED(msg) __declspec(deprecated(msg))
|
||||
# else // defined(__GNUC__) || defined(__clang__)
|
||||
# define RYML_DEPRECATED(msg) __attribute__((deprecated(msg)))
|
||||
# endif
|
||||
#endif
|
||||
/** @endcond */
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -127,46 +230,58 @@ struct RYML_EXPORT Location : public LineCol
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** the type of the function used to report errors. This function must
|
||||
* interrupt execution, either by raising an exception or calling
|
||||
* std::abort().
|
||||
/** @addtogroup doc_callbacks
|
||||
*
|
||||
* @warning the error callback must never return: it must either abort
|
||||
* or throw an exception. Otherwise, the parser will enter into an
|
||||
* infinite loop, or the program may crash. */
|
||||
using pfn_error = void (*)(const char* msg, size_t msg_len, Location location, void *user_data);
|
||||
/** the type of the function used to allocate memory */
|
||||
* @{ */
|
||||
|
||||
struct Callbacks;
|
||||
|
||||
|
||||
/** set the global callbacks for the library; after a call to this
|
||||
* function, these callbacks will be used by newly created objects
|
||||
* (unless they are copying older objects with different
|
||||
* callbacks). If @ref RYML_NO_DEFAULT_CALLBACKS is defined, it is
|
||||
* mandatory to call this function prior to using any other library
|
||||
* facility.
|
||||
*
|
||||
* @warning This function is NOT thread-safe.
|
||||
*
|
||||
* @warning the error callback must never return: see @ref pfn_error
|
||||
* for more details */
|
||||
RYML_EXPORT void set_callbacks(Callbacks const& c);
|
||||
|
||||
/** get the global callbacks
|
||||
* @warning This function is not thread-safe. */
|
||||
RYML_EXPORT Callbacks const& get_callbacks();
|
||||
|
||||
/** set the global callbacks back to their defaults ()
|
||||
* @warning This function is not thread-safe. */
|
||||
RYML_EXPORT void reset_callbacks();
|
||||
|
||||
|
||||
/** the type of the function used to report errors
|
||||
*
|
||||
* @warning When given by the user, this function MUST interrupt
|
||||
* execution, typically by either throwing an exception, or using
|
||||
* `std::longjmp()` ([see
|
||||
* documentation](https://en.cppreference.com/w/cpp/utility/program/setjmp))
|
||||
* or by calling `std::abort()`. If the function returned, the parser
|
||||
* would enter into an infinite loop, or the program may crash. */
|
||||
using pfn_error = void (*) (const char* msg, size_t msg_len, Location location, void *user_data);
|
||||
|
||||
|
||||
/** the type of the function used to allocate memory; ryml will only
|
||||
* allocate memory through this callback. */
|
||||
using pfn_allocate = void* (*)(size_t len, void* hint, void *user_data);
|
||||
/** the type of the function used to free memory */
|
||||
|
||||
|
||||
/** the type of the function used to free memory; ryml will only free
|
||||
* memory through this callback. */
|
||||
using pfn_free = void (*)(void* mem, size_t size, void *user_data);
|
||||
|
||||
/** trigger an error: call the current error callback. */
|
||||
RYML_EXPORT void error(const char *msg, size_t msg_len, Location loc);
|
||||
/** @overload error */
|
||||
inline void error(const char *msg, size_t msg_len)
|
||||
{
|
||||
error(msg, msg_len, Location{});
|
||||
}
|
||||
/** @overload error */
|
||||
template<size_t N>
|
||||
inline void error(const char (&msg)[N], Location loc)
|
||||
{
|
||||
error(msg, N-1, loc);
|
||||
}
|
||||
/** @overload error */
|
||||
template<size_t N>
|
||||
inline void error(const char (&msg)[N])
|
||||
{
|
||||
error(msg, N-1, Location{});
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** a c-style callbacks class
|
||||
*
|
||||
* @warning the error callback must never return: it must either abort
|
||||
* or throw an exception. Otherwise, the parser will enter into an
|
||||
* infinite loop, or the program may crash. */
|
||||
/** a c-style callbacks class. Can be used globally by the library
|
||||
* and/or locally by @ref Tree and @ref Parser objects. */
|
||||
struct RYML_EXPORT Callbacks
|
||||
{
|
||||
void * m_user_data;
|
||||
@@ -174,8 +289,32 @@ struct RYML_EXPORT Callbacks
|
||||
pfn_free m_free;
|
||||
pfn_error m_error;
|
||||
|
||||
/** Construct an object with the default callbacks. If
|
||||
* @ref RYML_NO_DEFAULT_CALLBACKS is defined, the object will have null
|
||||
* members.*/
|
||||
Callbacks();
|
||||
Callbacks(void *user_data, pfn_allocate alloc, pfn_free free, pfn_error error_);
|
||||
|
||||
/** Construct an object with the given callbacks.
|
||||
*
|
||||
* @param user_data Data to be forwarded in every call to a callback.
|
||||
*
|
||||
* @param alloc A pointer to an allocate function. Unless
|
||||
* @ref RYML_NO_DEFAULT_CALLBACKS is defined, when this
|
||||
* parameter is null, will fall back to ryml's default
|
||||
* alloc implementation.
|
||||
*
|
||||
* @param free A pointer to a free function. Unless
|
||||
* @ref RYML_NO_DEFAULT_CALLBACKS is defined, when this
|
||||
* parameter is null, will fall back to ryml's default free
|
||||
* implementation.
|
||||
*
|
||||
* @param error A pointer to an error function, which must never
|
||||
* return (see @ref pfn_error). Unless
|
||||
* @ref RYML_NO_DEFAULT_CALLBACKS is defined, when this
|
||||
* parameter is null, will fall back to ryml's default
|
||||
* error implementation.
|
||||
*/
|
||||
Callbacks(void *user_data, pfn_allocate alloc, pfn_free free, pfn_error error);
|
||||
|
||||
bool operator!= (Callbacks const& that) const { return !operator==(that); }
|
||||
bool operator== (Callbacks const& that) const
|
||||
@@ -187,24 +326,44 @@ struct RYML_EXPORT Callbacks
|
||||
}
|
||||
};
|
||||
|
||||
/** set the global callbacks.
|
||||
*
|
||||
* @warning the error callback must never return: it must either abort
|
||||
* or throw an exception. Otherwise, the parser will enter into an
|
||||
* infinite loop, or the program may crash. */
|
||||
RYML_EXPORT void set_callbacks(Callbacks const& c);
|
||||
/// get the global callbacks
|
||||
RYML_EXPORT Callbacks const& get_callbacks();
|
||||
/// set the global callbacks back to their defaults
|
||||
RYML_EXPORT void reset_callbacks();
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/// @cond dev
|
||||
|
||||
// BEWARE! MSVC requires that [[noreturn]] appears before RYML_EXPORT
|
||||
[[noreturn]] RYML_EXPORT void error(Callbacks const& cb, const char *msg, size_t msg_len, Location loc);
|
||||
[[noreturn]] RYML_EXPORT void error(const char *msg, size_t msg_len, Location loc);
|
||||
|
||||
[[noreturn]] inline void error(const char *msg, size_t msg_len)
|
||||
{
|
||||
error(msg, msg_len, Location{});
|
||||
}
|
||||
template<size_t N>
|
||||
[[noreturn]] inline void error(const char (&msg)[N], Location loc)
|
||||
{
|
||||
error(msg, N-1, loc);
|
||||
}
|
||||
template<size_t N>
|
||||
[[noreturn]] inline void error(const char (&msg)[N])
|
||||
{
|
||||
error(msg, N-1, Location{});
|
||||
}
|
||||
|
||||
#define _RYML_CB_ERR(cb, msg_literal) \
|
||||
do \
|
||||
{ \
|
||||
const char msg[] = msg_literal; \
|
||||
RYML_DEBUG_BREAK() \
|
||||
(cb).m_error(msg, sizeof(msg), c4::yml::Location(__FILE__, 0, __LINE__, 0), (cb).m_user_data); \
|
||||
c4::yml::error((cb), \
|
||||
msg, sizeof(msg), \
|
||||
c4::yml::Location(__FILE__, 0, __LINE__, 0)); \
|
||||
C4_UNREACHABLE_AFTER_ERR(); \
|
||||
} while(0)
|
||||
#define _RYML_CB_CHECK(cb, cond) \
|
||||
do \
|
||||
@@ -213,7 +372,10 @@ do \
|
||||
{ \
|
||||
const char msg[] = "check failed: " #cond; \
|
||||
RYML_DEBUG_BREAK() \
|
||||
(cb).m_error(msg, sizeof(msg), c4::yml::Location(__FILE__, 0, __LINE__, 0), (cb).m_user_data); \
|
||||
c4::yml::error((cb), \
|
||||
msg, sizeof(msg), \
|
||||
c4::yml::Location(__FILE__, 0, __LINE__, 0)); \
|
||||
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)
|
||||
@@ -225,7 +387,6 @@ do \
|
||||
} while(0)
|
||||
|
||||
|
||||
|
||||
namespace detail {
|
||||
template<int8_t signedval, uint8_t unsignedval>
|
||||
struct _charconstant_t
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include "c4/yml/emit.hpp"
|
||||
#endif
|
||||
|
||||
/** @file emit.def.hpp Definitions for emit functions. */
|
||||
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
@@ -16,6 +18,8 @@ substr Emitter<Writer>::emit_as(EmitType_e type, Tree const& t, size_t id, bool
|
||||
_RYML_CB_ASSERT(t.callbacks(), id == NONE);
|
||||
return {};
|
||||
}
|
||||
if(id == NONE)
|
||||
id = t.root_id();
|
||||
_RYML_CB_CHECK(t.callbacks(), id < t.capacity());
|
||||
m_tree = &t;
|
||||
if(type == EMIT_YAML)
|
||||
@@ -24,6 +28,7 @@ substr Emitter<Writer>::emit_as(EmitType_e type, Tree const& t, size_t id, bool
|
||||
_do_visit_json(id);
|
||||
else
|
||||
_RYML_CB_ERR(m_tree->callbacks(), "unknown emit type");
|
||||
m_tree = nullptr;
|
||||
return this->Writer::_get(error_on_excess);
|
||||
}
|
||||
|
||||
@@ -269,13 +274,15 @@ void Emitter<Writer>::_do_visit_flow_sl(size_t node, size_t ilevel)
|
||||
}
|
||||
}
|
||||
|
||||
C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4702) // unreachable error, triggered by flow_ml not implemented
|
||||
|
||||
template<class Writer>
|
||||
void Emitter<Writer>::_do_visit_flow_ml(size_t id, size_t ilevel, size_t do_indent)
|
||||
{
|
||||
C4_UNUSED(id);
|
||||
C4_UNUSED(ilevel);
|
||||
C4_UNUSED(do_indent);
|
||||
RYML_CHECK(false/*not implemented*/);
|
||||
c4::yml::error("not implemented");
|
||||
}
|
||||
|
||||
template<class Writer>
|
||||
@@ -452,6 +459,9 @@ void Emitter<Writer>::_do_visit_block(size_t node, size_t ilevel, size_t do_inde
|
||||
_do_visit_block_container(node, next_level, do_indent);
|
||||
}
|
||||
|
||||
C4_SUPPRESS_WARNING_MSVC_POP
|
||||
|
||||
|
||||
template<class Writer>
|
||||
void Emitter<Writer>::_do_visit_json(size_t id)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef _C4_YML_EMIT_HPP_
|
||||
#define _C4_YML_EMIT_HPP_
|
||||
|
||||
/** @file emit.hpp Utilities to emit YAML and JSON. */
|
||||
|
||||
#ifndef _C4_YML_WRITER_HPP_
|
||||
#include "./writer.hpp"
|
||||
#endif
|
||||
@@ -13,12 +15,11 @@
|
||||
#include "./node.hpp"
|
||||
#endif
|
||||
|
||||
|
||||
#define RYML_DEPRECATE_EMIT \
|
||||
RYML_DEPRECATED("use emit_yaml() instead. See https://github.com/biojppm/rapidyaml/issues/120")
|
||||
#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")
|
||||
|
||||
@@ -30,50 +31,58 @@
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
template<class Writer> class Emitter;
|
||||
/** @addtogroup doc_emit
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
// fwd declarations
|
||||
template<class Writer> class Emitter;
|
||||
template<class OStream>
|
||||
using EmitterOStream = Emitter<WriterOStream<OStream>>;
|
||||
using EmitterFile = Emitter<WriterFile>;
|
||||
using EmitterBuf = Emitter<WriterBuf>;
|
||||
|
||||
/** Specifies the type of content to emit */
|
||||
typedef enum {
|
||||
EMIT_YAML = 0,
|
||||
EMIT_JSON = 1
|
||||
EMIT_YAML = 0, ///< emit YAML
|
||||
EMIT_JSON = 1 ///< emit JSON
|
||||
} EmitType_e;
|
||||
|
||||
|
||||
/** mark a tree or node to be emitted as json */
|
||||
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()) {}
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** A stateful emitter, for use with a writer such as @ref WriterBuf,
|
||||
* @ref WriterFile, or @ref WriterOStream */
|
||||
template<class Writer>
|
||||
class Emitter : public Writer
|
||||
{
|
||||
public:
|
||||
|
||||
using Writer::Writer;
|
||||
|
||||
/** Construct the emitter and its internal Writer state. Every
|
||||
* parameter is forwarded to the constructor of the writer. */
|
||||
template<class ...Args>
|
||||
Emitter(Args &&...args) : Writer(std::forward<Args>(args)...), m_tree() {}
|
||||
/** emit!
|
||||
|
||||
*
|
||||
* When writing to a buffer, returns a substr of the emitted YAML.
|
||||
* If the given buffer has insufficient space, the returned span will
|
||||
* be null and its size will be the needed space. No writes are done
|
||||
* after the end of the buffer.
|
||||
* If the given buffer has insufficient space, the returned substr
|
||||
* will be null and its size will be the needed space. Whatever
|
||||
* the size of the buffer, it is guaranteed that no writes are
|
||||
* done past its end.
|
||||
*
|
||||
* When writing to a file, the returned substr will be null, but its
|
||||
* length will be set to the number of bytes written. */
|
||||
* length will be set to the number of bytes written.
|
||||
*
|
||||
* @param type specify what to emit
|
||||
* @param t the tree to emit
|
||||
* @param id the id of the node to emit
|
||||
* @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);
|
||||
/** emit starting at the root node */
|
||||
substr emit_as(EmitType_e type, Tree const& t, bool error_on_excess=true);
|
||||
@@ -132,6 +141,12 @@ private:
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @defgroup doc_emit_to_file Emit to file
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** 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)
|
||||
@@ -139,11 +154,6 @@ inline size_t emit_yaml(Tree const& t, size_t id, FILE *f)
|
||||
EmitterFile em(f);
|
||||
return em.emit_as(EMIT_YAML, t, id, /*error_on_excess*/true).len;
|
||||
}
|
||||
RYML_DEPRECATE_EMIT inline size_t emit(Tree const& t, size_t id, FILE *f)
|
||||
{
|
||||
return emit_yaml(t, id, f);
|
||||
}
|
||||
|
||||
/** 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)
|
||||
@@ -161,11 +171,6 @@ 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;
|
||||
}
|
||||
RYML_DEPRECATE_EMIT inline size_t emit(Tree const& t, FILE *f=nullptr)
|
||||
{
|
||||
return emit_yaml(t, f);
|
||||
}
|
||||
|
||||
/** emit JSON to the given file. A null file defaults to stdout.
|
||||
* Return the number of bytes written.
|
||||
* @overload */
|
||||
@@ -184,11 +189,6 @@ inline size_t emit_yaml(ConstNodeRef const& r, FILE *f=nullptr)
|
||||
EmitterFile em(f);
|
||||
return em.emit_as(EMIT_YAML, r, /*error_on_excess*/true).len;
|
||||
}
|
||||
RYML_DEPRECATE_EMIT inline size_t emit(ConstNodeRef const& r, FILE *f=nullptr)
|
||||
{
|
||||
return emit_yaml(r, f);
|
||||
}
|
||||
|
||||
/** emit JSON to the given file. A null file defaults to stdout.
|
||||
* Return the number of bytes written.
|
||||
* @overload */
|
||||
@@ -198,9 +198,34 @@ inline size_t emit_json(ConstNodeRef const& r, FILE *f=nullptr)
|
||||
return em.emit_as(EMIT_JSON, r, /*error_on_excess*/true).len;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @defgroup doc_emit_to_ostream Emit to an STL-like ostream
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** 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)
|
||||
@@ -229,9 +254,15 @@ inline OStream& operator<< (OStream& s, as_json const& j)
|
||||
return s;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @defgroup doc_emit_to_buffer Emit to memory buffer
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** emit YAML to the given buffer. Return a substr trimmed to the emitted YAML.
|
||||
* @param error_on_excess Raise an error if the space in the buffer is insufficient.
|
||||
@@ -241,11 +272,6 @@ inline substr emit_yaml(Tree const& t, size_t id, substr buf, bool error_on_exce
|
||||
EmitterBuf em(buf);
|
||||
return em.emit_as(EMIT_YAML, t, id, error_on_excess);
|
||||
}
|
||||
RYML_DEPRECATE_EMIT inline substr emit(Tree const& t, size_t id, substr buf, bool error_on_excess=true)
|
||||
{
|
||||
return emit_yaml(t, id, buf, error_on_excess);
|
||||
}
|
||||
|
||||
/** emit JSON to the given buffer. Return a substr trimmed to the emitted JSON.
|
||||
* @param error_on_excess Raise an error if the space in the buffer is insufficient.
|
||||
* @overload */
|
||||
@@ -264,11 +290,6 @@ 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);
|
||||
}
|
||||
RYML_DEPRECATE_EMIT inline substr emit(Tree const& t, substr buf, bool error_on_excess=true)
|
||||
{
|
||||
return emit_yaml(t, buf, error_on_excess);
|
||||
}
|
||||
|
||||
/** emit JSON to the given buffer. Return a substr trimmed to the emitted JSON.
|
||||
* @param error_on_excess Raise an error if the space in the buffer is insufficient.
|
||||
* @overload */
|
||||
@@ -288,11 +309,6 @@ inline substr emit_yaml(ConstNodeRef const& r, substr buf, bool error_on_excess=
|
||||
EmitterBuf em(buf);
|
||||
return em.emit_as(EMIT_YAML, r, error_on_excess);
|
||||
}
|
||||
RYML_DEPRECATE_EMIT inline substr emit(ConstNodeRef const& r, substr buf, bool error_on_excess=true)
|
||||
{
|
||||
return emit_yaml(r, buf, error_on_excess);
|
||||
}
|
||||
|
||||
/** emit JSON to the given buffer. Return a substr trimmed to the emitted JSON.
|
||||
* @param error_on_excess Raise an error if the space in the buffer is insufficient.
|
||||
* @overload
|
||||
@@ -306,7 +322,7 @@ 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
|
||||
/** emit+resize: emit YAML to the given `std::string`/`std::vector`-like
|
||||
* container, resizing it as needed to fit the emitted YAML. */
|
||||
template<class CharOwningContainer>
|
||||
substr emitrs_yaml(Tree const& t, size_t id, CharOwningContainer * cont)
|
||||
@@ -321,13 +337,7 @@ substr emitrs_yaml(Tree const& t, size_t id, CharOwningContainer * cont)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
template<class CharOwningContainer>
|
||||
RYML_DEPRECATE_EMITRS substr emitrs(Tree const& t, size_t id, CharOwningContainer * cont)
|
||||
{
|
||||
return emitrs_yaml(t, id, cont);
|
||||
}
|
||||
|
||||
/** emit+resize: emit JSON to the given std::string/std::vector-like
|
||||
/** emit+resize: emit JSON to the given `std::string`/`std::vector`-like
|
||||
* container, resizing it as needed to fit the emitted JSON. */
|
||||
template<class CharOwningContainer>
|
||||
substr emitrs_json(Tree const& t, size_t id, CharOwningContainer * cont)
|
||||
@@ -344,7 +354,7 @@ substr emitrs_json(Tree const& t, size_t id, CharOwningContainer * cont)
|
||||
}
|
||||
|
||||
|
||||
/** emit+resize: emit YAML to the given std::string/std::vector-like
|
||||
/** emit+resize: emit YAML to the given `std::string`/`std::vector`-like
|
||||
* container, resizing it as needed to fit the emitted YAML. */
|
||||
template<class CharOwningContainer>
|
||||
CharOwningContainer emitrs_yaml(Tree const& t, size_t id)
|
||||
@@ -353,15 +363,7 @@ CharOwningContainer emitrs_yaml(Tree const& t, size_t id)
|
||||
emitrs_yaml(t, id, &c);
|
||||
return c;
|
||||
}
|
||||
template<class CharOwningContainer>
|
||||
RYML_DEPRECATE_EMITRS CharOwningContainer emitrs(Tree const& t, size_t id)
|
||||
{
|
||||
CharOwningContainer c;
|
||||
emitrs_yaml(t, id, &c);
|
||||
return c;
|
||||
}
|
||||
|
||||
/** emit+resize: emit JSON to the given std::string/std::vector-like
|
||||
/** emit+resize: emit JSON to the given `std::string`/`std::vector`-like
|
||||
* container, resizing it as needed to fit the emitted JSON. */
|
||||
template<class CharOwningContainer>
|
||||
CharOwningContainer emitrs_json(Tree const& t, size_t id)
|
||||
@@ -372,7 +374,7 @@ CharOwningContainer emitrs_json(Tree const& t, size_t id)
|
||||
}
|
||||
|
||||
|
||||
/** emit+resize: YAML to the given std::string/std::vector-like
|
||||
/** emit+resize: YAML to the given `std::string`/`std::vector`-like
|
||||
* container, resizing it as needed to fit the emitted YAML. */
|
||||
template<class CharOwningContainer>
|
||||
substr emitrs_yaml(Tree const& t, CharOwningContainer * cont)
|
||||
@@ -381,13 +383,7 @@ substr emitrs_yaml(Tree const& t, CharOwningContainer * cont)
|
||||
return {};
|
||||
return emitrs_yaml(t, t.root_id(), cont);
|
||||
}
|
||||
template<class CharOwningContainer>
|
||||
RYML_DEPRECATE_EMITRS substr emitrs(Tree const& t, CharOwningContainer * cont)
|
||||
{
|
||||
return emitrs_yaml(t, cont);
|
||||
}
|
||||
|
||||
/** emit+resize: JSON to the given std::string/std::vector-like
|
||||
/** emit+resize: JSON to the given `std::string`/`std::vector`-like
|
||||
* container, resizing it as needed to fit the emitted JSON. */
|
||||
template<class CharOwningContainer>
|
||||
substr emitrs_json(Tree const& t, CharOwningContainer * cont)
|
||||
@@ -398,7 +394,7 @@ substr emitrs_json(Tree const& t, CharOwningContainer * cont)
|
||||
}
|
||||
|
||||
|
||||
/** emit+resize: YAML to the given std::string/std::vector-like container,
|
||||
/** emit+resize: YAML to the given `std::string`/`std::vector`-like container,
|
||||
* resizing it as needed to fit the emitted YAML. */
|
||||
template<class CharOwningContainer>
|
||||
CharOwningContainer emitrs_yaml(Tree const& t)
|
||||
@@ -409,13 +405,7 @@ CharOwningContainer emitrs_yaml(Tree const& t)
|
||||
emitrs_yaml(t, t.root_id(), &c);
|
||||
return c;
|
||||
}
|
||||
template<class CharOwningContainer>
|
||||
RYML_DEPRECATE_EMITRS CharOwningContainer emitrs(Tree const& t)
|
||||
{
|
||||
return emitrs_yaml<CharOwningContainer>(t);
|
||||
}
|
||||
|
||||
/** emit+resize: JSON to the given std::string/std::vector-like container,
|
||||
/** emit+resize: JSON to the given `std::string`/`std::vector`-like container,
|
||||
* resizing it as needed to fit the emitted JSON. */
|
||||
template<class CharOwningContainer>
|
||||
CharOwningContainer emitrs_json(Tree const& t)
|
||||
@@ -428,7 +418,7 @@ CharOwningContainer emitrs_json(Tree const& t)
|
||||
}
|
||||
|
||||
|
||||
/** emit+resize: YAML to the given std::string/std::vector-like container,
|
||||
/** emit+resize: YAML to the given `std::string`/`std::vector`-like container,
|
||||
* resizing it as needed to fit the emitted YAML. */
|
||||
template<class CharOwningContainer>
|
||||
substr emitrs_yaml(ConstNodeRef const& n, CharOwningContainer * cont)
|
||||
@@ -436,13 +426,7 @@ substr emitrs_yaml(ConstNodeRef const& n, CharOwningContainer * cont)
|
||||
_RYML_CB_CHECK(n.tree()->callbacks(), n.readable());
|
||||
return emitrs_yaml(*n.tree(), n.id(), cont);
|
||||
}
|
||||
template<class CharOwningContainer>
|
||||
RYML_DEPRECATE_EMITRS substr emitrs(ConstNodeRef const& n, CharOwningContainer * cont)
|
||||
{
|
||||
return emitrs_yaml(n, cont);
|
||||
}
|
||||
|
||||
/** emit+resize: JSON to the given std::string/std::vector-like container,
|
||||
/** emit+resize: JSON to the given `std::string`/`std::vector`-like container,
|
||||
* resizing it as needed to fit the emitted JSON. */
|
||||
template<class CharOwningContainer>
|
||||
substr emitrs_json(ConstNodeRef const& n, CharOwningContainer * cont)
|
||||
@@ -452,7 +436,7 @@ substr emitrs_json(ConstNodeRef const& n, CharOwningContainer * cont)
|
||||
}
|
||||
|
||||
|
||||
/** emit+resize: YAML to the given std::string/std::vector-like container,
|
||||
/** emit+resize: YAML to the given `std::string`/`std::vector`-like container,
|
||||
* resizing it as needed to fit the emitted YAML. */
|
||||
template<class CharOwningContainer>
|
||||
CharOwningContainer emitrs_yaml(ConstNodeRef const& n)
|
||||
@@ -462,13 +446,7 @@ CharOwningContainer emitrs_yaml(ConstNodeRef const& n)
|
||||
emitrs_yaml(*n.tree(), n.id(), &c);
|
||||
return c;
|
||||
}
|
||||
template<class CharOwningContainer>
|
||||
RYML_DEPRECATE_EMITRS CharOwningContainer emitrs(ConstNodeRef const& n)
|
||||
{
|
||||
return emitrs_yaml<CharOwningContainer>(n);
|
||||
}
|
||||
|
||||
/** emit+resize: JSON to the given std::string/std::vector-like container,
|
||||
/** emit+resize: JSON to the given `std::string`/`std::vector`-like container,
|
||||
* resizing it as needed to fit the emitted JSON. */
|
||||
template<class CharOwningContainer>
|
||||
CharOwningContainer emitrs_json(ConstNodeRef const& n)
|
||||
@@ -479,6 +457,72 @@ CharOwningContainer emitrs_json(ConstNodeRef const& n)
|
||||
return c;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @cond dev */
|
||||
|
||||
RYML_DEPRECATE_EMIT inline size_t emit(Tree const& t, size_t id, FILE *f)
|
||||
{
|
||||
return emit_yaml(t, id, f);
|
||||
}
|
||||
RYML_DEPRECATE_EMIT inline size_t emit(Tree const& t, FILE *f=nullptr)
|
||||
{
|
||||
return emit_yaml(t, f);
|
||||
}
|
||||
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)
|
||||
{
|
||||
return emit_yaml(t, id, buf, error_on_excess);
|
||||
}
|
||||
RYML_DEPRECATE_EMIT inline substr emit(Tree const& t, substr buf, bool error_on_excess=true)
|
||||
{
|
||||
return emit_yaml(t, buf, error_on_excess);
|
||||
}
|
||||
RYML_DEPRECATE_EMIT inline substr emit(ConstNodeRef const& r, substr buf, bool error_on_excess=true)
|
||||
{
|
||||
return emit_yaml(r, buf, error_on_excess);
|
||||
}
|
||||
|
||||
template<class CharOwningContainer>
|
||||
RYML_DEPRECATE_EMITRS substr emitrs(Tree const& t, size_t id, CharOwningContainer * cont)
|
||||
{
|
||||
return emitrs_yaml(t, id, cont);
|
||||
}
|
||||
template<class CharOwningContainer>
|
||||
RYML_DEPRECATE_EMITRS CharOwningContainer emitrs(Tree const& t, size_t id)
|
||||
{
|
||||
return emitrs_yaml<CharOwningContainer>(t, id);
|
||||
}
|
||||
template<class CharOwningContainer>
|
||||
RYML_DEPRECATE_EMITRS substr emitrs(Tree const& t, CharOwningContainer * cont)
|
||||
{
|
||||
return emitrs_yaml(t, cont);
|
||||
}
|
||||
template<class CharOwningContainer>
|
||||
RYML_DEPRECATE_EMITRS CharOwningContainer emitrs(Tree const& t)
|
||||
{
|
||||
return emitrs_yaml<CharOwningContainer>(t);
|
||||
}
|
||||
template<class CharOwningContainer>
|
||||
RYML_DEPRECATE_EMITRS substr emitrs(ConstNodeRef const& n, CharOwningContainer * cont)
|
||||
{
|
||||
return emitrs_yaml(n, cont);
|
||||
}
|
||||
template<class CharOwningContainer>
|
||||
RYML_DEPRECATE_EMITRS CharOwningContainer emitrs(ConstNodeRef const& n)
|
||||
{
|
||||
return emitrs_yaml<CharOwningContainer>(n);
|
||||
}
|
||||
/** @endcond */
|
||||
|
||||
|
||||
} // namespace yml
|
||||
} // namespace c4
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#ifndef _C4_YML_NODE_HPP_
|
||||
#define _C4_YML_NODE_HPP_
|
||||
|
||||
/** @file node.hpp
|
||||
* @see NodeRef */
|
||||
/** @file node.hpp Node classes */
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
@@ -26,6 +25,16 @@
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
/** @addtogroup doc_node_classes
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup doc_serialization_helpers Serialization helpers
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
template<class K> struct Key { K & k; };
|
||||
template<> struct Key<fmt::const_base64_wrapper> { fmt::const_base64_wrapper wrapper; };
|
||||
template<> struct Key<fmt::base64_wrapper> { fmt::base64_wrapper wrapper; };
|
||||
@@ -44,6 +53,8 @@ template<class T>
|
||||
typename std::enable_if< std::is_floating_point<T>::value, bool>::type
|
||||
read(NodeRef const& n, T *v);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -53,10 +64,12 @@ read(NodeRef const& n, T *v);
|
||||
class NodeRef;
|
||||
class ConstNodeRef;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @cond dev */
|
||||
namespace detail {
|
||||
|
||||
template<class NodeRefType>
|
||||
@@ -145,14 +158,22 @@ bool _visit_stacked(NodeRefType &node, Visitor fn, size_t indentation_level, boo
|
||||
return false;
|
||||
}
|
||||
|
||||
template<class Impl, class ConstImpl>
|
||||
struct RoNodeMethods;
|
||||
} // detail
|
||||
/** @endcond */
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** a CRTP base for read-only node methods */
|
||||
|
||||
/** a CRTP base providing read-only methods for @ref ConstNodeRef and @ref NodeRef */
|
||||
template<class Impl, class ConstImpl>
|
||||
struct RoNodeMethods
|
||||
struct detail::RoNodeMethods
|
||||
{
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wcast-align")
|
||||
/** @cond dev */
|
||||
// helper CRTP macros, undefined at the end
|
||||
#define tree_ ((ConstImpl const* C4_RESTRICT)this)->m_tree
|
||||
#define id_ ((ConstImpl const* C4_RESTRICT)this)->m_id
|
||||
@@ -163,8 +184,9 @@ struct RoNodeMethods
|
||||
#define _C4RR() \
|
||||
RYML_ASSERT(tree_ != nullptr); \
|
||||
_RYML_CB_ASSERT(tree_->m_callbacks, id_ != NONE); \
|
||||
_RYML_CB_ASSERT(tree_->m_callbacks, (((Impl const* C4_RESTRICT)this)->readable()));
|
||||
_RYML_CB_ASSERT(tree_->m_callbacks, (((Impl const* C4_RESTRICT)this)->readable()))
|
||||
#define _C4_IF_MUTABLE(ty) typename std::enable_if<!std::is_same<U, ConstImpl>::value, ty>::type
|
||||
/** @endcond */
|
||||
|
||||
public:
|
||||
|
||||
@@ -177,7 +199,7 @@ public:
|
||||
template<class U=Impl>
|
||||
C4_ALWAYS_INLINE auto get() RYML_NOEXCEPT -> _C4_IF_MUTABLE(NodeData*) { return ((Impl const*)this)->readable() ? tree__->get(id__) : nullptr; }
|
||||
|
||||
C4_ALWAYS_INLINE NodeType type() const RYML_NOEXCEPT { _C4RR(); return tree_->type(id_); }
|
||||
C4_ALWAYS_INLINE NodeType type() const RYML_NOEXCEPT { _C4RR(); return tree_->type(id_); }
|
||||
C4_ALWAYS_INLINE const char* type_str() const RYML_NOEXCEPT { _C4RR(); return tree_->type_str(id_); }
|
||||
|
||||
C4_ALWAYS_INLINE csubstr key() const RYML_NOEXCEPT { _C4RR(); return tree_->key(id_); }
|
||||
@@ -203,33 +225,33 @@ public:
|
||||
/** @name node property predicates */
|
||||
/** @{ */
|
||||
|
||||
C4_ALWAYS_INLINE bool empty() const RYML_NOEXCEPT { _C4RR(); return tree_->empty(id_); }
|
||||
C4_ALWAYS_INLINE bool is_stream() const RYML_NOEXCEPT { _C4RR(); return tree_->is_stream(id_); }
|
||||
C4_ALWAYS_INLINE bool is_doc() const RYML_NOEXCEPT { _C4RR(); return tree_->is_doc(id_); }
|
||||
C4_ALWAYS_INLINE bool is_container() const RYML_NOEXCEPT { _C4RR(); return tree_->is_container(id_); }
|
||||
C4_ALWAYS_INLINE bool is_map() const RYML_NOEXCEPT { _C4RR(); return tree_->is_map(id_); }
|
||||
C4_ALWAYS_INLINE bool is_seq() const RYML_NOEXCEPT { _C4RR(); return tree_->is_seq(id_); }
|
||||
C4_ALWAYS_INLINE bool has_val() const RYML_NOEXCEPT { _C4RR(); return tree_->has_val(id_); }
|
||||
C4_ALWAYS_INLINE bool has_key() const RYML_NOEXCEPT { _C4RR(); return tree_->has_key(id_); }
|
||||
C4_ALWAYS_INLINE bool is_val() const RYML_NOEXCEPT { _C4RR(); return tree_->is_val(id_); }
|
||||
C4_ALWAYS_INLINE bool is_keyval() const RYML_NOEXCEPT { _C4RR(); return tree_->is_keyval(id_); }
|
||||
C4_ALWAYS_INLINE bool has_key_tag() const RYML_NOEXCEPT { _C4RR(); return tree_->has_key_tag(id_); }
|
||||
C4_ALWAYS_INLINE bool has_val_tag() const RYML_NOEXCEPT { _C4RR(); return tree_->has_val_tag(id_); }
|
||||
C4_ALWAYS_INLINE bool has_key_anchor() const RYML_NOEXCEPT { _C4RR(); return tree_->has_key_anchor(id_); }
|
||||
C4_ALWAYS_INLINE bool is_key_anchor() const RYML_NOEXCEPT { _C4RR(); return tree_->is_key_anchor(id_); }
|
||||
C4_ALWAYS_INLINE bool has_val_anchor() const RYML_NOEXCEPT { _C4RR(); return tree_->has_val_anchor(id_); }
|
||||
C4_ALWAYS_INLINE bool is_val_anchor() const RYML_NOEXCEPT { _C4RR(); return tree_->is_val_anchor(id_); }
|
||||
C4_ALWAYS_INLINE bool has_anchor() const RYML_NOEXCEPT { _C4RR(); return tree_->has_anchor(id_); }
|
||||
C4_ALWAYS_INLINE bool is_anchor() const RYML_NOEXCEPT { _C4RR(); return tree_->is_anchor(id_); }
|
||||
C4_ALWAYS_INLINE bool is_key_ref() const RYML_NOEXCEPT { _C4RR(); return tree_->is_key_ref(id_); }
|
||||
C4_ALWAYS_INLINE bool is_val_ref() const RYML_NOEXCEPT { _C4RR(); return tree_->is_val_ref(id_); }
|
||||
C4_ALWAYS_INLINE bool is_ref() const RYML_NOEXCEPT { _C4RR(); return tree_->is_ref(id_); }
|
||||
C4_ALWAYS_INLINE bool is_anchor_or_ref() const RYML_NOEXCEPT { _C4RR(); return tree_->is_anchor_or_ref(id_); }
|
||||
C4_ALWAYS_INLINE bool is_key_quoted() const RYML_NOEXCEPT { _C4RR(); return tree_->is_key_quoted(id_); }
|
||||
C4_ALWAYS_INLINE bool is_val_quoted() const RYML_NOEXCEPT { _C4RR(); return tree_->is_val_quoted(id_); }
|
||||
C4_ALWAYS_INLINE bool is_quoted() const RYML_NOEXCEPT { _C4RR(); return tree_->is_quoted(id_); }
|
||||
C4_ALWAYS_INLINE bool parent_is_seq() const RYML_NOEXCEPT { _C4RR(); return tree_->parent_is_seq(id_); }
|
||||
C4_ALWAYS_INLINE bool parent_is_map() const RYML_NOEXCEPT { _C4RR(); return tree_->parent_is_map(id_); }
|
||||
C4_ALWAYS_INLINE bool empty() const RYML_NOEXCEPT { _C4RR(); return tree_->empty(id_); } /**< Forward to Tree::empty(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool is_stream() const RYML_NOEXCEPT { _C4RR(); return tree_->is_stream(id_); } /**< Forward to Tree::is_stream(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool is_doc() const RYML_NOEXCEPT { _C4RR(); return tree_->is_doc(id_); } /**< Forward to Tree::is_doc(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool is_container() const RYML_NOEXCEPT { _C4RR(); return tree_->is_container(id_); } /**< Forward to Tree::is_container(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool is_map() const RYML_NOEXCEPT { _C4RR(); return tree_->is_map(id_); } /**< Forward to Tree::is_map(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool is_seq() const RYML_NOEXCEPT { _C4RR(); return tree_->is_seq(id_); } /**< Forward to Tree::is_seq(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool has_val() const RYML_NOEXCEPT { _C4RR(); return tree_->has_val(id_); } /**< Forward to Tree::has_val(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool has_key() const RYML_NOEXCEPT { _C4RR(); return tree_->has_key(id_); } /**< Forward to Tree::has_key(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool is_val() const RYML_NOEXCEPT { _C4RR(); return tree_->is_val(id_); } /**< Forward to Tree::is_val(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool is_keyval() const RYML_NOEXCEPT { _C4RR(); return tree_->is_keyval(id_); } /**< Forward to Tree::is_keyval(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool has_key_tag() const RYML_NOEXCEPT { _C4RR(); return tree_->has_key_tag(id_); } /**< Forward to Tree::has_key_tag(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool has_val_tag() const RYML_NOEXCEPT { _C4RR(); return tree_->has_val_tag(id_); } /**< Forward to Tree::has_val_tag(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool has_key_anchor() const RYML_NOEXCEPT { _C4RR(); return tree_->has_key_anchor(id_); } /**< Forward to Tree::has_key_anchor(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool is_key_anchor() const RYML_NOEXCEPT { _C4RR(); return tree_->is_key_anchor(id_); } /**< Forward to Tree::is_key_anchor(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool has_val_anchor() const RYML_NOEXCEPT { _C4RR(); return tree_->has_val_anchor(id_); } /**< Forward to Tree::has_val_anchor(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool is_val_anchor() const RYML_NOEXCEPT { _C4RR(); return tree_->is_val_anchor(id_); } /**< Forward to Tree::is_val_anchor(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool has_anchor() const RYML_NOEXCEPT { _C4RR(); return tree_->has_anchor(id_); } /**< Forward to Tree::has_anchor(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool is_anchor() const RYML_NOEXCEPT { _C4RR(); return tree_->is_anchor(id_); } /**< Forward to Tree::is_anchor(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool is_key_ref() const RYML_NOEXCEPT { _C4RR(); return tree_->is_key_ref(id_); } /**< Forward to Tree::is_key_ref(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool is_val_ref() const RYML_NOEXCEPT { _C4RR(); return tree_->is_val_ref(id_); } /**< Forward to Tree::is_val_ref(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool is_ref() const RYML_NOEXCEPT { _C4RR(); return tree_->is_ref(id_); } /**< Forward to Tree::is_ref(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool is_anchor_or_ref() const RYML_NOEXCEPT { _C4RR(); return tree_->is_anchor_or_ref(id_); } /**< Forward to Tree::is_anchor_or_ref(. Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool is_key_quoted() const RYML_NOEXCEPT { _C4RR(); return tree_->is_key_quoted(id_); } /**< Forward to Tree::is_key_quoted(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool is_val_quoted() const RYML_NOEXCEPT { _C4RR(); return tree_->is_val_quoted(id_); } /**< Forward to Tree::is_val_quoted(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool is_quoted() const RYML_NOEXCEPT { _C4RR(); return tree_->is_quoted(id_); } /**< Forward to Tree::is_quoted(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool parent_is_seq() const RYML_NOEXCEPT { _C4RR(); return tree_->parent_is_seq(id_); } /**< Forward to Tree::parent_is_seq(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool parent_is_map() const RYML_NOEXCEPT { _C4RR(); return tree_->parent_is_map(id_); } /**< Forward to Tree::parent_is_map(). Node must be readable. */
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -238,17 +260,17 @@ public:
|
||||
/** @name hierarchy predicates */
|
||||
/** @{ */
|
||||
|
||||
C4_ALWAYS_INLINE bool is_root() const RYML_NOEXCEPT { _C4RR(); return tree_->is_root(id_); }
|
||||
C4_ALWAYS_INLINE bool has_parent() const RYML_NOEXCEPT { _C4RR(); return tree_->has_parent(id_); }
|
||||
C4_ALWAYS_INLINE bool is_root() const RYML_NOEXCEPT { _C4RR(); return tree_->is_root(id_); } /**< Forward to Tree::is_root(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool has_parent() const RYML_NOEXCEPT { _C4RR(); return tree_->has_parent(id_); } /**< Forward to Tree::has_parent() Node must be readable. */
|
||||
|
||||
C4_ALWAYS_INLINE bool has_child(ConstImpl const& n) const RYML_NOEXCEPT { _C4RR(); return n.readable() ? tree_->has_child(id_, n.m_id) : false; }
|
||||
C4_ALWAYS_INLINE bool has_child(size_t node) const RYML_NOEXCEPT { _C4RR(); return tree_->has_child(id_, node); }
|
||||
C4_ALWAYS_INLINE bool has_child(csubstr name) const RYML_NOEXCEPT { _C4RR(); return tree_->has_child(id_, name); }
|
||||
C4_ALWAYS_INLINE bool has_children() const RYML_NOEXCEPT { _C4RR(); return tree_->has_children(id_); }
|
||||
C4_ALWAYS_INLINE bool has_child(ConstImpl const& n) const RYML_NOEXCEPT { _C4RR(); return n.readable() ? tree_->has_child(id_, n.m_id) : false; } /**< Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool has_child(size_t node) const RYML_NOEXCEPT { _C4RR(); return tree_->has_child(id_, node); } /**< Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool has_child(csubstr name) const RYML_NOEXCEPT { _C4RR(); return tree_->has_child(id_, name); } /**< Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool has_children() const RYML_NOEXCEPT { _C4RR(); return tree_->has_children(id_); } /**< Node must be readable. */
|
||||
|
||||
C4_ALWAYS_INLINE bool has_sibling(ConstImpl const& n) const RYML_NOEXCEPT { _C4RR(); return n.readable() ? tree_->has_sibling(id_, n.m_id) : false; }
|
||||
C4_ALWAYS_INLINE bool has_sibling(size_t node) const RYML_NOEXCEPT { _C4RR(); return tree_->has_sibling(id_, node); }
|
||||
C4_ALWAYS_INLINE bool has_sibling(csubstr name) const RYML_NOEXCEPT { _C4RR(); return tree_->has_sibling(id_, name); }
|
||||
C4_ALWAYS_INLINE bool has_sibling(ConstImpl const& n) const RYML_NOEXCEPT { _C4RR(); return n.readable() ? tree_->has_sibling(id_, n.m_id) : false; } /**< Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool has_sibling(size_t node) const RYML_NOEXCEPT { _C4RR(); return tree_->has_sibling(id_, node); } /**< Node must be readable. */
|
||||
C4_ALWAYS_INLINE bool has_sibling(csubstr name) const RYML_NOEXCEPT { _C4RR(); return tree_->has_sibling(id_, name); } /**< Node must be readable. */
|
||||
/** does not count with this */
|
||||
C4_ALWAYS_INLINE bool has_other_siblings() const RYML_NOEXCEPT { _C4RR(); return tree_->has_other_siblings(id_); }
|
||||
|
||||
@@ -262,65 +284,66 @@ public:
|
||||
/** @name hierarchy getters */
|
||||
/** @{ */
|
||||
|
||||
/** succeeds even when the node may have invalid or seed id */
|
||||
template<class U=Impl>
|
||||
C4_ALWAYS_INLINE auto doc(size_t num) RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { RYML_ASSERT(tree_); return {tree__, tree__->doc(num)}; }
|
||||
/** succeeds even when the node may have invalid or seed id */
|
||||
C4_ALWAYS_INLINE ConstImpl doc(size_t num) const RYML_NOEXCEPT { RYML_ASSERT(tree_); return {tree_, tree_->doc(num)}; }
|
||||
C4_ALWAYS_INLINE auto doc(size_t i) RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { RYML_ASSERT(tree_); return {tree__, tree__->doc(i)}; } /**< Forward to Tree::doc(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE ConstImpl doc(size_t i) const RYML_NOEXCEPT { RYML_ASSERT(tree_); return {tree_, tree_->doc(i)}; } /**< Forward to Tree::doc(). Node must be readable. */
|
||||
|
||||
template<class U=Impl>
|
||||
C4_ALWAYS_INLINE auto parent() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->parent(id__)}; }
|
||||
C4_ALWAYS_INLINE ConstImpl parent() const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->parent(id_)}; }
|
||||
C4_ALWAYS_INLINE auto parent() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->parent(id__)}; } /**< Forward to Tree::parent(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE ConstImpl parent() const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->parent(id_)}; } /**< Forward to Tree::parent(). Node must be readable. */
|
||||
|
||||
template<class U=Impl>
|
||||
C4_ALWAYS_INLINE auto first_child() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->first_child(id__)}; }
|
||||
C4_ALWAYS_INLINE ConstImpl first_child() const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->first_child(id_)}; }
|
||||
C4_ALWAYS_INLINE auto first_child() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->first_child(id__)}; } /**< Forward to Tree::first_child(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE ConstImpl first_child() const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->first_child(id_)}; } /**< Forward to Tree::first_child(). Node must be readable. */
|
||||
|
||||
template<class U=Impl>
|
||||
C4_ALWAYS_INLINE auto last_child() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->last_child(id__)}; }
|
||||
C4_ALWAYS_INLINE ConstImpl last_child () const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->last_child (id_)}; }
|
||||
C4_ALWAYS_INLINE auto last_child() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->last_child(id__)}; } /**< Forward to Tree::last_child(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE ConstImpl last_child () const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->last_child (id_)}; } /**< Forward to Tree::last_child(). Node must be readable. */
|
||||
|
||||
template<class U=Impl>
|
||||
C4_ALWAYS_INLINE auto child(size_t pos) RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->child(id__, pos)}; }
|
||||
C4_ALWAYS_INLINE ConstImpl child(size_t pos) const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->child(id_, pos)}; }
|
||||
C4_ALWAYS_INLINE auto child(size_t pos) RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->child(id__, pos)}; } /**< Forward to Tree::child(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE ConstImpl child(size_t pos) const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->child(id_, pos)}; } /**< Forward to Tree::child(). Node must be readable. */
|
||||
|
||||
template<class U=Impl>
|
||||
C4_ALWAYS_INLINE auto find_child(csubstr name) RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->find_child(id__, name)}; }
|
||||
C4_ALWAYS_INLINE ConstImpl find_child(csubstr name) const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->find_child(id_, name)}; }
|
||||
C4_ALWAYS_INLINE auto find_child(csubstr name) RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->find_child(id__, name)}; } /**< Forward to Tree::first_child(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE ConstImpl find_child(csubstr name) const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->find_child(id_, name)}; } /**< Forward to Tree::first_child(). Node must be readable. */
|
||||
|
||||
template<class U=Impl>
|
||||
C4_ALWAYS_INLINE auto prev_sibling() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->prev_sibling(id__)}; }
|
||||
C4_ALWAYS_INLINE ConstImpl prev_sibling() const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->prev_sibling(id_)}; }
|
||||
C4_ALWAYS_INLINE auto prev_sibling() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->prev_sibling(id__)}; } /**< Forward to Tree::prev_sibling(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE ConstImpl prev_sibling() const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->prev_sibling(id_)}; } /**< Forward to Tree::prev_sibling(). Node must be readable. */
|
||||
|
||||
template<class U=Impl>
|
||||
C4_ALWAYS_INLINE auto next_sibling() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->next_sibling(id__)}; }
|
||||
C4_ALWAYS_INLINE ConstImpl next_sibling() const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->next_sibling(id_)}; }
|
||||
C4_ALWAYS_INLINE auto next_sibling() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->next_sibling(id__)}; } /**< Forward to Tree::next_sibling(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE ConstImpl next_sibling() const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->next_sibling(id_)}; } /**< Forward to Tree::next_sibling(). Node must be readable. */
|
||||
|
||||
template<class U=Impl>
|
||||
C4_ALWAYS_INLINE auto first_sibling() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->first_sibling(id__)}; }
|
||||
C4_ALWAYS_INLINE ConstImpl first_sibling() const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->first_sibling(id_)}; }
|
||||
C4_ALWAYS_INLINE auto first_sibling() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->first_sibling(id__)}; } /**< Forward to Tree::first_sibling(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE ConstImpl first_sibling() const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->first_sibling(id_)}; } /**< Forward to Tree::first_sibling(). Node must be readable. */
|
||||
|
||||
template<class U=Impl>
|
||||
C4_ALWAYS_INLINE auto last_sibling() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->last_sibling(id__)}; }
|
||||
C4_ALWAYS_INLINE ConstImpl last_sibling () const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->last_sibling(id_)}; }
|
||||
C4_ALWAYS_INLINE auto last_sibling() RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->last_sibling(id__)}; } /**< Forward to Tree::last_sibling(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE ConstImpl last_sibling () const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->last_sibling(id_)}; } /**< Forward to Tree::last_sibling(). Node must be readable. */
|
||||
|
||||
template<class U=Impl>
|
||||
C4_ALWAYS_INLINE auto sibling(size_t pos) RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->sibling(id__, pos)}; }
|
||||
C4_ALWAYS_INLINE ConstImpl sibling(size_t pos) const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->sibling(id_, pos)}; }
|
||||
C4_ALWAYS_INLINE auto sibling(size_t pos) RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->sibling(id__, pos)}; } /**< Forward to Tree::sibling(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE ConstImpl sibling(size_t pos) const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->sibling(id_, pos)}; } /**< Forward to Tree::sibling(). Node must be readable. */
|
||||
|
||||
template<class U=Impl>
|
||||
C4_ALWAYS_INLINE auto find_sibling(csubstr name) RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->find_sibling(id__, name)}; }
|
||||
C4_ALWAYS_INLINE ConstImpl find_sibling(csubstr name) const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->find_sibling(id_, name)}; }
|
||||
C4_ALWAYS_INLINE auto find_sibling(csubstr name) RYML_NOEXCEPT -> _C4_IF_MUTABLE(Impl) { _C4RR(); return {tree__, tree__->find_sibling(id__, name)}; } /**< Forward to Tree::find_sibling(). Node must be readable. */
|
||||
C4_ALWAYS_INLINE ConstImpl find_sibling(csubstr name) const RYML_NOEXCEPT { _C4RR(); return {tree_, tree_->find_sibling(id_, name)}; } /**< Forward to Tree::find_sibling(). Node must be readable. */
|
||||
|
||||
/** O(#num_children) */
|
||||
C4_ALWAYS_INLINE size_t child_pos(ConstImpl const& n) const RYML_NOEXCEPT { _C4RR(); _RYML_CB_ASSERT(tree_->m_callbacks, n.readable()); return tree_->child_pos(id_, n.m_id); }
|
||||
|
||||
/** O(#num_children) */
|
||||
/** O(num_children). Forward to Tree::num_children(). */
|
||||
C4_ALWAYS_INLINE size_t num_children() const RYML_NOEXCEPT { _C4RR(); return tree_->num_children(id_); }
|
||||
|
||||
/** O(#num_siblings) */
|
||||
C4_ALWAYS_INLINE size_t num_siblings() const RYML_NOEXCEPT { _C4RR(); return tree_->num_siblings(id_); }
|
||||
|
||||
/** O(num_siblings). Return the number of siblings except this. */
|
||||
C4_ALWAYS_INLINE size_t num_other_siblings() const RYML_NOEXCEPT { _C4RR(); return tree_->num_other_siblings(id_); }
|
||||
|
||||
/** O(num_children). Return the position of a child within this node, using Tree::child_pos(). */
|
||||
C4_ALWAYS_INLINE size_t child_pos(ConstImpl const& n) const RYML_NOEXCEPT { _C4RR(); _RYML_CB_ASSERT(tree_->m_callbacks, n.readable()); return tree_->child_pos(id_, n.m_id); }
|
||||
|
||||
/** O(num_siblings) */
|
||||
C4_ALWAYS_INLINE size_t sibling_pos(ConstImpl const& n) const RYML_NOEXCEPT { _C4RR(); _RYML_CB_ASSERT(tree_->callbacks(), n.readable()); return tree_->child_pos(tree_->parent(id_), n.m_id); }
|
||||
|
||||
/** @} */
|
||||
@@ -551,7 +574,7 @@ public:
|
||||
|
||||
public:
|
||||
|
||||
/** deserialization */
|
||||
/** @name deserialization */
|
||||
/** @{ */
|
||||
|
||||
template<class T>
|
||||
@@ -746,14 +769,12 @@ public:
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_POP
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This object holds a pointer to an existing tree, and a node id. It
|
||||
* can be used only to read from the tree.
|
||||
/** Holds a pointer to an existing tree, and a node id. It can be used
|
||||
* only to read from the tree.
|
||||
*
|
||||
* @warning The lifetime of the tree must be larger than that of this
|
||||
* object. It is up to the user to ensure that this happens. */
|
||||
@@ -843,11 +864,13 @@ public:
|
||||
C4_ALWAYS_INLINE bool operator== (ConstNodeRef const& that) const RYML_NOEXCEPT { return that.m_tree == m_tree && m_id == that.m_id; }
|
||||
C4_ALWAYS_INLINE bool operator!= (ConstNodeRef const& that) const RYML_NOEXCEPT { return ! this->operator== (that); }
|
||||
|
||||
/** @cond dev */
|
||||
RYML_DEPRECATED("use invalid()") bool operator== (std::nullptr_t) const noexcept { return m_tree == nullptr || m_id == NONE; }
|
||||
RYML_DEPRECATED("use !invalid()") bool operator!= (std::nullptr_t) const noexcept { return !(m_tree == nullptr || m_id == NONE); }
|
||||
|
||||
RYML_DEPRECATED("use (this->val() == s)") bool operator== (csubstr s) const RYML_NOEXCEPT { RYML_ASSERT(m_tree); _RYML_CB_ASSERT(m_tree->m_callbacks, m_id != NONE); return m_tree->val(m_id) == s; }
|
||||
RYML_DEPRECATED("use (this->val() != s)") bool operator!= (csubstr s) const RYML_NOEXCEPT { RYML_ASSERT(m_tree); _RYML_CB_ASSERT(m_tree->m_callbacks, m_id != NONE); return m_tree->val(m_id) != s; }
|
||||
/** @endcond */
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -863,10 +886,10 @@ public:
|
||||
*
|
||||
* Unlike its imutable ConstNodeRef peer, a NodeRef can be used to
|
||||
* mutate the tree, both by writing to existing nodes and by creating
|
||||
* new nodes to subsequently write to. So, semantically, a NodeRef
|
||||
* new nodes to subsequently write to. Semantically, a NodeRef
|
||||
* object can be in one of three states:
|
||||
*
|
||||
* ```
|
||||
* ```text
|
||||
* invalid := not pointing at anything
|
||||
* readable := points at an existing tree/node
|
||||
* seed := points at an existing tree, and the node
|
||||
@@ -875,11 +898,11 @@ public:
|
||||
*
|
||||
* So both `readable` and `seed` are states where the node is also `valid`.
|
||||
*
|
||||
* ```c++
|
||||
* Tree tree = parse("{a: b}");
|
||||
* ```cpp
|
||||
* Tree t = parse_in_arena("{a: b}");
|
||||
* NodeRef invalid; // not pointing at anything.
|
||||
* NodeRef readable = tree["a"]; // also valid, because "a" exists
|
||||
* NodeRef seed = tree["none"]; // also valid, but is seed because "none" is not in the map
|
||||
* NodeRef readable = t["a"]; // also valid, because "a" exists
|
||||
* NodeRef seed = t["none"]; // also valid, but is seed because "none" is not in the map
|
||||
* ```
|
||||
*
|
||||
* When the object is in seed state, using it to read from the tree is
|
||||
@@ -943,6 +966,8 @@ public:
|
||||
NodeRef(Tree *t, size_t id, csubstr seed_key) : m_tree(t), m_id(id), m_seed(seed_key) {}
|
||||
NodeRef(std::nullptr_t) : m_tree(nullptr), m_id(NONE), m_seed() {}
|
||||
|
||||
inline void _clear_seed() { /*do the following manually or an assert is triggered: */ m_seed.str = nullptr; m_seed.len = NONE; }
|
||||
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
@@ -972,8 +997,6 @@ public:
|
||||
|
||||
RYML_DEPRECATED("use one of readable(), is_seed() or !invalid()") inline bool valid() const { return m_tree != nullptr && m_id != NONE; }
|
||||
|
||||
inline void _clear_seed() { /*do the following manually or an assert is triggered: */ m_seed.str = nullptr; m_seed.len = NONE; }
|
||||
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
@@ -1004,18 +1027,20 @@ public:
|
||||
inline bool operator== (ConstNodeRef const& that) const { return m_tree == that.m_tree && m_id == that.m_id && !is_seed(); }
|
||||
inline bool operator!= (ConstNodeRef const& that) const { return ! this->operator==(that); }
|
||||
|
||||
/** @cond dev */
|
||||
RYML_DEPRECATED("use !readable()") bool operator== (std::nullptr_t) const { return m_tree == nullptr || m_id == NONE || is_seed(); }
|
||||
RYML_DEPRECATED("use readable()") bool operator!= (std::nullptr_t) const { return !(m_tree == nullptr || m_id == NONE || is_seed()); }
|
||||
|
||||
RYML_DEPRECATED("use (this->val() == s)") bool operator== (csubstr s) const { _C4RV(); _RYML_CB_ASSERT(m_tree->m_callbacks, has_val()); return m_tree->val(m_id) == s; }
|
||||
RYML_DEPRECATED("use (this->val() != s)") bool operator!= (csubstr s) const { _C4RV(); _RYML_CB_ASSERT(m_tree->m_callbacks, has_val()); return m_tree->val(m_id) != s; }
|
||||
RYML_DEPRECATED("use `this->val() == s`") bool operator== (csubstr s) const { _C4RV(); _RYML_CB_ASSERT(m_tree->m_callbacks, has_val()); return m_tree->val(m_id) == s; }
|
||||
RYML_DEPRECATED("use `this->val() != s`") bool operator!= (csubstr s) const { _C4RV(); _RYML_CB_ASSERT(m_tree->m_callbacks, has_val()); return m_tree->val(m_id) != s; }
|
||||
/** @endcond */
|
||||
|
||||
/** @} */
|
||||
|
||||
public:
|
||||
|
||||
/** @name node property getters */
|
||||
/** @{ */
|
||||
/** @name node_property_getters
|
||||
* @{ */
|
||||
|
||||
C4_ALWAYS_INLINE C4_PURE Tree * tree() noexcept { return m_tree; }
|
||||
C4_ALWAYS_INLINE C4_PURE Tree const* tree() const noexcept { return m_tree; }
|
||||
@@ -1026,7 +1051,7 @@ public:
|
||||
|
||||
public:
|
||||
|
||||
/** @name node modifiers */
|
||||
/** @name node_modifiers */
|
||||
/** @{ */
|
||||
|
||||
void create() { _apply_seed(); }
|
||||
@@ -1075,8 +1100,6 @@ public:
|
||||
* blob */
|
||||
size_t set_val_serialized(fmt::const_base64_wrapper w);
|
||||
|
||||
public:
|
||||
|
||||
inline void clear()
|
||||
{
|
||||
if(is_seed())
|
||||
@@ -1309,8 +1332,6 @@ public:
|
||||
return r;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
inline NodeRef insert_sibling(ConstNodeRef const& after)
|
||||
{
|
||||
_C4RV();
|
||||
@@ -1507,6 +1528,11 @@ inline ConstNodeRef& ConstNodeRef::operator= (NodeRef && that)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @addtogroup doc_serialization_helpers
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
template<class T>
|
||||
inline void write(NodeRef *n, T const& v)
|
||||
{
|
||||
@@ -1539,6 +1565,10 @@ inline read(ConstNodeRef const& n, T *v)
|
||||
return from_chars_float(n.val(), v);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
} // namespace yml
|
||||
} // namespace c4
|
||||
|
||||
@@ -426,7 +426,8 @@ void Parser::_err(csubstr fmt, Args const& C4_RESTRICT ...args) const
|
||||
writer.append('\n');
|
||||
_fmt_msg(dumpfn);
|
||||
size_t len = writer.pos < RYML_ERRMSG_SIZE ? writer.pos : RYML_ERRMSG_SIZE;
|
||||
m_tree->m_callbacks.m_error(errmsg, len, m_state->pos, m_tree->m_callbacks.m_user_data);
|
||||
c4::yml::error(m_tree->m_callbacks, errmsg, len, m_state->pos);
|
||||
C4_UNREACHABLE_AFTER_ERR();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -1043,8 +1044,7 @@ bool Parser::_handle_seq_flow()
|
||||
{
|
||||
_c4err("internal error");
|
||||
}
|
||||
|
||||
return true;
|
||||
C4_UNREACHABLE();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -1572,8 +1572,7 @@ bool Parser::_handle_map_flow()
|
||||
{
|
||||
_c4err("internal error");
|
||||
}
|
||||
|
||||
return false;
|
||||
C4_UNREACHABLE();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -1849,8 +1848,7 @@ bool Parser::_handle_map_blck()
|
||||
{
|
||||
_c4err("internal error");
|
||||
}
|
||||
|
||||
return false;
|
||||
C4_UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
@@ -1900,8 +1898,7 @@ bool Parser::_handle_top()
|
||||
{
|
||||
_c4err("parse error");
|
||||
}
|
||||
|
||||
return false;
|
||||
C4_UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
@@ -1934,8 +1931,7 @@ bool Parser::_handle_key_anchors_and_refs()
|
||||
else if(C4_UNLIKELY(rem.begins_with('*')))
|
||||
{
|
||||
_c4err("not implemented - this should have been catched elsewhere");
|
||||
C4_NEVER_REACH();
|
||||
return false;
|
||||
C4_UNREACHABLE();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1993,8 +1989,7 @@ bool Parser::_handle_val_anchors_and_refs()
|
||||
else if(C4_UNLIKELY(rem.begins_with('*')))
|
||||
{
|
||||
_c4err("not implemented - this should have been catched elsewhere");
|
||||
C4_NEVER_REACH();
|
||||
return false;
|
||||
C4_UNREACHABLE();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef _C4_YML_PARSE_HPP_
|
||||
#define _C4_YML_PARSE_HPP_
|
||||
|
||||
/** @file parse.hpp Utilities to parse YAML and JSON */
|
||||
|
||||
#ifndef _C4_YML_TREE_HPP_
|
||||
#include "c4/yml/tree.hpp"
|
||||
#endif
|
||||
@@ -23,6 +25,12 @@
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
/** @addtogroup doc_parse
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Options to initialize a @ref Parser object. */
|
||||
struct RYML_EXPORT ParserOptions
|
||||
{
|
||||
private:
|
||||
@@ -57,6 +65,7 @@ public:
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
/** A reusable object to parse YAML/JSON and create the ryml @ref Tree. */
|
||||
class RYML_EXPORT Parser
|
||||
{
|
||||
public:
|
||||
@@ -141,7 +150,10 @@ public:
|
||||
|
||||
public:
|
||||
|
||||
/** @name parse_in_place */
|
||||
/** @name parse_in_place
|
||||
*
|
||||
* parse a mutable buffer in situ, potentially mutating it.
|
||||
*/
|
||||
/** @{ */
|
||||
|
||||
/** Create a new tree and parse into its root.
|
||||
@@ -185,8 +197,10 @@ public:
|
||||
|
||||
public:
|
||||
|
||||
/** @name parse_in_arena: copy the YAML source buffer to the
|
||||
* tree's arena, then parse the copy in situ
|
||||
/** @name parse_in_arena
|
||||
*
|
||||
* copy the YAML source buffer to the tree's arena, then parse the
|
||||
* copy in situ
|
||||
*
|
||||
* @note overloads receiving a substr YAML buffer are intentionally
|
||||
* left undefined, such that calling parse_in_arena() with a substr
|
||||
@@ -201,10 +215,12 @@ public:
|
||||
|
||||
// READ THE NOTE ABOVE!
|
||||
#define RYML_DONT_PARSE_SUBSTR_IN_ARENA "Do not pass a (mutable) substr to parse_in_arena(); if you have a substr, it should be parsed in place. Consider using parse_in_place() instead, or convert the buffer to csubstr prior to calling. This function is deliberately left undefined and will cause a linker error."
|
||||
/** @cond dev */
|
||||
RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) Tree parse_in_arena(csubstr filename, substr csrc);
|
||||
RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(csubstr filename, substr csrc, Tree *t);
|
||||
RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(csubstr filename, substr csrc, Tree *t, size_t node_id);
|
||||
RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(csubstr filename, substr csrc, NodeRef node);
|
||||
/** @endcond */
|
||||
|
||||
/** Create a new tree and parse into its root.
|
||||
* The immutable YAML source is first copied to the tree's arena,
|
||||
@@ -253,10 +269,12 @@ public:
|
||||
this->parse_in_place(filename, src, node.tree(), node.id());
|
||||
}
|
||||
|
||||
/** @cond dev */
|
||||
RYML_DEPRECATED("use parse_in_arena() instead") Tree parse(csubstr filename, csubstr csrc) { return parse_in_arena(filename, csrc); }
|
||||
RYML_DEPRECATED("use parse_in_arena() instead") void parse(csubstr filename, csubstr csrc, Tree *t) { parse_in_arena(filename, csrc, t); }
|
||||
RYML_DEPRECATED("use parse_in_arena() instead") void parse(csubstr filename, csubstr csrc, Tree *t, size_t node_id) { parse_in_arena(filename, csrc, t, node_id); }
|
||||
RYML_DEPRECATED("use parse_in_arena() instead") void parse(csubstr filename, csubstr csrc, NodeRef node) { parse_in_arena(filename, csrc, node); }
|
||||
/** @endcond */
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -565,7 +583,7 @@ private:
|
||||
#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> [[noreturn]] void _err(csubstr fmt, Args const& C4_RESTRICT ...args) const;
|
||||
template<class DumpFn> void _fmt_msg(DumpFn &&dumpfn) const;
|
||||
static csubstr _prfl(substr buf, flag_t v);
|
||||
|
||||
@@ -608,17 +626,19 @@ private:
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @name parse_in_place
|
||||
/** @defgroup doc_parse_in_place Parse in place
|
||||
*
|
||||
* @desc parse a mutable YAML source buffer.
|
||||
* Parse a mutable YAML source buffer to create a ryml @ref Tree,
|
||||
* potentially mutating the buffer.
|
||||
*
|
||||
* @note These freestanding functions use a temporary parser object,
|
||||
* and are convenience functions to easily parse YAML without the need
|
||||
* to instantiate a separate parser. Note that some properties
|
||||
* (notably node locations in the original source code) are only
|
||||
* available through the parser object after it has parsed the
|
||||
* code. If you need access to any of these properties, use
|
||||
* Parser::parse_in_place() */
|
||||
* These freestanding functions use a temporary parser object, and are
|
||||
* convenience functions to easily parse YAML without the need to
|
||||
* instantiate a separate parser. Note that some properties (notably
|
||||
* node locations in the original source code) are only available
|
||||
* through the parser object after it has parsed the code. If you need
|
||||
* access to any of these properties, use Parser::parse_in_place().
|
||||
*
|
||||
* @see Parser */
|
||||
/** @{ */
|
||||
|
||||
inline Tree parse_in_place( substr yaml ) { Parser np; return np.parse_in_place({} , yaml); } //!< parse in-situ a modifiable YAML source buffer.
|
||||
@@ -630,6 +650,7 @@ inline void parse_in_place(csubstr filename, substr yaml, Tree *t, size_t node_i
|
||||
inline void parse_in_place( substr yaml, NodeRef node ) { Parser np; np.parse_in_place({} , yaml, node); } //!< reusing the YAML tree, parse in-situ a modifiable YAML source buffer
|
||||
inline void parse_in_place(csubstr filename, substr yaml, NodeRef node ) { Parser np; np.parse_in_place(filename, yaml, node); } //!< reusing the YAML tree, parse in-situ a modifiable YAML source buffer, providing a filename for error messages.
|
||||
|
||||
/** @cond dev */
|
||||
RYML_DEPRECATED("use parse_in_place() instead") inline Tree parse( substr yaml ) { Parser np; return np.parse_in_place({} , yaml); }
|
||||
RYML_DEPRECATED("use parse_in_place() instead") inline Tree parse(csubstr filename, substr yaml ) { Parser np; return np.parse_in_place(filename, yaml); }
|
||||
RYML_DEPRECATED("use parse_in_place() instead") inline void parse( substr yaml, Tree *t ) { Parser np; np.parse_in_place({} , yaml, t); }
|
||||
@@ -638,22 +659,25 @@ RYML_DEPRECATED("use parse_in_place() instead") inline void parse(
|
||||
RYML_DEPRECATED("use parse_in_place() instead") inline void parse(csubstr filename, substr yaml, Tree *t, size_t node_id) { Parser np; np.parse_in_place(filename, yaml, t, node_id); }
|
||||
RYML_DEPRECATED("use parse_in_place() instead") inline void parse( substr yaml, NodeRef node ) { Parser np; np.parse_in_place({} , yaml, node); }
|
||||
RYML_DEPRECATED("use parse_in_place() instead") inline void parse(csubstr filename, substr yaml, NodeRef node ) { Parser np; np.parse_in_place(filename, yaml, node); }
|
||||
/** @endcond */
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @name parse_in_arena
|
||||
* @desc parse a read-only YAML source buffer, copying it first to the tree's arena.
|
||||
/** @defgroup doc_parse_in_arena Parse in arena
|
||||
*
|
||||
* @note These freestanding functions use a temporary parser object,
|
||||
* and are convenience functions to easily parse YAML without the need
|
||||
* to instantiate a separate parser. Note that some properties
|
||||
* (notably node locations in the original source code) are only
|
||||
* available through the parser object after it has parsed the
|
||||
* code. If you need access to any of these properties, use
|
||||
* Parser::parse_in_arena().
|
||||
* Parse a read-only YAML source buffer to create a ryml @ref Tree,
|
||||
* copying the buffer first to the tree's arena. The copy of the
|
||||
* buffer is then parsed in place.
|
||||
*
|
||||
* These freestanding functions use a temporary parser object, and are
|
||||
* convenience functions to easily parse YAML without the need to
|
||||
* instantiate a separate parser. Note that some properties (notably
|
||||
* node locations in the original source code) are only available
|
||||
* through the parser object after it has parsed the code. If you need
|
||||
* access to any of these properties, use Parser::parse_in_arena().
|
||||
*
|
||||
* @note overloads receiving a substr YAML buffer are intentionally
|
||||
* left undefined, such that calling parse_in_arena() with a substr
|
||||
@@ -663,10 +687,13 @@ RYML_DEPRECATED("use parse_in_place() instead") inline void parse(csubstr filena
|
||||
* a mutable buffer in the tree's arena, convert it first to immutable
|
||||
* by assigning the substr to a csubstr prior to calling parse_in_arena().
|
||||
* This is not needed for parse_in_place() because csubstr is not
|
||||
* implicitly convertible to substr. */
|
||||
* implicitly convertible to substr.
|
||||
*
|
||||
* @see Parser */
|
||||
/** @{ */
|
||||
|
||||
/* READ THE NOTE ABOVE! */
|
||||
/** @cond dev */
|
||||
RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) Tree parse_in_arena( substr yaml );
|
||||
RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) Tree parse_in_arena(csubstr filename, substr yaml );
|
||||
RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena( substr yaml, Tree *t );
|
||||
@@ -675,6 +702,7 @@ RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(
|
||||
RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(csubstr filename, substr yaml, Tree *t, size_t node_id);
|
||||
RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena( substr yaml, NodeRef node );
|
||||
RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(csubstr filename, substr yaml, NodeRef node );
|
||||
/** @endcond */
|
||||
|
||||
inline Tree parse_in_arena( csubstr yaml ) { Parser np; return np.parse_in_arena({} , yaml); } //!< parse a read-only YAML source buffer, copying it first to the tree's source arena.
|
||||
inline Tree parse_in_arena(csubstr filename, csubstr yaml ) { Parser np; return np.parse_in_arena(filename, yaml); } //!< parse a read-only YAML source buffer, copying it first to the tree's source arena, providing a filename for error messages.
|
||||
@@ -685,6 +713,7 @@ inline void parse_in_arena(csubstr filename, csubstr yaml, Tree *t, size_t node_
|
||||
inline void parse_in_arena( csubstr yaml, NodeRef node ) { Parser np; np.parse_in_arena({} , yaml, node); } //!< reusing the YAML tree, parse a read-only YAML source buffer, copying it first to the tree's source arena.
|
||||
inline void parse_in_arena(csubstr filename, csubstr yaml, NodeRef node ) { Parser np; np.parse_in_arena(filename, yaml, node); } //!< reusing the YAML tree, parse a read-only YAML source buffer, copying it first to the tree's source arena, providing a filename for error messages.
|
||||
|
||||
/** @cond dev */
|
||||
RYML_DEPRECATED("use parse_in_arena() instead") inline Tree parse( csubstr yaml ) { Parser np; return np.parse_in_arena({} , yaml); } //!< parse a read-only YAML source buffer, copying it first to the tree's source arena.
|
||||
RYML_DEPRECATED("use parse_in_arena() instead") inline Tree parse(csubstr filename, csubstr yaml ) { Parser np; return np.parse_in_arena(filename, yaml); } //!< parse a read-only YAML source buffer, copying it first to the tree's source arena, providing a filename for error messages.
|
||||
RYML_DEPRECATED("use parse_in_arena() instead") inline void parse( csubstr yaml, Tree *t ) { Parser np; np.parse_in_arena({} , yaml, t); } //!< reusing the YAML tree, parse a read-only YAML source buffer, copying it first to the tree's source arena.
|
||||
@@ -693,7 +722,9 @@ RYML_DEPRECATED("use parse_in_arena() instead") inline void parse(
|
||||
RYML_DEPRECATED("use parse_in_arena() instead") inline void parse(csubstr filename, csubstr yaml, Tree *t, size_t node_id) { Parser np; np.parse_in_arena(filename, yaml, t, node_id); } //!< reusing the YAML tree, parse a read-only YAML source buffer, copying it first to the tree's source arena, providing a filename for error messages.
|
||||
RYML_DEPRECATED("use parse_in_arena() instead") inline void parse( csubstr yaml, NodeRef node ) { Parser np; np.parse_in_arena({} , yaml, node); } //!< reusing the YAML tree, parse a read-only YAML source buffer, copying it first to the tree's source arena.
|
||||
RYML_DEPRECATED("use parse_in_arena() instead") inline void parse(csubstr filename, csubstr yaml, NodeRef node ) { Parser np; np.parse_in_arena(filename, yaml, node); } //!< reusing the YAML tree, parse a read-only YAML source buffer, copying it first to the tree's source arena, providing a filename for error messages.
|
||||
/** @endcond */
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
||||
} // namespace yml
|
||||
|
||||
@@ -3,16 +3,6 @@
|
||||
|
||||
/** @file preprocess.hpp Functions for preprocessing YAML prior to parsing. */
|
||||
|
||||
/** @defgroup Preprocessors Preprocessor functions
|
||||
*
|
||||
* These are the existing preprocessors:
|
||||
*
|
||||
* @code{.cpp}
|
||||
* size_t preprocess_json(csubstr json, substr buf)
|
||||
* size_t preprocess_rxmap(csubstr json, substr buf)
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
#ifndef _C4_YML_COMMON_HPP_
|
||||
#include "./common.hpp"
|
||||
#endif
|
||||
@@ -22,6 +12,11 @@
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
/** @addtogroup doc_preprocessors
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @cond dev */
|
||||
namespace detail {
|
||||
using Preprocessor = size_t(csubstr, substr);
|
||||
template<Preprocessor PP, class CharContainer>
|
||||
@@ -41,13 +36,15 @@ substr preprocess_into_container(csubstr input, CharContainer *out)
|
||||
return to_substr(*out).first(sz);
|
||||
}
|
||||
} // namespace detail
|
||||
/** @endcond */
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @name preprocess_rxmap
|
||||
* Convert flow-type relaxed maps (with implicit bools) into strict YAML
|
||||
* flow map.
|
||||
/** @defgroup doc_preprocess_rxmap preprocess_rxmap
|
||||
*
|
||||
* @brief Convert flow-type relaxed maps (with implicit bools) into strict YAML
|
||||
* flow map:
|
||||
*
|
||||
* @code{.yaml}
|
||||
* {a, b, c, d: [e, f], g: {a, b}}
|
||||
@@ -59,10 +56,10 @@ substr preprocess_into_container(csubstr input, CharContainer *out)
|
||||
* @param rxmap A relaxed map
|
||||
* @param buf output buffer
|
||||
* @param out output container
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
//@{
|
||||
|
||||
/** Write into a given output buffer. This function is safe to call with
|
||||
* empty or small buffers; it won't write beyond the end of the buffer.
|
||||
*
|
||||
@@ -91,7 +88,8 @@ CharContainer preprocess_rxmap(csubstr rxmap)
|
||||
return out;
|
||||
}
|
||||
|
||||
//@}
|
||||
/** @} */ // preprocess_rxmap
|
||||
/** @} */ // group
|
||||
|
||||
} // namespace yml
|
||||
} // namespace c4
|
||||
|
||||
@@ -1436,7 +1436,7 @@ struct ReferenceResolver
|
||||
snprintf(errmsg, RYML_ERRMSG_SIZE, "anchor does not exist: '%.*s'",
|
||||
static_cast<int>(refname.size()), refname.data());
|
||||
c4::yml::error(errmsg);
|
||||
return NONE;
|
||||
C4_UNREACHABLE_AFTER_ERR();
|
||||
}
|
||||
|
||||
void resolve()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef _C4_YML_TREE_HPP_
|
||||
#define _C4_YML_TREE_HPP_
|
||||
|
||||
/** @file tree.hpp */
|
||||
|
||||
#include "c4/error.hpp"
|
||||
#include "c4/types.hpp"
|
||||
@@ -85,13 +86,19 @@ bool from_chars_float(csubstr buf, T *C4_RESTRICT val)
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** @addtogroup doc_tag_utils
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** 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 {
|
||||
// container types
|
||||
TAG_NONE = 0,
|
||||
TAG_NONE = 0, /**< no tag is set */
|
||||
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 */
|
||||
@@ -131,6 +138,7 @@ struct TagDirective
|
||||
#define RYML_MAX_TAG_DIRECTIVES 4
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -138,11 +146,17 @@ struct TagDirective
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** @addtogroup doc_node_type
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** the integral type necessary to cover all the bits marking node types */
|
||||
using type_bits = uint64_t;
|
||||
|
||||
|
||||
/** a bit mask for marking node types */
|
||||
/** a bit mask for marking node types. See NodeType */
|
||||
typedef enum : type_bits {
|
||||
// a convenience define, undefined below
|
||||
#define c4bit(v) (type_bits(1) << v)
|
||||
@@ -171,9 +185,9 @@ typedef enum : type_bits {
|
||||
_KEYMASK = KEY | KEYQUO | KEYANCH | KEYREF | KEYTAG,
|
||||
_VALMASK = VAL | VALQUO | VALANCH | VALREF | VALTAG,
|
||||
// these flags are from a work in progress and should be used with care
|
||||
_WIP_STYLE_FLOW_SL = c4bit(14), ///< mark container with single-line flow format (seqs as '[val1,val2], maps as '{key: val, key2: val2}')
|
||||
_WIP_STYLE_FLOW_ML = c4bit(15), ///< mark container with multi-line flow format (seqs as '[val1,\nval2], maps as '{key: val,\nkey2: val2}')
|
||||
_WIP_STYLE_BLOCK = c4bit(16), ///< mark container with block format (seqs as '- val\n', maps as 'key: val')
|
||||
_WIP_STYLE_FLOW_SL = c4bit(14), ///< mark container with single-line flow format (seqs as `[val1,val2]`, maps as `{key: val, key2: val2}`)
|
||||
_WIP_STYLE_FLOW_ML = c4bit(15), ///< mark container with multi-line flow format (seqs as `[val1,\nval2]`, maps as `{key: val,\nkey2: val2}`)
|
||||
_WIP_STYLE_BLOCK = c4bit(16), ///< mark container with block format (seqs as `- val\n`, maps as `key: val`)
|
||||
_WIP_KEY_LITERAL = c4bit(17), ///< mark key scalar as multiline, block literal |
|
||||
_WIP_VAL_LITERAL = c4bit(18), ///< mark val scalar as multiline, block literal |
|
||||
_WIP_KEY_FOLDED = c4bit(19), ///< mark key scalar as multiline, block folded >
|
||||
@@ -299,10 +313,19 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/** @addtogroup doc_tree
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** a node scalar is a csubstr, which may be tagged and anchored. */
|
||||
struct NodeScalar
|
||||
{
|
||||
@@ -495,38 +518,36 @@ public:
|
||||
size_t id(NodeData const* n) const
|
||||
{
|
||||
if( ! n)
|
||||
{
|
||||
return NONE;
|
||||
}
|
||||
_RYML_CB_ASSERT(m_callbacks, n >= m_buf && n < m_buf + m_cap);
|
||||
return static_cast<size_t>(n - m_buf);
|
||||
}
|
||||
|
||||
//! get a pointer to a node's NodeData.
|
||||
//! i can be NONE, in which case a nullptr is returned
|
||||
inline NodeData *get(size_t i)
|
||||
inline NodeData *get(size_t node)
|
||||
{
|
||||
if(i == NONE)
|
||||
if(node == NONE)
|
||||
return nullptr;
|
||||
_RYML_CB_ASSERT(m_callbacks, i >= 0 && i < m_cap);
|
||||
return m_buf + i;
|
||||
_RYML_CB_ASSERT(m_callbacks, node >= 0 && node < m_cap);
|
||||
return m_buf + node;
|
||||
}
|
||||
//! get a pointer to a node's NodeData.
|
||||
//! i can be NONE, in which case a nullptr is returned.
|
||||
inline NodeData const *get(size_t i) const
|
||||
inline NodeData const *get(size_t node) const
|
||||
{
|
||||
if(i == NONE)
|
||||
if(node == NONE)
|
||||
return nullptr;
|
||||
_RYML_CB_ASSERT(m_callbacks, i >= 0 && i < m_cap);
|
||||
return m_buf + i;
|
||||
_RYML_CB_ASSERT(m_callbacks, node >= 0 && node < m_cap);
|
||||
return m_buf + node;
|
||||
}
|
||||
|
||||
//! An if-less form of get() that demands a valid node index.
|
||||
//! This function is implementation only; use at your own risk.
|
||||
inline NodeData * _p(size_t i) { _RYML_CB_ASSERT(m_callbacks, i != NONE && i >= 0 && i < m_cap); return m_buf + i; }
|
||||
inline NodeData * _p(size_t node) { _RYML_CB_ASSERT(m_callbacks, node != NONE && node >= 0 && node < m_cap); return m_buf + node; }
|
||||
//! An if-less form of get() that demands a valid node index.
|
||||
//! This function is implementation only; use at your own risk.
|
||||
inline NodeData const * _p(size_t i) const { _RYML_CB_ASSERT(m_callbacks, i != NONE && i >= 0 && i < m_cap); return m_buf + i; }
|
||||
inline NodeData const * _p(size_t node) const { _RYML_CB_ASSERT(m_callbacks, node != NONE && node >= 0 && node < m_cap); return m_buf + node; }
|
||||
|
||||
//! Get the id of the root node
|
||||
size_t root_id() { if(m_cap == 0) { reserve(16); } _RYML_CB_ASSERT(m_callbacks, m_cap > 0 && m_size > 0); return 0; }
|
||||
@@ -534,11 +555,11 @@ public:
|
||||
size_t root_id() const { _RYML_CB_ASSERT(m_callbacks, m_cap > 0 && m_size > 0); return 0; }
|
||||
|
||||
//! Get a NodeRef of a node by id
|
||||
NodeRef ref(size_t id);
|
||||
NodeRef ref(size_t node);
|
||||
//! Get a NodeRef of a node by id
|
||||
ConstNodeRef ref(size_t id) const;
|
||||
ConstNodeRef ref(size_t node) const;
|
||||
//! Get a NodeRef of a node by id
|
||||
ConstNodeRef cref(size_t id) const;
|
||||
ConstNodeRef cref(size_t node) const;
|
||||
|
||||
//! Get the root as a NodeRef
|
||||
NodeRef rootref();
|
||||
@@ -548,10 +569,10 @@ public:
|
||||
ConstNodeRef crootref() const;
|
||||
|
||||
//! get the i-th document of the stream
|
||||
//! @note @i is NOT the node id, but the doc position within the stream
|
||||
//! @note @p i is NOT the node id, but the doc position within the stream
|
||||
NodeRef docref(size_t i);
|
||||
//! get the i-th document of the stream
|
||||
//! @note @i is NOT the node id, but the doc position within the stream
|
||||
//! @note @p i is NOT the node id, but the doc position within the stream
|
||||
ConstNodeRef docref(size_t i) const;
|
||||
|
||||
//! find a root child by name, return it as a NodeRef
|
||||
@@ -562,10 +583,10 @@ public:
|
||||
ConstNodeRef operator[] (csubstr key) const;
|
||||
|
||||
//! find a root child by index: return the root node's @p i-th child as a NodeRef
|
||||
//! @note @i is NOT the node id, but the child's position
|
||||
//! @note @p i is NOT the node id, but the child's position
|
||||
NodeRef operator[] (size_t i);
|
||||
//! find a root child by index: return the root node's @p i-th child as a NodeRef
|
||||
//! @note @i is NOT the node id, but the child's position
|
||||
//! @note @p i is NOT the node id, but the child's position
|
||||
ConstNodeRef operator[] (size_t i) const;
|
||||
|
||||
/** @} */
|
||||
@@ -1260,6 +1281,8 @@ private:
|
||||
|
||||
public:
|
||||
|
||||
/** @cond dev*/
|
||||
|
||||
#if ! RYML_USE_ASSERT
|
||||
C4_ALWAYS_INLINE void _check_next_flags(size_t, type_bits) {}
|
||||
#else
|
||||
@@ -1449,6 +1472,8 @@ public:
|
||||
_rem_flags(node, VAL);
|
||||
}
|
||||
|
||||
/** @endcond */
|
||||
|
||||
private:
|
||||
|
||||
void _clear_range(size_t first, size_t num);
|
||||
@@ -1483,6 +1508,8 @@ public:
|
||||
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
} // namespace yml
|
||||
} // namespace c4
|
||||
|
||||
|
||||
@@ -13,6 +13,15 @@
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
/** @addtogroup doc_emit
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup doc_writers Writer objects to use with an Emitter
|
||||
* @see Emitter
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** Repeat-Character: a character to be written a number of times. */
|
||||
struct RepC
|
||||
@@ -222,6 +231,10 @@ struct WriterBuf
|
||||
}
|
||||
};
|
||||
|
||||
/** @ } */
|
||||
|
||||
/** @ } */
|
||||
|
||||
|
||||
} // namespace yml
|
||||
} // namespace c4
|
||||
|
||||
@@ -18,10 +18,11 @@ Location stored_location;
|
||||
void * stored_mem;
|
||||
size_t stored_length;
|
||||
|
||||
void test_error_impl(const char* msg, size_t length, Location loc, void * /*user_data*/)
|
||||
C4_NORETURN void test_error_impl(const char* msg, size_t length, Location loc, void * /*user_data*/)
|
||||
{
|
||||
stored_msg = std::string(msg, length);
|
||||
stored_location = loc;
|
||||
throw std::runtime_error(stored_msg);
|
||||
}
|
||||
|
||||
void* test_allocate_impl(size_t length, void * /*hint*/, void * /*user_data*/)
|
||||
@@ -286,14 +287,24 @@ TEST(error, basic)
|
||||
set_callbacks(cb);
|
||||
// message
|
||||
EXPECT_EQ(get_callbacks().m_error, &test_error_impl);
|
||||
c4::yml::error("some message 123"); // calls test_error_impl, which sets stored_msg and stored_location
|
||||
try {
|
||||
c4::yml::error("some message 123"); // calls test_error_impl, which sets stored_msg and stored_location
|
||||
}
|
||||
catch (std::exception const&) {
|
||||
;
|
||||
}
|
||||
EXPECT_EQ(stored_msg, "some message 123");
|
||||
EXPECT_EQ(stored_location.name, "");
|
||||
EXPECT_EQ(stored_location.offset, 0u);
|
||||
EXPECT_EQ(stored_location.line, 0u);
|
||||
EXPECT_EQ(stored_location.col, 0u);
|
||||
// location
|
||||
c4::yml::error("some message 456", Location("file.yml", 433u, 123u, 4u));
|
||||
try {
|
||||
c4::yml::error("some message 456", Location("file.yml", 433u, 123u, 4u));
|
||||
}
|
||||
catch (std::exception const&) {
|
||||
;
|
||||
}
|
||||
EXPECT_EQ(stored_msg, "some message 456");
|
||||
EXPECT_EQ(stored_location.name, "file.yml");
|
||||
EXPECT_EQ(stored_location.offset, 433u);
|
||||
@@ -308,7 +319,14 @@ TEST(RYML_CHECK, basic)
|
||||
EXPECT_NE(get_callbacks().m_error, &test_error_impl);
|
||||
Callbacks cb(nullptr, nullptr, nullptr, &test_error_impl);
|
||||
set_callbacks(cb);
|
||||
size_t the_line = __LINE__; RYML_CHECK(false); // keep both statements in the same line
|
||||
ASSERT_EQ(get_callbacks(), cb);
|
||||
size_t the_line;
|
||||
try {
|
||||
the_line = __LINE__; RYML_CHECK(false); // keep both statements in the same line
|
||||
}
|
||||
catch (std::exception const&) {
|
||||
;
|
||||
}
|
||||
EXPECT_EQ(stored_msg, "check failed: false");
|
||||
EXPECT_EQ(stored_location.name, __FILE__);
|
||||
EXPECT_EQ(stored_location.offset, 0u);
|
||||
@@ -326,7 +344,13 @@ TEST(RYML_ASSERT, basic)
|
||||
set_callbacks(cb);
|
||||
stored_msg = "";
|
||||
stored_location = {};
|
||||
size_t the_line = __LINE__; RYML_ASSERT(false); // keep both statements in the same line
|
||||
size_t the_line;
|
||||
try {
|
||||
the_line = __LINE__; RYML_ASSERT(false); // keep both statements in the same line
|
||||
}
|
||||
catch (std::exception const&) {
|
||||
;
|
||||
}
|
||||
#if RYML_USE_ASSERT
|
||||
EXPECT_EQ(stored_msg, "check failed: false");
|
||||
EXPECT_EQ(stored_location.name, __FILE__);
|
||||
|
||||
@@ -192,9 +192,10 @@ ExpectError::ExpectError(Tree *tree, Location loc)
|
||||
, m_tree_prev(tree ? tree->callbacks() : Callbacks{})
|
||||
, expected_location(loc)
|
||||
{
|
||||
auto err = [](const char* msg, size_t len, Location errloc, void *this_) {
|
||||
auto err = [](const char* msg, size_t len, Location errloc, void *this_) {
|
||||
((ExpectError*)this_)->m_got_an_error = true;
|
||||
throw ExpectedError(msg, len, errloc);
|
||||
C4_UNREACHABLE_AFTER_ERR();
|
||||
};
|
||||
#ifdef RYML_NO_DEFAULT_CALLBACKS
|
||||
c4::yml::Callbacks tcb((void*)this, nullptr, nullptr, err);
|
||||
@@ -687,7 +688,7 @@ void test_invariants(ConstNodeRef const& n)
|
||||
{
|
||||
EXPECT_EQ(n.parent().num_children() > 1, n.has_other_siblings()) _MORE_INFO;
|
||||
EXPECT_TRUE(n.parent().has_child(n)) _MORE_INFO;
|
||||
EXPECT_EQ(n.parent().num_children(), n.num_siblings()) _MORE_INFO;
|
||||
EXPECT_EQ(n.parent().num_children(), 1 + n.num_other_siblings()) _MORE_INFO;
|
||||
// doc parent must be a seq and a stream
|
||||
if(n.is_doc())
|
||||
{
|
||||
|
||||
@@ -27,11 +27,13 @@ int main(int argc, const char *argv[])
|
||||
return 1;
|
||||
}
|
||||
Callbacks callbacks = {};
|
||||
callbacks.m_error = [](const char *msg, size_t msg_len, Location location, void *)
|
||||
pfn_error error = [](const char *msg, size_t msg_len, Location location, void *)
|
||||
{
|
||||
report_error(msg, msg_len, location, stderr);
|
||||
throw std::runtime_error({msg, msg_len});
|
||||
C4_UNREACHABLE_AFTER_ERR();
|
||||
};
|
||||
callbacks.m_error = error;
|
||||
try {
|
||||
Tree tree(callbacks);
|
||||
csubstr filename = to_csubstr(argv[1]);
|
||||
|
||||
Reference in New Issue
Block a user