Hyperiso 1.0.3
Modular flavour-physics calculations, Wilson coefficients and statistical inference
Loading...
Searching...
No Matches
YamlParser.cpp
Go to the documentation of this file.
1#include "YamlParser.h"
2
3bool isInteger(const std::string& s) {
4 return !s.empty() && std::all_of(s.begin(), s.end(), ::isdigit);
5}
6
7bool isDouble(const std::string& s) {
8 std::istringstream iss(s);
9 double d;
10 return (iss >> d) && (iss.eof());
11}
12
13bool isBoolean(const std::string& s) {
14 return s == "true" || s == "false";
15}
16
17bool parseBool(const std::string& s) {
18 return s == "true";
19}
20
21std::shared_ptr<DBNode> YAMLParser::parse(const std::string& input) const {
22 std::istringstream stream(input);
23 return parseYAMLDBNode(stream, 0);
24}
25
26std::shared_ptr<DBNode> YAMLParser::parseYAMLDBNode(std::istringstream& stream, int indentLevel) {
27 auto node = std::make_shared<DBNode>();
28 std::string line;
29
30 while (std::getline(stream, line)) {
31 if(line == ""){
32 continue;
33 }
34 int currentIndent = countLeadingSpaces(line);
35 if (currentIndent < indentLevel) {
36 stream.seekg(-static_cast<int>(line.size()) - 1, std::ios_base::cur);
37 return node;
38 }
39
40 line = trim(line);
41 if (line.empty() || line[0] == '#') continue;
42
43 if (line[0] == '-') {
44 processList(node, stream, currentIndent, line);
45 } else if (line.find(":") != std::string::npos) {
46 processKeyValue(line, node, stream, currentIndent + 2);
47 }
48 }
49 return node;
50}
51
52void YAMLParser::processKeyValue(const std::string& line, std::shared_ptr<DBNode>& node, std::istringstream& stream, int indentLevel) {
53 size_t colonPos = line.find(":");
54 std::string key = trim(line.substr(0, colonPos));
55 std::string value = trim(line.substr(colonPos + 1));
56 if (value.empty()) {
57 auto childDBNode = parseYAMLDBNode(stream, indentLevel);
58 node->set(childDBNode, key);
59 } else {
60 node->set(parseScalar(value), key);
61 }
62}
63
64void YAMLParser::processList(std::shared_ptr<DBNode>& node, std::istringstream& stream, int indentLevel, std::string firstLine) {
65 std::map<BlockName, DBNode::Value> listData;
66 size_t index = 0;
67 std::string line = firstLine;
68 bool first {true};
69
70 DBNode::Value currentDBNode;
71 auto tempDBNode = std::make_shared<DBNode>();
72
73 while (true) {
74 if (!first && !std::getline(stream, line)){
75 listData[std::to_string(index)] = tempDBNode->countChildren() != 0 ? tempDBNode : currentDBNode;
76 break;
77 }
78
79 if(trim(line) == ""){
80 continue;
81 }
82
83 if (!first && countLeadingSpaces(line) < indentLevel) {
84 stream.seekg(-static_cast<int>(line.size()) - 1, std::ios_base::cur);
85 listData[std::to_string(index)] = tempDBNode->countChildren() != 0 ? tempDBNode : currentDBNode;
86 break;
87 }
88
89 line = trim(line);
90 if (line[0] == '-') {
91 if (!first) {
92 if (tempDBNode->countChildren() != 0) {
93 currentDBNode = tempDBNode;
94 tempDBNode = std::make_shared<DBNode>();
95 }
96 listData[std::to_string(index)] = currentDBNode;
97 currentDBNode = DBNode::Value();
98 index++;
99 } else {
100 first = false;
101 }
102 line = trim(line.substr(1));
103 }
104
105 size_t colonPos = line.find(":");
106
107 if (colonPos != std::string::npos) {
108 std::string key = trim(line.substr(0, colonPos));
109 std::string value = trim(line.substr(colonPos + 1));
110 if (value.empty()) {
111 auto childDBNode = parseYAMLDBNode(stream, indentLevel + 2);
112 tempDBNode->set(childDBNode, key);
113 } else {
114 tempDBNode->set(parseScalar(value), key);
115 }
116 } else {
117 currentDBNode = parseScalar(trim(line));
118 }
119 }
120
121 node->setGroup({}, listData);
122}
123
124
125
126DBNode::Value YAMLParser::parseScalar(const std::string& value) {
127 if (isInteger(value)) {
128 return std::stoi(value);
129 } else if (isDouble(value)) {
130 return std::stod(value);
131 } else if (value == "true" || value == "false") {
132 return value == "true";
133 }
134 return value;
135}
136
137
138int YAMLParser::countLeadingSpaces(const std::string& str) {
139 return str.find_first_not_of(' ');
140}
141
142std::string YAMLParser::trim(const std::string& str) {
143 size_t first = str.find_first_not_of(" \t");
144 if (first == std::string::npos) return "";
145 size_t last = str.find_last_not_of(" \t");
146 return str.substr(first, last - first + 1);
147}
148
149bool YAMLParser::isInteger(const std::string& str) {
150 return !str.empty() && std::all_of(str.begin(), str.end(), ::isdigit);
151}
152
153bool YAMLParser::isDouble(const std::string& str) {
154 char* end = nullptr;
155 std::strtod(str.c_str(), &end);
156 return end != str.c_str() && *end == '\0';
157}
158
159
160bool YAMLParser::isListDBNode(const std::shared_ptr<DBNode>& node) const {
161 for (const auto& [key, _] : node->getGroup({})) {
162 std::string keyStr = key.to_string();
163
164 if (!std::all_of(keyStr.begin(), keyStr.end(), ::isdigit)) {
165 return false;
166 }
167 }
168 return true;
169}
170
171DBNode::Value YAMLParser::parseValue(const std::string& value) const {
172 if (value.empty()) return "";
173
174 if (!value.empty() && std::all_of(value.begin(), value.end(), ::isdigit)) {
175 return std::stoi(value);
176 }
177
178 if (value.find_first_of(".eE") != std::string::npos) {
179 try {
180 return parseNumber(value);
181 } catch (...) {}
182 }
183
184 if (value == "true") return true;
185 if (value == "false") return false;
186
187 return value;
188}
189
190double YAMLParser::parseNumber(const std::string& value) const {
191 try {
192 return std::stod(value);
193 } catch (const std::exception&) {
194 throw std::runtime_error("Invalid numeric format: " + value);
195 }
196}
197
198void YAMLParser::writeToFile(const std::string& filename, const std::shared_ptr<DBNode>& root) const {
199 std::ofstream file(filename);
200 if (!file.is_open())
201 throw std::runtime_error("Unable to open file for writing: " + filename);
202 root->printYAMLToStream(file);
203 file << '\n';
204 file.flush();
205 if (!file)
206 throw std::runtime_error("Error while writing YAML file: " + filename);
207}
208
209std::shared_ptr<DBNode> YAMLParser::readFromFile(const std::string& filename) const {
210 std::ifstream file(filename);
211 if (!file.is_open()) throw std::runtime_error("Unable to open file for reading");
212
213 std::ostringstream oss;
214 oss << file.rdbuf();
215 return parse(oss.str());
216}
bool isBoolean(const std::string &s)
bool isInteger(const std::string &s)
Definition YamlParser.cpp:3
bool isDouble(const std::string &s)
Definition YamlParser.cpp:7
bool parseBool(const std::string &s)
Lightweight YAML parser/serializer for DBNode trees.
std::variant< BlockName, int, double, bool, std::shared_ptr< DBNode >, std::vector< std::shared_ptr< DBNode > > > Value
Variant type used to store values in the tree.
Definition DBNode.h:45
std::shared_ptr< DBNode > readFromFile(const std::string &filename) const override
Reads and parses YAML data from a file.
std::shared_ptr< DBNode > parse(const std::string &input) const override
Parses a YAML string into a DBNode hierarchy.
void writeToFile(const std::string &filename, const std::shared_ptr< DBNode > &root) const override
Writes a DBNode hierarchy to a YAML file.