Function sample_tree_arena
Synopsis
#include <samples/quickstart.cpp>
void sample_tree_arena()
Description
interact with the tree's serialization arena
demonstrates explicit and implicit interaction with the tree's string arena. Notice that ryml only holds strings in the tree's nodes.
Mentioned in
- Getting Started / Quick start
Source
Lines 1722-1873 in samples/quickstart.cpp. Line 58 in samples/quickstart.cpp.
void sample_tree_arena()
{
// mutable buffers are parsed in situ:
{
char buf[] = "[a, b, c, d]";
ryml::substr yml = buf;
ryml::Tree tree = ryml::parse(yml);
// notice the arena is empty:
CHECK(tree.arena().empty());
// and the tree is pointing at the original buffer:
ryml::NodeRef root = tree.rootref();
CHECK(root[0].val().is_sub(yml));
CHECK(root[1].val().is_sub(yml));
CHECK(root[2].val().is_sub(yml));
CHECK(root[3].val().is_sub(yml));
CHECK(yml.is_super(root[0].val()));
CHECK(yml.is_super(root[1].val()));
CHECK(yml.is_super(root[2].val()));
CHECK(yml.is_super(root[3].val()));
}
// when parsing immutable buffers, the buffer is first copied to the
// tree's arena; the copy in the arena is then the buffer which is
// actually parsed
{
ryml::csubstr yml = "[a, b, c, d]";
ryml::Tree tree = ryml::parse(yml);
// notice the buffer was copied to the arena:
CHECK(tree.arena().data() != yml.data());
CHECK(tree.arena() == yml);
// and the tree is pointing at the arena instead of to the
// original buffer:
ryml::NodeRef root = tree.rootref();
ryml::csubstr arena = tree.arena();
CHECK(root[0].val().is_sub(arena));
CHECK(root[1].val().is_sub(arena));
CHECK(root[2].val().is_sub(arena));
CHECK(root[3].val().is_sub(arena));
CHECK(arena.is_super(root[0].val()));
CHECK(arena.is_super(root[1].val()));
CHECK(arena.is_super(root[2].val()));
CHECK(arena.is_super(root[3].val()));
}
// the arena is also used when the data is serialized to string
// with NodeRef::operator<<(): mutable buffer
{
char buf[] = "[a, b, c, d]"; // mutable
ryml::substr yml = buf;
ryml::Tree tree = ryml::parse(yml);
// notice the arena is empty:
CHECK(tree.arena().empty());
ryml::NodeRef root = tree.rootref();
// serialize an integer, and mutate the tree
CHECK(root[2].val() == "c");
CHECK(root[2].val().is_sub(yml)); // val is first pointing at the buffer
root[2] << 12345;
CHECK(root[2].val() == "12345");
CHECK(root[2].val().is_sub(tree.arena())); // now val is pointing at the arena
// notice the serialized string was appended to the tree's arena:
CHECK(tree.arena() == "12345");
// serialize an integer, and mutate the tree
CHECK(root[3].val() == "d");
CHECK(root[3].val().is_sub(yml)); // val is first pointing at the buffer
root[3] << 67890;
CHECK(root[3].val() == "67890");
CHECK(root[3].val().is_sub(tree.arena())); // now val is pointing at the arena
// notice the serialized string was appended to the tree's arena:
CHECK(tree.arena() == "1234567890");
}
// the arena is also used when the data is serialized to string
// with NodeRef::operator<<(): immutable buffer
{
ryml::csubstr yml = "[a, b, c, d]"; // immutable
ryml::Tree tree = ryml::parse(yml);
// notice the buffer was copied to the arena:
CHECK(tree.arena().data() != yml.data());
CHECK(tree.arena() == yml);
ryml::NodeRef root = tree.rootref();
// serialize an integer, and mutate the tree
CHECK(root[2].val() == "c");
root[2] << 12345; // serialize an integer
CHECK(root[2].val() == "12345");
// notice the serialized string was appended to the tree's arena:
// notice also the previous values remain there.
// RYML DOES NOT KEEP TRACK OF REFERENCES TO THE ARENA.
CHECK(tree.arena() == "[a, b, c, d]12345");
// old values: --------------^
// serialize an integer, and mutate the tree
root[3] << 67890;
CHECK(root[3].val() == "67890");
// notice the serialized string was appended to the tree's arena:
// notice also the previous values remain there.
// RYML DOES NOT KEEP TRACK OF REFERENCES TO THE ARENA.
CHECK(tree.arena() == "[a, b, c, d]1234567890");
// old values: --------------^ ---^^^^^
}
// to_arena(): directly serialize values to the arena:
{
ryml::Tree tree = ryml::parse("{a: b}");
ryml::csubstr c10 = tree.to_arena(10101010);
CHECK(c10 == "10101010");
CHECK(c10.is_sub(tree.arena()));
CHECK(tree.arena() == "{a: b}10101010");
CHECK(tree.key(1) == "a");
CHECK(tree.val(1) == "b");
tree.set_val(1, c10);
CHECK(tree.val(1) == c10);
// and you can also do it through a node:
ryml::NodeRef root = tree.rootref();
root["a"].set_val_serialized(2222);
CHECK(root["a"].val() == "2222");
CHECK(tree.arena() == "{a: b}101010102222");
}
// copy_to_arena(): manually copy a string to the arena:
{
ryml::Tree tree = ryml::parse("{a: b}");
ryml::csubstr mystr = "Gosset Grande Reserve";
ryml::csubstr copied = tree.copy_to_arena(mystr);
CHECK(!copied.overlaps(mystr));
CHECK(copied == mystr);
CHECK(tree.arena() == "{a: b}Gosset Grande Reserve");
}
// alloc_arena(): allocate a buffer from the arena:
{
ryml::Tree tree = ryml::parse("{a: b}");
ryml::csubstr mystr = "Gosset Grande Reserve";
ryml::substr copied = tree.alloc_arena(mystr.size());
CHECK(!copied.overlaps(mystr));
memcpy(copied.str, mystr.str, mystr.len);
CHECK(copied == mystr);
CHECK(tree.arena() == "{a: b}Gosset Grande Reserve");
}
// reserve_arena(): ensure the arena has a certain size to avoid reallocations
{
ryml::Tree tree = ryml::parse("{a: b}");
CHECK(tree.arena().size() == strlen("{a: b}"));
tree.reserve_arena(100);
CHECK(tree.arena_capacity() >= 100);
CHECK(tree.arena().size() == strlen("{a: b}"));
tree.to_arena(123456);
CHECK(tree.arena().first(12) == "{a: b}123456");
}
}