rapidyaml 0.16.0
parse and emit YAML, and do it fast
Loading...
Searching...
No Matches
YAML anchors

Functions

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

Detailed Description

Function Documentation

◆ sample_anchors_and_aliases()

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.

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
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 resolve(ReferenceResolver *rr, bool clear_anchors=true)
Resolve references (aliases <- anchors), by forwarding to ReferenceResolver::resolve(); refer to Refe...
Definition tree.cpp:1206
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
#define CHECK(predicate)
a testing assertion, used only in this quickstart
csubstr to_csubstr(const char(&s)[N]) noexcept
Definition substr.hpp:2380

Referenced by main().

◆ sample_anchors_and_aliases_create()

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.

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!
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();
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
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();
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");
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();
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}
A reference to a node in an existing yaml tree, offering a more convenient API than the index-based A...
Definition node.hpp:1063
NodeRef append_child()
Definition node.hpp:1715
void set_val_ref(csubstr val_ref)
Definition node.hpp:1265
void set_val_ref(id_type node, csubstr ref)
Definition tree.hpp:748
NodeRef rootref()
Get the root as a NodeRef . Note that a non-const Tree implicitly converts to NodeRef.
Definition tree.cpp:56
void set_val(id_type node, csubstr val) RYML_NOEXCEPT
Definition tree.hpp:688
void set_val_anchor(id_type node, csubstr anchor)
Definition tree.hpp:746
void set_key_anchor(id_type node, csubstr anchor)
Definition tree.hpp:745
substr emitrs_yaml(Tree const &t, id_type id, EmitOptions const &opts, CharOwningContainer *cont, bool append=false)
(1) emit+resize: emit YAML to the given std::string/std::vector<char>-like container,...
@ BLOCK
mark container with block style

Referenced by main().