1 #ifndef GARLIC_YAML_CPP_H
2 #define GARLIC_YAML_CPP_H
12 #include "../utility.h"
13 #include "yaml-cpp/node/node.h"
14 #include "yaml-cpp/node/parse.h"
15 #include "yaml-cpp/node/type.h"
16 #include "yaml-cpp/yaml.h"
18 namespace garlic::adapters::yamlcpp {
22 template<
typename Iterator>
23 struct MemberIteratorWrapper {
24 using output_type = MemberPair<YamlNode>;
25 using iterator_type = Iterator;
27 iterator_type iterator;
29 inline output_type wrap()
const {
31 YamlNode{this->iterator->first},
32 YamlNode{this->iterator->second}
38 using ValueType = YAML::Node;
39 using ConstValueIterator = BasicForwardIterator<YamlNode, typename ValueType::const_iterator>;
40 using ConstMemberIterator = ForwardIterator<MemberIteratorWrapper<typename ValueType::const_iterator>>;
41 using MemberIterator = ForwardIterator<MemberIteratorWrapper<typename ValueType::iterator>>;
43 YamlNode () =
default;
44 YamlNode (
const ValueType& node) : node_(node) {}
46 bool is_null() const noexcept {
return node_.IsNull(); }
47 bool is_int() const noexcept {
return this->is<int>(); }
48 bool is_string() const noexcept {
return node_.IsScalar(); }
49 bool is_double() const noexcept {
return this->is<double>(); }
50 bool is_object() const noexcept {
return node_.IsMap(); }
51 bool is_list() const noexcept {
return node_.IsSequence(); }
52 bool is_bool() const noexcept {
return this->is<bool>(); }
55 bool is() const noexcept {
57 return YAML::convert<T>::decode(node_, placeholder);
60 int get_int() const noexcept {
return node_.as<
int>(); }
61 std::string get_string() const noexcept {
return node_.as<std::string>(); }
62 std::string_view get_string_view() const noexcept {
return std::string_view{node_.Scalar().c_str()}; }
63 const char* get_cstr() const noexcept {
return node_.Scalar().c_str(); }
64 double get_double() const noexcept {
return node_.as<
double>(); }
65 bool get_bool() const noexcept {
return node_.as<
bool>(); }
67 void set_string(
const char* value) { node_ = value; }
68 void set_string(
const std::string& value) { node_ = value; }
69 void set_string(
const std::string_view value) { node_ = value.data(); }
70 void set_int(
int value) { node_ = value; }
71 void set_double(
double value) { node_ = value; }
72 void set_bool(
bool value) { node_ = value; }
73 void set_null() { node_.reset(); }
74 void set_list() {
if(!is_list()) node_.reset(YAML::Node{YAML::NodeType::Sequence}); }
75 void set_object() {
if(!is_object()) node_.reset(YAML::Node{YAML::NodeType::Map}); }
77 YamlNode& operator = (
double value) { this->set_double(value);
return *
this; }
78 YamlNode& operator = (
int value) { this->set_int(value);
return *
this; }
79 YamlNode& operator = (
const char* value) { this->set_string(value);
return *
this; }
80 YamlNode& operator = (
const std::string& value) { this->set_string(value);
return *
this; }
81 YamlNode& operator = (std::string_view value) { this->set_string(value);
return *
this; }
82 YamlNode& operator = (
bool value) { this->set_bool(value);
return *
this; }
84 bool operator == (
const YamlNode& node)
const {
85 return node.node_ == node_;
88 ConstValueIterator begin_list()
const {
return ConstValueIterator({node_.begin()}); }
89 ConstValueIterator end_list()
const {
return ConstValueIterator({node_.end()}); }
90 auto get_list()
const {
return ConstListRange<YamlNode>{*
this}; }
92 ConstMemberIterator begin_member()
const {
return ConstMemberIterator({node_.begin()}); }
93 ConstMemberIterator end_member()
const {
return ConstMemberIterator({node_.end()}); }
94 ConstMemberIterator find_member(
const char* key)
const {
95 return std::find_if(this->begin_member(), this->end_member(), [&key](
const auto& item) {
96 return strcmp(key, item.key.get_cstr()) == 0;
99 ConstMemberIterator find_member(std::string_view key)
const {
100 return std::find_if(this->begin_member(), this->end_member(), [&key](
const auto& item) {
101 return key.compare(item.key.get_cstr()) == 0;
104 ConstMemberIterator find_member(
const YamlNode& value)
const {
return this->find_member(value.get_cstr()); }
105 auto get_object()
const {
return ConstMemberRange<YamlNode>{*
this}; }
107 MemberIterator begin_member() {
return MemberIterator({node_.begin()}); }
108 MemberIterator end_member() {
return MemberIterator({node_.end()}); }
109 auto get_object() {
return MemberRange<YamlNode>{*
this}; }
112 void clear() { node_.reset(YAML::Node{YAML::NodeType::Sequence}); }
113 template<
typename Callable>
114 void push_back_builder(Callable&& cb) {
117 node_.push_back(node_);
119 void push_back() { node_.push_back(YAML::Node()); }
120 void push_back(
const YamlNode& value) { node_.push_back(value.get_inner_value()); }
121 void push_back(
const std::string& value) { node_.push_back(value); }
122 void push_back(
const std::string_view value) { node_.push_back(value.data()); }
123 void push_back(
const char* value) { node_.push_back(value); }
124 void push_back(
int value) { node_.push_back(value); }
125 void push_back(
double value) { node_.push_back(value); }
126 void push_back(
bool value) { node_.push_back(value); }
129 MemberIterator find_member(
const char* key) {
130 return std::find_if(this->begin_member(), this->end_member(), [&key](
const auto& item) {
131 return strcmp(item.key.get_cstr(), key) == 0;
134 MemberIterator find_member(
const YamlNode& value) {
return this->find_member(value.get_cstr()); }
135 void add_member(
const YamlNode& key,
const YamlNode& value) {
136 node_.force_insert(key.get_inner_value(), value.get_inner_value());
138 void add_member(
const YamlNode& key) { node_.force_insert(key.get_inner_value(), YAML::Node()); }
139 void add_member(YAML::Node&& key, YAML::Node&& value) {
140 node_.force_insert(std::move(key), std::move(value));
142 void add_member(
const char* key) { this->add_member(YAML::Node(key)); }
143 void add_member(
const char* key, YAML::Node&& value) { this->add_member(key, std::move(value)); }
144 void add_member(
const char* key,
const char* value) { this->add_member(key, YAML::Node(value)); }
145 void add_member(
const char* key,
const std::string& value) { this->add_member(key, YAML::Node(value)); }
146 void add_member(
const char* key,
const std::string_view value) { this->add_member(key, YAML::Node(value.data())); }
147 void add_member(
const char* key,
double value) { this->add_member(key, YAML::Node(value)); }
148 void add_member(
const char* key,
int value) { this->add_member(key, YAML::Node(value)); }
149 void add_member(
const char* key,
bool value) { this->add_member(key, YAML::Node(value)); }
151 template<
typename Callable>
152 void add_member_builder(
const char* key, Callable&& cb) {
155 this->add_member(key, value);
158 void remove_member(
const char* key) { node_.remove(key); }
159 void remove_member(
const YamlNode& key) { node_.remove(key.get_inner_value()); }
160 void erase_member(MemberIterator position) {
161 auto pair = *position;
162 if (pair.key.is_string()) this->remove_member(pair.key.get_cstr());
165 const ValueType& get_inner_value()
const {
return node_; }
166 YamlNode get_view()
const {
return YamlNode{node_}; }
174 static YamlNode load(
const char * data) {
175 return YamlNode{YAML::Load(data)};
178 static YamlNode load(FILE * file) {
179 auto buffer = FileStreamBuffer(file);
180 std::istream input_stream(&buffer);
181 return YamlNode{YAML::Load(input_stream)};