YAML-CPP#

Introduction#
.yaml
files.key:values
pair. Those can be scalars (integers, float, string, bool), lists, associative arrays (maps, dictionaries) also seen as NODES, which are simply lists of multiple key:values.RootNode:
ANode1:
aString: My Name
aSubNode:
aFloat: 3.14
aSubNode2:
aFloat: 1.57
aBool: true
ANode2:
aInt : 34
How to use#
The library can be found here.
Prepare library#
- First, it must be built thanks to CMake for your particular builder.
A build for MSVC 2019 can be found on GitLab.
Once built/copied to a chosen path, the folder
YAML_CPP\share\cmake\yaml-cpp
must be added to PATH.
Use it inside your project#
YAML_CPP_INCLUDE_DIR
to the include_directories()
directive, and YAML_CPP_LIBRARIES
under target_link_libraries()
. 1project(MyProject)
2set(CMAKE_BINARY_DIR ${CMAKE_SOURCE_DIR}/bin)
3set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR})
4set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR})
5# Find includes in corresponding build directories
6set(CMAKE_INCLUDE_CURRENT_DIR ON)
7# Find the library
8find_package(yaml-cpp REQUIRED) # here to ensure library exists
9file(GLOB project_SOURCES
10 "src/*.h"
11 "src/*.hpp"
12 "src/*.cpp"
13 )
14#Main app
15add_executable(${PROJECT_NAME} "src/main.cpp" ${project_SOURCES})
16target_link_libraries(${PROJECT_NAME} yaml-cpp) # here to include it
Warning
The library uses exceptions throwing whenever something goes wrong.
Please ensure to embrace your code with throw{} catch(...){}
directives.
Documentation for the library can be found on Github.
Reading a YAML file#
Once you get the file path, you can read it with :
1YAML::Node root;
2try
3{
4 root = YAML::LoadFile(filepath);
5}
6catch(...){/*error - could not load*/}
Afterward, it is up to you to know how your file is structured. In the example given before, the first step is to ensure our root node RootNode
exists and that it contains data :
1// Do we have data as Nodes in our file ?
2if(!root.IsMap())
3{
4 // error - exit
5}
6// Check our RootNode exists
7if(!root["RootNode"])
8{
9 // error - exit
10}
11// OK, we can iterate over data
If you know exactly how you data should be, you must first ensure you key exists, then read the value while specifying its format :
1// Example to access aFloat field
2if(!root["RootNode"]["ANode1"]["aSubNode"]["aFloat"])
3{
4 // does not exist
5}
6else
7{
8 float value = root["RootNode"]["ANode1"]["aSubNode"]["aFloat"].as<float>();
9 // if wrong type is passed, throws an exception
10}
1// Ensure node exists
2if(!root["RootNode"]["ANode1"])
3{
4 // error
5}
6else
7{
8 // create a const ref (we are just reading, so we won't modify it)
9 const YAML::Node& whereSubNodes = root["RootNode"]["ANode1"];
10 // iterate through keys to find our subnodes
11 try
12 {
13 for (YAML::const_iterator it = whereSubNodes.begin(); it != whereSubNodes.end(); ++it)
14 {
15 // it->first gives key, it->second gives value (can be a node too !)
16 if(it->first.as<std::string>().find("aSubNode") != std::string::npos)
17 {
18 // we found a correct Node, read float value if field exists else gives -1.0
19 float val = it->second["aFloat"] ? it->second["aFloat"].as<float>() : -1.0;
20 }
21 }
22 } catch(...) {/*error*/}
23}
Writing a YAML file#
YAML::Emitter
can be used to create a file. It can be written thanks to a special formatting. 1// Root of our file
2YAML::Node root;
3// Create a node listing some values
4root["MyNode"] = YAML::Node(YAML::NodeType::Map);
5// We now will write our values under root["MyNode"]
6YAML::Node& wrnode = root["MyNode"];
7// Write some values
8wrnode["seed"] = 3.14;
9wrnode["name"] = "Glados";
10wrnode["isTurret"] = false;
11// Populate emitter
12YAML::Emitter emitter;
13emitter << root;
14// Write to file
15std::ofstream fout("my/path/to/file.yaml");
16fout << emitter.c_str();
this will create the following file :
MyNode:
seed: 3.14
name: Glados
isTurret: False