ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

xmlparser.h

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #ifndef XML_PARSER_H
00024 #define XML_PARSER_H
00025 
00026 #include "common/scummsys.h"
00027 #include "common/types.h"
00028 
00029 #include "common/fs.h"
00030 #include "common/list.h"
00031 #include "common/hashmap.h"
00032 #include "common/hash-str.h"
00033 #include "common/stack.h"
00034 #include "common/memorypool.h"
00035 
00036 
00037 namespace Common {
00038 
00039 class SeekableReadStream;
00040 
00041 #define MAX_XML_DEPTH 8
00042 
00043 #define XML_KEY(keyName) {\
00044         lay = new CustomXMLKeyLayout;\
00045         lay->callback = (&kLocalParserName::parserCallback_##keyName);\
00046         layout.top()->children[#keyName] = lay;\
00047         layout.push(lay); \
00048         _layoutList.push_back(lay);
00049 
00050 #define XML_KEY_RECURSIVE(keyName) {\
00051             layout.top()->children[#keyName] = layout.top();\
00052             layout.push(layout.top());\
00053         }
00054 
00055 #define KEY_END() layout.pop(); }
00056 
00057 #define XML_PROP(propName, req) {\
00058         prop.name = #propName; \
00059         prop.required = req; \
00060         layout.top()->properties.push_back(prop); }
00061 
00062 
00063 
00064 #define CUSTOM_XML_PARSER(parserName) \
00065     protected: \
00066     typedef parserName kLocalParserName; \
00067     bool keyCallback(ParserNode *node) {return node->layout->doCallback(this, node); }\
00068     struct CustomXMLKeyLayout : public XMLKeyLayout {\
00069         typedef bool (parserName::*ParserCallback)(ParserNode *node);\
00070         ParserCallback callback;\
00071         bool doCallback(XMLParser *parent, ParserNode *node) {return ((kLocalParserName *)parent->*callback)(node);} };\
00072     virtual void buildLayout() { \
00073         Common::Stack<XMLKeyLayout *> layout; \
00074         CustomXMLKeyLayout *lay = 0; \
00075         XMLKeyLayout::XMLKeyProperty prop; \
00076         _XMLkeys = new CustomXMLKeyLayout; \
00077         layout.push(_XMLkeys);
00078 
00079 #define PARSER_END() layout.clear(); }
00080 
00090 class XMLParser {
00091 public:
00095     XMLParser() : _XMLkeys(nullptr), _stream(nullptr) {}
00096 
00097     virtual ~XMLParser();
00098 
00100     enum ParserState {
00101         kParserNeedHeader,
00102         kParserNeedKey,
00103         kParserNeedKeyName,
00104 
00105         kParserNeedPropertyName,
00106         kParserNeedPropertyOperator,
00107         kParserNeedPropertyValue,
00108 
00109         kParserError
00110     };
00111 
00112     struct XMLKeyLayout;
00113     struct ParserNode;
00114 
00115     typedef HashMap<String, XMLParser::XMLKeyLayout*, IgnoreCase_Hash, IgnoreCase_EqualTo> ChildMap;
00116 
00118     struct XMLKeyLayout {
00119         struct XMLKeyProperty {
00120             String name;
00121             bool required;
00122         };
00123 
00124         List<XMLKeyProperty> properties;
00125         ChildMap children;
00126 
00127         virtual bool doCallback(XMLParser *parent, ParserNode *node) = 0;
00128 
00129         virtual ~XMLKeyLayout() {
00130             properties.clear();
00131         }
00132     };
00133 
00134     XMLKeyLayout *_XMLkeys;
00135 
00137     struct ParserNode {
00138         String name;
00139         StringMap values;
00140         bool ignore;
00141         bool header;
00142         int depth;
00143         XMLKeyLayout *layout;
00144     };
00145 
00146     ObjectPool<ParserNode, MAX_XML_DEPTH> _nodePool;
00147 
00148     ParserNode *allocNode() {
00149         return new (_nodePool) ParserNode;
00150     }
00151 
00152     void freeNode(ParserNode *node) {
00153         _nodePool.deleteChunk(node);
00154     }
00155 
00163     bool loadFile(const String &filename);
00164 
00165     bool loadFile(const FSNode &node);
00166 
00178     bool loadBuffer(const byte *buffer, uint32 size, DisposeAfterUse::Flag disposable = DisposeAfterUse::NO);
00179 
00180     bool loadStream(SeekableReadStream *stream);
00181 
00182     void close();
00183 
00188     bool parse();
00189 
00194     ParserNode *getActiveNode() {
00195         if (!_activeKey.empty())
00196             return _activeKey.top();
00197 
00198         return nullptr;
00199     }
00200 
00204     ParserNode *getParentNode(ParserNode *child) {
00205         return child->depth > 0 ? _activeKey[child->depth - 1] : 0;
00206     }
00207 
00208 protected:
00209 
00217     virtual void buildLayout() = 0;
00218 
00237     virtual bool keyCallback(ParserNode *node) = 0;
00238 
00252     virtual bool closedKeyCallback(ParserNode *node) {
00253         return true;
00254     }
00255 
00260     bool closeKey();
00261 
00265     bool parseKeyValue(String keyName);
00266 
00271     bool parseActiveKey(bool closed);
00272 
00278     bool parserError(const String &errStr);
00279 
00284     bool skipSpaces();
00285 
00290     bool skipComments();
00291 
00297     virtual inline bool isValidNameChar(char c) {
00298         return isAlnum(c) || c == '_';
00299     }
00300 
00304     bool parseToken();
00305 
00324     bool parseIntegerKey(const char *key, int count, ...);
00325     bool parseIntegerKey(const String &keyStr, int count, ...);
00326     bool vparseIntegerKey(const char *key, int count, va_list args);
00327 
00328     bool parseXMLHeader(ParserNode *node);
00329 
00335     virtual void cleanup() {}
00336 
00337     List<XMLKeyLayout *> _layoutList;
00338 
00339 private:
00340     char _char;
00341     SeekableReadStream *_stream;
00342     String _fileName;
00343 
00344     ParserState _state; 
00346     String _error; 
00347     String _token; 
00349     Stack<ParserNode *> _activeKey; 
00350 };
00351 
00352 } // End of namespace Common
00353 
00354 #endif


Generated on Sat Mar 16 2019 05:02:03 for ResidualVM by doxygen 1.7.1
curved edge   curved edge