parse.hpp (33234B)
1 #ifndef _C4_YML_PARSE_HPP_ 2 #define _C4_YML_PARSE_HPP_ 3 4 #ifndef _C4_YML_TREE_HPP_ 5 #include "c4/yml/tree.hpp" 6 #endif 7 8 #ifndef _C4_YML_NODE_HPP_ 9 #include "c4/yml/node.hpp" 10 #endif 11 12 #ifndef _C4_YML_DETAIL_STACK_HPP_ 13 #include "c4/yml/detail/stack.hpp" 14 #endif 15 16 #include <stdarg.h> 17 18 #if defined(_MSC_VER) 19 # pragma warning(push) 20 # pragma warning(disable: 4251/*needs to have dll-interface to be used by clients of struct*/) 21 #endif 22 23 namespace c4 { 24 namespace yml { 25 26 struct RYML_EXPORT ParserOptions 27 { 28 private: 29 30 typedef enum : uint32_t { 31 LOCATIONS = (1 << 0), 32 DEFAULTS = 0, 33 } Flags_e; 34 35 uint32_t flags = DEFAULTS; 36 public: 37 ParserOptions() = default; 38 39 /** @name source location tracking */ 40 /** @{ */ 41 42 /** enable/disable source location tracking */ 43 ParserOptions& locations(bool enabled) 44 { 45 if(enabled) 46 flags |= LOCATIONS; 47 else 48 flags &= ~LOCATIONS; 49 return *this; 50 } 51 bool locations() const { return (flags & LOCATIONS) != 0u; } 52 53 /** @} */ 54 }; 55 56 57 //----------------------------------------------------------------------------- 58 //----------------------------------------------------------------------------- 59 //----------------------------------------------------------------------------- 60 class RYML_EXPORT Parser 61 { 62 public: 63 64 /** @name construction and assignment */ 65 /** @{ */ 66 67 Parser(Callbacks const& cb, ParserOptions opts={}); 68 Parser(ParserOptions opts={}) : Parser(get_callbacks(), opts) {} 69 ~Parser(); 70 71 Parser(Parser &&); 72 Parser(Parser const&); 73 Parser& operator=(Parser &&); 74 Parser& operator=(Parser const&); 75 76 /** @} */ 77 78 public: 79 80 /** @name modifiers */ 81 /** @{ */ 82 83 /** Reserve a certain capacity for the parsing stack. 84 * This should be larger than the expected depth of the parsed 85 * YAML tree. 86 * 87 * The parsing stack is the only (potential) heap memory used by 88 * the parser. 89 * 90 * If the requested capacity is below the default 91 * stack size of 16, the memory is used directly in the parser 92 * object; otherwise it will be allocated from the heap. 93 * 94 * @note this reserves memory only for the parser itself; all the 95 * allocations for the parsed tree will go through the tree's 96 * allocator. 97 * 98 * @note the tree and the arena can (and should) also be reserved. */ 99 void reserve_stack(size_t capacity) 100 { 101 m_stack.reserve(capacity); 102 } 103 104 /** Reserve a certain capacity for the array used to track node 105 * locations in the source buffer. */ 106 void reserve_locations(size_t num_source_lines) 107 { 108 _resize_locations(num_source_lines); 109 } 110 111 /** Reserve a certain capacity for the character arena used to 112 * filter scalars. */ 113 void reserve_filter_arena(size_t num_characters) 114 { 115 _resize_filter_arena(num_characters); 116 } 117 118 /** @} */ 119 120 public: 121 122 /** @name getters and modifiers */ 123 /** @{ */ 124 125 /** Get the current callbacks in the parser. */ 126 Callbacks callbacks() const { return m_stack.m_callbacks; } 127 128 /** Get the name of the latest file parsed by this object. */ 129 csubstr filename() const { return m_file; } 130 131 /** Get the latest YAML buffer parsed by this object. */ 132 csubstr source() const { return m_buf; } 133 134 size_t stack_capacity() const { return m_stack.capacity(); } 135 size_t locations_capacity() const { return m_newline_offsets_capacity; } 136 size_t filter_arena_capacity() const { return m_filter_arena.len; } 137 138 ParserOptions const& options() const { return m_options; } 139 140 /** @} */ 141 142 public: 143 144 /** @name parse_in_place */ 145 /** @{ */ 146 147 /** Create a new tree and parse into its root. 148 * The tree is created with the callbacks currently in the parser. */ 149 Tree parse_in_place(csubstr filename, substr src) 150 { 151 Tree t(callbacks()); 152 t.reserve(_estimate_capacity(src)); 153 this->parse_in_place(filename, src, &t, t.root_id()); 154 return t; 155 } 156 157 /** Parse into an existing tree, starting at its root node. 158 * The callbacks in the tree are kept, and used to allocate 159 * the tree members, if any allocation is required. */ 160 void parse_in_place(csubstr filename, substr src, Tree *t) 161 { 162 this->parse_in_place(filename, src, t, t->root_id()); 163 } 164 165 /** Parse into an existing node. 166 * The callbacks in the tree are kept, and used to allocate 167 * the tree members, if any allocation is required. */ 168 void parse_in_place(csubstr filename, substr src, Tree *t, size_t node_id); 169 // ^^^^^^^^^^^^^ this is the workhorse overload; everything else is syntactic candy 170 171 /** Parse into an existing node. 172 * The callbacks in the tree are kept, and used to allocate 173 * the tree members, if any allocation is required. */ 174 void parse_in_place(csubstr filename, substr src, NodeRef node) 175 { 176 this->parse_in_place(filename, src, node.tree(), node.id()); 177 } 178 179 RYML_DEPRECATED("use parse_in_place() instead") Tree parse(csubstr filename, substr src) { return parse_in_place(filename, src); } 180 RYML_DEPRECATED("use parse_in_place() instead") void parse(csubstr filename, substr src, Tree *t) { parse_in_place(filename, src, t); } 181 RYML_DEPRECATED("use parse_in_place() instead") void parse(csubstr filename, substr src, Tree *t, size_t node_id) { parse_in_place(filename, src, t, node_id); } 182 RYML_DEPRECATED("use parse_in_place() instead") void parse(csubstr filename, substr src, NodeRef node) { parse_in_place(filename, src, node); } 183 184 /** @} */ 185 186 public: 187 188 /** @name parse_in_arena: copy the YAML source buffer to the 189 * tree's arena, then parse the copy in situ 190 * 191 * @note overloads receiving a substr YAML buffer are intentionally 192 * left undefined, such that calling parse_in_arena() with a substr 193 * will cause a linker error. This is to prevent an accidental 194 * copy of the source buffer to the tree's arena, because substr 195 * is implicitly convertible to csubstr. If you really intend to parse 196 * a mutable buffer in the tree's arena, convert it first to immutable 197 * by assigning the substr to a csubstr prior to calling parse_in_arena(). 198 * This is not needed for parse_in_place() because csubstr is not 199 * implicitly convertible to substr. */ 200 /** @{ */ 201 202 // READ THE NOTE ABOVE! 203 #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." 204 RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) Tree parse_in_arena(csubstr filename, substr csrc); 205 RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(csubstr filename, substr csrc, Tree *t); 206 RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(csubstr filename, substr csrc, Tree *t, size_t node_id); 207 RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(csubstr filename, substr csrc, NodeRef node); 208 209 /** Create a new tree and parse into its root. 210 * The immutable YAML source is first copied to the tree's arena, 211 * and parsed from there. 212 * The callbacks in the tree are kept, and used to allocate 213 * the tree members, if any allocation is required. */ 214 Tree parse_in_arena(csubstr filename, csubstr csrc) 215 { 216 Tree t(callbacks()); 217 substr src = t.copy_to_arena(csrc); 218 t.reserve(_estimate_capacity(csrc)); 219 this->parse_in_place(filename, src, &t, t.root_id()); 220 return t; 221 } 222 223 /** Parse into an existing tree, starting at its root node. 224 * The immutable YAML source is first copied to the tree's arena, 225 * and parsed from there. 226 * The callbacks in the tree are kept, and used to allocate 227 * the tree members, if any allocation is required. */ 228 void parse_in_arena(csubstr filename, csubstr csrc, Tree *t) 229 { 230 substr src = t->copy_to_arena(csrc); 231 this->parse_in_place(filename, src, t, t->root_id()); 232 } 233 234 /** Parse into a specific node in an existing tree. 235 * The immutable YAML source is first copied to the tree's arena, 236 * and parsed from there. 237 * The callbacks in the tree are kept, and used to allocate 238 * the tree members, if any allocation is required. */ 239 void parse_in_arena(csubstr filename, csubstr csrc, Tree *t, size_t node_id) 240 { 241 substr src = t->copy_to_arena(csrc); 242 this->parse_in_place(filename, src, t, node_id); 243 } 244 245 /** Parse into a specific node in an existing tree. 246 * The immutable YAML source is first copied to the tree's arena, 247 * and parsed from there. 248 * The callbacks in the tree are kept, and used to allocate 249 * the tree members, if any allocation is required. */ 250 void parse_in_arena(csubstr filename, csubstr csrc, NodeRef node) 251 { 252 substr src = node.tree()->copy_to_arena(csrc); 253 this->parse_in_place(filename, src, node.tree(), node.id()); 254 } 255 256 RYML_DEPRECATED("use parse_in_arena() instead") Tree parse(csubstr filename, csubstr csrc) { return parse_in_arena(filename, csrc); } 257 RYML_DEPRECATED("use parse_in_arena() instead") void parse(csubstr filename, csubstr csrc, Tree *t) { parse_in_arena(filename, csrc, t); } 258 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); } 259 RYML_DEPRECATED("use parse_in_arena() instead") void parse(csubstr filename, csubstr csrc, NodeRef node) { parse_in_arena(filename, csrc, node); } 260 261 /** @} */ 262 263 public: 264 265 /** @name locations */ 266 /** @{ */ 267 268 /** Get the location of a node of the last tree to be parsed by this parser. */ 269 Location location(Tree const& tree, size_t node_id) const; 270 /** Get the location of a node of the last tree to be parsed by this parser. */ 271 Location location(ConstNodeRef node) const; 272 /** Get the string starting at a particular location, to the end 273 * of the parsed source buffer. */ 274 csubstr location_contents(Location const& loc) const; 275 /** Given a pointer to a buffer position, get the location. @p val 276 * must be pointing to somewhere in the source buffer that was 277 * last parsed by this object. */ 278 Location val_location(const char *val) const; 279 280 /** @} */ 281 282 private: 283 284 typedef enum { 285 BLOCK_LITERAL, //!< keep newlines (|) 286 BLOCK_FOLD //!< replace newline with single space (>) 287 } BlockStyle_e; 288 289 typedef enum { 290 CHOMP_CLIP, //!< single newline at end (default) 291 CHOMP_STRIP, //!< no newline at end (-) 292 CHOMP_KEEP //!< all newlines from end (+) 293 } BlockChomp_e; 294 295 private: 296 297 using flag_t = int; 298 299 static size_t _estimate_capacity(csubstr src) { size_t c = _count_nlines(src); c = c >= 16 ? c : 16; return c; } 300 301 void _reset(); 302 303 bool _finished_file() const; 304 bool _finished_line() const; 305 306 csubstr _peek_next_line(size_t pos=npos) const; 307 bool _advance_to_peeked(); 308 void _scan_line(); 309 310 csubstr _slurp_doc_scalar(); 311 312 /** 313 * @param [out] quoted 314 * Will only be written to if this method returns true. 315 * Will be set to true if the scanned scalar was quoted, by '', "", > or |. 316 */ 317 bool _scan_scalar_seq_blck(csubstr *C4_RESTRICT scalar, bool *C4_RESTRICT quoted); 318 bool _scan_scalar_map_blck(csubstr *C4_RESTRICT scalar, bool *C4_RESTRICT quoted); 319 bool _scan_scalar_seq_flow(csubstr *C4_RESTRICT scalar, bool *C4_RESTRICT quoted); 320 bool _scan_scalar_map_flow(csubstr *C4_RESTRICT scalar, bool *C4_RESTRICT quoted); 321 bool _scan_scalar_unk(csubstr *C4_RESTRICT scalar, bool *C4_RESTRICT quoted); 322 323 csubstr _scan_comment(); 324 csubstr _scan_squot_scalar(); 325 csubstr _scan_dquot_scalar(); 326 csubstr _scan_block(); 327 substr _scan_plain_scalar_blck(csubstr currscalar, csubstr peeked_line, size_t indentation); 328 substr _scan_plain_scalar_flow(csubstr currscalar, csubstr peeked_line); 329 substr _scan_complex_key(csubstr currscalar, csubstr peeked_line); 330 csubstr _scan_to_next_nonempty_line(size_t indentation); 331 csubstr _extend_scanned_scalar(csubstr currscalar); 332 333 csubstr _filter_squot_scalar(const substr s); 334 csubstr _filter_dquot_scalar(substr s); 335 csubstr _filter_plain_scalar(substr s, size_t indentation); 336 csubstr _filter_block_scalar(substr s, BlockStyle_e style, BlockChomp_e chomp, size_t indentation); 337 template<bool backslash_is_escape, bool keep_trailing_whitespace> 338 bool _filter_nl(substr scalar, size_t *C4_RESTRICT pos, size_t *C4_RESTRICT filter_arena_pos, size_t indentation); 339 template<bool keep_trailing_whitespace> 340 void _filter_ws(substr scalar, size_t *C4_RESTRICT pos, size_t *C4_RESTRICT filter_arena_pos); 341 bool _apply_chomp(substr buf, size_t *C4_RESTRICT pos, BlockChomp_e chomp); 342 343 void _handle_finished_file(); 344 void _handle_line(); 345 346 bool _handle_indentation(); 347 348 bool _handle_unk(); 349 bool _handle_map_flow(); 350 bool _handle_map_blck(); 351 bool _handle_seq_flow(); 352 bool _handle_seq_blck(); 353 bool _handle_top(); 354 bool _handle_types(); 355 bool _handle_key_anchors_and_refs(); 356 bool _handle_val_anchors_and_refs(); 357 void _move_val_tag_to_key_tag(); 358 void _move_key_tag_to_val_tag(); 359 void _move_key_tag2_to_key_tag(); 360 void _move_val_anchor_to_key_anchor(); 361 void _move_key_anchor_to_val_anchor(); 362 363 void _push_level(bool explicit_flow_chars = false); 364 void _pop_level(); 365 366 void _start_unk(bool as_child=true); 367 368 void _start_map(bool as_child=true); 369 void _start_map_unk(bool as_child); 370 void _stop_map(); 371 372 void _start_seq(bool as_child=true); 373 void _stop_seq(); 374 375 void _start_seqimap(); 376 void _stop_seqimap(); 377 378 void _start_doc(bool as_child=true); 379 void _stop_doc(); 380 void _start_new_doc(csubstr rem); 381 void _end_stream(); 382 383 NodeData* _append_val(csubstr val, flag_t quoted=false); 384 NodeData* _append_key_val(csubstr val, flag_t val_quoted=false); 385 bool _rval_dash_start_or_continue_seq(); 386 387 void _store_scalar(csubstr s, flag_t is_quoted); 388 csubstr _consume_scalar(); 389 void _move_scalar_from_top(); 390 391 inline NodeData* _append_val_null(const char *str) { _RYML_CB_ASSERT(m_stack.m_callbacks, str >= m_buf.begin() && str <= m_buf.end()); return _append_val({nullptr, size_t(0)}); } 392 inline NodeData* _append_key_val_null(const char *str) { _RYML_CB_ASSERT(m_stack.m_callbacks, str >= m_buf.begin() && str <= m_buf.end()); return _append_key_val({nullptr, size_t(0)}); } 393 inline void _store_scalar_null(const char *str) { _RYML_CB_ASSERT(m_stack.m_callbacks, str >= m_buf.begin() && str <= m_buf.end()); _store_scalar({nullptr, size_t(0)}, false); } 394 395 void _set_indentation(size_t behind); 396 void _save_indentation(size_t behind=0); 397 bool _maybe_set_indentation_from_anchor_or_tag(); 398 399 void _write_key_anchor(size_t node_id); 400 void _write_val_anchor(size_t node_id); 401 402 void _handle_directive(csubstr directive); 403 404 void _skipchars(char c); 405 template<size_t N> 406 void _skipchars(const char (&chars)[N]); 407 408 private: 409 410 static size_t _count_nlines(csubstr src); 411 412 private: 413 414 typedef enum : flag_t { 415 RTOP = 0x01 << 0, ///< reading at top level 416 RUNK = 0x01 << 1, ///< reading an unknown: must determine whether scalar, map or seq 417 RMAP = 0x01 << 2, ///< reading a map 418 RSEQ = 0x01 << 3, ///< reading a seq 419 FLOW = 0x01 << 4, ///< reading is inside explicit flow chars: [] or {} 420 QMRK = 0x01 << 5, ///< reading an explicit key (`? key`) 421 RKEY = 0x01 << 6, ///< reading a scalar as key 422 RVAL = 0x01 << 7, ///< reading a scalar as val 423 RNXT = 0x01 << 8, ///< read next val or keyval 424 SSCL = 0x01 << 9, ///< there's a stored scalar 425 QSCL = 0x01 << 10, ///< stored scalar was quoted 426 RSET = 0x01 << 11, ///< the (implicit) map being read is a !!set. @see https://yaml.org/type/set.html 427 NDOC = 0x01 << 12, ///< no document mode. a document has ended and another has not started yet. 428 //! reading an implicit map nested in an explicit seq. 429 //! eg, {key: [key2: value2, key3: value3]} 430 //! is parsed as {key: [{key2: value2}, {key3: value3}]} 431 RSEQIMAP = 0x01 << 13, 432 } State_e; 433 434 struct LineContents 435 { 436 csubstr full; ///< the full line, including newlines on the right 437 csubstr stripped; ///< the stripped line, excluding newlines on the right 438 csubstr rem; ///< the stripped line remainder; initially starts at the first non-space character 439 size_t indentation; ///< the number of spaces on the beginning of the line 440 441 LineContents() : full(), stripped(), rem(), indentation() {} 442 443 void reset_with_next_line(csubstr buf, size_t pos); 444 445 void reset(csubstr full_, csubstr stripped_) 446 { 447 full = full_; 448 stripped = stripped_; 449 rem = stripped_; 450 // find the first column where the character is not a space 451 indentation = full.first_not_of(' '); 452 } 453 454 size_t current_col() const 455 { 456 return current_col(rem); 457 } 458 459 size_t current_col(csubstr s) const 460 { 461 RYML_ASSERT(s.str >= full.str); 462 RYML_ASSERT(full.is_super(s)); 463 size_t col = static_cast<size_t>(s.str - full.str); 464 return col; 465 } 466 }; 467 468 struct State 469 { 470 flag_t flags; 471 size_t level; 472 size_t node_id; // don't hold a pointer to the node as it will be relocated during tree resizes 473 csubstr scalar; 474 size_t scalar_col; // the column where the scalar (or its quotes) begin 475 476 Location pos; 477 LineContents line_contents; 478 size_t indref; 479 480 State() : flags(), level(), node_id(), scalar(), scalar_col(), pos(), line_contents(), indref() {} 481 482 void reset(const char *file, size_t node_id_) 483 { 484 flags = RUNK|RTOP; 485 level = 0; 486 pos.name = to_csubstr(file); 487 pos.offset = 0; 488 pos.line = 1; 489 pos.col = 1; 490 node_id = node_id_; 491 scalar_col = 0; 492 scalar.clear(); 493 indref = 0; 494 } 495 }; 496 497 void _line_progressed(size_t ahead); 498 void _line_ended(); 499 void _line_ended_undo(); 500 501 void _prepare_pop() 502 { 503 RYML_ASSERT(m_stack.size() > 1); 504 State const& curr = m_stack.top(); 505 State & next = m_stack.top(1); 506 next.pos = curr.pos; 507 next.line_contents = curr.line_contents; 508 next.scalar = curr.scalar; 509 } 510 511 inline bool _at_line_begin() const 512 { 513 return m_state->line_contents.rem.begin() == m_state->line_contents.full.begin(); 514 } 515 inline bool _at_line_end() const 516 { 517 csubstr r = m_state->line_contents.rem; 518 return r.empty() || r.begins_with(' ', r.len); 519 } 520 inline bool _token_is_from_this_line(csubstr token) const 521 { 522 return token.is_sub(m_state->line_contents.full); 523 } 524 525 inline NodeData * node(State const* s) const { return m_tree->get(s->node_id); } 526 inline NodeData * node(State const& s) const { return m_tree->get(s .node_id); } 527 inline NodeData * node(size_t node_id) const { return m_tree->get( node_id); } 528 529 inline bool has_all(flag_t f) const { return (m_state->flags & f) == f; } 530 inline bool has_any(flag_t f) const { return (m_state->flags & f) != 0; } 531 inline bool has_none(flag_t f) const { return (m_state->flags & f) == 0; } 532 533 static inline bool has_all(flag_t f, State const* s) { return (s->flags & f) == f; } 534 static inline bool has_any(flag_t f, State const* s) { return (s->flags & f) != 0; } 535 static inline bool has_none(flag_t f, State const* s) { return (s->flags & f) == 0; } 536 537 inline void set_flags(flag_t f) { set_flags(f, m_state); } 538 inline void add_flags(flag_t on) { add_flags(on, m_state); } 539 inline void addrem_flags(flag_t on, flag_t off) { addrem_flags(on, off, m_state); } 540 inline void rem_flags(flag_t off) { rem_flags(off, m_state); } 541 542 void set_flags(flag_t f, State * s); 543 void add_flags(flag_t on, State * s); 544 void addrem_flags(flag_t on, flag_t off, State * s); 545 void rem_flags(flag_t off, State * s); 546 547 void _resize_filter_arena(size_t num_characters); 548 void _grow_filter_arena(size_t num_characters); 549 substr _finish_filter_arena(substr dst, size_t pos); 550 551 void _prepare_locations(); 552 void _resize_locations(size_t sz); 553 bool _locations_dirty() const; 554 555 bool _location_from_cont(Tree const& tree, size_t node, Location *C4_RESTRICT loc) const; 556 bool _location_from_node(Tree const& tree, size_t node, Location *C4_RESTRICT loc, size_t level) const; 557 558 private: 559 560 void _free(); 561 void _clr(); 562 void _cp(Parser const* that); 563 void _mv(Parser *that); 564 565 #ifdef RYML_DBG 566 template<class ...Args> void _dbg(csubstr fmt, Args const& C4_RESTRICT ...args) const; 567 #endif 568 template<class ...Args> void _err(csubstr fmt, Args const& C4_RESTRICT ...args) const; 569 template<class DumpFn> void _fmt_msg(DumpFn &&dumpfn) const; 570 static csubstr _prfl(substr buf, flag_t v); 571 572 private: 573 574 ParserOptions m_options; 575 576 csubstr m_file; 577 substr m_buf; 578 579 size_t m_root_id; 580 Tree * m_tree; 581 582 detail::stack<State> m_stack; 583 State * m_state; 584 585 size_t m_key_tag_indentation; 586 size_t m_key_tag2_indentation; 587 csubstr m_key_tag; 588 csubstr m_key_tag2; 589 size_t m_val_tag_indentation; 590 csubstr m_val_tag; 591 592 bool m_key_anchor_was_before; 593 size_t m_key_anchor_indentation; 594 csubstr m_key_anchor; 595 size_t m_val_anchor_indentation; 596 csubstr m_val_anchor; 597 598 substr m_filter_arena; 599 600 size_t *m_newline_offsets; 601 size_t m_newline_offsets_size; 602 size_t m_newline_offsets_capacity; 603 csubstr m_newline_offsets_buf; 604 }; 605 606 607 //----------------------------------------------------------------------------- 608 //----------------------------------------------------------------------------- 609 //----------------------------------------------------------------------------- 610 611 /** @name parse_in_place 612 * 613 * @desc parse a mutable YAML source buffer. 614 * 615 * @note These freestanding functions use a temporary parser object, 616 * and are convenience functions to easily parse YAML without the need 617 * to instantiate a separate parser. Note that some properties 618 * (notably node locations in the original source code) are only 619 * available through the parser object after it has parsed the 620 * code. If you need access to any of these properties, use 621 * Parser::parse_in_place() */ 622 /** @{ */ 623 624 inline Tree parse_in_place( substr yaml ) { Parser np; return np.parse_in_place({} , yaml); } //!< parse in-situ a modifiable YAML source buffer. 625 inline Tree parse_in_place(csubstr filename, substr yaml ) { Parser np; return np.parse_in_place(filename, yaml); } //!< parse in-situ a modifiable YAML source buffer, providing a filename for error messages. 626 inline void parse_in_place( substr yaml, Tree *t ) { Parser np; np.parse_in_place({} , yaml, t); } //!< reusing the YAML tree, parse in-situ a modifiable YAML source buffer 627 inline void parse_in_place(csubstr filename, substr yaml, Tree *t ) { Parser np; np.parse_in_place(filename, yaml, t); } //!< reusing the YAML tree, parse in-situ a modifiable YAML source buffer, providing a filename for error messages. 628 inline void parse_in_place( substr yaml, Tree *t, size_t node_id) { Parser np; np.parse_in_place({} , yaml, t, node_id); } //!< reusing the YAML tree, parse in-situ a modifiable YAML source buffer 629 inline void parse_in_place(csubstr filename, substr yaml, Tree *t, size_t node_id) { Parser np; np.parse_in_place(filename, yaml, t, node_id); } //!< reusing the YAML tree, parse in-situ a modifiable YAML source buffer, providing a filename for error messages. 630 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 631 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. 632 633 RYML_DEPRECATED("use parse_in_place() instead") inline Tree parse( substr yaml ) { Parser np; return np.parse_in_place({} , yaml); } 634 RYML_DEPRECATED("use parse_in_place() instead") inline Tree parse(csubstr filename, substr yaml ) { Parser np; return np.parse_in_place(filename, yaml); } 635 RYML_DEPRECATED("use parse_in_place() instead") inline void parse( substr yaml, Tree *t ) { Parser np; np.parse_in_place({} , yaml, t); } 636 RYML_DEPRECATED("use parse_in_place() instead") inline void parse(csubstr filename, substr yaml, Tree *t ) { Parser np; np.parse_in_place(filename, yaml, t); } 637 RYML_DEPRECATED("use parse_in_place() instead") inline void parse( substr yaml, Tree *t, size_t node_id) { Parser np; np.parse_in_place({} , yaml, t, node_id); } 638 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); } 639 RYML_DEPRECATED("use parse_in_place() instead") inline void parse( substr yaml, NodeRef node ) { Parser np; np.parse_in_place({} , yaml, node); } 640 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); } 641 642 /** @} */ 643 644 645 //----------------------------------------------------------------------------- 646 647 /** @name parse_in_arena 648 * @desc parse a read-only YAML source buffer, copying it first to the tree's arena. 649 * 650 * @note These freestanding functions use a temporary parser object, 651 * and are convenience functions to easily parse YAML without the need 652 * to instantiate a separate parser. Note that some properties 653 * (notably node locations in the original source code) are only 654 * available through the parser object after it has parsed the 655 * code. If you need access to any of these properties, use 656 * Parser::parse_in_arena(). 657 * 658 * @note overloads receiving a substr YAML buffer are intentionally 659 * left undefined, such that calling parse_in_arena() with a substr 660 * will cause a linker error. This is to prevent an accidental 661 * copy of the source buffer to the tree's arena, because substr 662 * is implicitly convertible to csubstr. If you really intend to parse 663 * a mutable buffer in the tree's arena, convert it first to immutable 664 * by assigning the substr to a csubstr prior to calling parse_in_arena(). 665 * This is not needed for parse_in_place() because csubstr is not 666 * implicitly convertible to substr. */ 667 /** @{ */ 668 669 /* READ THE NOTE ABOVE! */ 670 RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) Tree parse_in_arena( substr yaml ); 671 RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) Tree parse_in_arena(csubstr filename, substr yaml ); 672 RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena( substr yaml, Tree *t ); 673 RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(csubstr filename, substr yaml, Tree *t ); 674 RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena( substr yaml, Tree *t, size_t node_id); 675 RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(csubstr filename, substr yaml, Tree *t, size_t node_id); 676 RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena( substr yaml, NodeRef node ); 677 RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(csubstr filename, substr yaml, NodeRef node ); 678 679 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. 680 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. 681 inline void parse_in_arena( 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. 682 inline void parse_in_arena(csubstr filename, csubstr yaml, Tree *t ) { Parser np; np.parse_in_arena(filename, yaml, t); } //!< 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. 683 inline void parse_in_arena( csubstr yaml, Tree *t, size_t node_id) { Parser np; np.parse_in_arena({} , yaml, t, node_id); } //!< reusing the YAML tree, parse a read-only YAML source buffer, copying it first to the tree's source arena. 684 inline void parse_in_arena(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. 685 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. 686 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. 687 688 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. 689 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. 690 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. 691 RYML_DEPRECATED("use parse_in_arena() instead") inline void parse(csubstr filename, csubstr yaml, Tree *t ) { Parser np; np.parse_in_arena(filename, yaml, t); } //!< 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. 692 RYML_DEPRECATED("use parse_in_arena() instead") inline void parse( csubstr yaml, Tree *t, size_t node_id) { Parser np; np.parse_in_arena({} , yaml, t, node_id); } //!< reusing the YAML tree, parse a read-only YAML source buffer, copying it first to the tree's source arena. 693 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. 694 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. 695 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. 696 697 /** @} */ 698 699 } // namespace yml 700 } // namespace c4 701 702 #if defined(_MSC_VER) 703 # pragma warning(pop) 704 #endif 705 706 #endif /* _C4_YML_PARSE_HPP_ */