Skip to content

Commit 78ab9b5

Browse files
committed
Allow to load YAML config from string
1 parent 79088fc commit 78ab9b5

File tree

6 files changed

+109
-18
lines changed

6 files changed

+109
-18
lines changed

src/Configuration.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@ SimpleConfigValue::SimpleConfigValue(const std::string &v): ConfigValue(SIMPLE),
133133

134134
}
135135

136+
SimpleConfigValue::SimpleConfigValue(): ConfigValue(SIMPLE), value("")
137+
{
138+
139+
}
140+
136141
SimpleConfigValue::~SimpleConfigValue()
137142
{
138143

src/Configuration.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class SimpleConfigValue : public ConfigValue
4444
{
4545
public:
4646
SimpleConfigValue(const std::string &value);
47+
SimpleConfigValue();
4748
virtual ~SimpleConfigValue();
4849
virtual void print(std::ostream &stream, int level = 0) const;
4950
virtual bool merge(std::shared_ptr<ConfigValue> other);

src/YAMLConfiguration.cpp

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ void YAMLConfigParser::displayMap(const YAML::Node &map, int level)
180180

181181
}
182182

183-
bool YAMLConfigParser::parseAndInsert(const std::string& configName, const std::string& ymlString, const std::string &pathStr, std::map< std::string, Configuration >& subConfigs)
183+
bool YAMLConfigParser::parseAndInsert(const std::string& configName, const std::string& ymlString, std::map< std::string, Configuration >& subConfigs)
184184
{
185185
std::string afterInsertion = applyStringVariableInsertions(ymlString);
186186

@@ -191,7 +191,7 @@ bool YAMLConfigParser::parseAndInsert(const std::string& configName, const std::
191191
return false;
192192
} catch (std::runtime_error &e)
193193
{
194-
std::cout << "Error loading sub config << '" << configName << "' of file " << pathStr << std::endl << " " << e.what() << std::endl;
194+
std::cout << "Error loading sub config << '" << configName << std::endl << " " << e.what() << std::endl;
195195
std::cout << "YML of subconfig was :" << std::endl << afterInsertion << std::endl;
196196
return false;
197197
}
@@ -202,41 +202,54 @@ bool YAMLConfigParser::parseAndInsert(const std::string& configName, const std::
202202

203203
bool YAMLConfigParser::loadConfigFile(const std::string& pathStr, std::map<std::string, Configuration> &subConfigs)
204204
{
205-
subConfigs.clear();
206205
using namespace boost::filesystem;
207-
208206
path path(pathStr);
209-
210207
if(!exists(path))
211208
{
212209
throw std::runtime_error(std::string("Error, could not find config file ") + path.c_str());
213210
}
214211

215-
//as this is non standard yml, we need to load and parse the config file first
216212
std::ifstream fin(path.c_str());
213+
bool st = loadConfig(fin, subConfigs);
214+
fin.close();
215+
return st;
216+
}
217+
218+
bool libConfig::YAMLConfigParser::loadConfigString(const std::string &yamlstring, std::map<std::string, libConfig::Configuration> &subConfigs)
219+
{
220+
std::istringstream ss;
221+
ss.str(yamlstring);
222+
return loadConfig(ss, subConfigs);
223+
}
224+
template <typename T>
225+
bool libConfig::YAMLConfigParser::loadConfig(T &stream, std::map<std::string, libConfig::Configuration> &subConfigs)
226+
{
227+
subConfigs.clear();
228+
229+
//as this is non standard yml, we need to load and parse the config file first
217230
std::string line;
218-
231+
219232
std::string buffer;
220-
233+
221234
std::string configName;
222-
223-
while(std::getline(fin, line))
235+
236+
while(std::getline(stream, line))
224237
{
225238
if(line.size() >= 3 && line.at(0) == '-' && line.at(1) == '-' && line.at(2) == '-' )
226239
{
227240
//found new subsection
228241
// std::cout << "found subsection " << line << std::endl;
229-
242+
230243
std::string searched("--- name:");
231244
if(!line.compare(0, searched.size(), searched))
232245
{
233246
if(!configName.empty())
234247
{
235-
if(!parseAndInsert(configName, buffer, pathStr, subConfigs))
248+
if(!parseAndInsert(configName, buffer, subConfigs))
236249
return false;
237250
buffer.clear();
238251
}
239-
252+
240253
configName = line.substr(searched.size(), line.size());
241254

242255
// std::cout << "Found new configuration " << curConfig.name << std::endl;
@@ -253,10 +266,10 @@ bool YAMLConfigParser::loadConfigFile(const std::string& pathStr, std::map<std::
253266
buffer.append("\n");
254267
}
255268
}
256-
269+
257270
if(!configName.empty())
258271
{
259-
if(!parseAndInsert(configName, buffer, pathStr, subConfigs))
272+
if(!parseAndInsert(configName, buffer, subConfigs))
260273
return false;
261274
}
262275

@@ -265,7 +278,7 @@ bool YAMLConfigParser::loadConfigFile(const std::string& pathStr, std::map<std::
265278
// std::cout << "Cur conf \"" << it->first << "\"" << std::endl;
266279
// displayConfiguration(it->second);
267280
// }
268-
281+
269282
return true;
270283
}
271284

src/YAMLConfiguration.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22

33
#include "Configuration.hpp"
44
#include <yaml-cpp/yaml.h>
5+
#include <istream>
56

67
namespace libConfig
78
{
89
class YAMLConfigParser {
9-
bool parseAndInsert(const std::string& configName, const std::string& ymlString, const std::string &pathStr, std::map< std::string, Configuration >& subConfigs);
10+
bool parseAndInsert(const std::string& configName, const std::string& ymlString, std::map< std::string, Configuration >& subConfigs);
1011
public:
1112
void displayMap(const YAML::Node &map, int level = 0);
1213

@@ -21,6 +22,9 @@ class YAMLConfigParser {
2122
bool insetMapIntoArray(const YAML::Node &map, Configuration &conf);
2223

2324
bool loadConfigFile(const std::string &path, std::map<std::string, Configuration> &subConfigs);
25+
bool loadConfigString(const std::string &yamlstring, std::map<std::string, Configuration> &subConfigs);
26+
template <typename T>
27+
bool loadConfig(T& stream, std::map<std::string, Configuration> &subConfigs);
2428

2529
bool parseYAML(Configuration &curConfig, const std::string &yamlBuffer);
2630

@@ -42,4 +46,4 @@ class YAMLConfigParser {
4246

4347

4448
};
45-
}
49+
}

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
INCLUDE_DIRECTORIES(../src)
22
rock_testsuite(test_suite suite.cpp
33
bundle.cpp
4+
yaml_configuration.cpp
45
DEPS lib_config)
56

67

test/yaml_configuration.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#include <boost/test/unit_test.hpp>
2+
#include <boost/filesystem.hpp>
3+
#include <iostream>
4+
#include "YAMLConfiguration.hpp"
5+
#include <string>
6+
#include <map>
7+
#include <fstream>
8+
#include <boost/filesystem/path.hpp>
9+
10+
namespace fs = boost::filesystem;
11+
12+
std::string prepare_config_file(){
13+
std::string filepath = (fs::path("/tmp/") / "my::Task.yml").string();
14+
std::ofstream fs(filepath,
15+
std::ios_base::out);
16+
fs << "--- name:default\n";
17+
fs << "axisScale: []\n";
18+
fs << "name: defaultname\n";
19+
20+
fs << "--- name:specialized\n";
21+
fs << "axisScale: [1,2,3]\n";
22+
fs << "name: specialized\n";
23+
fs << "--- name:other\n";
24+
fs << "axisScale: [1,2,3]\n";
25+
fs << "name: other\n";
26+
fs.close();
27+
return filepath;
28+
}
29+
30+
std::string complex_type(){
31+
return "axisScale: [1,2,3]\nname: hallo";
32+
}
33+
34+
BOOST_AUTO_TEST_CASE(load_from_file)
35+
{
36+
std::string filepath = prepare_config_file();
37+
38+
libConfig::YAMLConfigParser parser;
39+
std::map<std::string, libConfig::Configuration> configs;
40+
parser.loadConfigFile(filepath, configs);
41+
BOOST_CHECK_EQUAL(configs.size(), 3);
42+
}
43+
44+
BOOST_AUTO_TEST_CASE(load_from_string)
45+
{
46+
std::string filepath = prepare_config_file();
47+
std::ifstream t(filepath);
48+
std::string yamlstring((std::istreambuf_iterator<char>(t)),
49+
std::istreambuf_iterator<char>());
50+
51+
libConfig::YAMLConfigParser parser;
52+
std::map<std::string, libConfig::Configuration> configs;
53+
parser.loadConfigString(yamlstring, configs);
54+
55+
BOOST_CHECK_EQUAL(configs.size(), 3);
56+
}
57+
58+
BOOST_AUTO_TEST_CASE(get_value)
59+
{
60+
libConfig::YAMLConfigParser parser;
61+
std::shared_ptr<libConfig::ConfigValue> val = parser.getConfigValue(complex_type());
62+
std::shared_ptr<libConfig::ComplexConfigValue> cval = std::dynamic_pointer_cast<libConfig::ComplexConfigValue>(val);
63+
BOOST_CHECK(cval != nullptr);
64+
65+
BOOST_CHECK_EQUAL(cval->getValues().size(), 2);
66+
67+
}

0 commit comments

Comments
 (0)