rapidyaml 0.14.0
parse and emit YAML, and do it fast
Loading...
Searching...
No Matches
reference_resolver.hpp
Go to the documentation of this file.
1#ifndef _C4_YML_REFERENCE_RESOLVER_HPP_
2#define _C4_YML_REFERENCE_RESOLVER_HPP_
3
4#include "c4/yml/tree.hpp"
5#include "c4/yml/detail/stack.hpp"
6
7
8namespace c4 {
9namespace yml {
10
11/** @addtogroup doc_ref_utils
12 * @{
13 */
14
15/** Reusable object to resolve references/aliases in a @ref Tree. */
17{
18 ReferenceResolver() = default;
19
20 /** Resolve references: for each reference, look for a matching
21 * anchor, and copy its contents to the ref node.
22 *
23 * @p tree the subject tree
24 *
25 * @p clear_anchors whether to clear existing anchors after
26 * resolving
27 *
28 * This method first does a full traversal of the tree to gather
29 * all anchors and references in a separate collection, then it
30 * goes through that collection to locate the names, which it does
31 * by obeying the YAML standard diktat that "an alias node refers
32 * to the most recent node in the serialization having the
33 * specified anchor"
34 *
35 * So, depending on the number of anchor/alias nodes, this is a
36 * potentially expensive operation, with a best-case linear
37 * complexity (from the initial traversal). This potential cost is
38 * one of the reasons for requiring an explicit call.
39 *
40 * The @ref Tree has an `Tree::resolve()` overload set forwarding
41 * here. Previously this operation was done there, using a
42 * discarded object; using this separate class offers opportunity
43 * for reuse of the object.
44 *
45 * @warning resolving references opens an attack vector when the
46 * data is malicious or severely malformed, as the tree can expand
47 * exponentially. See for example the [Billion Laughs
48 * Attack](https://en.wikipedia.org/wiki/Billion_laughs_attack).
49 *
50 */
51 RYML_EXPORT void resolve(Tree *tree, bool clear_anchors=true);
52
53public:
54
55 /** @cond dev */
56
57 struct RefData
58 {
59 NodeType type;
60 id_type node;
61 id_type prev_anchor;
62 id_type target;
63 id_type parent_ref;
64 id_type parent_ref_sibling;
65 };
66
67 void reset_(Tree *t_);
68 void resolve_();
69 void gather_anchors_and_refs_();
70 void gather_anchors_and_refs__(id_type n);
71 id_type count_anchors_and_refs_(id_type n);
72
73 id_type lookup_(RefData const* C4_RESTRICT ra);
74
75 Tree *C4_RESTRICT m_tree;
76 /** We're using this stack purely as an array. */
77 detail::stack<RefData> m_refs;
78
79 /** @endcond */
80};
81
82/** @} */
83
84} // namespace ryml
85} // namespace c4
86
87
88#endif // _C4_YML_REFERENCE_RESOLVER_HPP_
#define RYML_EXPORT
Definition export.hpp:18
RYML_ID_TYPE id_type
The type of a node id in the YAML tree; to override the default type, define the macro RYML_ID_TYPE t...
Definition common.hpp:249
(Undefined by default) Use shorter error message from checks/asserts: do not show the check condition...
Definition common.cpp:14
wraps a NodeType_e element with some syntactic sugar and predicates
void resolve(Tree *tree, bool clear_anchors=true)
Resolve references: for each reference, look for a matching anchor, and copy its contents to the ref ...