rapidyaml  0.16.0
parseandemitYAML,anddoitfast
YAML anchors

Functions

void sample_anchors_and_aliases ()
 deal with YAML anchors and aliases More...
 
void sample_anchors_and_aliases_create ()
 how to create YAML anchors and aliases More...
 

Detailed Description

Function Documentation

void sample_anchors_and_aliases ( )

deal with YAML anchors and aliases

demonstrates usage with anchors and alias references.

Note that dereferencing is opt-in; after parsing, you have to call c4::yml::Tree::resolve() explicitly if you want resolved references in the tree. This method will resolve all references and substitute the anchored values in place of the reference.

The c4::yml::Tree::resolve() method first does a full traversal of the tree to gather all anchors and references in a separate collection, then it goes through that collection to locate the names, which it does by obeying the YAML standard diktat that

> an alias node refers to the most recent node in
> the serialization having the specified anchor

So, depending on the number of anchor/alias nodes, this is a potentially expensive operation, with a best-case linear complexity (from the initial traversal) and a worst-case quadratic complexity (if every node has an alias/anchor). This potential cost is the reason for requiring an explicit call to c4::yml::Tree::resolve()

Definition at line 5914 of file quickstart.cpp.

Referenced by main().

5915 {
5916  std::string unresolved = ""
5917  "base: &base" "\n"
5918  " name: Everyone has same name" "\n"
5919  "foo: &foo" "\n"
5920  " <<: *base" "\n"
5921  " age: 10" "\n"
5922  "bar: &bar" "\n"
5923  " <<: *base" "\n"
5924  " age: 20" "\n"
5925  "bill_to: &id001" "\n"
5926  " street: |-" "\n"
5927  " 123 Tornado Alley" "\n"
5928  " Suite 16" "\n"
5929  " city: East Centerville" "\n"
5930  " state: KS" "\n"
5931  "ship_to: *id001" "\n"
5932  "&keyref key: &valref val" "\n"
5933  "*valref : *keyref" "\n"
5934  "";
5935  std::string resolved = ""
5936  "base:" "\n"
5937  " name: Everyone has same name" "\n"
5938  "foo:" "\n"
5939  " name: Everyone has same name" "\n"
5940  " age: 10" "\n"
5941  "bar:" "\n"
5942  " name: Everyone has same name" "\n"
5943  " age: 20" "\n"
5944  "bill_to:" "\n"
5945  " street: |-" "\n"
5946  " 123 Tornado Alley" "\n"
5947  " Suite 16" "\n"
5948  " city: East Centerville" "\n"
5949  " state: KS" "\n"
5950  "ship_to:" "\n"
5951  " street: |-" "\n"
5952  " 123 Tornado Alley" "\n"
5953  " Suite 16" "\n"
5954  " city: East Centerville" "\n"
5955  " state: KS" "\n"
5956  "key: val" "\n"
5957  "val: key" "\n"
5958  "";
5959 
5960  ryml::Tree tree = ryml::parse_in_arena(ryml::to_csubstr(unresolved));
5961  // by default, references are not resolved when parsing:
5962  CHECK( ! tree["base"].has_key_anchor());
5963  CHECK( tree["base"].has_val_anchor());
5964  CHECK( tree["base"].val_anchor() == "base");
5965  CHECK( tree["key"].key_anchor() == "keyref");
5966  CHECK( tree["key"].val_anchor() == "valref");
5967  CHECK( tree["*valref"].is_key_ref());
5968  CHECK( tree["*valref"].is_val_ref());
5969  CHECK( tree["*valref"].key_ref() == "valref");
5970  CHECK( tree["*valref"].val_ref() == "keyref");
5971 
5972  // to resolve references, simply call tree.resolve(),
5973  // which will perform the reference instantiations:
5974  tree.resolve();
5975 
5976  // all the anchors and references are substistuted and then removed:
5977  CHECK( ! tree["base"].has_key_anchor());
5978  CHECK( ! tree["base"].has_val_anchor());
5979  CHECK( ! tree["base"].has_val_anchor());
5980  CHECK( ! tree["key"].has_key_anchor());
5981  CHECK( ! tree["key"].has_val_anchor());
5982  CHECK( ! tree["val"].is_key_ref()); // notice *valref is now turned to val
5983  CHECK( ! tree["val"].is_val_ref()); // notice *valref is now turned to val
5984 
5985  CHECK(tree["ship_to"]["city"].val() == "East Centerville");
5986  CHECK(tree["ship_to"]["state"].val() == "KS");
5987 }
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 resolve(ReferenceResolver *rr, bool clear_anchors=true)
Resolve references (aliases <- anchors), by forwarding to ReferenceResolver::resolve(); refer to Refe...
Definition: tree.cpp:1206
csubstr to_csubstr(const char(&s)[N]) noexcept
Definition: substr.hpp:2380
#define CHECK(predicate)
a testing assertion, used only in this quickstart
Definition: quickstart.cpp:310
void sample_anchors_and_aliases_create ( )

how to create YAML anchors and aliases

demonstrates how to use the API to programatically create anchors and aliases

Definition at line 5991 of file quickstart.cpp.

Referenced by main().

5992 {
5993  // part 1: anchor/ref
5994  {
5995  ryml::Tree t;
5997  t["kanchor"].set_val("2");
5998  t["kanchor"].set_key_anchor("kanchor");
5999  t["vanchor"].set_val("3");
6000  t["vanchor"].set_val_anchor("vanchor");
6001  // to set a reference, need to call .set_val_ref()/.set_key_ref()
6002  t["kref"].set_val_ref("kanchor");
6003  t["vref"].set_val_ref("vanchor");
6004  t["nref"].set_val("*vanchor"); // NOTE: this is not set as a reference in the tree!
6005  CHECK(ryml::emitrs_yaml<std::string>(t) == ""
6006  "&kanchor kanchor: 2" "\n"
6007  "vanchor: &vanchor 3" "\n"
6008  "kref: *kanchor" "\n"
6009  "vref: *vanchor" "\n"
6010  // note that ryml emits nref with quotes to disambiguate
6011  // (because no style was set)
6012  "nref: '*vanchor'" "\n"
6013  "");
6014  t.resolve();
6015  CHECK(ryml::emitrs_yaml<std::string>(t) == ""
6016  "kanchor: 2" "\n"
6017  "vanchor: 3" "\n"
6018  "kref: kanchor" "\n"
6019  "vref: 3" "\n"
6020  // note that nref was not resolved
6021  "nref: '*vanchor'" "\n"
6022  "");
6023  }
6024 
6025  // part 2: simple inheritance (ie, adding `<<: *anchor` nodes)
6026  {
6028  "orig: &orig {foo: bar, baz: bat}" "\n"
6029  "copy: {}" "\n"
6030  "notcopy: {}" "\n"
6031  "notref: {}" "\n"
6032  "");
6033  t["copy"]["<<"].set_val_ref("orig");
6034  t["notcopy"]["test"].set_val_ref("orig");
6035  t["notcopy"]["<<"].set_val_ref("orig");
6036  t["notref"]["<<"].set_val("*orig"); // not a reference! .set_val_ref() was not called
6037  CHECK(ryml::emitrs_yaml<std::string>(t) == ""
6038  "orig: &orig {foo: bar,baz: bat}" "\n"
6039  "copy: {<<: *orig}" "\n"
6040  "notcopy: {test: *orig,<<: *orig}" "\n"
6041  "notref: {<<: '*orig'}" "\n"
6042  "");
6043  t.resolve();
6044  CHECK(ryml::emitrs_yaml<std::string>(t) == ""
6045  "orig: {foo: bar,baz: bat}" "\n"
6046  "copy: {foo: bar,baz: bat}" "\n"
6047  "notcopy: {test: {foo: bar,baz: bat},foo: bar,baz: bat}" "\n"
6048  "notref: {<<: '*orig'}" "\n"
6049  "");
6050  }
6051 
6052  // part 3: multiple inheritance (ie, `<<: [*ref1,*ref2,*etc]`)
6053  {
6055  "orig1: &orig1 {foo: bar}" "\n"
6056  "orig2: &orig2 {baz: bat}" "\n"
6057  "orig3: &orig3 {and: more}" "\n"
6058  "copy: {}" "\n"
6059  "");
6060  ryml::NodeRef seq = t["copy"]["<<"];
6061  seq.set_seq();
6062  seq.append_child().set_val_ref("orig1");
6063  seq.append_child().set_val_ref("orig2");
6064  seq.append_child().set_val_ref("orig3");
6065  CHECK(ryml::emitrs_yaml<std::string>(t) == ""
6066  "orig1: &orig1 {foo: bar}" "\n"
6067  "orig2: &orig2 {baz: bat}" "\n"
6068  "orig3: &orig3 {and: more}" "\n"
6069  "copy: {<<: [*orig1,*orig2,*orig3]}" "\n"
6070  "");
6071  t.resolve();
6072  CHECK(ryml::emitrs_yaml<std::string>(t) == ""
6073  "orig1: {foo: bar}" "\n"
6074  "orig2: {baz: bat}" "\n"
6075  "orig3: {and: more}" "\n"
6076  "copy: {foo: bar,baz: bat,and: more}" "\n");
6077  }
6078 }
void set_val(id_type node, csubstr val) RYML_NOEXCEPT
Definition: tree.hpp:688
void set_val_ref(id_type node, csubstr ref)
Definition: tree.hpp:748
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
A reference to a node in an existing yaml tree, offering a more convenient API than the index-based A...
Definition: node.hpp:1062
void set_val_anchor(id_type node, csubstr anchor)
Definition: tree.hpp:746
void resolve(ReferenceResolver *rr, bool clear_anchors=true)
Resolve references (aliases <- anchors), by forwarding to ReferenceResolver::resolve(); refer to Refe...
Definition: tree.cpp:1206
#define CHECK(predicate)
a testing assertion, used only in this quickstart
Definition: quickstart.cpp:310
mark container with block style < - seqs as <
Definition: node_type.hpp:136
NodeRef rootref()
Get the root as a NodeRef . Note that a non-const Tree implicitly converts to NodeRef.
Definition: tree.cpp:56
void set_key_anchor(id_type node, csubstr anchor)
Definition: tree.hpp:745
NodeRef append_child()
Definition: node.hpp:1715
void set_val_ref(csubstr val_ref)
Definition: node.hpp:1265
void set_seq()
Definition: node.hpp:1254
void set_map()
Definition: node.hpp:1257