YAML을 읽고 쓰기 편리한 라이브러리이다.
소스를 다운받고 공유 라이브러리 형태로 컴파일해본다.
$ sudo apt -y install cmake
$ git clone https://github.com/jbeder/yaml-cpp.git
$ cd yaml-cpp/
$ mkdir build
$ cd build
$ cmake -DYAML_BUILD_SHARED_LIBS=ON ..
$ make && sudo make install
$ cd ../
$ sudo cp -r include/yaml-cpp /usr/local/include
$ rm -rf build/
arm으로 컴파일하려면 다음과 같이 cmake를 실행한다.
$ cmake ../ -DCMAKE_FIND_ROOT_PATH=/ -DCMAKE_CXX_COMPILER=/usr/bin/aarch64-linux-gnu-g++ -DYAML_BUILD_SHARED_LIBS=ON
컴파일 시 libyaml-cpp.so
를 링킹하여 컴파일한다.
addresses와 같이 배열은 Sequence
타입, dhcp4나 gateway4와 같이 값만 있다면 Scalar
, 그 외 network나 ethernets와 같이 하위 키가 또 있다면 Map
으로 타입이 정의된다.
재귀 형식으로 데이터를 파싱해보자.
#include <yaml-cpp/yaml.h>
#include <iostream>
void ParsingYAMLFile(YAML::Node Node) {
for (YAML::iterator iter = Node.begin(); iter != Node.end(); ++iter)
{
std::cout << "KEY\t\t" << iter->first << std::endl;
if (iter->second.IsMap()) ParsingYAMLFile(iter->second);
else if (iter->second.IsScalar()) std::cout << "Value\t\t" << iter->second << std::endl;
else if (iter->second.IsSequence())
{
for (std::size_t idx = 0; idx < iter->second.size(); idx++) std::cout << "Sequence [" << idx << "]\t" << iter->second[idx] << std::endl;
}
}
}
int main(void) {
YAML::Node Node = YAML::LoadFile("example1.yaml");
ParsingYAMLFile(Node);
return 0;
}
혹은 Map의 이름으로 접근할 수 있다.
#include <yaml-cpp/yaml.h>
#include <iostream>
int main(void) {
YAML::Node Node = YAML::LoadFile("example1.yaml");
std::cout << std::endl;
std::cout << "[network]" << std::endl;
std::cout << Node["network"] << std::endl;
std::cout << "[ethernets]" << std::endl;
std::cout << Node["network"]["ethernets"] << std::endl;
std::cout << "[enp1s0]" << std::endl;
std::cout << Node["network"]["ethernets"]["enp1s0"] << std::endl;
std::cout << "[dhcp4]" << std::endl;
std::cout << Node["network"]["ethernets"]["enp1s0"]["dhcp4"] << std::endl;
return 0;
}
as를 이용하여 데이터 타입을 변환할 수 있다.
#include <yaml-cpp/yaml.h>
#include <iostream>
int main(void) {
YAML::Node Node = YAML::LoadFile("example1.yaml");
std::cout << ((Node["network"]["ethernets"]["enp1s0"]["dhcp4"].as<bool>()) ? "dhcp is true" : "dhcp is false") << std::endl;
std::cout << Node["network"]["ethernets"]["enp1s0"]["dhcp4"].as<bool>() << std::endl;
std::cout << Node["network"]["ethernets"]["enp1s0"]["dhcp4"].as<std::string>() << std::endl;
return 0;
}
Map을 작성하려면 BeginMap
으로 시작 후 EndMap
으로 끝나게 사용하며
배열은 BeginSeq
와 EndSeq
를 이용한다.
#include <yaml-cpp/yaml.h>
#include <iostream>
#include <fstream>
int main(void) {
std::ofstream writeFile("example2.yaml");
YAML::Emitter Emitter;
Emitter << YAML::BeginMap;
Emitter << YAML::Key << "network" << YAML::Value;
Emitter << YAML::BeginMap;
Emitter << YAML::Key << "ethernets" << YAML::Value;
Emitter << YAML::BeginMap;
Emitter << YAML::Key << "enp1s0" << YAML::Value;
Emitter << YAML::BeginMap;
Emitter << YAML::Key << "addresses" << YAML::Value << YAML::Flow << YAML::BeginSeq << "192.168.2.1/24" << YAML::EndSeq;
Emitter << YAML::Key << "gateway4" << YAML::Value << "192.168.2.1";
Emitter << YAML::Key << "nameservers" << YAML::Value;
Emitter << YAML::BeginMap;
Emitter << YAML::Key << "addresses" << YAML::Value << YAML::Flow << YAML::BeginSeq << "168.126.63.1" << "168.126.63.2" << YAML::EndSeq;
Emitter << YAML::EndMap;
Emitter << YAML::Key << "dhcp4" << YAML::Value << "false";
Emitter << YAML::EndMap;
Emitter << YAML::Key << "enp2s0" << YAML::Value;
Emitter << YAML::BeginMap;
Emitter << YAML::Key << "addresses" << YAML::Value << YAML::Flow << YAML::BeginSeq << "192.168.1.1/24" << YAML::EndSeq;
Emitter << YAML::Key << "dhcp4" << YAML::Value << "false";
Emitter << YAML::EndMap;
Emitter << YAML::EndMap;
Emitter << YAML::EndMap;
Emitter << YAML::EndMap;
writeFile << Emitter.c_str();
writeFile.close();
return 0;
}