mirror of
https://github.com/biojppm/rapidyaml.git
synced 2026-01-18 21:41:18 +01:00
[refac] remove the parser options: lazily cache the location accelerator
This commit is contained in:
@@ -569,14 +569,13 @@ CHECK(stream_result == expected_result);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Getting the location of nodes in the source:
|
||||
ryml::Parser parser(ryml::ParseOptions::TRACK_LOCATION);
|
||||
ryml::Parser parser;
|
||||
ryml::Tree tree2 = parser.parse_in_arena("expected.yml", expected_result);
|
||||
ryml::Location loc = parser.location(tree2["bar"][1]);
|
||||
CHECK(parser.location_contents(loc).begins_with("30"));
|
||||
CHECK(loc.line == 3u);
|
||||
CHECK(loc.col == 4u);
|
||||
// For further details in location tracking,
|
||||
// refer to the sample function.
|
||||
// For further details in location tracking, refer to the sample function.
|
||||
```
|
||||
|
||||
The [quickstart.cpp sample](./samples/quickstart.cpp) (from which the
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
### Breaking changes
|
||||
|
||||
- Rename `c4::yml::parse()` and `c4::yml::Parser::parse()` overloads
|
||||
to either `parse_in_place()` or `parse_in_arena()`:
|
||||
- `parse_in_place()` receives only `substr` buffers, ie mutable YAML
|
||||
source buffers. Trying to pass a `csubstr` buffer to
|
||||
`parse_in_place()` will cause a compile error:
|
||||
As part of the [new feature to track source locations](https://github.com/biojppm/rapidyaml/pull/168), opportunity was taken to address a number of pre-existing API issues. These changes consisted of:
|
||||
|
||||
- Deprecate `c4::yml::parse()` and `c4::yml::Parser::parse()` overloads; all these functions will be shortly removed. Until removal, any call from client code will trigger a compiler warning.
|
||||
- Add `parse()` alternatives, either `parse_in_place()` or `parse_in_arena()`:
|
||||
- `parse_in_place()` receives only `substr` buffers, ie mutable YAML source buffers. Trying to pass a `csubstr` buffer to `parse_in_place()` will cause a compile error:
|
||||
```c++
|
||||
substr readwrite = /*...*/;
|
||||
Tree tree = parse_in_place(readwrite); // OK
|
||||
@@ -12,94 +12,84 @@
|
||||
csubstr readonly = /*...*/;
|
||||
Tree tree = parse_in_place(readonly); // compile error
|
||||
```
|
||||
- `parse_in_arena()` receives only `csubstr` buffers, ie immutable
|
||||
YAML source buffers. Prior to parsing, the buffer is copied to
|
||||
the tree's arena, then the copy is parsed in place. Because
|
||||
`parse_in_arena()` is meant for immutable buffers, overloads
|
||||
receiving a `substr` YAML buffer are now declared, and
|
||||
intentionally left undefined, such that calling
|
||||
`parse_in_arena()` with a `substr` will cause a linker
|
||||
error.
|
||||
- `parse_in_arena()` receives only `csubstr` buffers, ie immutable YAML source buffers. Prior to parsing, the buffer is copied to the tree's arena, then the copy is parsed in place. Because `parse_in_arena()` is meant for immutable buffers, overloads receiving a `substr` YAML buffer are now declared and marked deprecated, and intentionally left undefined, such that calling `parse_in_arena()` with a `substr` will cause a linker error.
|
||||
```c++
|
||||
substr readwrite = /*...*/;
|
||||
Tree tree = parse_in_arena(readwrite); // linker error
|
||||
Tree tree = parse_in_arena(readwrite); // compile warning+linker error
|
||||
```
|
||||
This is to prevent an accidental extra copy of the source buffer
|
||||
to the tree's arena, because `substr` is implicitly convertible
|
||||
to `csubstr`. If you really intend to parse an originally 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 to prevent an accidental extra copy of the mutable source buffer to the tree's arena: `substr` is implicitly convertible to `csubstr`. If you really intend to parse an originally 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()`:
|
||||
```c++
|
||||
substr readwrite = /*...*/;
|
||||
csubstr as_readonly = readwrite; // ok
|
||||
Tree tree = parse_in_arena(as_readonly); // ok
|
||||
csubstr readonly = readwrite; // ok
|
||||
Tree tree = parse_in_arena(readonly); // ok
|
||||
```
|
||||
This approach is not needed for `parse_in_place()`
|
||||
because `csubstr` is not implicitly convertible to `substr`.
|
||||
This problem is not raised by `parse_in_place()` because `csubstr` is not implicitly convertible to `substr`.
|
||||
- In the python API, `ryml.parse()` was removed and not just deprecated; the `parse_in_arena()` and `parse_in_place()` now replace this.
|
||||
- `Callbacks`: changed behavior in `Parser` and `Tree`:
|
||||
- When a tree is copy-constructed or move-constructed to another,
|
||||
the receiving tree will start with the callbacks of the original.
|
||||
- When a tree is copy-assigned or move-assigned to another, the
|
||||
receiving tree will now change its callbacks to the original.
|
||||
- When a parser creates a new tree, the tree will now use a copy of
|
||||
the parser's callbacks object.
|
||||
- When an existing tree is given directly to the parser, both the
|
||||
tree and the parser now retain their own callback objects; any
|
||||
allocation or error during parsing will go through the respective
|
||||
callback object.
|
||||
- When a tree is copy-constructed or move-constructed to another, the receiving tree will start with the callbacks of the original.
|
||||
- When a tree is copy-assigned or move-assigned to another, the receiving tree will now change its callbacks to the original.
|
||||
- When a parser creates a new tree, the tree will now use a copy of the parser's callbacks object.
|
||||
- When an existing tree is given directly to the parser, both the tree and the parser now retain their own callback objects; any allocation or error during parsing will go through the respective callback object.
|
||||
|
||||
|
||||
### New features
|
||||
|
||||
- Add tracking of source code locations. This is useful for reporting semantic errors (ie where the YAML is syntatically valid but the contents are semantically invalid). It is implemented opt-in when creating the parser:
|
||||
- `Parser`:
|
||||
- add `source()` and `filename()` to get the latest buffer and filename to be parsed
|
||||
- add `callbacks()` to get the parser's callbacks
|
||||
- Add tracking of source code locations. This is useful for reporting semantic errors (ie where the YAML is syntatically valid but the contents are semantically invalid). The locations can be obtained lazily from the parser when the first location is queried:
|
||||
```c++
|
||||
ryml::csubstr yaml = "{c1: contents, c14: [one, [two, three]]}";
|
||||
// enable the parser to track locations.
|
||||
ryml::Parser parser(ryml::ParseOptions::TRACK_LOCATION);
|
||||
auto is_at = [&parser](ryml::csubstr str, ryml::Location const& loc){
|
||||
return parser.location_contents(loc).begins_with(str);
|
||||
};
|
||||
// ... has effect only on the next parse:
|
||||
ryml::Tree tree = parser.parse_in_arena("source.yml", yaml);
|
||||
ryml::Location loc;
|
||||
loc = parser.location(tree.rootref());
|
||||
CHECK(is_at("{", loc));
|
||||
CHECK(loc.offset == 0u);
|
||||
CHECK(loc.line == 0u);
|
||||
CHECK(loc.col == 0u);
|
||||
loc = parser.location(tree["c1"]);
|
||||
CHECK(is_at("c1", loc));
|
||||
CHECK(loc.offset == 1u);
|
||||
CHECK(loc.line == 0u);
|
||||
CHECK(loc.col == 1u);
|
||||
loc = parser.location(tree["c15"]);
|
||||
CHECK(is_at("c15", loc));
|
||||
CHECK(loc.offset == 15u);
|
||||
CHECK(loc.line == 0u);
|
||||
CHECK(loc.col == 15u);
|
||||
loc = parser.location(tree["c15"][0]);
|
||||
CHECK(is_at("one", loc));
|
||||
CHECK(loc.offset == 21u);
|
||||
CHECK(loc.line == 0u);
|
||||
CHECK(loc.col == 21u);
|
||||
loc = parser.location(tree["c15"][1]);
|
||||
CHECK(is_at("[", loc));
|
||||
CHECK(loc.offset == 26u);
|
||||
CHECK(loc.line == 0u);
|
||||
CHECK(loc.col == 26u);
|
||||
loc = parser.location(tree["c15"][1][0]);
|
||||
CHECK(is_at("two", loc));
|
||||
CHECK(loc.offset == 27u);
|
||||
CHECK(loc.line == 0u);
|
||||
CHECK(loc.col == 27u);
|
||||
loc = parser.location(tree["c15"][1][1]);
|
||||
CHECK(is_at("three", loc));
|
||||
CHECK(loc.offset == 32u);
|
||||
CHECK(loc.line == 0u);
|
||||
CHECK(loc.col == 32u);
|
||||
// To obtain locations, use of the parser is needed:
|
||||
ryml::Parser parser;
|
||||
ryml::Tree tree = parser.parse_in_arena("source.yml", R"({
|
||||
aa: contents,
|
||||
foo: [one, [two, three]]
|
||||
})");
|
||||
// After parsing, on the first call to obtain a location,
|
||||
// the parser will cache a lookup structure to accelerate
|
||||
// tracking the location of a node, with complexity
|
||||
// O(numchars(srcbuffer)). Then it will do the lookup, with
|
||||
// complexity O(log(numlines(srcbuffer))).
|
||||
ryml::Location loc = parser.location(tree.rootref());
|
||||
assert(parser.location_contents(loc).begins_with("{"));
|
||||
// note the location members are zero-based:
|
||||
assert(loc.offset == 0u);
|
||||
assert(loc.line == 0u);
|
||||
assert(loc.col == 0u);
|
||||
// On the next call to location(), the accelerator is reused
|
||||
// and only the lookup is done.
|
||||
loc = parser.location(tree["aa"]);
|
||||
assert(parser.location_contents(loc).begins_with("aa"));
|
||||
assert(loc.offset == 2u);
|
||||
assert(loc.line == 1u);
|
||||
assert(loc.col == 0u);
|
||||
// KEYSEQ in flow style: points at the key
|
||||
loc = parser.location(tree["foo"]);
|
||||
assert(parser.location_contents(loc).begins_with("foo"));
|
||||
assert(loc.offset == 16u);
|
||||
assert(loc.line == 2u);
|
||||
assert(loc.col == 0u);
|
||||
loc = parser.location(tree["foo"][0]);
|
||||
assert(parser.location_contents(loc).begins_with("one"));
|
||||
assert(loc.line == 2u);
|
||||
assert(loc.col == 6u);
|
||||
// SEQ in flow style: location points at the opening '[' (there's no key)
|
||||
loc = parser.location(tree["foo"][1]);
|
||||
assert(parser.location_contents(loc).begins_with("["));
|
||||
assert(loc.line == 2u);
|
||||
assert(loc.col == 11u);
|
||||
loc = parser.location(tree["foo"][1][0]);
|
||||
assert(parser.location_contents(loc).begins_with("two"));
|
||||
assert(loc.line == 2u);
|
||||
assert(loc.col == 12u);
|
||||
loc = parser.location(tree["foo"][1][1]);
|
||||
assert(parser.location_contents(loc).begins_with("three"));
|
||||
assert(loc.line == 2u);
|
||||
assert(loc.col == 17u);
|
||||
// NOTE: reusing the parser with a new YAML source buffer
|
||||
// will invalidate the accelerator.
|
||||
```
|
||||
See more details in the [quickstart sample](https://github.com/biojppm/rapidyaml/blob/master/samples/quickstart.cpp).
|
||||
See more details in the [quickstart sample](https://github.com/biojppm/rapidyaml/blob/bfb073265abf8c58bbeeeed7fb43270e9205c71c/samples/quickstart.cpp#L3759).
|
||||
|
||||
|
||||
### Fixes
|
||||
|
||||
@@ -483,7 +483,7 @@ I am somebody: indeed
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Getting the location of nodes in the source:
|
||||
ryml::Parser parser(ryml::ParseOptions::TRACK_LOCATION);
|
||||
ryml::Parser parser;
|
||||
ryml::Tree tree2 = parser.parse_in_arena("expected.yml", expected_result);
|
||||
ryml::Location loc = parser.location(tree2["bar"][1]);
|
||||
CHECK(parser.location_contents(loc).begins_with("30"));
|
||||
@@ -3767,16 +3767,37 @@ void sample_location_tracking()
|
||||
aa: contents,
|
||||
foo: [one, [two, three]]
|
||||
})";
|
||||
// Enable the parser to track locations.
|
||||
ryml::Parser parser(ryml::ParseOptions::TRACK_LOCATION);
|
||||
// On the next parse, the parser will cache a lookup structure to
|
||||
// accelerate tracking the location of a node:
|
||||
// A parser is needed to track locations. The parser caches a
|
||||
// source-to-node lookup structure using the parsed source buffer
|
||||
// to accelerate tracking the location of a node.
|
||||
ryml::Parser parser;
|
||||
// On each parse, the location structure is marked dirty, but not
|
||||
// rebuilt. This enables having locations and paying for them
|
||||
// only when they are used.
|
||||
ryml::Tree tree = parser.parse_in_arena("source.yml", yaml);
|
||||
// Thereafter, on the first location query after parsing, the
|
||||
// parser will (re)build the location accelerator. This may
|
||||
// trigger an allocation, but we can avoid this allocation by
|
||||
// reserving at the beginning:
|
||||
parser.reserve_locations(50u); // reserve for 50 lines
|
||||
// Rebuilding the acceleration structure consists of a single scan
|
||||
// over the source buffer, and is not expensive:
|
||||
// complexity=O(numchars).
|
||||
//
|
||||
// As for the complexity of the query: for large buffers it is
|
||||
// O(log(numlines)). For short source buffers (30 lines and less),
|
||||
// it is O(numlines), as a plain linear search is faster in this
|
||||
// case.
|
||||
//
|
||||
// So the complexity of the first location call after parsing is:
|
||||
// cost(rebuild lookup) + cost(lookup) = O(numchars) + O(log(numlines))
|
||||
ryml::Location loc = parser.location(tree.rootref());
|
||||
CHECK(parser.location_contents(loc).begins_with("{"));
|
||||
CHECK(loc.offset == 0u);
|
||||
CHECK(loc.line == 0u);
|
||||
CHECK(loc.col == 0u);
|
||||
CHECK(loc.col == 0u);\
|
||||
// on the next call, we only pay O(log(numlines)) because the
|
||||
// rebuild is already available:
|
||||
loc = parser.location(tree["aa"]);
|
||||
CHECK(parser.location_contents(loc).begins_with("aa"));
|
||||
CHECK(loc.offset == 2u);
|
||||
|
||||
@@ -76,7 +76,7 @@ Parser::~Parser()
|
||||
_clr();
|
||||
}
|
||||
|
||||
Parser::Parser(ParseOptions opts, Callbacks const& cb)
|
||||
Parser::Parser(Callbacks const& cb)
|
||||
: m_file()
|
||||
, m_buf()
|
||||
, m_root_id(NONE)
|
||||
@@ -94,9 +94,10 @@ Parser::Parser(ParseOptions opts, Callbacks const& cb)
|
||||
, m_key_anchor()
|
||||
, m_val_anchor_indentation(0)
|
||||
, m_val_anchor()
|
||||
, m_parse_options(opts)
|
||||
, m_newline_offsets()
|
||||
, m_newline_offsets_size(0)
|
||||
, m_newline_offsets_capacity(0)
|
||||
, m_newline_offsets_buf()
|
||||
{
|
||||
m_stack.push(State{});
|
||||
m_state = &m_stack.top();
|
||||
@@ -120,9 +121,10 @@ Parser::Parser(Parser &&that)
|
||||
, m_key_anchor(that.m_key_anchor)
|
||||
, m_val_anchor_indentation(that.m_val_anchor_indentation)
|
||||
, m_val_anchor(that.m_val_anchor)
|
||||
, m_parse_options(that.m_parse_options)
|
||||
, m_newline_offsets(that.m_newline_offsets)
|
||||
, m_newline_offsets_size(that.m_newline_offsets_size)
|
||||
, m_newline_offsets_capacity(that.m_newline_offsets_capacity)
|
||||
, m_newline_offsets_buf(that.m_newline_offsets_buf)
|
||||
{
|
||||
that._clr();
|
||||
}
|
||||
@@ -145,58 +147,85 @@ Parser::Parser(Parser const& that)
|
||||
, m_key_anchor(that.m_key_anchor)
|
||||
, m_val_anchor_indentation(that.m_val_anchor_indentation)
|
||||
, m_val_anchor(that.m_val_anchor)
|
||||
, m_parse_options(that.m_parse_options)
|
||||
, m_newline_offsets()
|
||||
, m_newline_offsets_size()
|
||||
, m_newline_offsets_capacity()
|
||||
, m_newline_offsets_buf()
|
||||
{
|
||||
if(that.m_newline_offsets_size)
|
||||
if(that.m_newline_offsets_capacity)
|
||||
{
|
||||
_resize_locations(that.m_newline_offsets_size);
|
||||
_resize_locations(that.m_newline_offsets_capacity);
|
||||
_RYML_CB_CHECK(m_stack.m_callbacks, m_newline_offsets_capacity == that.m_newline_offsets_capacity);
|
||||
memcpy(m_newline_offsets, that.m_newline_offsets, that.m_newline_offsets_size * sizeof(size_t));
|
||||
m_newline_offsets_size = that.m_newline_offsets_size;
|
||||
}
|
||||
}
|
||||
|
||||
Parser& Parser::operator=(Parser &&that)
|
||||
{
|
||||
_free();
|
||||
_cb(that.m_stack.m_callbacks);
|
||||
_mv(&that);
|
||||
m_file = (that.m_file);
|
||||
m_buf = (that.m_buf);
|
||||
m_root_id = (that.m_root_id);
|
||||
m_tree = (that.m_tree);
|
||||
m_stack = std::move(that.m_stack);
|
||||
m_state = (&m_stack.top());
|
||||
m_key_tag_indentation = (that.m_key_tag_indentation);
|
||||
m_key_tag2_indentation = (that.m_key_tag2_indentation);
|
||||
m_key_tag = (that.m_key_tag);
|
||||
m_key_tag2 = (that.m_key_tag2);
|
||||
m_val_tag_indentation = (that.m_val_tag_indentation);
|
||||
m_val_tag = (that.m_val_tag);
|
||||
m_key_anchor_was_before = (that.m_key_anchor_was_before);
|
||||
m_key_anchor_indentation = (that.m_key_anchor_indentation);
|
||||
m_key_anchor = (that.m_key_anchor);
|
||||
m_val_anchor_indentation = (that.m_val_anchor_indentation);
|
||||
m_val_anchor = (that.m_val_anchor);
|
||||
m_newline_offsets = (that.m_newline_offsets);
|
||||
m_newline_offsets_size = (that.m_newline_offsets_size);
|
||||
m_newline_offsets_capacity = (that.m_newline_offsets_capacity);
|
||||
m_newline_offsets_buf = (that.m_newline_offsets_buf);
|
||||
that._clr();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Parser& Parser::operator=(Parser const& that)
|
||||
{
|
||||
_free();
|
||||
_cb(that.m_stack.m_callbacks);
|
||||
_cp(&that);
|
||||
m_file = (that.m_file);
|
||||
m_buf = (that.m_buf);
|
||||
m_root_id = (that.m_root_id);
|
||||
m_tree = (that.m_tree);
|
||||
m_stack = that.m_stack;
|
||||
m_state = &m_stack.top();
|
||||
m_key_tag_indentation = (that.m_key_tag_indentation);
|
||||
m_key_tag2_indentation = (that.m_key_tag2_indentation);
|
||||
m_key_tag = (that.m_key_tag);
|
||||
m_key_tag2 = (that.m_key_tag2);
|
||||
m_val_tag_indentation = (that.m_val_tag_indentation);
|
||||
m_val_tag = (that.m_val_tag);
|
||||
m_key_anchor_was_before = (that.m_key_anchor_was_before);
|
||||
m_key_anchor_indentation = (that.m_key_anchor_indentation);
|
||||
m_key_anchor = (that.m_key_anchor);
|
||||
m_val_anchor_indentation = (that.m_val_anchor_indentation);
|
||||
m_val_anchor = (that.m_val_anchor);
|
||||
if(that.m_newline_offsets_capacity > m_newline_offsets_capacity)
|
||||
_resize_locations(that.m_newline_offsets_capacity);
|
||||
_RYML_CB_CHECK(m_stack.m_callbacks, m_newline_offsets_capacity >= that.m_newline_offsets_capacity);
|
||||
_RYML_CB_CHECK(m_stack.m_callbacks, m_newline_offsets_capacity >= that.m_newline_offsets_size);
|
||||
memcpy(m_newline_offsets, that.m_newline_offsets, that.m_newline_offsets_size * sizeof(size_t));
|
||||
m_newline_offsets_size = that.m_newline_offsets_size;
|
||||
m_newline_offsets_buf = that.m_newline_offsets_buf;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Parser::_cp(Parser const* that)
|
||||
{
|
||||
_cb(that->m_stack.m_callbacks);
|
||||
m_stack = that->m_stack;
|
||||
m_state = &m_stack.top();
|
||||
if(that->m_newline_offsets_size > m_newline_offsets_size)
|
||||
_resize_locations(that->m_newline_offsets_size);
|
||||
}
|
||||
|
||||
void Parser::_mv(Parser * that)
|
||||
{
|
||||
_cb(that->m_stack.m_callbacks);
|
||||
m_stack = std::move(that->m_stack);
|
||||
m_state = &m_stack.top();
|
||||
if(that->m_newline_offsets_size > m_newline_offsets_size)
|
||||
_resize_locations(that->m_newline_offsets_size);
|
||||
}
|
||||
|
||||
void Parser::_clr()
|
||||
{
|
||||
m_file = {};
|
||||
m_buf = {};
|
||||
m_root_id = {};
|
||||
m_tree = {};
|
||||
m_stack = {};
|
||||
m_stack.clear();
|
||||
m_state = {};
|
||||
m_key_tag_indentation = {};
|
||||
m_key_tag2_indentation = {};
|
||||
@@ -209,9 +238,10 @@ void Parser::_clr()
|
||||
m_key_anchor = {};
|
||||
m_val_anchor_indentation = {};
|
||||
m_val_anchor = {};
|
||||
m_parse_options = {};
|
||||
m_newline_offsets = {};
|
||||
m_newline_offsets_size = {};
|
||||
m_newline_offsets_capacity = {};
|
||||
m_newline_offsets_buf = {};
|
||||
}
|
||||
|
||||
void Parser::_cb(Callbacks const& cb)
|
||||
@@ -227,9 +257,11 @@ void Parser::_free()
|
||||
{
|
||||
if(m_newline_offsets)
|
||||
{
|
||||
_RYML_CB_FREE(m_stack.m_callbacks, m_newline_offsets, size_t, m_newline_offsets_size);
|
||||
_RYML_CB_FREE(m_stack.m_callbacks, m_newline_offsets, size_t, m_newline_offsets_capacity);
|
||||
m_newline_offsets = nullptr;
|
||||
m_newline_offsets_size = 0u;
|
||||
m_newline_offsets_capacity = 0u;
|
||||
m_newline_offsets_buf = 0u;
|
||||
}
|
||||
m_stack._free();
|
||||
}
|
||||
@@ -259,7 +291,7 @@ void Parser::_reset()
|
||||
m_val_anchor_indentation = 0;
|
||||
m_val_anchor.clear();
|
||||
|
||||
// keep the location buffer
|
||||
_mark_locations_dirty();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -288,8 +320,6 @@ void Parser::parse_in_place(csubstr file, substr buf, Tree *t, size_t node_id)
|
||||
m_root_id = node_id;
|
||||
m_tree = t;
|
||||
_reset();
|
||||
if(m_parse_options.flags & ParseOptions::TRACK_LOCATION)
|
||||
_prepare_locations();
|
||||
while( ! _finished_file())
|
||||
{
|
||||
_scan_line();
|
||||
@@ -4516,8 +4546,9 @@ Location Parser::location(NodeRef node) const
|
||||
|
||||
Location Parser::location(Tree const& tree, size_t node) const
|
||||
{
|
||||
_RYML_CB_CHECK(m_stack.m_callbacks, m_buf.str == m_newline_offsets_buf.str);
|
||||
_RYML_CB_CHECK(m_stack.m_callbacks, m_buf.len == m_newline_offsets_buf.len);
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, &tree == m_tree);
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_newline_offsets != nullptr);
|
||||
if(tree.has_key(node))
|
||||
{
|
||||
csubstr k = tree.key(node);
|
||||
@@ -4554,9 +4585,10 @@ Location Parser::location(Tree const& tree, size_t node) const
|
||||
Location loc = location(tree, tree.first_child(node));
|
||||
if(loc.offset > 0)
|
||||
{
|
||||
// Try finding a token where the container starts.
|
||||
// Search back for the last non-whitespace prior to
|
||||
// the child's offset:
|
||||
// Improve the location for the container by trying to
|
||||
// find a token where the container starts: search
|
||||
// back for the last non-whitespace prior to the
|
||||
// child's offset:
|
||||
size_t offs = m_buf.last_not_of(" \t\r\n", loc.offset);
|
||||
if(offs != npos)
|
||||
{
|
||||
@@ -4590,10 +4622,14 @@ Location Parser::location(Tree const& tree, size_t node) const
|
||||
|
||||
Location Parser::val_location(const char *val) const
|
||||
{
|
||||
if(_locations_dirty())
|
||||
_prepare_locations();
|
||||
csubstr src = m_buf;
|
||||
_RYML_CB_CHECK(m_stack.m_callbacks, src.str == m_newline_offsets_buf.str);
|
||||
_RYML_CB_CHECK(m_stack.m_callbacks, src.len == m_newline_offsets_buf.len);
|
||||
_RYML_CB_CHECK(m_stack.m_callbacks, val >= src.begin() && val <= src.end());
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_newline_offsets != nullptr);
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_newline_offsets_size > 0);
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, val >= src.begin() && val <= src.end());
|
||||
using linetype = size_t const* C4_RESTRICT;
|
||||
linetype line = nullptr;
|
||||
size_t offset = (size_t)(val - src.begin());
|
||||
@@ -4648,33 +4684,42 @@ Location Parser::val_location(const char *val) const
|
||||
return loc;
|
||||
}
|
||||
|
||||
void Parser::_prepare_locations()
|
||||
void Parser::_prepare_locations() const
|
||||
{
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, !m_file.empty());
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, !m_buf.empty());
|
||||
size_t pos = 0;
|
||||
size_t numnewlines = 1u + m_buf.count('\n');
|
||||
_resize_locations(numnewlines);
|
||||
m_newline_offsets_size = 0;
|
||||
for(size_t i = 0; i < m_buf.len; i++)
|
||||
{
|
||||
if(m_buf[i] == '\n')
|
||||
m_newline_offsets[pos++] = i;
|
||||
}
|
||||
m_newline_offsets[pos++] = m_buf.len;
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, pos == numnewlines);
|
||||
m_newline_offsets[m_newline_offsets_size++] = i;
|
||||
m_newline_offsets[m_newline_offsets_size++] = m_buf.len;
|
||||
_RYML_CB_ASSERT(m_stack.m_callbacks, m_newline_offsets_size == numnewlines);
|
||||
}
|
||||
|
||||
void Parser::_resize_locations(size_t numnewlines)
|
||||
void Parser::_resize_locations(size_t numnewlines) const
|
||||
{
|
||||
if(numnewlines > m_newline_offsets_size)
|
||||
if(numnewlines > m_newline_offsets_capacity)
|
||||
{
|
||||
if(m_newline_offsets)
|
||||
_RYML_CB_FREE(m_stack.m_callbacks, m_newline_offsets, size_t, numnewlines);
|
||||
_RYML_CB_FREE(m_stack.m_callbacks, m_newline_offsets, size_t, m_newline_offsets_capacity);
|
||||
m_newline_offsets = _RYML_CB_ALLOC_HINT(m_stack.m_callbacks, size_t, numnewlines, m_newline_offsets);
|
||||
m_newline_offsets_size = numnewlines;
|
||||
m_newline_offsets_capacity = numnewlines;
|
||||
}
|
||||
}
|
||||
|
||||
void Parser::_mark_locations_dirty()
|
||||
{
|
||||
m_newline_offsets_size = 0u;
|
||||
m_newline_offsets_buf = m_buf;
|
||||
}
|
||||
|
||||
bool Parser::_locations_dirty() const
|
||||
{
|
||||
return (!m_newline_offsets_buf.empty()) && (!m_newline_offsets_size);
|
||||
}
|
||||
|
||||
} // namespace yml
|
||||
} // namespace c4
|
||||
|
||||
|
||||
@@ -23,25 +23,6 @@
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
struct ParseOptions
|
||||
{
|
||||
typedef enum : int {
|
||||
NOFLAGS = 0,
|
||||
RESOLVE_REFERENCES = 0x01 << 0,
|
||||
TRACK_LOCATION = 0x01 << 1,
|
||||
DEFAULTS = NOFLAGS,
|
||||
} ParseOptionFlags_e;
|
||||
|
||||
ParseOptions(ParseOptionFlags_e f=DEFAULTS) : flags(f) {}
|
||||
ParseOptionFlags_e flags;
|
||||
|
||||
// to simplify flag specification
|
||||
operator ParseOptionFlags_e () const { return flags; }
|
||||
friend ParseOptionFlags_e operator| (ParseOptionFlags_e lhs, ParseOptionFlags_e rhs) { return (ParseOptionFlags_e)((int)lhs|(int)rhs); }
|
||||
friend ParseOptionFlags_e operator& (ParseOptionFlags_e lhs, ParseOptionFlags_e rhs) { return (ParseOptionFlags_e)((int)lhs&(int)rhs); }
|
||||
friend ParseOptionFlags_e operator~ (ParseOptionFlags_e rhs) { return (ParseOptionFlags_e)(~(int)rhs); }
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -53,10 +34,8 @@ public:
|
||||
/** @name construction and assignment */
|
||||
/** @{ */
|
||||
|
||||
Parser() : Parser(ParseOptions{}, get_callbacks()) {}
|
||||
Parser(ParseOptions opts) : Parser(opts, get_callbacks()) {}
|
||||
Parser(Callbacks const& cb) : Parser(ParseOptions{}, cb) {}
|
||||
Parser(ParseOptions opts, Callbacks const& cb);
|
||||
Parser() : Parser(get_callbacks()) {}
|
||||
Parser(Callbacks const& cb);
|
||||
~Parser();
|
||||
|
||||
Parser(Parser &&);
|
||||
@@ -71,10 +50,6 @@ public:
|
||||
/** @name modifiers */
|
||||
/** @{ */
|
||||
|
||||
/** Set the parsing options. These will only have effect for the
|
||||
* next parsing operation. */
|
||||
void options(ParseOptions opts) { m_parse_options = opts; }
|
||||
|
||||
/** Reserve a certain capacity for the parsing stack.
|
||||
* This should be larger than the expected depth of the parsed
|
||||
* YAML tree.
|
||||
@@ -110,9 +85,6 @@ public:
|
||||
/** @name getters and modifiers */
|
||||
/** @{ */
|
||||
|
||||
/** Get the current parsing options */
|
||||
ParseOptions options() const { return m_parse_options; }
|
||||
|
||||
/** Get the current callbacks in the parser. */
|
||||
Callbacks callbacks() const { return m_stack.m_callbacks; }
|
||||
|
||||
@@ -512,8 +484,10 @@ private:
|
||||
void addrem_flags(size_t on, size_t off, State * s);
|
||||
void rem_flags(size_t off, State * s);
|
||||
|
||||
void _prepare_locations();
|
||||
void _resize_locations(size_t sz);
|
||||
void _prepare_locations() const; // only changes mutable members
|
||||
void _resize_locations(size_t sz) const; // only changes mutable members
|
||||
void _mark_locations_dirty();
|
||||
bool _locations_dirty() const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -554,10 +528,10 @@ private:
|
||||
size_t m_val_anchor_indentation;
|
||||
csubstr m_val_anchor;
|
||||
|
||||
ParseOptions m_parse_options;
|
||||
|
||||
size_t *m_newline_offsets;
|
||||
size_t m_newline_offsets_size;
|
||||
mutable size_t *m_newline_offsets;
|
||||
mutable size_t m_newline_offsets_size;
|
||||
mutable size_t m_newline_offsets_capacity;
|
||||
mutable csubstr m_newline_offsets_buf;
|
||||
};
|
||||
|
||||
|
||||
@@ -578,23 +552,23 @@ private:
|
||||
* Parser::parse_in_place() */
|
||||
/** @{ */
|
||||
|
||||
inline Tree parse_in_place( substr yaml, ParseOptions opts={}) { Parser np(opts); return np.parse_in_place({} , yaml); } //!< parse in-situ a modifiable YAML source buffer.
|
||||
inline Tree parse_in_place(csubstr filename, substr yaml, ParseOptions opts={}) { Parser np(opts); return np.parse_in_place(filename, yaml); } //!< parse in-situ a modifiable YAML source buffer, providing a filename for error messages.
|
||||
inline void parse_in_place( substr yaml, Tree *t, ParseOptions opts={}) { Parser np(opts); np.parse_in_place({} , yaml, t); } //!< reusing the YAML tree, parse in-situ a modifiable YAML source buffer
|
||||
inline void parse_in_place(csubstr filename, substr yaml, Tree *t, ParseOptions opts={}) { Parser np(opts); 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.
|
||||
inline void parse_in_place( substr yaml, Tree *t, size_t node_id, ParseOptions opts={}) { Parser np(opts); np.parse_in_place({} , yaml, t, node_id); } //!< reusing the YAML tree, parse in-situ a modifiable YAML source buffer
|
||||
inline void parse_in_place(csubstr filename, substr yaml, Tree *t, size_t node_id, ParseOptions opts={}) { Parser np(opts); 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.
|
||||
inline void parse_in_place( substr yaml, NodeRef node, ParseOptions opts={}) { Parser np(opts); 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, ParseOptions opts={}) { Parser np(opts); 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.
|
||||
inline Tree parse_in_place( substr yaml ) { Parser np; return np.parse_in_place({} , yaml); } //!< parse in-situ a modifiable YAML source buffer.
|
||||
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.
|
||||
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
|
||||
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.
|
||||
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
|
||||
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.
|
||||
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.
|
||||
|
||||
RYML_DEPRECATED("use parse_in_place() instead") inline Tree parse( substr yaml, ParseOptions opts={}) { Parser np(opts); return np.parse_in_place({} , yaml); }
|
||||
RYML_DEPRECATED("use parse_in_place() instead") inline Tree parse(csubstr filename, substr yaml, ParseOptions opts={}) { Parser np(opts); return np.parse_in_place(filename, yaml); }
|
||||
RYML_DEPRECATED("use parse_in_place() instead") inline void parse( substr yaml, Tree *t, ParseOptions opts={}) { Parser np(opts); np.parse_in_place({} , yaml, t); }
|
||||
RYML_DEPRECATED("use parse_in_place() instead") inline void parse(csubstr filename, substr yaml, Tree *t, ParseOptions opts={}) { Parser np(opts); np.parse_in_place(filename, yaml, t); }
|
||||
RYML_DEPRECATED("use parse_in_place() instead") inline void parse( substr yaml, Tree *t, size_t node_id, ParseOptions opts={}) { Parser np(opts); np.parse_in_place({} , yaml, t, node_id); }
|
||||
RYML_DEPRECATED("use parse_in_place() instead") inline void parse(csubstr filename, substr yaml, Tree *t, size_t node_id, ParseOptions opts={}) { Parser np(opts); np.parse_in_place(filename, yaml, t, node_id); }
|
||||
RYML_DEPRECATED("use parse_in_place() instead") inline void parse( substr yaml, NodeRef node, ParseOptions opts={}) { Parser np(opts); np.parse_in_place({} , yaml, node); }
|
||||
RYML_DEPRECATED("use parse_in_place() instead") inline void parse(csubstr filename, substr yaml, NodeRef node, ParseOptions opts={}) { Parser np(opts); np.parse_in_place(filename, yaml, node); }
|
||||
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); }
|
||||
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); }
|
||||
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); }
|
||||
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); }
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -624,32 +598,32 @@ RYML_DEPRECATED("use parse_in_place() instead") inline void parse(csubstr filena
|
||||
/** @{ */
|
||||
|
||||
/* READ THE NOTE ABOVE! */
|
||||
RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) Tree parse_in_arena( substr yaml, ParseOptions opts={});
|
||||
RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) Tree parse_in_arena(csubstr filename, substr yaml, ParseOptions opts={});
|
||||
RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena( substr yaml, Tree *t, ParseOptions opts={});
|
||||
RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(csubstr filename, substr yaml, Tree *t, ParseOptions opts={});
|
||||
RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena( substr yaml, Tree *t, size_t node_id, ParseOptions opts={});
|
||||
RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(csubstr filename, substr yaml, Tree *t, size_t node_id, ParseOptions opts={});
|
||||
RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena( substr yaml, NodeRef node, ParseOptions opts={});
|
||||
RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(csubstr filename, substr yaml, NodeRef node, ParseOptions opts={});
|
||||
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 );
|
||||
RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena(csubstr filename, substr yaml, Tree *t );
|
||||
RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) void parse_in_arena( substr yaml, Tree *t, size_t node_id);
|
||||
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 );
|
||||
|
||||
inline Tree parse_in_arena( csubstr yaml, ParseOptions opts={}) { Parser np(opts); 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, ParseOptions opts={}) { Parser np(opts); 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.
|
||||
inline void parse_in_arena( csubstr yaml, Tree *t, ParseOptions opts={}) { Parser np(opts); 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.
|
||||
inline void parse_in_arena(csubstr filename, csubstr yaml, Tree *t, ParseOptions opts={}) { Parser np(opts); 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.
|
||||
inline void parse_in_arena( csubstr yaml, Tree *t, size_t node_id, ParseOptions opts={}) { Parser np(opts); 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.
|
||||
inline void parse_in_arena(csubstr filename, csubstr yaml, Tree *t, size_t node_id, ParseOptions opts={}) { Parser np(opts); 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.
|
||||
inline void parse_in_arena( csubstr yaml, NodeRef node, ParseOptions opts={}) { Parser np(opts); 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, ParseOptions opts={}) { Parser np(opts); 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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
|
||||
RYML_DEPRECATED("use parse_in_arena() instead") inline Tree parse( csubstr yaml, ParseOptions opts={}) { Parser np(opts); 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, ParseOptions opts={}) { Parser np(opts); 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, ParseOptions opts={}) { Parser np(opts); 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.
|
||||
RYML_DEPRECATED("use parse_in_arena() instead") inline void parse(csubstr filename, csubstr yaml, Tree *t, ParseOptions opts={}) { Parser np(opts); 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.
|
||||
RYML_DEPRECATED("use parse_in_arena() instead") inline void parse( csubstr yaml, Tree *t, size_t node_id, ParseOptions opts={}) { Parser np(opts); 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.
|
||||
RYML_DEPRECATED("use parse_in_arena() instead") inline void parse(csubstr filename, csubstr yaml, Tree *t, size_t node_id, ParseOptions opts={}) { Parser np(opts); 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, ParseOptions opts={}) { Parser np(opts); 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, ParseOptions opts={}) { Parser np(opts); 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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
const ParseOptions use_locations{ParseOptions::TRACK_LOCATION};
|
||||
|
||||
#define _checkloc(node, line_, col_, str) \
|
||||
{ \
|
||||
const Location loc = parser.location(node); \
|
||||
@@ -23,7 +21,7 @@ const ParseOptions use_locations{ParseOptions::TRACK_LOCATION};
|
||||
TEST(locations, seq_block)
|
||||
{
|
||||
Tree t;
|
||||
Parser parser(use_locations);
|
||||
Parser parser;
|
||||
csubstr yaml = R"(
|
||||
- this
|
||||
- is
|
||||
@@ -66,7 +64,7 @@ TEST(locations, seq_block)
|
||||
TEST(locations, seq_flow)
|
||||
{
|
||||
Tree t;
|
||||
Parser parser(use_locations);
|
||||
Parser parser;
|
||||
csubstr yaml = R"([one,two,three,four,items])";
|
||||
parser.parse_in_arena("myfile.yml", yaml, &t);
|
||||
const NodeRef seq = t.rootref();
|
||||
@@ -82,7 +80,7 @@ TEST(locations, seq_flow)
|
||||
TEST(locations, seq_flow_nested)
|
||||
{
|
||||
Tree t;
|
||||
Parser parser(use_locations);
|
||||
Parser parser;
|
||||
csubstr yaml = R"([
|
||||
one,
|
||||
two,
|
||||
@@ -123,7 +121,7 @@ TEST(locations, seq_flow_nested)
|
||||
TEST(locations, small)
|
||||
{
|
||||
Tree t;
|
||||
Parser parser(use_locations);
|
||||
Parser parser;
|
||||
csubstr yaml = R"(---
|
||||
foo: definitely
|
||||
bar:
|
||||
@@ -156,7 +154,7 @@ baz:
|
||||
TEST(locations, large)
|
||||
{
|
||||
Tree t;
|
||||
Parser parser(use_locations);
|
||||
Parser parser;
|
||||
csubstr yaml = R"(---
|
||||
foo1: definitely # 1
|
||||
bar1:
|
||||
|
||||
@@ -19,51 +19,12 @@ bool is_same(csubstr lhs, csubstr rhs)
|
||||
void mklarge(Parser *p, Callbacks const& cb)
|
||||
{
|
||||
p->~Parser();
|
||||
new ((void*)p) Parser(ParseOptions::TRACK_LOCATION, cb);
|
||||
new ((void*)p) Parser(cb);
|
||||
p->reserve_stack(20); // cause an allocation
|
||||
p->reserve_locations(128); // cause an allocation
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
TEST(ParseOptions, no_flags)
|
||||
{
|
||||
ParseOptions opts = ParseOptions::NOFLAGS;
|
||||
EXPECT_EQ(opts & ParseOptions::TRACK_LOCATION, ParseOptions::NOFLAGS);
|
||||
EXPECT_EQ(opts & ParseOptions::RESOLVE_REFERENCES, ParseOptions::NOFLAGS);
|
||||
}
|
||||
|
||||
TEST(ParseOptions, one_flag)
|
||||
{
|
||||
ParseOptions opts = ParseOptions::TRACK_LOCATION;
|
||||
EXPECT_EQ(opts & ParseOptions::TRACK_LOCATION, ParseOptions::TRACK_LOCATION);
|
||||
}
|
||||
|
||||
TEST(ParseOptions, two_flags)
|
||||
{
|
||||
ParseOptions opts = ParseOptions::RESOLVE_REFERENCES|ParseOptions::TRACK_LOCATION;
|
||||
EXPECT_EQ(opts & ParseOptions::TRACK_LOCATION, ParseOptions::TRACK_LOCATION);
|
||||
EXPECT_EQ(opts & ParseOptions::RESOLVE_REFERENCES, ParseOptions::RESOLVE_REFERENCES);
|
||||
}
|
||||
|
||||
TEST(ParseOptions, three_flags)
|
||||
{
|
||||
ParseOptions opts = ParseOptions::RESOLVE_REFERENCES|ParseOptions::TRACK_LOCATION|ParseOptions::DEFAULTS;
|
||||
EXPECT_EQ(opts & ParseOptions::DEFAULTS, ParseOptions::DEFAULTS);
|
||||
EXPECT_EQ(opts & ParseOptions::TRACK_LOCATION, ParseOptions::TRACK_LOCATION);
|
||||
EXPECT_EQ(opts & ParseOptions::RESOLVE_REFERENCES, ParseOptions::RESOLVE_REFERENCES);
|
||||
}
|
||||
|
||||
TEST(ParseOptions, and_not)
|
||||
{
|
||||
ParseOptions opts = ParseOptions::DEFAULTS & ~ParseOptions::TRACK_LOCATION;
|
||||
EXPECT_EQ(opts & ParseOptions::TRACK_LOCATION, ParseOptions::NOFLAGS);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -72,14 +33,6 @@ TEST(Parser, empty_ctor)
|
||||
{
|
||||
Parser parser;
|
||||
EXPECT_EQ(parser.callbacks(), get_callbacks());
|
||||
EXPECT_EQ(parser.options().flags, ParseOptions::DEFAULTS);
|
||||
}
|
||||
|
||||
TEST(Parser, opts_ctor)
|
||||
{
|
||||
Parser parser(ParseOptions::TRACK_LOCATION);
|
||||
EXPECT_EQ(parser.callbacks(), get_callbacks());
|
||||
EXPECT_EQ(parser.options().flags, ParseOptions::TRACK_LOCATION);
|
||||
}
|
||||
|
||||
TEST(Parser, callbacks_ctor)
|
||||
@@ -88,19 +41,6 @@ TEST(Parser, callbacks_ctor)
|
||||
{
|
||||
Parser parser(cbt.callbacks());
|
||||
EXPECT_EQ(parser.callbacks(), cbt.callbacks());
|
||||
EXPECT_EQ(parser.options().flags, ParseOptions::DEFAULTS);
|
||||
}
|
||||
EXPECT_EQ(cbt.num_allocs, 0u);
|
||||
EXPECT_EQ(cbt.num_deallocs, 0u);
|
||||
}
|
||||
|
||||
TEST(Parser, opts_callbacks_ctor)
|
||||
{
|
||||
CallbacksTester cbt;
|
||||
{
|
||||
Parser parser(ParseOptions::TRACK_LOCATION, cbt.callbacks());
|
||||
EXPECT_EQ(parser.callbacks(), cbt.callbacks());
|
||||
EXPECT_EQ(parser.options().flags, ParseOptions::TRACK_LOCATION);
|
||||
}
|
||||
EXPECT_EQ(cbt.num_allocs, 0u);
|
||||
EXPECT_EQ(cbt.num_deallocs, 0u);
|
||||
@@ -132,7 +72,7 @@ TEST(Parser, reserve_locations)
|
||||
{
|
||||
CallbacksTester ts;
|
||||
{
|
||||
Parser parser(ParseOptions::TRACK_LOCATION, ts.callbacks());
|
||||
Parser parser(ts.callbacks());
|
||||
EXPECT_EQ(parser.callbacks(), ts.callbacks());
|
||||
EXPECT_EQ(ts.num_allocs, 0u);
|
||||
EXPECT_EQ(ts.num_deallocs, 0u);
|
||||
@@ -195,7 +135,7 @@ TEST(Parser, move_ctor)
|
||||
size_t nbefore = ts.num_allocs;
|
||||
EXPECT_GT(ts.num_allocs, 0u);
|
||||
Parser dst(std::move(src));
|
||||
ASSERT_EQ(src.callbacks(), get_callbacks());
|
||||
ASSERT_EQ(src.callbacks(), ts.callbacks());
|
||||
ASSERT_EQ(dst.callbacks(), ts.callbacks());
|
||||
EXPECT_EQ(ts.num_allocs, nbefore);
|
||||
}
|
||||
@@ -268,7 +208,7 @@ TEST(Parser, move_assign_same_callbacks)
|
||||
dst = std::move(src);
|
||||
ASSERT_EQ(src.callbacks(), ts.callbacks());
|
||||
ASSERT_EQ(dst.callbacks(), ts.callbacks());
|
||||
EXPECT_GT(ts.num_allocs, nbefore); // dst frees then allocates
|
||||
EXPECT_EQ(ts.num_allocs, nbefore);
|
||||
}
|
||||
EXPECT_EQ(ts.num_allocs, ts.num_deallocs);
|
||||
EXPECT_EQ(ts.alloc_size, ts.dealloc_size);
|
||||
@@ -292,7 +232,7 @@ TEST(Parser, move_assign_diff_callbacks)
|
||||
ASSERT_EQ(src.callbacks(), ts.callbacks());
|
||||
ASSERT_EQ(dst.callbacks(), ts.callbacks());
|
||||
EXPECT_EQ(td.num_allocs, nbefore); // dst frees with td
|
||||
EXPECT_GT(ts.num_allocs, nbefore); // dst allocs with ts
|
||||
EXPECT_EQ(ts.num_allocs, nbefore); // dst moves from ts
|
||||
}
|
||||
EXPECT_EQ(ts.num_allocs, ts.num_deallocs);
|
||||
EXPECT_EQ(ts.alloc_size, ts.dealloc_size);
|
||||
@@ -590,6 +530,5 @@ Case const* get_case(csubstr /*name*/)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace yml
|
||||
} // namespace c4
|
||||
|
||||
Reference in New Issue
Block a user