aboutsummaryrefslogtreecommitdiff
path: root/common/xmlparser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'common/xmlparser.cpp')
-rw-r--r--common/xmlparser.cpp35
1 files changed, 33 insertions, 2 deletions
diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp
index d0c89a9d3e..030b5b9491 100644
--- a/common/xmlparser.cpp
+++ b/common/xmlparser.cpp
@@ -84,6 +84,27 @@ bool XMLParser::parserError(const char *errorString, ...) {
bool XMLParser::parseActiveKey(bool closed) {
bool ignore = false;
+ assert(_activeKey.empty() == false);
+
+ ParserNode *key = _activeKey.top();
+ XMLKeyLayout *layout = (_activeKey.size() == 1) ? _XMLkeys : getParentNode(key)->layout;
+
+ if (layout->children.contains(key->name) == false)
+ return parserError("Unexpected key in the active scope: '%s'.", key->name.c_str());
+
+ key->layout = layout->children[key->name];
+
+ Common::StringMap localMap = key->values;
+
+ for (Common::List<XMLKeyLayout::XMLKeyProperty>::const_iterator i = key->layout->properties.begin(); i != key->layout->properties.end(); ++i) {
+ if (localMap.contains(i->name))
+ localMap.erase(i->name);
+ else if (i->required)
+ return parserError("Missing required property '%s' inside key '%s'", i->name.c_str(), key->name.c_str());
+ }
+
+ if (localMap.empty() == false)
+ return parserError("Unhandled property inside key '%s': '%s'", key->name.c_str(), localMap.begin()->_key.c_str());
// check if any of the parents must be ignored.
// if a parent is ignored, all children are too.
@@ -92,7 +113,13 @@ bool XMLParser::parseActiveKey(bool closed) {
ignore = true;
}
- if (ignore == false && keyCallback(_activeKey.top()->name) == false) {
+ if (ignore == false && keyCallback(key) == false) {
+ // HACK: People may be stupid and overlook the fact that
+ // when keyCallback() fails, a parserError() must be set.
+ // We set it manually in that case.
+ if (_state != kParserError)
+ parserError("Unhandled exception when parsing '%s' key.", key->name.c_str());
+
return false;
}
@@ -133,6 +160,9 @@ bool XMLParser::parse() {
if (_text.ready() == false)
return parserError("XML stream not ready for reading.");
+
+ if (_XMLkeys == 0)
+ buildLayout();
cleanup();
@@ -186,6 +216,7 @@ bool XMLParser::parse() {
node->name = _token;
node->ignore = false;
node->depth = _activeKey.size();
+ node->layout = 0;
_activeKey.push(node);
}
@@ -194,7 +225,7 @@ bool XMLParser::parse() {
case kParserNeedPropertyName:
if (activeClosure) {
- if (!closedKeyCallback(_activeKey.top()->name)) {
+ if (!closedKeyCallback(_activeKey.top())) {
parserError("Missing data when closing key '%s'.", _activeKey.top()->name.c_str());
break;
}