Unify Framework Lib 1.6.0
yaml_parser.hpp
Go to the documentation of this file.
1/******************************************************************************
2 * # License
3 * <b>Copyright 2021 Silicon Laboratories Inc. www.silabs.com</b>
4 ******************************************************************************
5 * The licensor of this software is Silicon Laboratories Inc. Your use of this
6 * software is governed by the terms of Silicon Labs Master Software License
7 * Agreement (MSLA) available at
8 * www.silabs.com/about-us/legal/master-software-license-agreement. This
9 * software is distributed to you in Source Code format and is governed by the
10 * sections of the MSLA applicable to Source Code.
11 *
12 *****************************************************************************/
13
32#ifndef BOOST_PROGRAM_OPTIONS_YAML_PARSER_HPP
33#define BOOST_PROGRAM_OPTIONS_YAML_PARSER_HPP
34
35#include <algorithm>
36#include <set>
37#include <string>
38#include <stdexcept>
39
40#include <yaml-cpp/yaml.h>
41#include <boost/program_options/parsers.hpp>
42#include <boost/program_options/options_description.hpp>
43
45{
46 public:
57 template<typename char_T = char>
58 static boost::program_options::basic_parsed_options<char_T>
59 parse(std::istream &istrm,
60 const boost::program_options::options_description &desc)
61 {
62 YAML::Node config = YAML::Load(istrm);
63 return parse(config, desc);
64 }
65
76 template<typename char_T = char>
77 static boost::program_options::basic_parsed_options<char_T>
78 parse(const YAML::Node &node,
79 const boost::program_options::options_description &desc)
80 {
81 boost::program_options::basic_parsed_options<char_T> result(&desc);
82 parse_subnode(node, "", result);
83 return result;
84 }
85
86 protected:
87 template<typename char_T> void static parse_subnode(
88 const YAML::Node &node,
89 const std::string &key,
90 boost::program_options::basic_parsed_options<char_T> &result)
91 {
92 switch (node.Type()) {
93 case YAML::NodeType::Scalar:
94 add_option(key, node.as<std::basic_string<char_T>>(), result);
95 break;
96 case YAML::NodeType::Sequence:
97 parse_subnode_sequence(node, key, result);
98 break;
99 case YAML::NodeType::Map:
100 parse_subnode_map(node, key, result);
101 break;
102 default:
103 throw std::invalid_argument("Unsupported node type");
104 break;
105 }
106 }
107
108 template<typename char_T> static void parse_subnode_sequence(
109 const YAML::Node &node,
110 const std::string &key,
111 boost::program_options::basic_parsed_options<char_T> &result)
112 {
113 for (const auto &subnode: node) {
114 parse_subnode(subnode, key, result);
115 }
116 }
117
118 template<typename char_T> static void parse_subnode_map(
119 const YAML::Node &node,
120 const std::string &key,
121 boost::program_options::basic_parsed_options<char_T> &result)
122 {
123 for (const auto &pair: node) {
124 std::string node_key = pair.first.as<std::string>();
125 try {
126 std::stoul(node_key); // check if we have an integer
127 node_key = key; // treat this as if it were a Sequence
128 } catch (std::invalid_argument &e) {
129 // not an integer
130 if (!key.empty()) {
131 node_key = key + '.' + node_key;
132 }
133 }
134 parse_subnode(pair.second, node_key, result);
135 }
136 }
137
138 template<typename char_T> static void
139 add_option(const std::string &key,
140 const std::basic_string<char_T> &value,
141 boost::program_options::basic_parsed_options<char_T> &result)
142 {
143 if (key.empty()) {
144 throw std::logic_error("Empty key - malformed Config file");
145 }
146 if (result.description->find_nothrow(key, false) == NULL) {
147 // If key is not defined in description, we ignore/skip it.
148 // Since the configuration file may be shared among multiple Unify modules,
149 // it is likely there are configuration options not for us.
150 return;
151 }
152 auto option_iter = std::find_if(
153 result.options.begin(),
154 result.options.end(),
155 [&key](const boost::program_options::basic_option<char_T> &test) {
156 return test.string_key == key;
157 });
158
159 if (option_iter == result.options.end()) {
160 result.options.emplace_back();
161 option_iter = result.options.end() - 1;
162 option_iter->string_key = key;
163 option_iter->unregistered
164 = (result.description->find_nothrow(key, false) == NULL);
165 }
166
167 option_iter->value.push_back(value);
168 }
169};
170
171#endif //BOOST_PROGRAM_OPTIONS_YAML_PARSER_HPP
Definition: yaml_parser.hpp:45
static void parse_subnode_map(const YAML::Node &node, const std::string &key, boost::program_options::basic_parsed_options< char_T > &result)
Definition: yaml_parser.hpp:118
static void add_option(const std::string &key, const std::basic_string< char_T > &value, boost::program_options::basic_parsed_options< char_T > &result)
Definition: yaml_parser.hpp:139
static boost::program_options::basic_parsed_options< char_T > parse(const YAML::Node &node, const boost::program_options::options_description &desc)
Pasre YAML configuration from YAML::Node.
Definition: yaml_parser.hpp:78
static boost::program_options::basic_parsed_options< char_T > parse(std::istream &istrm, const boost::program_options::options_description &desc)
Parse YAML configuration from istream.
Definition: yaml_parser.hpp:59
static void parse_subnode(const YAML::Node &node, const std::string &key, boost::program_options::basic_parsed_options< char_T > &result)
Definition: yaml_parser.hpp:87
static void parse_subnode_sequence(const YAML::Node &node, const std::string &key, boost::program_options::basic_parsed_options< char_T > &result)
Definition: yaml_parser.hpp:108
#define NULL
Definition: list.c:50