yaml-cpp.h
1 #ifndef GARLIC_YAML_CPP_H
2 #define GARLIC_YAML_CPP_H
3 
4 #include <algorithm>
5 #include <cstddef>
6 #include <cstring>
7 #include <istream>
8 #include <iterator>
9 #include <string>
10 
11 #include "../layer.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"
17 
18 namespace garlic::adapters::yamlcpp {
19 
20  class YamlNode {
21 
22  template<typename Iterator>
23  struct MemberIteratorWrapper {
24  using output_type = MemberPair<YamlNode>;
25  using iterator_type = Iterator;
26 
27  iterator_type iterator;
28 
29  inline output_type wrap() const {
30  return output_type {
31  YamlNode{this->iterator->first},
32  YamlNode{this->iterator->second}
33  };
34  }
35  };
36 
37  public:
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>>;
42 
43  YamlNode () = default;
44  YamlNode (const ValueType& node) : node_(node) {}
45 
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>(); }
53 
54  template<typename T>
55  bool is() const noexcept {
56  T placeholder;
57  return YAML::convert<T>::decode(node_, placeholder);
58  }
59 
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>(); }
66 
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}); }
76 
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; }
83 
84  bool operator == (const YamlNode& node) const {
85  return node.node_ == node_;
86  }
87 
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}; }
91 
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;
97  });
98  }
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;
102  });
103  }
104  ConstMemberIterator find_member(const YamlNode& value) const { return this->find_member(value.get_cstr()); }
105  auto get_object() const { return ConstMemberRange<YamlNode>{*this}; }
106 
107  MemberIterator begin_member() { return MemberIterator({node_.begin()}); }
108  MemberIterator end_member() { return MemberIterator({node_.end()}); }
109  auto get_object() { return MemberRange<YamlNode>{*this}; }
110 
111  // list functions.
112  void clear() { node_.reset(YAML::Node{YAML::NodeType::Sequence}); }
113  template<typename Callable>
114  void push_back_builder(Callable&& cb) {
115  YAML::Node node_;
116  cb(YamlNode(node_));
117  node_.push_back(node_);
118  }
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); }
127 
128  // member functions.
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;
132  });
133  }
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());
137  }
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));
141  }
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)); }
150 
151  template<typename Callable>
152  void add_member_builder(const char* key, Callable&& cb) {
153  YAML::Node value;
154  cb(YamlNode(value));
155  this->add_member(key, value);
156  }
157 
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());
163  }
164 
165  const ValueType& get_inner_value() const { return node_; }
166  YamlNode get_view() const { return YamlNode{node_}; }
167 
168  private:
169  ValueType node_;
170  };
171 
172 
173  struct Yaml {
174  static YamlNode load(const char * data) {
175  return YamlNode{YAML::Load(data)};
176  }
177 
178  static YamlNode load(FILE * file) {
179  auto buffer = FileStreamBuffer(file);
180  std::istream input_stream(&buffer);
181  return YamlNode{YAML::Load(input_stream)};
182  }
183  };
184 
185 }
186 
187 #endif /* end of include guard: GARLIC_YAML_CPP_H */