rapidyaml 0.15.2
parse and emit YAML, and do it fast
Loading...
Searching...
No Matches
parse.cpp
Go to the documentation of this file.
1#include "c4/yml/parse.hpp"
2
3#ifndef _C4_YML_NODE_HPP_
4#include "c4/yml/node.hpp"
5#endif
6#ifndef _C4_YML_PARSE_ENGINE_HPP_
8#endif
9#ifndef _C4_YML_PARSE_ENGINE_DEF_HPP_
11#endif
12#ifndef _C4_YML_EVENT_HANDLER_TREE_HPP_
14#endif
15
16
17//-----------------------------------------------------------------------------
18
19namespace c4 {
20namespace yml {
21
22
23// instantiate the parser class
25
26
27namespace {
28// so many things can go wrong...
29void check_(Tree *tree)
30{
31 if(C4_UNLIKELY(!tree))
32 _RYML_ERR_BASIC("null tree");
33 if(C4_UNLIKELY(tree->empty()))
34 tree->reserve();
35}
36void check_(NodeRef &node)
37{
38 check_(node.tree());
39 if(C4_UNLIKELY(node.id() == NONE))
40 _RYML_ERR_VISIT_(node.tree()->m_callbacks, node.tree(), node.id(), "invalid node");
41 node.create();
42}
43void check_(Parser *parser)
44{
45 if(C4_UNLIKELY(!parser))
46 _RYML_ERR_BASIC("null parser");
47 if(C4_UNLIKELY(!parser->m_evt_handler))
48 // the parser callbacks are from the handler. do not use parser->callbacks()
49 _RYML_ERR_BASIC("null handler");
50}
51void check_(Parser *parser, Tree *tree)
52{
53 if(C4_UNLIKELY(!parser && !tree))
54 {
55 _RYML_ERR_BASIC("null parser and tree");
56 }
57 else if(C4_UNLIKELY(!parser))
58 {
59 _RYML_ERR_BASIC_(tree->callbacks(), "null parser");
60 }
61 else if(C4_UNLIKELY(!tree))
62 {
63 if(C4_UNLIKELY(!parser->m_evt_handler))
64 _RYML_ERR_BASIC("null tree and handler");
65 else
66 _RYML_ERR_BASIC_(parser->callbacks(), "null tree");
67 }
68 if(C4_UNLIKELY(!parser->m_evt_handler))
69 {
70 _RYML_ERR_BASIC("null handler");
71 }
72 if(C4_UNLIKELY(tree->empty()))
73 {
74 tree->reserve();
75 }
76}
77void check_(Parser *parser, NodeRef &node)
78{
79 check_(parser, node.tree());
80 check_(node);
81}
82void checksrc_(Tree *tree, csubstr src)
83{
84 if(C4_UNLIKELY(src.len && !src.str))
85 _RYML_ERR_BASIC_(tree->callbacks(), "null source buffer");
86}
87substr cpsrc_(Tree *tree, csubstr src)
88{
89 checksrc_(tree, src);
90 return tree->copy_to_arena(src);
91}
92// helpers: check and copy to arena
93substr checkcp_(Tree *tree, csubstr src)
94{
95 check_(tree);
96 return cpsrc_(tree, src);
97}
98substr checkcp_(NodeRef &node, csubstr src)
99{
100 check_(node);
101 return cpsrc_(node.tree(), src);
102}
103substr checkcp_(Parser *parser, Tree *tree, csubstr src)
104{
105 check_(parser, tree);
106 return cpsrc_(tree, src);
107}
108substr checkcp_(Parser *parser, NodeRef &node, csubstr src)
109{
110 check_(parser, node);
111 return cpsrc_(node.tree(), src);
112}
113using Handler = Parser::handler_type;
114struct TmpParser
115{
116 Handler handler;
117 Parser parser;
118 // assumes checks above were done prior to instantiation
119 TmpParser(ParserOptions const& opts={})
120 : handler(get_callbacks())
121 , parser(&handler, opts)
122 {
123 }
124 TmpParser(Tree* tree, ParserOptions const& opts={})
125 : handler(tree->callbacks())
126 , parser(&handler, opts)
127 {
128 }
129 TmpParser(NodeRef &node, ParserOptions const& opts={})
130 : handler(node.tree()->callbacks())
131 , parser(&handler, opts)
132 {
133 }
134};
135// assumes checks above were done prior to calling
136C4_ALWAYS_INLINE void reset_handler_(Parser *parser, Tree *tree, id_type node_id)
137{
138 _RYML_ASSERT_BASIC(parser); // LCOV_EXCL_LINE lcov weirdly fails here
139 _RYML_ASSERT_BASIC(parser->m_evt_handler);
140 _RYML_ASSERT_BASIC(tree);
141 if(C4_UNLIKELY(node_id == NONE || node_id >= tree->capacity()))
142 _RYML_ERR_VISIT_(tree->m_callbacks, tree, node_id, "invalid node");
143 parser->m_evt_handler->reset(tree, node_id);
144 _RYML_ASSERT_BASIC(parser->m_evt_handler->m_tree == tree);
145}
146// assumes checks above were done prior to calling
147void parse_yaml_(Parser *parser, csubstr filename, substr yaml, Tree *tree, id_type node_id)
148{
149 reset_handler_(parser, tree, node_id);
150 checksrc_(tree, yaml);
151 parser->parse_in_place_ev(filename, yaml);
152}
153// assumes checks above were done prior to calling
154void parse_json_(Parser *parser, csubstr filename, substr json, Tree *tree, id_type node_id)
155{
156 reset_handler_(parser, tree, node_id);
157 checksrc_(tree, json);
158 parser->parse_json_in_place_ev(filename, json);
159}
160} // namespace
161
162
163
164// this is vertically aligned to highlight the parameter differences.
165void parse_in_place(Parser *parser, csubstr filename, substr yaml, Tree *tree, id_type node_id) { check_(parser, tree); parse_yaml_(parser, filename, yaml, tree, node_id); }
166void parse_in_place(Parser *parser, substr yaml, Tree *tree, id_type node_id) { check_(parser, tree); parse_yaml_(parser, {} , yaml, tree, node_id); }
167void parse_in_place(Parser *parser, csubstr filename, substr yaml, Tree *tree ) { check_(parser, tree); parse_yaml_(parser, filename, yaml, tree, tree->root_id()); }
168void parse_in_place(Parser *parser, substr yaml, Tree *tree ) { check_(parser, tree); parse_yaml_(parser, {} , yaml, tree, tree->root_id()); }
169void parse_in_place(Parser *parser, csubstr filename, substr yaml, NodeRef node ) { check_(parser, node); parse_yaml_(parser, filename, yaml, node.tree(), node.id()); }
170void parse_in_place(Parser *parser, substr yaml, NodeRef node ) { check_(parser, node); parse_yaml_(parser, {} , yaml, node.tree(), node.id()); }
171Tree parse_in_place(Parser *parser, csubstr filename, substr yaml ) { check_(parser); Tree tree(parser->callbacks()); parse_yaml_(parser, filename, yaml, &tree, tree.root_id()); return tree; }
172Tree parse_in_place(Parser *parser, substr yaml ) { check_(parser); Tree tree(parser->callbacks()); parse_yaml_(parser, {} , yaml, &tree, tree.root_id()); return tree; }
173
174// this is vertically aligned to highlight the parameter differences.
175void parse_in_place(csubstr filename, substr yaml, Tree *tree, id_type node_id, ParserOptions const& opts) { check_(tree); TmpParser tmp(tree, opts); parse_yaml_(&tmp.parser, filename, yaml, tree, node_id); }
176void parse_in_place( substr yaml, Tree *tree, id_type node_id, ParserOptions const& opts) { check_(tree); TmpParser tmp(tree, opts); parse_yaml_(&tmp.parser, {} , yaml, tree, node_id); }
177void parse_in_place(csubstr filename, substr yaml, Tree *tree , ParserOptions const& opts) { check_(tree); TmpParser tmp(tree, opts); parse_yaml_(&tmp.parser, filename, yaml, tree, tree->root_id()); }
178void parse_in_place( substr yaml, Tree *tree , ParserOptions const& opts) { check_(tree); TmpParser tmp(tree, opts); parse_yaml_(&tmp.parser, {} , yaml, tree, tree->root_id()); }
179void parse_in_place(csubstr filename, substr yaml, NodeRef node , ParserOptions const& opts) { check_(node); TmpParser tmp(node, opts); parse_yaml_(&tmp.parser, filename, yaml, node.tree(), node.id()); }
180void parse_in_place( substr yaml, NodeRef node , ParserOptions const& opts) { check_(node); TmpParser tmp(node, opts); parse_yaml_(&tmp.parser, {} , yaml, node.tree(), node.id()); }
181Tree parse_in_place(csubstr filename, substr yaml , ParserOptions const& opts) { TmpParser tmp(opts); Tree tree; parse_yaml_(&tmp.parser, filename, yaml, &tree, tree.root_id()); return tree; }
182Tree parse_in_place( substr yaml , ParserOptions const& opts) { TmpParser tmp(opts); Tree tree; parse_yaml_(&tmp.parser, {} , yaml, &tree, tree.root_id()); return tree; }
183
184
185
186// this is vertically aligned to highlight the parameter differences.
187void parse_json_in_place(Parser *parser, csubstr filename, substr json, Tree *tree, id_type node_id) { check_(parser, tree); parse_json_(parser, filename, json, tree, node_id); }
188void parse_json_in_place(Parser *parser, substr json, Tree *tree, id_type node_id) { check_(parser, tree); parse_json_(parser, {} , json, tree, node_id); }
189void parse_json_in_place(Parser *parser, csubstr filename, substr json, Tree *tree ) { check_(parser, tree); parse_json_(parser, filename, json, tree, tree->root_id()); }
190void parse_json_in_place(Parser *parser, substr json, Tree *tree ) { check_(parser, tree); parse_json_(parser, {} , json, tree, tree->root_id()); }
191void parse_json_in_place(Parser *parser, csubstr filename, substr json, NodeRef node ) { check_(parser, node); parse_json_(parser, filename, json, node.tree(), node.id()); }
192void parse_json_in_place(Parser *parser, substr json, NodeRef node ) { check_(parser, node); parse_json_(parser, {} , json, node.tree(), node.id()); }
193Tree parse_json_in_place(Parser *parser, csubstr filename, substr json ) { check_(parser); Tree tree(parser->callbacks()); parse_json_(parser, filename, json, &tree, tree.root_id()); return tree; }
194Tree parse_json_in_place(Parser *parser, substr json ) { check_(parser); Tree tree(parser->callbacks()); parse_json_(parser, {} , json, &tree, tree.root_id()); return tree; }
195
196// this is vertically aligned to highlight the parameter differences.
197void parse_json_in_place(csubstr filename, substr json, Tree *tree, id_type node_id, ParserOptions const& opts) { check_(tree); TmpParser tmp(tree, opts); parse_json_(&tmp.parser, filename, json, tree, node_id); }
198void parse_json_in_place( substr json, Tree *tree, id_type node_id, ParserOptions const& opts) { check_(tree); TmpParser tmp(tree, opts); parse_json_(&tmp.parser, {} , json, tree, node_id); }
199void parse_json_in_place(csubstr filename, substr json, Tree *tree , ParserOptions const& opts) { check_(tree); TmpParser tmp(tree, opts); parse_json_(&tmp.parser, filename, json, tree, tree->root_id()); }
200void parse_json_in_place( substr json, Tree *tree , ParserOptions const& opts) { check_(tree); TmpParser tmp(tree, opts); parse_json_(&tmp.parser, {} , json, tree, tree->root_id()); }
201void parse_json_in_place(csubstr filename, substr json, NodeRef node , ParserOptions const& opts) { check_(node); TmpParser tmp(node, opts); parse_json_(&tmp.parser, filename, json, node.tree(), node.id()); }
202void parse_json_in_place( substr json, NodeRef node , ParserOptions const& opts) { check_(node); TmpParser tmp(node, opts); parse_json_(&tmp.parser, {} , json, node.tree(), node.id()); }
203Tree parse_json_in_place(csubstr filename, substr json , ParserOptions const& opts) { TmpParser tmp(opts); Tree tree; parse_json_(&tmp.parser, filename, json, &tree, tree.root_id()); return tree; }
204Tree parse_json_in_place( substr json , ParserOptions const& opts) { TmpParser tmp(opts); Tree tree; parse_json_(&tmp.parser, {} , json, &tree, tree.root_id()); return tree; }
205
206
207
208// this is vertically aligned to highlight the parameter differences.
209void parse_in_arena(Parser *parser, csubstr filename, csubstr yaml, Tree *tree, id_type node_id) { substr src = checkcp_(parser, tree, yaml); parse_yaml_(parser, filename, src, tree, node_id); }
210void parse_in_arena(Parser *parser, csubstr yaml, Tree *tree, id_type node_id) { substr src = checkcp_(parser, tree, yaml); parse_yaml_(parser, {} , src, tree, node_id); }
211void parse_in_arena(Parser *parser, csubstr filename, csubstr yaml, Tree *tree ) { substr src = checkcp_(parser, tree, yaml); parse_yaml_(parser, filename, src, tree, tree->root_id()); }
212void parse_in_arena(Parser *parser, csubstr yaml, Tree *tree ) { substr src = checkcp_(parser, tree, yaml); parse_yaml_(parser, {} , src, tree, tree->root_id()); }
213void parse_in_arena(Parser *parser, csubstr filename, csubstr yaml, NodeRef node ) { substr src = checkcp_(parser, node, yaml); parse_yaml_(parser, filename, src, node.tree(), node.id()); }
214void parse_in_arena(Parser *parser, csubstr yaml, NodeRef node ) { substr src = checkcp_(parser, node, yaml); parse_yaml_(parser, {} , src, node.tree(), node.id()); }
215Tree parse_in_arena(Parser *parser, csubstr filename, csubstr yaml ) { check_(parser); Tree tree(parser->callbacks()); substr src = cpsrc_(&tree, yaml); parse_yaml_(parser, filename, src, &tree, tree.root_id()); return tree; }
216Tree parse_in_arena(Parser *parser, csubstr yaml ) { check_(parser); Tree tree(parser->callbacks()); substr src = cpsrc_(&tree, yaml); parse_yaml_(parser, {} , src, &tree, tree.root_id()); return tree; }
217
218// this is vertically aligned to highlight the parameter differences.
219void parse_in_arena(csubstr filename, csubstr yaml, Tree *tree, id_type node_id, ParserOptions const& opts) { substr src = checkcp_(tree, yaml); TmpParser tmp(tree, opts); parse_yaml_(&tmp.parser, filename, src, tree, node_id); }
220void parse_in_arena( csubstr yaml, Tree *tree, id_type node_id, ParserOptions const& opts) { substr src = checkcp_(tree, yaml); TmpParser tmp(tree, opts); parse_yaml_(&tmp.parser, {} , src, tree, node_id); }
221void parse_in_arena(csubstr filename, csubstr yaml, Tree *tree , ParserOptions const& opts) { substr src = checkcp_(tree, yaml); TmpParser tmp(tree, opts); parse_yaml_(&tmp.parser, filename, src, tree, tree->root_id()); }
222void parse_in_arena( csubstr yaml, Tree *tree , ParserOptions const& opts) { substr src = checkcp_(tree, yaml); TmpParser tmp(tree, opts); parse_yaml_(&tmp.parser, {} , src, tree, tree->root_id()); }
223void parse_in_arena(csubstr filename, csubstr yaml, NodeRef node , ParserOptions const& opts) { substr src = checkcp_(node, yaml); TmpParser tmp(node, opts); parse_yaml_(&tmp.parser, filename, src, node.tree(), node.id()); }
224void parse_in_arena( csubstr yaml, NodeRef node , ParserOptions const& opts) { substr src = checkcp_(node, yaml); TmpParser tmp(node, opts); parse_yaml_(&tmp.parser, {} , src, node.tree(), node.id()); }
225Tree parse_in_arena(csubstr filename, csubstr yaml , ParserOptions const& opts) { TmpParser tmp(opts); Tree tree; substr src = cpsrc_(&tree, yaml); parse_yaml_(&tmp.parser, filename, src, &tree, tree.root_id()); return tree; }
226Tree parse_in_arena( csubstr yaml , ParserOptions const& opts) { TmpParser tmp(opts); Tree tree; substr src = cpsrc_(&tree, yaml); parse_yaml_(&tmp.parser, {} , src, &tree, tree.root_id()); return tree; }
227
228
229
230// this is vertically aligned to highlight the parameter differences.
231void parse_json_in_arena(Parser *parser, csubstr filename, csubstr json, Tree *tree, id_type node_id) { substr src = checkcp_(parser, tree, json); parse_json_(parser, filename, src, tree, node_id); }
232void parse_json_in_arena(Parser *parser, csubstr json, Tree *tree, id_type node_id) { substr src = checkcp_(parser, tree, json); parse_json_(parser, {} , src, tree, node_id); }
233void parse_json_in_arena(Parser *parser, csubstr filename, csubstr json, Tree *tree ) { substr src = checkcp_(parser, tree, json); parse_json_(parser, filename, src, tree, tree->root_id()); }
234void parse_json_in_arena(Parser *parser, csubstr json, Tree *tree ) { substr src = checkcp_(parser, tree, json); parse_json_(parser, {} , src, tree, tree->root_id()); }
235void parse_json_in_arena(Parser *parser, csubstr filename, csubstr json, NodeRef node ) { substr src = checkcp_(parser, node, json); parse_json_(parser, filename, src, node.tree(), node.id()); }
236void parse_json_in_arena(Parser *parser, csubstr json, NodeRef node ) { substr src = checkcp_(parser, node, json); parse_json_(parser, {} , src, node.tree(), node.id()); }
237Tree parse_json_in_arena(Parser *parser, csubstr filename, csubstr json ) { check_(parser); Tree tree(parser->callbacks()); substr src = cpsrc_(&tree, json); parse_json_(parser, filename, src, &tree, tree.root_id()); return tree; }
238Tree parse_json_in_arena(Parser *parser, csubstr json ) { check_(parser); Tree tree(parser->callbacks()); substr src = cpsrc_(&tree, json); parse_json_(parser, {} , src, &tree, tree.root_id()); return tree; }
239
240// this is vertically aligned to highlight the parameter differences.
241void parse_json_in_arena(csubstr filename, csubstr json, Tree *tree, id_type node_id, ParserOptions const& opts) { substr src = checkcp_(tree, json); TmpParser tmp(tree, opts); parse_json_(&tmp.parser, filename, src, tree, node_id); }
242void parse_json_in_arena( csubstr json, Tree *tree, id_type node_id, ParserOptions const& opts) { substr src = checkcp_(tree, json); TmpParser tmp(tree, opts); parse_json_(&tmp.parser, {} , src, tree, node_id); }
243void parse_json_in_arena(csubstr filename, csubstr json, Tree *tree , ParserOptions const& opts) { substr src = checkcp_(tree, json); TmpParser tmp(tree, opts); parse_json_(&tmp.parser, filename, src, tree, tree->root_id()); }
244void parse_json_in_arena( csubstr json, Tree *tree , ParserOptions const& opts) { substr src = checkcp_(tree, json); TmpParser tmp(tree, opts); parse_json_(&tmp.parser, {} , src, tree, tree->root_id()); }
245void parse_json_in_arena(csubstr filename, csubstr json, NodeRef node , ParserOptions const& opts) { substr src = checkcp_(node, json); TmpParser tmp(node, opts); parse_json_(&tmp.parser, filename, src, node.tree(), node.id()); }
246void parse_json_in_arena( csubstr json, NodeRef node , ParserOptions const& opts) { substr src = checkcp_(node, json); TmpParser tmp(node, opts); parse_json_(&tmp.parser, {} , src, node.tree(), node.id()); }
247Tree parse_json_in_arena(csubstr filename, csubstr json , ParserOptions const& opts) { TmpParser tmp(opts); Tree tree; substr src = cpsrc_(&tree, json); parse_json_(&tmp.parser, filename, src, &tree, tree.root_id()); return tree; }
248Tree parse_json_in_arena( csubstr json , ParserOptions const& opts) { TmpParser tmp(opts); Tree tree; substr src = cpsrc_(&tree, json); parse_json_(&tmp.parser, {} , src, &tree, tree.root_id()); return tree; }
249
250
251
252//-----------------------------------------------------------------------------
253
255{
256 id_type num_nodes = 1; // root
257 for(size_t i = 0; i < src.len; ++i)
258 {
259 const char c = src.str[i];
260 num_nodes += (c == '\n') || (c == ',') || (c == '[') || (c == '{');
261 }
262 return num_nodes;
263}
264
265} // namespace yml
266} // namespace c4
A reference to a node in an existing yaml tree, offering a more convenient API than the index-based A...
Definition node.hpp:787
Tree * tree() noexcept
Definition node.hpp:914
id_type id() const noexcept
Definition node.hpp:917
This is the main driver of parsing logic: it scans the YAML or JSON source for tokens,...
Callbacks const & callbacks() const
Get the current callbacks in the parser.
id_type root_id() const
Get the id of the root node. The tree must not be empty. The tree can be empty only when constructed ...
Definition tree.hpp:333
#define RYML_EXPORT
Definition export.hpp:18
Callbacks const & get_callbacks()
get the global callbacks
Definition common.cpp:94
void parse_in_arena(Parser *parser, csubstr filename, csubstr yaml, Tree *tree, id_type node_id)
(1) parse YAML into an existing tree node. The filename will be used in any error messages arising du...
Definition parse.cpp:209
void parse_json_in_arena(Parser *parser, csubstr filename, csubstr json, Tree *tree, id_type node_id)
(1) parse JSON into an existing tree node. The filename will be used in any error messages arising du...
Definition parse.cpp:231
void parse_json_in_place(Parser *parser, csubstr filename, substr json, Tree *tree, id_type node_id)
(1) parse JSON into an existing tree node. The filename will be used in any error messages arising du...
Definition parse.cpp:187
void parse_in_place(Parser *parser, csubstr filename, substr yaml, Tree *tree, id_type node_id)
(1) parse YAML into an existing tree node.
Definition parse.cpp:165
ParseEngine< EventHandlerTree > Parser
This is the main ryml parser, where the parser events are handled to create a ryml tree (see Event Ha...
Definition fwd.hpp:19
id_type estimate_tree_capacity(csubstr src)
Quickly inspect the source to estimate the number of nodes the resulting tree is likely to have.
Definition parse.cpp:254
basic_substring< char > substr
a mutable string view
Definition substr.hpp:2356
basic_substring< const char > csubstr
an immutable string view
Definition substr.hpp:2357
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:305
@ NONE
an index to none
Definition common.hpp:312
(Undefined by default) Use shorter error message from checks/asserts: do not show the check condition...
Definition common.cpp:14
Node classes.
size_t len
the length of the substring
Definition substr.hpp:218
C * str
a restricted pointer to the first character of the substring
Definition substr.hpp:216
Options to give to the ParseEngine to control its behavior.