1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116 | #include "YAMLParser.hpp"
YAMLParser::YAMLParser() {
yaml_parser_initialize(&parser);
}
YAMLParser::~YAMLParser() {
yaml_parser_delete(&parser);
}
YAMLNode YAMLParser::parse(const std::filesystem::path& filename) {
YAMLNode root;
FILE* file = fopen(filename.string().c_str(), "r");
if (!file) {
throw std::runtime_error("could not read file " + filename.string());
}
yaml_parser_set_input_file(&parser, file);
bool done = false;
try {
while (!done) {
if (!yaml_parser_parse(&parser, &event)) {
throw std::runtime_error("YAML syntax error in file " +
filename.string());
}
if (event.type == YAML_SEQUENCE_START_EVENT) {
parseSequence(filename, root);
} else if (event.type == YAML_MAPPING_START_EVENT) {
parseMapping(filename, root);
} else if (event.type == YAML_DOCUMENT_END_EVENT ||
event.type == YAML_STREAM_END_EVENT) {
done = true;
yaml_event_delete(&event);
} else {
yaml_event_delete(&event);
}
}
} catch (const std::runtime_error& e) {
/* close file before propagating exception */
fclose(file);
throw e;
}
fclose(file);
return root;
}
void YAMLParser::parseMapping(const std::filesystem::path& filename,
YAMLNode& node) {
yaml_event_delete(&event);
node.setMapping();
int done = 0;
while (!done) {
/* read one name/value pair on each iteration */
if (!yaml_parser_parse(&parser, &event)) {
throw std::runtime_error("YAML syntax error in file " +
filename.string());
}
if (event.type == YAML_SCALAR_EVENT) {
/* key */
auto data = (char*)event.data.scalar.value;
auto length = event.data.scalar.length;
auto key = std::string{data, length};
yaml_event_delete(&event);
/* value */
if (!yaml_parser_parse(&parser, &event)) {
throw std::runtime_error("YAML syntax error in file " +
filename.string());
}
if (event.type == YAML_SCALAR_EVENT) {
parseValue(filename, node.insert(key));
} else if (event.type == YAML_SEQUENCE_START_EVENT) {
parseSequence(filename, node.insert(key));
} else if (event.type == YAML_MAPPING_START_EVENT) {
parseMapping(filename, node.insert(key));
} else {
yaml_event_delete(&event);
}
} else {
done = event.type == YAML_MAPPING_END_EVENT;
yaml_event_delete(&event);
}
}
}
void YAMLParser::parseSequence(const std::filesystem::path& filename,
YAMLNode& node) {
yaml_event_delete(&event);
node.setSequence();
int done = 0;
while (!done) {
if (!yaml_parser_parse(&parser, &event)) {
throw std::runtime_error("YAML syntax error in file " +
filename.string());
}
if (event.type == YAML_SCALAR_EVENT) {
parseValue(filename, node.push());
} else if (event.type == YAML_SEQUENCE_START_EVENT) {
parseSequence(filename, node.push());
} else if (event.type == YAML_MAPPING_START_EVENT) {
parseMapping(filename, node.push());
} else {
done = event.type == YAML_SEQUENCE_END_EVENT;
yaml_event_delete(&event);
}
}
}
void YAMLParser::parseValue(const std::filesystem::path& filename,
YAMLNode& node) {
auto data = (char*)event.data.scalar.value;
auto length = event.data.scalar.length;
node.set(std::string(data, length));
yaml_event_delete(&event);
}
|