93 lines
2.6 KiB
C++
93 lines
2.6 KiB
C++
#include "yamlparser.h"
|
|
#include <QFile>
|
|
#include <QTextStream>
|
|
#include <vector>
|
|
|
|
YamlNode YamlParser::parseFile(const QString &filePath)
|
|
{
|
|
QFile file(filePath);
|
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
return YamlNode();
|
|
}
|
|
QTextStream in(&file);
|
|
return parseString(in.readAll());
|
|
}
|
|
|
|
YamlNode YamlParser::parseString(const QString &content)
|
|
{
|
|
YamlNode root;
|
|
QStringList lines = content.split('\n');
|
|
|
|
struct StackEntry {
|
|
int indent;
|
|
YamlNode *node;
|
|
};
|
|
|
|
std::vector<StackEntry> stack;
|
|
stack.push_back({-1, &root});
|
|
|
|
for (int i = 0; i < lines.size(); ++i) {
|
|
QString rawLine = lines[i];
|
|
|
|
// Strip comments
|
|
int commentIdx = rawLine.indexOf('#');
|
|
if (commentIdx != -1) {
|
|
rawLine = rawLine.left(commentIdx);
|
|
}
|
|
|
|
// Calculate leading indentation spaces (tabs expanded to 2 spaces)
|
|
int indent = 0;
|
|
int idx = 0;
|
|
while (idx < rawLine.length()) {
|
|
if (rawLine[idx] == ' ') {
|
|
indent++;
|
|
idx++;
|
|
} else if (rawLine[idx] == '\t') {
|
|
indent += 2;
|
|
idx++;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
QString trimmed = rawLine.trimmed();
|
|
if (trimmed.isEmpty()) continue;
|
|
|
|
// Pop stack until parent has smaller indent
|
|
while (stack.size() > 1 && stack.back().indent >= indent) {
|
|
stack.pop_back();
|
|
}
|
|
|
|
YamlNode *parent = stack.back().node;
|
|
|
|
// Check for list item: "- something"
|
|
if (trimmed.startsWith("- ")) {
|
|
QString itemVal = trimmed.mid(2).trimmed();
|
|
if ((itemVal.startsWith('"') && itemVal.endsWith('"')) || (itemVal.startsWith('\'') && itemVal.endsWith('\''))) {
|
|
itemVal = itemVal.mid(1, itemVal.length() - 2);
|
|
}
|
|
parent->listValues.append(itemVal);
|
|
continue;
|
|
}
|
|
|
|
// Check for key: value
|
|
int colonIdx = trimmed.indexOf(':');
|
|
if (colonIdx != -1) {
|
|
QString key = trimmed.left(colonIdx).trimmed();
|
|
QString val = trimmed.mid(colonIdx + 1).trimmed();
|
|
|
|
if ((val.startsWith('"') && val.endsWith('"')) || (val.startsWith('\'') && val.endsWith('\''))) {
|
|
val = val.mid(1, val.length() - 2);
|
|
}
|
|
|
|
parent->children[key] = YamlNode();
|
|
YamlNode *newNode = &(parent->children[key]);
|
|
newNode->value = val;
|
|
|
|
stack.push_back({indent, newNode});
|
|
}
|
|
}
|
|
|
|
return root;
|
|
}
|