aboutsummaryrefslogtreecommitdiff
path: root/common/xmlparser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'common/xmlparser.cpp')
-rw-r--r--common/xmlparser.cpp94
1 files changed, 77 insertions, 17 deletions
diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp
index d0c89a9d3e..900f2f81ab 100644
--- a/common/xmlparser.cpp
+++ b/common/xmlparser.cpp
@@ -41,25 +41,34 @@ bool XMLParser::parserError(const char *errorString, ...) {
int lineCount = 1;
int lineStart = 0;
- do {
- if (_text[pos] == '\n' || _text[pos] == '\r') {
- lineCount++;
-
- if (lineStart == 0)
- lineStart = MAX(pos + 1, _pos - 60);
- }
- } while (pos-- > 0);
+ if (_fileName == "Memory Stream") {
+ lineStart = MAX(0, _pos - 35);
+ lineCount = 0;
+ } else {
+ do {
+ if (_text[pos] == '\n' || _text[pos] == '\r') {
+ lineCount++;
+
+ if (lineStart == 0)
+ lineStart = MAX(pos + 1, _pos - 60);
+ }
+ } while (pos-- > 0);
+ }
char lineStr[70];
_text.stream()->seek(lineStart, SEEK_SET);
_text.stream()->readLine(lineStr, 70);
+
+ for (int i = 0; i < 70; ++i)
+ if (lineStr[i] == '\n')
+ lineStr[i] = ' ';
- printf(" File <%s>, line %d:\n", _fileName.c_str(), lineCount);
+ printf("\n File <%s>, line %d:\n", _fileName.c_str(), lineCount);
bool startFull = lineStr[0] == '<';
bool endFull = lineStr[strlen(lineStr) - 1] == '>';
- printf("%s%s%s\n", startFull ? "" : "...", endFull ? "" : "...", lineStr);
+ printf("%s%s%s\n", startFull ? "" : "...", lineStr, endFull ? "" : "...");
int cursor = MIN(_pos - lineStart, 70);
@@ -77,13 +86,36 @@ bool XMLParser::parserError(const char *errorString, ...) {
vprintf(errorString, args);
va_end(args);
- printf("\n");
+ printf("\n\n");
return false;
}
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)) {
+ 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());
+
+ } else {
+ return parserError("Unexpected key in the active scope: '%s'.", key->name.c_str());
+ }
// check if any of the parents must be ignored.
// if a parent is ignored, all children are too.
@@ -92,13 +124,18 @@ 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;
}
- if (closed) {
- delete _activeKey.pop();
- }
+ if (closed)
+ return closeKey();
return true;
}
@@ -129,10 +166,33 @@ bool XMLParser::parseKeyValue(Common::String keyName) {
return true;
}
+bool XMLParser::closeKey() {
+ bool ignore = false;
+ bool result = true;
+
+ for (int i = _activeKey.size() - 1; i >= 0; --i) {
+ if (_activeKey[i]->ignore)
+ ignore = true;
+ }
+
+ if (ignore == false)
+ result = closedKeyCallback(_activeKey.top());
+
+ delete _activeKey.pop();
+
+ return result;
+}
+
bool XMLParser::parse() {
if (_text.ready() == false)
return parserError("XML stream not ready for reading.");
+
+ if (_XMLkeys == 0)
+ buildLayout();
+
+ while (!_activeKey.empty())
+ delete _activeKey.pop();
cleanup();
@@ -186,6 +246,7 @@ bool XMLParser::parse() {
node->name = _token;
node->ignore = false;
node->depth = _activeKey.size();
+ node->layout = 0;
_activeKey.push(node);
}
@@ -194,13 +255,12 @@ bool XMLParser::parse() {
case kParserNeedPropertyName:
if (activeClosure) {
- if (!closedKeyCallback(_activeKey.top()->name)) {
+ if (!closeKey()) {
parserError("Missing data when closing key '%s'.", _activeKey.top()->name.c_str());
break;
}
activeClosure = false;
- delete _activeKey.pop();
if (_text[_pos++] != '>')
parserError("Invalid syntax in key closure.");