Release 0.6.0
Add API documentation
- PR#423: add Doxygen-based API documentation, now hosted in https://rapidyaml.readthedocs.io/!
- It uses the base doxygen docs, as I couldn't get doxyrest or breathe or exhale to produce anything meaningful using the doxygen groups already defined in the source code.
Error handling
Fix major error handling problem reported in #389 (PR#411):
- The
NodeRef
andConstNodeRef
classes are now conditional noexcept usingRYML_NOEXCEPT
, which evaluates either to nothing when assertions are enabled, and tonoexcept
otherwise. The problem was that these classes had many methods explicitly markednoexcept
, but were doing assertions which could throw exceptions, causing an abort instead of a throw whenever the assertion called an exception-throwing error callback. - This problem was compounded by assertions being enabled in every build type -- despite the intention to have them only in debug builds. There was a problem in the preprocessor code to enable assertions which led to assertions being enabled in release builds even when
RYML_USE_ASSERT
was defined to 0. Thanks to @jdrouhard for reporting this. - Although the code is and was extensively tested, the testing was addressing mostly the happy path. Tests were added to ensure that the error behavior is as intended.
- Together with this changeset, a major revision was carried out of the asserting/checking status of each function in the node classes. In most cases, assertions were added to functions that were missing them. So beware - some user code that was invalid will now assert or error out. Also, assertions and checks are now directed as much as possible to the callbacks of the closest scope: ie, if a tree has custom callbacks, errors within the tree class should go through those callbacks.
- Also, the intended assertion behavior is now in place: no assertions in release builds. Beware as well - user code which was relying on this will now silently succeed and return garbage in release builds. See the next points, which may help.
- Added new methods to the
NodeRef
/ConstNodeRef
classes:/** Distinguish between a valid seed vs a valid non-seed ref. */ bool readable() const { return valid() && !is_seed(); } /** Get a child by name, with error checking; complexity is * O(num_children). * * Behaves as operator[](csubstr) const, but always raises an * error (even when RYML_USE_ASSERT is set to false) when the * returned node does not exist, or when this node is not * readable, or when it is not a map. This behaviour is similar to * std::vector::at(), but the error consists in calling the error * callback instead of directly raising an exception. */ ConstNodeRef at(csubstr key) const; /** Likewise, but return a seed node when the key is not found */ NodeRef at(csubstr key); /** Get a child by position, with error checking; complexity is * O(pos). * * Behaves as operator[](size_t) const, but always raises an error * (even when RYML_USE_ASSERT is set to false) when the returned * node does not exist, or when this node is not readable, or when * it is not a container. This behaviour is similar to * std::vector::at(), but the error consists in calling the error * callback instead of directly raising an exception. */ ConstNodeRef at(size_t pos) const; /** Likewise, but return a seed node when pos is not found */ NodeRef at(csubstr key);
- The state for
NodeRef
was refined, and now there are three mutually exclusive states (and class predicates) for an object of this class:.invalid()
when the object was not initialized to any node.readable()
when the object points at an existing tree+node.is_seed()
when the object points at an hypotethic tree+node- The previous state
.valid()
was deprecated: its semantics were confusing as it actually could be any of.readable()
or.is_seed()
- Deprecated also the following methods for
NodeRef
/ConstNodeRef
:RYML_DEPRECATED() bool operator== (std::nullptr_t) const; RYML_DEPRECATED() bool operator!= (std::nullptr_t) const; RYML_DEPRECATED() bool operator== (csubstr val) const; RYML_DEPRECATED() bool operator!= (csubstr val) const;
- Added macros and respective cmake options to control error handling:
RYML_USE_ASSERT
- enable assertions regardless of build type. This is disabled by default. This macro was already defined; the current PR adds the cmake option.RYML_DEFAULT_CALLBACK_USES_EXCEPTIONS
- make the default error handler provided by ryml throw exceptions instead of callingstd::abort()
. This is disabled by default.
- Also,
RYML_DEBUG_BREAK()
is now enabled only ifRYML_DBG
is defined, as reported in #362. - As part of PR#423, to improve linters and codegen:
- annotate the error handlers with
[[noreturn]]
/C4_NORETURN
- annotate some error sites with
C4_UNREACHABLE_AFTER_ERR()
- annotate the error handlers with
More fixes
Tree::arena() const
was returning asubstr
; this was an error. This function was changed to:csubstr Tree::arena() const; substr Tree::arena();
- Fix #390 -
csubstr::first_real_span()
failed on scientific numbers with one digit in the exponent (PR#415). - Fix #361 - parse error on map scalars containing
:
and starting on the next line:--- # failed to parse: description: foo:bar --- # but this was ok: description: foo:bar
- PR#368 - fix pedantic compiler warnings.
- Fix #373 - false parse error with empty quoted keys in block-style map (PR#374).
- Fix #356 - fix overzealous check in
emit_as()
. An id may be larger than the tree's size, eg when nodes were removed. (PR#357). - Fix #417 - add quickstart example explaining how to avoid precision loss while serializing floats (PR#420).
- Fix #380 - Debug visualizer .natvis file for Visual Studio was missing
ConstNodeRef
(PR#383). - FR #403 - install is now optional when using cmake. The relevant option is
RYML_INSTALL
.