aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorVicent Marti2008-10-18 09:14:43 +0000
committerVicent Marti2008-10-18 09:14:43 +0000
commitdf8af387fb33d5ef645e41b554267aaafd2432bf (patch)
tree0b48d85a3da98b274aa993e1c12bf5104e8b0c80 /common
parent6e8adf4ea69914dd48322a2b3aeb7d91301dbb45 (diff)
downloadscummvm-rg350-df8af387fb33d5ef645e41b554267aaafd2432bf.tar.gz
scummvm-rg350-df8af387fb33d5ef645e41b554267aaafd2432bf.tar.bz2
scummvm-rg350-df8af387fb33d5ef645e41b554267aaafd2432bf.zip
Changed XML Parser to require standards-compilant XML header.
Updated STX version to 0.3 svn-id: r34817
Diffstat (limited to 'common')
-rw-r--r--common/xmlparser.cpp56
-rw-r--r--common/xmlparser.h6
2 files changed, 52 insertions, 10 deletions
diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp
index b3fb2e3cc5..2440a08803 100644
--- a/common/xmlparser.cpp
+++ b/common/xmlparser.cpp
@@ -54,7 +54,7 @@ bool XMLParser::parserError(const char *errorString, ...) {
lineCount++;
}
- _stream->seek(-middle, SEEK_CUR);
+ _stream->seek(-MIN(middle, startPosition), SEEK_CUR);
for (int i = 0, j = 0; i < kErrorMessageWidth; ++i, ++j) {
c = _stream->readByte();
@@ -105,11 +105,32 @@ bool XMLParser::parserError(const char *errorString, ...) {
return false;
}
+bool XMLParser::parseXMLHeader(ParserNode *node) {
+ assert(node->header);
+
+ if (_activeKey.size() != 1)
+ return parserError("XML Header is expected in the global scope.");
+
+ if (!node->values.contains("version"))
+ return parserError("Missing XML version in XML header.");
+
+ if (node->values["version"] != "1.0")
+ return parserError("Unsupported XML version.");
+
+ return true;
+}
+
bool XMLParser::parseActiveKey(bool closed) {
bool ignore = false;
assert(_activeKey.empty() == false);
ParserNode *key = _activeKey.top();
+
+ if (key->name == "xml" && key->header == true) {
+ assert(closed);
+ return parseXMLHeader(key) && closeKey();
+ }
+
XMLKeyLayout *layout = (_activeKey.size() == 1) ? _XMLkeys : getParentNode(key)->layout;
if (layout->children.contains(key->name)) {
@@ -217,9 +238,10 @@ bool XMLParser::parse() {
cleanup();
bool activeClosure = false;
- bool selfClosure = false;
+ bool activeHeader = false;
+ bool selfClosure;
- _state = kParserNeedKey;
+ _state = kParserNeedHeader;
_activeKey.clear();
_char = _stream->readByte();
@@ -232,6 +254,7 @@ bool XMLParser::parse() {
continue;
switch (_state) {
+ case kParserNeedHeader:
case kParserNeedKey:
if (_char != '<') {
parserError("Parser expecting key start.");
@@ -243,7 +266,15 @@ bool XMLParser::parse() {
break;
}
- if (_char == '/') { // FIXME: What if it's a comment start
+ if (_state == kParserNeedHeader) {
+ if (_char != '?') {
+ parserError("Expecting XML header.");
+ break;
+ }
+
+ _char = _stream->readByte();
+ activeHeader = true;
+ } else if (_char == '/') {
_char = _stream->readByte();
activeClosure = true;
}
@@ -266,6 +297,7 @@ bool XMLParser::parse() {
ParserNode *node = allocNode(); //new ParserNode;
node->name = _token;
node->ignore = false;
+ node->header = activeHeader;
node->depth = _activeKey.size();
node->layout = 0;
_activeKey.push(node);
@@ -291,23 +323,29 @@ bool XMLParser::parse() {
_char = _stream->readByte();
break;
}
-
+
selfClosure = false;
- if (_char == '/') { // FIXME: comment start?
+ if (_char == '/' || (_char == '?' && activeHeader)) {
selfClosure = true;
_char = _stream->readByte();
}
if (_char == '>') {
- if (parseActiveKey(selfClosure)) {
+ if (activeHeader && !selfClosure) {
+ parserError("XML Header must be self-closed.");
+ } else if (parseActiveKey(selfClosure)) {
_char = _stream->readByte();
_state = kParserNeedKey;
}
+
+ activeHeader = false;
break;
}
-
- if (!parseToken())
+
+ if (selfClosure)
+ parserError("Expecting key closure after '/' symbol.");
+ else if (!parseToken())
parserError("Error when parsing key value.");
else
_state = kParserNeedPropertyOperator;
diff --git a/common/xmlparser.h b/common/xmlparser.h
index f7a3c664e9..fd4788a426 100644
--- a/common/xmlparser.h
+++ b/common/xmlparser.h
@@ -129,6 +129,7 @@ public:
/** Active state for the parser */
enum ParserState {
+ kParserNeedHeader,
kParserNeedKey,
kParserNeedKeyName,
@@ -166,6 +167,7 @@ public:
Common::String name;
Common::StringMap values;
bool ignore;
+ bool header;
int depth;
XMLKeyLayout *layout;
};
@@ -404,7 +406,7 @@ protected:
_char = _stream->readByte();
}
- return isspace(_char) != 0 || _char == '>' || _char == '=' || _char == '/';
+ return isspace(_char) != 0 || _char == '>' || _char == '=' || _char == '/' || _char == '?';
}
/**
@@ -451,6 +453,8 @@ protected:
va_end(args);
return (*key == 0);
}
+
+ bool parseXMLHeader(ParserNode *node);
/**
* Overload if your parser needs to support parsing the same file