rapidyaml 0.15.2
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 5830 of file quickstart.cpp.

5831{
5832 std::string unresolved = ""
5833 "base: &base" "\n"
5834 " name: Everyone has same name" "\n"
5835 "foo: &foo" "\n"
5836 " <<: *base" "\n"
5837 " age: 10" "\n"
5838 "bar: &bar" "\n"
5839 " <<: *base" "\n"
5840 " age: 20" "\n"
5841 "bill_to: &id001" "\n"
5842 " street: |-" "\n"
5843 " 123 Tornado Alley" "\n"
5844 " Suite 16" "\n"
5845 " city: East Centerville" "\n"
5846 " state: KS" "\n"
5847 "ship_to: *id001" "\n"
5848 "&keyref key: &valref val" "\n"
5849 "*valref : *keyref" "\n"
5850 "";
5851 std::string resolved = ""
5852 "base:" "\n"
5853 " name: Everyone has same name" "\n"
5854 "foo:" "\n"
5855 " name: Everyone has same name" "\n"
5856 " age: 10" "\n"
5857 "bar:" "\n"
5858 " name: Everyone has same name" "\n"
5859 " age: 20" "\n"
5860 "bill_to:" "\n"
5861 " street: |-" "\n"
5862 " 123 Tornado Alley" "\n"
5863 " Suite 16" "\n"
5864 " city: East Centerville" "\n"
5865 " state: KS" "\n"
5866 "ship_to:" "\n"
5867 " street: |-" "\n"
5868 " 123 Tornado Alley" "\n"
5869 " Suite 16" "\n"
5870 " city: East Centerville" "\n"
5871 " state: KS" "\n"
5872 "key: val" "\n"
5873 "val: key" "\n"
5874 "";
5875
5877 // by default, references are not resolved when parsing:
5878 CHECK( ! tree["base"].has_key_anchor());
5879 CHECK( tree["base"].has_val_anchor());
5880 CHECK( tree["base"].val_anchor() == "base");
5881 CHECK( tree["key"].key_anchor() == "keyref");
5882 CHECK( tree["key"].val_anchor() == "valref");
5883 CHECK( tree["*valref"].is_key_ref());
5884 CHECK( tree["*valref"].is_val_ref());
5885 CHECK( tree["*valref"].key_ref() == "valref");
5886 CHECK( tree["*valref"].val_ref() == "keyref");
5887
5888 // to resolve references, simply call tree.resolve(),
5889 // which will perform the reference instantiations:
5890 tree.resolve();
5891
5892 // all the anchors and references are substistuted and then removed:
5893 CHECK( ! tree["base"].has_key_anchor());
5894 CHECK( ! tree["base"].has_val_anchor());
5895 CHECK( ! tree["base"].has_val_anchor());
5896 CHECK( ! tree["key"].has_key_anchor());
5897 CHECK( ! tree["key"].has_val_anchor());
5898 CHECK( ! tree["val"].is_key_ref()); // notice *valref is now turned to val
5899 CHECK( ! tree["val"].is_val_ref()); // notice *valref is now turned to val
5900
5901 CHECK(tree["ship_to"]["city"].val() == "East Centerville");
5902 CHECK(tree["ship_to"]["state"].val() == "KS");
5903}
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 5907 of file quickstart.cpp.

5908{
5909 // part 1: anchor/ref
5910 {
5911 ryml::Tree t;
5913 t["kanchor"].set_val("2");
5914 t["kanchor"].set_key_anchor("kanchor");
5915 t["vanchor"].set_val("3");
5916 t["vanchor"].set_val_anchor("vanchor");
5917 // to set a reference, need to call .set_val_ref()/.set_key_ref()
5918 t["kref"].set_val_ref("kanchor");
5919 t["vref"].set_val_ref("vanchor");
5920 t["nref"].set_val("*vanchor"); // NOTE: this is not set as a reference in the tree!
5922 "&kanchor kanchor: 2" "\n"
5923 "vanchor: &vanchor 3" "\n"
5924 "kref: *kanchor" "\n"
5925 "vref: *vanchor" "\n"
5926 // note that ryml emits nref with quotes to disambiguate
5927 // (because no style was set)
5928 "nref: '*vanchor'" "\n"
5929 "");
5930 t.resolve();
5932 "kanchor: 2" "\n"
5933 "vanchor: 3" "\n"
5934 "kref: kanchor" "\n"
5935 "vref: 3" "\n"
5936 // note that nref was not resolved
5937 "nref: '*vanchor'" "\n"
5938 "");
5939 }
5940
5941 // part 2: simple inheritance (ie, adding `<<: *anchor` nodes)
5942 {
5944 "orig: &orig {foo: bar, baz: bat}" "\n"
5945 "copy: {}" "\n"
5946 "notcopy: {}" "\n"
5947 "notref: {}" "\n"
5948 "");
5949 t["copy"]["<<"].set_val_ref("orig");
5950 t["notcopy"]["test"].set_val_ref("orig");
5951 t["notcopy"]["<<"].set_val_ref("orig");
5952 t["notref"]["<<"].set_val("*orig"); // not a reference! .set_val_ref() was not called
5954 "orig: &orig {foo: bar,baz: bat}" "\n"
5955 "copy: {<<: *orig}" "\n"
5956 "notcopy: {test: *orig,<<: *orig}" "\n"
5957 "notref: {<<: '*orig'}" "\n"
5958 "");
5959 t.resolve();
5961 "orig: {foo: bar,baz: bat}" "\n"
5962 "copy: {foo: bar,baz: bat}" "\n"
5963 "notcopy: {test: {foo: bar,baz: bat},foo: bar,baz: bat}" "\n"
5964 "notref: {<<: '*orig'}" "\n"
5965 "");
5966 }
5967
5968 // part 3: multiple inheritance (ie, `<<: [*ref1,*ref2,*etc]`)
5969 {
5971 "orig1: &orig1 {foo: bar}" "\n"
5972 "orig2: &orig2 {baz: bat}" "\n"
5973 "orig3: &orig3 {and: more}" "\n"
5974 "copy: {}" "\n"
5975 "");
5976 ryml::NodeRef seq = t["copy"]["<<"];
5977 seq.set_seq();
5978 seq.append_child().set_val_ref("orig1");
5979 seq.append_child().set_val_ref("orig2");
5980 seq.append_child().set_val_ref("orig3");
5982 "orig1: &orig1 {foo: bar}" "\n"
5983 "orig2: &orig2 {baz: bat}" "\n"
5984 "orig3: &orig3 {and: more}" "\n"
5985 "copy: {<<: [*orig1,*orig2,*orig3]}" "\n"
5986 "");
5987 t.resolve();
5989 "orig1: {foo: bar}" "\n"
5990 "orig2: {baz: bat}" "\n"
5991 "orig3: {and: more}" "\n"
5992 "copy: {foo: bar,baz: bat,and: more}" "\n");
5993 }
5994}
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().