SAX based XML parser
Dependents: giken9_HTMLServer_Temp_Sample
expatpp.cpp@0:07919e3d6c56, 2011-04-08 (annotated)
- Committer:
- andrewbonney
- Date:
- Fri Apr 08 09:18:41 2011 +0000
- Revision:
- 0:07919e3d6c56
- Child:
- 1:e96b2af301dd
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
andrewbonney | 0:07919e3d6c56 | 1 | // expatpp |
andrewbonney | 0:07919e3d6c56 | 2 | #ifdef UNDER_CE |
andrewbonney | 0:07919e3d6c56 | 3 | #include <string.h> |
andrewbonney | 0:07919e3d6c56 | 4 | #include <windows.h> |
andrewbonney | 0:07919e3d6c56 | 5 | #include <dbgapi.h> |
andrewbonney | 0:07919e3d6c56 | 6 | #define assert ASSERT |
andrewbonney | 0:07919e3d6c56 | 7 | #else |
andrewbonney | 0:07919e3d6c56 | 8 | #include <string> |
andrewbonney | 0:07919e3d6c56 | 9 | using namespace std; |
andrewbonney | 0:07919e3d6c56 | 10 | #include <assert.h> |
andrewbonney | 0:07919e3d6c56 | 11 | #endif |
andrewbonney | 0:07919e3d6c56 | 12 | #include "expatpp.h" |
andrewbonney | 0:07919e3d6c56 | 13 | |
andrewbonney | 0:07919e3d6c56 | 14 | #pragma diag_suppress 1299 |
andrewbonney | 0:07919e3d6c56 | 15 | |
andrewbonney | 0:07919e3d6c56 | 16 | |
andrewbonney | 0:07919e3d6c56 | 17 | // may be defined in xmltchar.h or elsewhere |
andrewbonney | 0:07919e3d6c56 | 18 | #ifndef tcscmp |
andrewbonney | 0:07919e3d6c56 | 19 | #ifdef XML_UNICODE |
andrewbonney | 0:07919e3d6c56 | 20 | #define tcscmp wcscmp |
andrewbonney | 0:07919e3d6c56 | 21 | #else |
andrewbonney | 0:07919e3d6c56 | 22 | #define tcscmp strcmp |
andrewbonney | 0:07919e3d6c56 | 23 | #endif // XML_UNICODE |
andrewbonney | 0:07919e3d6c56 | 24 | #endif // tcscmp |
andrewbonney | 0:07919e3d6c56 | 25 | |
andrewbonney | 0:07919e3d6c56 | 26 | |
andrewbonney | 0:07919e3d6c56 | 27 | #ifndef BUFSIZ |
andrewbonney | 0:07919e3d6c56 | 28 | #define BUFSIZ 4096 |
andrewbonney | 0:07919e3d6c56 | 29 | #endif |
andrewbonney | 0:07919e3d6c56 | 30 | |
andrewbonney | 0:07919e3d6c56 | 31 | expatpp::expatpp(bool createParser) : |
andrewbonney | 0:07919e3d6c56 | 32 | mParser(0), // in case of exception below |
andrewbonney | 0:07919e3d6c56 | 33 | mHaveParsed(false) |
andrewbonney | 0:07919e3d6c56 | 34 | { |
andrewbonney | 0:07919e3d6c56 | 35 | if (createParser) { |
andrewbonney | 0:07919e3d6c56 | 36 | // subclasses may call this ctor after parser created! |
andrewbonney | 0:07919e3d6c56 | 37 | mParser = XML_ParserCreate(0); |
andrewbonney | 0:07919e3d6c56 | 38 | SetupHandlers(); |
andrewbonney | 0:07919e3d6c56 | 39 | } |
andrewbonney | 0:07919e3d6c56 | 40 | } |
andrewbonney | 0:07919e3d6c56 | 41 | |
andrewbonney | 0:07919e3d6c56 | 42 | |
andrewbonney | 0:07919e3d6c56 | 43 | void |
andrewbonney | 0:07919e3d6c56 | 44 | expatpp::SetupHandlers() |
andrewbonney | 0:07919e3d6c56 | 45 | { |
andrewbonney | 0:07919e3d6c56 | 46 | ::XML_SetUserData(mParser, this); |
andrewbonney | 0:07919e3d6c56 | 47 | ::XML_SetElementHandler(mParser, startElementCallback, endElementCallback); |
andrewbonney | 0:07919e3d6c56 | 48 | ::XML_SetCharacterDataHandler(mParser, charDataCallback); |
andrewbonney | 0:07919e3d6c56 | 49 | ::XML_SetProcessingInstructionHandler(mParser, processingInstructionCallback); |
andrewbonney | 0:07919e3d6c56 | 50 | ::XML_SetDefaultHandler(mParser, defaultHandlerCallback); |
andrewbonney | 0:07919e3d6c56 | 51 | ::XML_SetUnparsedEntityDeclHandler(mParser, unParsedEntityDeclCallback); |
andrewbonney | 0:07919e3d6c56 | 52 | ::XML_SetNotationDeclHandler(mParser, notationDeclCallback); |
andrewbonney | 0:07919e3d6c56 | 53 | ::XML_SetNotStandaloneHandler(mParser, notStandaloneHandlerCallback); |
andrewbonney | 0:07919e3d6c56 | 54 | ::XML_SetNamespaceDeclHandler(mParser, startNamespaceCallback, endNamespaceCallback); |
andrewbonney | 0:07919e3d6c56 | 55 | #ifndef EXPATPP_COMPATIBLE_EXPAT12 |
andrewbonney | 0:07919e3d6c56 | 56 | ::XML_SetAttlistDeclHandler(mParser, attlistDeclCallback); |
andrewbonney | 0:07919e3d6c56 | 57 | ::XML_SetCdataSectionHandler(mParser, startCdataSectionCallback, endCdataSectionCallback); |
andrewbonney | 0:07919e3d6c56 | 58 | ::XML_SetCommentHandler(mParser, commentCallback); |
andrewbonney | 0:07919e3d6c56 | 59 | ::XML_SetDoctypeDeclHandler(mParser, startDoctypeDeclCallback, endDoctypeDeclCallback); |
andrewbonney | 0:07919e3d6c56 | 60 | ::XML_SetElementDeclHandler(mParser, elementDeclCallback); |
andrewbonney | 0:07919e3d6c56 | 61 | ::XML_SetEntityDeclHandler(mParser, entityDeclCallback); |
andrewbonney | 0:07919e3d6c56 | 62 | ::XML_SetSkippedEntityHandler(mParser, skippedEntityCallback); |
andrewbonney | 0:07919e3d6c56 | 63 | ::XML_SetXmlDeclHandler(mParser, xmlDeclCallback); |
andrewbonney | 0:07919e3d6c56 | 64 | #endif |
andrewbonney | 0:07919e3d6c56 | 65 | } |
andrewbonney | 0:07919e3d6c56 | 66 | |
andrewbonney | 0:07919e3d6c56 | 67 | |
andrewbonney | 0:07919e3d6c56 | 68 | expatpp::~expatpp() |
andrewbonney | 0:07919e3d6c56 | 69 | { |
andrewbonney | 0:07919e3d6c56 | 70 | if (mParser) // allows subclasses to avoid finishing parsing |
andrewbonney | 0:07919e3d6c56 | 71 | ReleaseParser(); |
andrewbonney | 0:07919e3d6c56 | 72 | } |
andrewbonney | 0:07919e3d6c56 | 73 | |
andrewbonney | 0:07919e3d6c56 | 74 | |
andrewbonney | 0:07919e3d6c56 | 75 | /** |
andrewbonney | 0:07919e3d6c56 | 76 | Provide single point that will call XML_ParserFree. |
andrewbonney | 0:07919e3d6c56 | 77 | Nothing else in this code should call XML_ParserFree! |
andrewbonney | 0:07919e3d6c56 | 78 | */ |
andrewbonney | 0:07919e3d6c56 | 79 | void |
andrewbonney | 0:07919e3d6c56 | 80 | expatpp::ReleaseParser() |
andrewbonney | 0:07919e3d6c56 | 81 | { |
andrewbonney | 0:07919e3d6c56 | 82 | ::XML_ParserFree(mParser); |
andrewbonney | 0:07919e3d6c56 | 83 | mParser = 0; |
andrewbonney | 0:07919e3d6c56 | 84 | } |
andrewbonney | 0:07919e3d6c56 | 85 | |
andrewbonney | 0:07919e3d6c56 | 86 | |
andrewbonney | 0:07919e3d6c56 | 87 | |
andrewbonney | 0:07919e3d6c56 | 88 | /** |
andrewbonney | 0:07919e3d6c56 | 89 | Provide single point that will call XML_ParserReset. |
andrewbonney | 0:07919e3d6c56 | 90 | Guarded against trivial reset before use in case that breaks |
andrewbonney | 0:07919e3d6c56 | 91 | expat or creates overhead. |
andrewbonney | 0:07919e3d6c56 | 92 | |
andrewbonney | 0:07919e3d6c56 | 93 | \todo pass in encoding to XML_ParserReset when we support encodings |
andrewbonney | 0:07919e3d6c56 | 94 | */ |
andrewbonney | 0:07919e3d6c56 | 95 | void |
andrewbonney | 0:07919e3d6c56 | 96 | expatpp::ResetParser() |
andrewbonney | 0:07919e3d6c56 | 97 | { |
andrewbonney | 0:07919e3d6c56 | 98 | #ifdef EXPATPP_COMPATIBLE_EXPAT12 |
andrewbonney | 0:07919e3d6c56 | 99 | assert(!"Reset not available in earlier than expat 1.95.3");s |
andrewbonney | 0:07919e3d6c56 | 100 | #else |
andrewbonney | 0:07919e3d6c56 | 101 | /*if (mHaveParsed) { |
andrewbonney | 0:07919e3d6c56 | 102 | ::XML_ParserReset(mParser, NULL); |
andrewbonney | 0:07919e3d6c56 | 103 | SetupHandlers(); |
andrewbonney | 0:07919e3d6c56 | 104 | mHaveParsed = false; |
andrewbonney | 0:07919e3d6c56 | 105 | }*/ |
andrewbonney | 0:07919e3d6c56 | 106 | if (mHaveParsed) { |
andrewbonney | 0:07919e3d6c56 | 107 | ReleaseParser(); |
andrewbonney | 0:07919e3d6c56 | 108 | mParser = XML_ParserCreate(0); |
andrewbonney | 0:07919e3d6c56 | 109 | SetupHandlers(); |
andrewbonney | 0:07919e3d6c56 | 110 | mHaveParsed = false; |
andrewbonney | 0:07919e3d6c56 | 111 | } |
andrewbonney | 0:07919e3d6c56 | 112 | #endif |
andrewbonney | 0:07919e3d6c56 | 113 | } |
andrewbonney | 0:07919e3d6c56 | 114 | |
andrewbonney | 0:07919e3d6c56 | 115 | |
andrewbonney | 0:07919e3d6c56 | 116 | /** |
andrewbonney | 0:07919e3d6c56 | 117 | Parse entire file, basically copy of the loop from the elements.c example. |
andrewbonney | 0:07919e3d6c56 | 118 | */ |
andrewbonney | 0:07919e3d6c56 | 119 | XML_Status |
andrewbonney | 0:07919e3d6c56 | 120 | expatpp::parseFile(FILE* inFile) |
andrewbonney | 0:07919e3d6c56 | 121 | { |
andrewbonney | 0:07919e3d6c56 | 122 | ResetParser(); |
andrewbonney | 0:07919e3d6c56 | 123 | |
andrewbonney | 0:07919e3d6c56 | 124 | char buf[BUFSIZ]; |
andrewbonney | 0:07919e3d6c56 | 125 | int done; |
andrewbonney | 0:07919e3d6c56 | 126 | if (!inFile) |
andrewbonney | 0:07919e3d6c56 | 127 | return XML_STATUS_ERROR; |
andrewbonney | 0:07919e3d6c56 | 128 | fseek(inFile, 0, SEEK_SET); // reset for reading |
andrewbonney | 0:07919e3d6c56 | 129 | do { |
andrewbonney | 0:07919e3d6c56 | 130 | size_t len = fread(buf, 1, sizeof(buf), inFile); |
andrewbonney | 0:07919e3d6c56 | 131 | done = len < sizeof(buf); |
andrewbonney | 0:07919e3d6c56 | 132 | enum XML_Status parseStatus; |
andrewbonney | 0:07919e3d6c56 | 133 | if ((parseStatus = XML_Parse(buf, len, done))!=XML_STATUS_OK) { |
andrewbonney | 0:07919e3d6c56 | 134 | return parseStatus; |
andrewbonney | 0:07919e3d6c56 | 135 | } |
andrewbonney | 0:07919e3d6c56 | 136 | } while (!done); |
andrewbonney | 0:07919e3d6c56 | 137 | return XML_STATUS_OK; |
andrewbonney | 0:07919e3d6c56 | 138 | } |
andrewbonney | 0:07919e3d6c56 | 139 | |
andrewbonney | 0:07919e3d6c56 | 140 | |
andrewbonney | 0:07919e3d6c56 | 141 | XML_Status |
andrewbonney | 0:07919e3d6c56 | 142 | expatpp::XML_Parse(const char *s, int len, int isFinal) |
andrewbonney | 0:07919e3d6c56 | 143 | { |
andrewbonney | 0:07919e3d6c56 | 144 | mHaveParsed = true; |
andrewbonney | 0:07919e3d6c56 | 145 | const XML_Status retStatus = ::XML_Parse(mParser, s, len, isFinal); |
andrewbonney | 0:07919e3d6c56 | 146 | if (isFinal) |
andrewbonney | 0:07919e3d6c56 | 147 | CheckFinalStatus(retStatus); |
andrewbonney | 0:07919e3d6c56 | 148 | return retStatus; |
andrewbonney | 0:07919e3d6c56 | 149 | } |
andrewbonney | 0:07919e3d6c56 | 150 | |
andrewbonney | 0:07919e3d6c56 | 151 | |
andrewbonney | 0:07919e3d6c56 | 152 | XML_Error |
andrewbonney | 0:07919e3d6c56 | 153 | expatpp::XML_GetErrorCode() |
andrewbonney | 0:07919e3d6c56 | 154 | { |
andrewbonney | 0:07919e3d6c56 | 155 | return ::XML_GetErrorCode(mParser); |
andrewbonney | 0:07919e3d6c56 | 156 | } |
andrewbonney | 0:07919e3d6c56 | 157 | |
andrewbonney | 0:07919e3d6c56 | 158 | |
andrewbonney | 0:07919e3d6c56 | 159 | int |
andrewbonney | 0:07919e3d6c56 | 160 | expatpp::XML_GetCurrentLineNumber() |
andrewbonney | 0:07919e3d6c56 | 161 | { |
andrewbonney | 0:07919e3d6c56 | 162 | return ::XML_GetCurrentLineNumber(mParser); |
andrewbonney | 0:07919e3d6c56 | 163 | } |
andrewbonney | 0:07919e3d6c56 | 164 | |
andrewbonney | 0:07919e3d6c56 | 165 | |
andrewbonney | 0:07919e3d6c56 | 166 | int |
andrewbonney | 0:07919e3d6c56 | 167 | expatpp::XML_GetCurrentColumnNumber() |
andrewbonney | 0:07919e3d6c56 | 168 | { |
andrewbonney | 0:07919e3d6c56 | 169 | return ::XML_GetCurrentColumnNumber(mParser); |
andrewbonney | 0:07919e3d6c56 | 170 | } |
andrewbonney | 0:07919e3d6c56 | 171 | |
andrewbonney | 0:07919e3d6c56 | 172 | |
andrewbonney | 0:07919e3d6c56 | 173 | |
andrewbonney | 0:07919e3d6c56 | 174 | |
andrewbonney | 0:07919e3d6c56 | 175 | /** |
andrewbonney | 0:07919e3d6c56 | 176 | Parse string which is assumed to be entire XML document. |
andrewbonney | 0:07919e3d6c56 | 177 | Written to stop stupid errors of being off by one in the string length causing |
andrewbonney | 0:07919e3d6c56 | 178 | wasted debugging time, such as: |
andrewbonney | 0:07919e3d6c56 | 179 | \verbatim |
andrewbonney | 0:07919e3d6c56 | 180 | const char[] kSampleSettings = "<settings/>"; |
andrewbonney | 0:07919e3d6c56 | 181 | const int sampleSize = sizeof(kSampleSettings)-1; // unless you remember to subtract one here will get invalid token error |
andrewbonney | 0:07919e3d6c56 | 182 | if (!parser.XML_Parse(kSampleSettings, sampleSize, 1)) { |
andrewbonney | 0:07919e3d6c56 | 183 | \endverbatim |
andrewbonney | 0:07919e3d6c56 | 184 | */ |
andrewbonney | 0:07919e3d6c56 | 185 | XML_Status |
andrewbonney | 0:07919e3d6c56 | 186 | expatpp::parseString(const char* inString) |
andrewbonney | 0:07919e3d6c56 | 187 | { |
andrewbonney | 0:07919e3d6c56 | 188 | ResetParser(); |
andrewbonney | 0:07919e3d6c56 | 189 | const int inLen = strlen(inString); |
andrewbonney | 0:07919e3d6c56 | 190 | return XML_Parse(inString, inLen, 1); |
andrewbonney | 0:07919e3d6c56 | 191 | } |
andrewbonney | 0:07919e3d6c56 | 192 | |
andrewbonney | 0:07919e3d6c56 | 193 | void |
andrewbonney | 0:07919e3d6c56 | 194 | expatpp::startElementCallback(void *userData, const XML_Char* name, const XML_Char** atts) |
andrewbonney | 0:07919e3d6c56 | 195 | { |
andrewbonney | 0:07919e3d6c56 | 196 | ((expatpp*)userData)->startElement(name, atts); |
andrewbonney | 0:07919e3d6c56 | 197 | } |
andrewbonney | 0:07919e3d6c56 | 198 | |
andrewbonney | 0:07919e3d6c56 | 199 | |
andrewbonney | 0:07919e3d6c56 | 200 | void |
andrewbonney | 0:07919e3d6c56 | 201 | expatpp::endElementCallback(void *userData, const XML_Char* name) |
andrewbonney | 0:07919e3d6c56 | 202 | { |
andrewbonney | 0:07919e3d6c56 | 203 | ((expatpp*)userData)->endElement(name); |
andrewbonney | 0:07919e3d6c56 | 204 | } |
andrewbonney | 0:07919e3d6c56 | 205 | |
andrewbonney | 0:07919e3d6c56 | 206 | |
andrewbonney | 0:07919e3d6c56 | 207 | void |
andrewbonney | 0:07919e3d6c56 | 208 | expatpp::startNamespaceCallback(void *userData, const XML_Char* prefix, const XML_Char* uri) |
andrewbonney | 0:07919e3d6c56 | 209 | { |
andrewbonney | 0:07919e3d6c56 | 210 | ((expatpp*)userData)->startNamespace(prefix, uri); |
andrewbonney | 0:07919e3d6c56 | 211 | } |
andrewbonney | 0:07919e3d6c56 | 212 | |
andrewbonney | 0:07919e3d6c56 | 213 | |
andrewbonney | 0:07919e3d6c56 | 214 | void |
andrewbonney | 0:07919e3d6c56 | 215 | expatpp::endNamespaceCallback(void *userData, const XML_Char* prefix) |
andrewbonney | 0:07919e3d6c56 | 216 | { |
andrewbonney | 0:07919e3d6c56 | 217 | ((expatpp*)userData)->endNamespace(prefix); |
andrewbonney | 0:07919e3d6c56 | 218 | } |
andrewbonney | 0:07919e3d6c56 | 219 | |
andrewbonney | 0:07919e3d6c56 | 220 | |
andrewbonney | 0:07919e3d6c56 | 221 | void |
andrewbonney | 0:07919e3d6c56 | 222 | expatpp::charDataCallback(void *userData, const XML_Char* s, int len) |
andrewbonney | 0:07919e3d6c56 | 223 | { |
andrewbonney | 0:07919e3d6c56 | 224 | ((expatpp*)userData)->charData(s, len); |
andrewbonney | 0:07919e3d6c56 | 225 | } |
andrewbonney | 0:07919e3d6c56 | 226 | |
andrewbonney | 0:07919e3d6c56 | 227 | |
andrewbonney | 0:07919e3d6c56 | 228 | void |
andrewbonney | 0:07919e3d6c56 | 229 | expatpp:: processingInstructionCallback(void *userData, const XML_Char* target, const XML_Char* data) |
andrewbonney | 0:07919e3d6c56 | 230 | { |
andrewbonney | 0:07919e3d6c56 | 231 | ((expatpp*)userData)->processingInstruction(target, data); |
andrewbonney | 0:07919e3d6c56 | 232 | } |
andrewbonney | 0:07919e3d6c56 | 233 | |
andrewbonney | 0:07919e3d6c56 | 234 | |
andrewbonney | 0:07919e3d6c56 | 235 | void |
andrewbonney | 0:07919e3d6c56 | 236 | expatpp::defaultHandlerCallback(void* userData, const XML_Char* s, int len) |
andrewbonney | 0:07919e3d6c56 | 237 | { |
andrewbonney | 0:07919e3d6c56 | 238 | ((expatpp*)userData)->defaultHandler(s, len); |
andrewbonney | 0:07919e3d6c56 | 239 | } |
andrewbonney | 0:07919e3d6c56 | 240 | |
andrewbonney | 0:07919e3d6c56 | 241 | |
andrewbonney | 0:07919e3d6c56 | 242 | int |
andrewbonney | 0:07919e3d6c56 | 243 | expatpp::notStandaloneHandlerCallback(void* userData) |
andrewbonney | 0:07919e3d6c56 | 244 | { |
andrewbonney | 0:07919e3d6c56 | 245 | return ((expatpp*)userData)->notStandaloneHandler(); |
andrewbonney | 0:07919e3d6c56 | 246 | } |
andrewbonney | 0:07919e3d6c56 | 247 | |
andrewbonney | 0:07919e3d6c56 | 248 | |
andrewbonney | 0:07919e3d6c56 | 249 | void |
andrewbonney | 0:07919e3d6c56 | 250 | expatpp::unParsedEntityDeclCallback(void* userData, const XML_Char* entityName, const XML_Char* base, const XML_Char* systemId, const XML_Char* publicId, const XML_Char* notationName) |
andrewbonney | 0:07919e3d6c56 | 251 | { |
andrewbonney | 0:07919e3d6c56 | 252 | ((expatpp*)userData)->unparsedEntityDecl(entityName, base, systemId, publicId, notationName); |
andrewbonney | 0:07919e3d6c56 | 253 | } |
andrewbonney | 0:07919e3d6c56 | 254 | |
andrewbonney | 0:07919e3d6c56 | 255 | |
andrewbonney | 0:07919e3d6c56 | 256 | void |
andrewbonney | 0:07919e3d6c56 | 257 | expatpp::notationDeclCallback(void *userData, const XML_Char* notationName, const XML_Char* base, const XML_Char* systemId, const XML_Char* publicId) |
andrewbonney | 0:07919e3d6c56 | 258 | { |
andrewbonney | 0:07919e3d6c56 | 259 | ((expatpp*)userData)->notationDecl(notationName, base, systemId, publicId); |
andrewbonney | 0:07919e3d6c56 | 260 | } |
andrewbonney | 0:07919e3d6c56 | 261 | |
andrewbonney | 0:07919e3d6c56 | 262 | |
andrewbonney | 0:07919e3d6c56 | 263 | void |
andrewbonney | 0:07919e3d6c56 | 264 | expatpp::startElement(const XML_Char*, const XML_Char**) |
andrewbonney | 0:07919e3d6c56 | 265 | {} |
andrewbonney | 0:07919e3d6c56 | 266 | |
andrewbonney | 0:07919e3d6c56 | 267 | |
andrewbonney | 0:07919e3d6c56 | 268 | void |
andrewbonney | 0:07919e3d6c56 | 269 | expatpp::endElement(const XML_Char*) |
andrewbonney | 0:07919e3d6c56 | 270 | {} |
andrewbonney | 0:07919e3d6c56 | 271 | |
andrewbonney | 0:07919e3d6c56 | 272 | |
andrewbonney | 0:07919e3d6c56 | 273 | void |
andrewbonney | 0:07919e3d6c56 | 274 | expatpp::startNamespace(const XML_Char* /* prefix */, const XML_Char* /* uri */) |
andrewbonney | 0:07919e3d6c56 | 275 | {} |
andrewbonney | 0:07919e3d6c56 | 276 | |
andrewbonney | 0:07919e3d6c56 | 277 | |
andrewbonney | 0:07919e3d6c56 | 278 | void |
andrewbonney | 0:07919e3d6c56 | 279 | expatpp::endNamespace(const XML_Char*) |
andrewbonney | 0:07919e3d6c56 | 280 | {} |
andrewbonney | 0:07919e3d6c56 | 281 | |
andrewbonney | 0:07919e3d6c56 | 282 | |
andrewbonney | 0:07919e3d6c56 | 283 | void |
andrewbonney | 0:07919e3d6c56 | 284 | expatpp::charData(const XML_Char*, int ) |
andrewbonney | 0:07919e3d6c56 | 285 | { |
andrewbonney | 0:07919e3d6c56 | 286 | } |
andrewbonney | 0:07919e3d6c56 | 287 | |
andrewbonney | 0:07919e3d6c56 | 288 | |
andrewbonney | 0:07919e3d6c56 | 289 | void |
andrewbonney | 0:07919e3d6c56 | 290 | expatpp::processingInstruction(const XML_Char*, const XML_Char*) |
andrewbonney | 0:07919e3d6c56 | 291 | { |
andrewbonney | 0:07919e3d6c56 | 292 | } |
andrewbonney | 0:07919e3d6c56 | 293 | |
andrewbonney | 0:07919e3d6c56 | 294 | |
andrewbonney | 0:07919e3d6c56 | 295 | void |
andrewbonney | 0:07919e3d6c56 | 296 | expatpp::defaultHandler(const XML_Char*, int) |
andrewbonney | 0:07919e3d6c56 | 297 | { |
andrewbonney | 0:07919e3d6c56 | 298 | } |
andrewbonney | 0:07919e3d6c56 | 299 | |
andrewbonney | 0:07919e3d6c56 | 300 | |
andrewbonney | 0:07919e3d6c56 | 301 | int |
andrewbonney | 0:07919e3d6c56 | 302 | expatpp::notStandaloneHandler() |
andrewbonney | 0:07919e3d6c56 | 303 | { |
andrewbonney | 0:07919e3d6c56 | 304 | return 0; |
andrewbonney | 0:07919e3d6c56 | 305 | } |
andrewbonney | 0:07919e3d6c56 | 306 | |
andrewbonney | 0:07919e3d6c56 | 307 | |
andrewbonney | 0:07919e3d6c56 | 308 | void |
andrewbonney | 0:07919e3d6c56 | 309 | expatpp::unparsedEntityDecl(const XML_Char*, const XML_Char*, const XML_Char*, const XML_Char*, const XML_Char*) |
andrewbonney | 0:07919e3d6c56 | 310 | { |
andrewbonney | 0:07919e3d6c56 | 311 | } |
andrewbonney | 0:07919e3d6c56 | 312 | |
andrewbonney | 0:07919e3d6c56 | 313 | |
andrewbonney | 0:07919e3d6c56 | 314 | void |
andrewbonney | 0:07919e3d6c56 | 315 | expatpp::notationDecl(const XML_Char*, const XML_Char*, const XML_Char*, const XML_Char*) |
andrewbonney | 0:07919e3d6c56 | 316 | { |
andrewbonney | 0:07919e3d6c56 | 317 | } |
andrewbonney | 0:07919e3d6c56 | 318 | |
andrewbonney | 0:07919e3d6c56 | 319 | |
andrewbonney | 0:07919e3d6c56 | 320 | int |
andrewbonney | 0:07919e3d6c56 | 321 | expatpp::skipWhiteSpace(const XML_Char* startFrom) |
andrewbonney | 0:07919e3d6c56 | 322 | { |
andrewbonney | 0:07919e3d6c56 | 323 | // use our own XML definition of white space |
andrewbonney | 0:07919e3d6c56 | 324 | // TO DO - confirm this is correct! |
andrewbonney | 0:07919e3d6c56 | 325 | const XML_Char* s = startFrom; |
andrewbonney | 0:07919e3d6c56 | 326 | XML_Char c = *s; |
andrewbonney | 0:07919e3d6c56 | 327 | while ((c==' ') || (c=='\t') || (c=='\n') || (c=='\r')) { |
andrewbonney | 0:07919e3d6c56 | 328 | s++; |
andrewbonney | 0:07919e3d6c56 | 329 | c = *s; |
andrewbonney | 0:07919e3d6c56 | 330 | } |
andrewbonney | 0:07919e3d6c56 | 331 | const int numSkipped = s - startFrom; |
andrewbonney | 0:07919e3d6c56 | 332 | return numSkipped; |
andrewbonney | 0:07919e3d6c56 | 333 | } |
andrewbonney | 0:07919e3d6c56 | 334 | |
andrewbonney | 0:07919e3d6c56 | 335 | |
andrewbonney | 0:07919e3d6c56 | 336 | /** |
andrewbonney | 0:07919e3d6c56 | 337 | Iterate the paired attribute name/value until find a pair with matching name. |
andrewbonney | 0:07919e3d6c56 | 338 | \return pointer to the value or null if not found. |
andrewbonney | 0:07919e3d6c56 | 339 | */ |
andrewbonney | 0:07919e3d6c56 | 340 | const XML_Char* |
andrewbonney | 0:07919e3d6c56 | 341 | expatpp::getAttribute(const XML_Char* matchingName, const XML_Char** atts) |
andrewbonney | 0:07919e3d6c56 | 342 | { |
andrewbonney | 0:07919e3d6c56 | 343 | for (int i=0; atts[i]; i++) { |
andrewbonney | 0:07919e3d6c56 | 344 | const XML_Char* attributeName = atts[i++]; |
andrewbonney | 0:07919e3d6c56 | 345 | assert(attributeName); // shouldn't fail this because of loop test above |
andrewbonney | 0:07919e3d6c56 | 346 | if(tcscmp(attributeName, matchingName)==0) { |
andrewbonney | 0:07919e3d6c56 | 347 | return atts[i]; // if 2nd item was missing, this returns 0 safely indicating failure |
andrewbonney | 0:07919e3d6c56 | 348 | } |
andrewbonney | 0:07919e3d6c56 | 349 | } |
andrewbonney | 0:07919e3d6c56 | 350 | return 0; |
andrewbonney | 0:07919e3d6c56 | 351 | } |
andrewbonney | 0:07919e3d6c56 | 352 | |
andrewbonney | 0:07919e3d6c56 | 353 | |
andrewbonney | 0:07919e3d6c56 | 354 | /** |
andrewbonney | 0:07919e3d6c56 | 355 | \bug will always return 0 for PPC |
andrewbonney | 0:07919e3d6c56 | 356 | */ |
andrewbonney | 0:07919e3d6c56 | 357 | bool |
andrewbonney | 0:07919e3d6c56 | 358 | expatpp::getIntegerAttribute(const XML_Char *matchingName, const XML_Char **atts, int& outAtt) |
andrewbonney | 0:07919e3d6c56 | 359 | { |
andrewbonney | 0:07919e3d6c56 | 360 | const XML_Char* attStr = getAttribute(matchingName, atts); |
andrewbonney | 0:07919e3d6c56 | 361 | if (!attStr) |
andrewbonney | 0:07919e3d6c56 | 362 | return false; |
andrewbonney | 0:07919e3d6c56 | 363 | int i=0; |
andrewbonney | 0:07919e3d6c56 | 364 | #ifdef XML_UNICODE |
andrewbonney | 0:07919e3d6c56 | 365 | fail to compile because need this now |
andrewbonney | 0:07919e3d6c56 | 366 | #else |
andrewbonney | 0:07919e3d6c56 | 367 | sscanf(attStr, "%d", &i); |
andrewbonney | 0:07919e3d6c56 | 368 | #endif |
andrewbonney | 0:07919e3d6c56 | 369 | outAtt = i; |
andrewbonney | 0:07919e3d6c56 | 370 | return true; |
andrewbonney | 0:07919e3d6c56 | 371 | } |
andrewbonney | 0:07919e3d6c56 | 372 | |
andrewbonney | 0:07919e3d6c56 | 373 | |
andrewbonney | 0:07919e3d6c56 | 374 | /** |
andrewbonney | 0:07919e3d6c56 | 375 | \bug will always return 0 for PPC |
andrewbonney | 0:07919e3d6c56 | 376 | */ |
andrewbonney | 0:07919e3d6c56 | 377 | bool |
andrewbonney | 0:07919e3d6c56 | 378 | expatpp::getDoubleAttribute(const XML_Char *matchingName, const XML_Char **atts, double& outAtt) |
andrewbonney | 0:07919e3d6c56 | 379 | { |
andrewbonney | 0:07919e3d6c56 | 380 | const XML_Char* attStr = getAttribute(matchingName, atts); |
andrewbonney | 0:07919e3d6c56 | 381 | if (!attStr) |
andrewbonney | 0:07919e3d6c56 | 382 | return false; |
andrewbonney | 0:07919e3d6c56 | 383 | float f = 0.0; // sscanf doesn't allow point to double |
andrewbonney | 0:07919e3d6c56 | 384 | #ifdef XML_UNICODE |
andrewbonney | 0:07919e3d6c56 | 385 | fail to compile because need this now |
andrewbonney | 0:07919e3d6c56 | 386 | #else |
andrewbonney | 0:07919e3d6c56 | 387 | sscanf(attStr, "%f", &f); |
andrewbonney | 0:07919e3d6c56 | 388 | #endif |
andrewbonney | 0:07919e3d6c56 | 389 | outAtt = f; |
andrewbonney | 0:07919e3d6c56 | 390 | return true; |
andrewbonney | 0:07919e3d6c56 | 391 | } |
andrewbonney | 0:07919e3d6c56 | 392 | |
andrewbonney | 0:07919e3d6c56 | 393 | |
andrewbonney | 0:07919e3d6c56 | 394 | bool |
andrewbonney | 0:07919e3d6c56 | 395 | expatpp::emptyCharData(const XML_Char *s, int len) |
andrewbonney | 0:07919e3d6c56 | 396 | { |
andrewbonney | 0:07919e3d6c56 | 397 | // usually call from top of overriden charData methods |
andrewbonney | 0:07919e3d6c56 | 398 | if (len==0) |
andrewbonney | 0:07919e3d6c56 | 399 | return true; //*** early exit - empty string, may never occur?? |
andrewbonney | 0:07919e3d6c56 | 400 | |
andrewbonney | 0:07919e3d6c56 | 401 | // skip newline and empty whitespace |
andrewbonney | 0:07919e3d6c56 | 402 | if ( |
andrewbonney | 0:07919e3d6c56 | 403 | ((len==1) && ( (s[0]=='\n') || (s[0]=='\r')) ) || // just CR or just LF |
andrewbonney | 0:07919e3d6c56 | 404 | ((len==2) && (s[0]=='\r') && (s[1]=='\n')) // DOS-style CRLF |
andrewbonney | 0:07919e3d6c56 | 405 | ) |
andrewbonney | 0:07919e3d6c56 | 406 | return true; //*** early exit - newline |
andrewbonney | 0:07919e3d6c56 | 407 | |
andrewbonney | 0:07919e3d6c56 | 408 | const int lastCharAt = len-1; |
andrewbonney | 0:07919e3d6c56 | 409 | if (s[lastCharAt]==' ') { // maybe all whitespace |
andrewbonney | 0:07919e3d6c56 | 410 | int i; |
andrewbonney | 0:07919e3d6c56 | 411 | for (i=0; i<lastCharAt; i++) { |
andrewbonney | 0:07919e3d6c56 | 412 | if (s[i]!=' ') |
andrewbonney | 0:07919e3d6c56 | 413 | break; |
andrewbonney | 0:07919e3d6c56 | 414 | } |
andrewbonney | 0:07919e3d6c56 | 415 | if (i==lastCharAt) |
andrewbonney | 0:07919e3d6c56 | 416 | return true; //*** early exit - all spaces |
andrewbonney | 0:07919e3d6c56 | 417 | } |
andrewbonney | 0:07919e3d6c56 | 418 | return false; |
andrewbonney | 0:07919e3d6c56 | 419 | } |
andrewbonney | 0:07919e3d6c56 | 420 | |
andrewbonney | 0:07919e3d6c56 | 421 | |
andrewbonney | 0:07919e3d6c56 | 422 | //-------- Added for expat 1.95.5--------------- |
andrewbonney | 0:07919e3d6c56 | 423 | void |
andrewbonney | 0:07919e3d6c56 | 424 | expatpp::attlistDeclCallback(void *userData, |
andrewbonney | 0:07919e3d6c56 | 425 | const XML_Char *elname, |
andrewbonney | 0:07919e3d6c56 | 426 | const XML_Char *attname, |
andrewbonney | 0:07919e3d6c56 | 427 | const XML_Char *att_type, |
andrewbonney | 0:07919e3d6c56 | 428 | const XML_Char *dflt, |
andrewbonney | 0:07919e3d6c56 | 429 | int isrequired) |
andrewbonney | 0:07919e3d6c56 | 430 | { |
andrewbonney | 0:07919e3d6c56 | 431 | ((expatpp*)userData)->attlistDecl(elname, attname, att_type, dflt, isrequired); |
andrewbonney | 0:07919e3d6c56 | 432 | } |
andrewbonney | 0:07919e3d6c56 | 433 | |
andrewbonney | 0:07919e3d6c56 | 434 | |
andrewbonney | 0:07919e3d6c56 | 435 | void |
andrewbonney | 0:07919e3d6c56 | 436 | expatpp::commentCallback(void *userData, const XML_Char *data) |
andrewbonney | 0:07919e3d6c56 | 437 | { |
andrewbonney | 0:07919e3d6c56 | 438 | ((expatpp*)userData)->comment(data); |
andrewbonney | 0:07919e3d6c56 | 439 | } |
andrewbonney | 0:07919e3d6c56 | 440 | |
andrewbonney | 0:07919e3d6c56 | 441 | |
andrewbonney | 0:07919e3d6c56 | 442 | void |
andrewbonney | 0:07919e3d6c56 | 443 | expatpp::elementDeclCallback(void *userData, const XML_Char *name, XML_Content *model) |
andrewbonney | 0:07919e3d6c56 | 444 | { |
andrewbonney | 0:07919e3d6c56 | 445 | ((expatpp*)userData)->elementDecl(name, model); |
andrewbonney | 0:07919e3d6c56 | 446 | } |
andrewbonney | 0:07919e3d6c56 | 447 | |
andrewbonney | 0:07919e3d6c56 | 448 | |
andrewbonney | 0:07919e3d6c56 | 449 | void |
andrewbonney | 0:07919e3d6c56 | 450 | expatpp::endCdataSectionCallback(void *userData) |
andrewbonney | 0:07919e3d6c56 | 451 | { |
andrewbonney | 0:07919e3d6c56 | 452 | ((expatpp*)userData)->endCdataSection(); |
andrewbonney | 0:07919e3d6c56 | 453 | } |
andrewbonney | 0:07919e3d6c56 | 454 | |
andrewbonney | 0:07919e3d6c56 | 455 | |
andrewbonney | 0:07919e3d6c56 | 456 | void |
andrewbonney | 0:07919e3d6c56 | 457 | expatpp::endDoctypeDeclCallback(void *userData) |
andrewbonney | 0:07919e3d6c56 | 458 | { |
andrewbonney | 0:07919e3d6c56 | 459 | ((expatpp*)userData)->endDoctypeDecl(); |
andrewbonney | 0:07919e3d6c56 | 460 | } |
andrewbonney | 0:07919e3d6c56 | 461 | |
andrewbonney | 0:07919e3d6c56 | 462 | |
andrewbonney | 0:07919e3d6c56 | 463 | void |
andrewbonney | 0:07919e3d6c56 | 464 | expatpp::entityDeclCallback(void *userData, |
andrewbonney | 0:07919e3d6c56 | 465 | const XML_Char *entityName, |
andrewbonney | 0:07919e3d6c56 | 466 | int is_parameter_entity, |
andrewbonney | 0:07919e3d6c56 | 467 | const XML_Char *value, |
andrewbonney | 0:07919e3d6c56 | 468 | int value_length, |
andrewbonney | 0:07919e3d6c56 | 469 | const XML_Char *base, |
andrewbonney | 0:07919e3d6c56 | 470 | const XML_Char *systemId, |
andrewbonney | 0:07919e3d6c56 | 471 | const XML_Char *publicId, |
andrewbonney | 0:07919e3d6c56 | 472 | const XML_Char *notationName) |
andrewbonney | 0:07919e3d6c56 | 473 | { |
andrewbonney | 0:07919e3d6c56 | 474 | ((expatpp*)userData)->entityDecl(entityName, is_parameter_entity, value, value_length, base, systemId, publicId, notationName); |
andrewbonney | 0:07919e3d6c56 | 475 | } |
andrewbonney | 0:07919e3d6c56 | 476 | |
andrewbonney | 0:07919e3d6c56 | 477 | |
andrewbonney | 0:07919e3d6c56 | 478 | void |
andrewbonney | 0:07919e3d6c56 | 479 | expatpp::skippedEntityCallback(void *userData, const XML_Char *entityName, int is_parameter_entity) |
andrewbonney | 0:07919e3d6c56 | 480 | { |
andrewbonney | 0:07919e3d6c56 | 481 | ((expatpp*)userData)->skippedEntity(entityName, is_parameter_entity); |
andrewbonney | 0:07919e3d6c56 | 482 | } |
andrewbonney | 0:07919e3d6c56 | 483 | |
andrewbonney | 0:07919e3d6c56 | 484 | |
andrewbonney | 0:07919e3d6c56 | 485 | void |
andrewbonney | 0:07919e3d6c56 | 486 | expatpp::startCdataSectionCallback(void *userData) |
andrewbonney | 0:07919e3d6c56 | 487 | { |
andrewbonney | 0:07919e3d6c56 | 488 | ((expatpp*)userData)->startCdataSection(); |
andrewbonney | 0:07919e3d6c56 | 489 | } |
andrewbonney | 0:07919e3d6c56 | 490 | |
andrewbonney | 0:07919e3d6c56 | 491 | |
andrewbonney | 0:07919e3d6c56 | 492 | void |
andrewbonney | 0:07919e3d6c56 | 493 | expatpp::startDoctypeDeclCallback(void *userData, |
andrewbonney | 0:07919e3d6c56 | 494 | const XML_Char *doctypeName, |
andrewbonney | 0:07919e3d6c56 | 495 | const XML_Char *sysid, |
andrewbonney | 0:07919e3d6c56 | 496 | const XML_Char *pubid, |
andrewbonney | 0:07919e3d6c56 | 497 | int has_internal_subset) |
andrewbonney | 0:07919e3d6c56 | 498 | { |
andrewbonney | 0:07919e3d6c56 | 499 | ((expatpp*)userData)->startDoctypeDecl(doctypeName, sysid, pubid, has_internal_subset); |
andrewbonney | 0:07919e3d6c56 | 500 | } |
andrewbonney | 0:07919e3d6c56 | 501 | |
andrewbonney | 0:07919e3d6c56 | 502 | |
andrewbonney | 0:07919e3d6c56 | 503 | void |
andrewbonney | 0:07919e3d6c56 | 504 | expatpp::xmlDeclCallback(void *userData, const XML_Char *version, |
andrewbonney | 0:07919e3d6c56 | 505 | const XML_Char *encoding, |
andrewbonney | 0:07919e3d6c56 | 506 | int standalone) |
andrewbonney | 0:07919e3d6c56 | 507 | { |
andrewbonney | 0:07919e3d6c56 | 508 | ((expatpp*)userData)->xmlDecl(version, encoding, standalone); |
andrewbonney | 0:07919e3d6c56 | 509 | } |
andrewbonney | 0:07919e3d6c56 | 510 | |
andrewbonney | 0:07919e3d6c56 | 511 | |
andrewbonney | 0:07919e3d6c56 | 512 | void |
andrewbonney | 0:07919e3d6c56 | 513 | expatpp::attlistDecl( |
andrewbonney | 0:07919e3d6c56 | 514 | const XML_Char *elname, |
andrewbonney | 0:07919e3d6c56 | 515 | const XML_Char *attname, |
andrewbonney | 0:07919e3d6c56 | 516 | const XML_Char *att_type, |
andrewbonney | 0:07919e3d6c56 | 517 | const XML_Char *dflt, |
andrewbonney | 0:07919e3d6c56 | 518 | int isrequired) |
andrewbonney | 0:07919e3d6c56 | 519 | { |
andrewbonney | 0:07919e3d6c56 | 520 | } |
andrewbonney | 0:07919e3d6c56 | 521 | |
andrewbonney | 0:07919e3d6c56 | 522 | |
andrewbonney | 0:07919e3d6c56 | 523 | void |
andrewbonney | 0:07919e3d6c56 | 524 | expatpp::comment( const XML_Char *data) |
andrewbonney | 0:07919e3d6c56 | 525 | { |
andrewbonney | 0:07919e3d6c56 | 526 | } |
andrewbonney | 0:07919e3d6c56 | 527 | |
andrewbonney | 0:07919e3d6c56 | 528 | |
andrewbonney | 0:07919e3d6c56 | 529 | void |
andrewbonney | 0:07919e3d6c56 | 530 | expatpp::elementDecl( const XML_Char *name, XML_Content *model) |
andrewbonney | 0:07919e3d6c56 | 531 | { |
andrewbonney | 0:07919e3d6c56 | 532 | } |
andrewbonney | 0:07919e3d6c56 | 533 | |
andrewbonney | 0:07919e3d6c56 | 534 | |
andrewbonney | 0:07919e3d6c56 | 535 | void |
andrewbonney | 0:07919e3d6c56 | 536 | expatpp::endCdataSection() |
andrewbonney | 0:07919e3d6c56 | 537 | { |
andrewbonney | 0:07919e3d6c56 | 538 | } |
andrewbonney | 0:07919e3d6c56 | 539 | |
andrewbonney | 0:07919e3d6c56 | 540 | |
andrewbonney | 0:07919e3d6c56 | 541 | void |
andrewbonney | 0:07919e3d6c56 | 542 | expatpp::endDoctypeDecl() |
andrewbonney | 0:07919e3d6c56 | 543 | { |
andrewbonney | 0:07919e3d6c56 | 544 | } |
andrewbonney | 0:07919e3d6c56 | 545 | |
andrewbonney | 0:07919e3d6c56 | 546 | |
andrewbonney | 0:07919e3d6c56 | 547 | void |
andrewbonney | 0:07919e3d6c56 | 548 | expatpp::entityDecl( |
andrewbonney | 0:07919e3d6c56 | 549 | const XML_Char *entityName, |
andrewbonney | 0:07919e3d6c56 | 550 | int is_parameter_entity, |
andrewbonney | 0:07919e3d6c56 | 551 | const XML_Char *value, |
andrewbonney | 0:07919e3d6c56 | 552 | int value_length, |
andrewbonney | 0:07919e3d6c56 | 553 | const XML_Char *base, |
andrewbonney | 0:07919e3d6c56 | 554 | const XML_Char *systemId, |
andrewbonney | 0:07919e3d6c56 | 555 | const XML_Char *publicId, |
andrewbonney | 0:07919e3d6c56 | 556 | const XML_Char *notationName) |
andrewbonney | 0:07919e3d6c56 | 557 | { |
andrewbonney | 0:07919e3d6c56 | 558 | } |
andrewbonney | 0:07919e3d6c56 | 559 | |
andrewbonney | 0:07919e3d6c56 | 560 | |
andrewbonney | 0:07919e3d6c56 | 561 | void |
andrewbonney | 0:07919e3d6c56 | 562 | expatpp::skippedEntity( const XML_Char *entityName, int is_parameter_entity) |
andrewbonney | 0:07919e3d6c56 | 563 | { |
andrewbonney | 0:07919e3d6c56 | 564 | } |
andrewbonney | 0:07919e3d6c56 | 565 | |
andrewbonney | 0:07919e3d6c56 | 566 | |
andrewbonney | 0:07919e3d6c56 | 567 | void |
andrewbonney | 0:07919e3d6c56 | 568 | expatpp::startCdataSection() |
andrewbonney | 0:07919e3d6c56 | 569 | { |
andrewbonney | 0:07919e3d6c56 | 570 | } |
andrewbonney | 0:07919e3d6c56 | 571 | |
andrewbonney | 0:07919e3d6c56 | 572 | |
andrewbonney | 0:07919e3d6c56 | 573 | void |
andrewbonney | 0:07919e3d6c56 | 574 | expatpp::startDoctypeDecl(const XML_Char *doctypeName, |
andrewbonney | 0:07919e3d6c56 | 575 | const XML_Char *sysid, |
andrewbonney | 0:07919e3d6c56 | 576 | const XML_Char *pubid, |
andrewbonney | 0:07919e3d6c56 | 577 | int has_internal_subset) |
andrewbonney | 0:07919e3d6c56 | 578 | { |
andrewbonney | 0:07919e3d6c56 | 579 | } |
andrewbonney | 0:07919e3d6c56 | 580 | |
andrewbonney | 0:07919e3d6c56 | 581 | |
andrewbonney | 0:07919e3d6c56 | 582 | void |
andrewbonney | 0:07919e3d6c56 | 583 | expatpp::xmlDecl( const XML_Char *version, |
andrewbonney | 0:07919e3d6c56 | 584 | const XML_Char *encoding, |
andrewbonney | 0:07919e3d6c56 | 585 | int standalone) |
andrewbonney | 0:07919e3d6c56 | 586 | { |
andrewbonney | 0:07919e3d6c56 | 587 | } |
andrewbonney | 0:07919e3d6c56 | 588 | |
andrewbonney | 0:07919e3d6c56 | 589 | |
andrewbonney | 0:07919e3d6c56 | 590 | |
andrewbonney | 0:07919e3d6c56 | 591 | |
andrewbonney | 0:07919e3d6c56 | 592 | // ------------------------------------------------------- |
andrewbonney | 0:07919e3d6c56 | 593 | // e x p a t p p N e s t i n g |
andrewbonney | 0:07919e3d6c56 | 594 | // ------------------------------------------------------- |
andrewbonney | 0:07919e3d6c56 | 595 | /** |
andrewbonney | 0:07919e3d6c56 | 596 | \param parent can be null in which case this is root parser |
andrewbonney | 0:07919e3d6c56 | 597 | |
andrewbonney | 0:07919e3d6c56 | 598 | \note The handlers set in here MUST be also set in SetupHandlers |
andrewbonney | 0:07919e3d6c56 | 599 | which is a virtual method invoked by expatpp::ResetParser. Otherwise |
andrewbonney | 0:07919e3d6c56 | 600 | you can have subtle bugs with a nested parser not properly returning |
andrewbonney | 0:07919e3d6c56 | 601 | after reusing a parser (nasty and found rapidly only via extensive unit |
andrewbonney | 0:07919e3d6c56 | 602 | tests and plentiful assertions!). |
andrewbonney | 0:07919e3d6c56 | 603 | |
andrewbonney | 0:07919e3d6c56 | 604 | \WARNING |
andrewbonney | 0:07919e3d6c56 | 605 | The assumption that is not obvious here is that if you want to use |
andrewbonney | 0:07919e3d6c56 | 606 | nested parsers, then your topmost parser must also be an expatppNesting |
andrewbonney | 0:07919e3d6c56 | 607 | subclass, NOT an expatpp subclass, because we need the |
andrewbonney | 0:07919e3d6c56 | 608 | nestedStartElementCallback and nestedEndElementCallback |
andrewbonney | 0:07919e3d6c56 | 609 | callbacks to override those in the expatpp ctor. |
andrewbonney | 0:07919e3d6c56 | 610 | |
andrewbonney | 0:07919e3d6c56 | 611 | |
andrewbonney | 0:07919e3d6c56 | 612 | |
andrewbonney | 0:07919e3d6c56 | 613 | \todo go back over code in detail and confirm above warning still valid |
andrewbonney | 0:07919e3d6c56 | 614 | I think if we used expat's functions to invoke the registered callback |
andrewbonney | 0:07919e3d6c56 | 615 | might be safer - the explicit function call we have in nestedEndElementCallback |
andrewbonney | 0:07919e3d6c56 | 616 | certainly assumes the parent type. |
andrewbonney | 0:07919e3d6c56 | 617 | */ |
andrewbonney | 0:07919e3d6c56 | 618 | expatppNesting::expatppNesting(expatppNesting* parent) : |
andrewbonney | 0:07919e3d6c56 | 619 | expatpp(parent==0), // don't create parser - we're taking over from parent if given |
andrewbonney | 0:07919e3d6c56 | 620 | mDepth(0), |
andrewbonney | 0:07919e3d6c56 | 621 | mParent(parent), |
andrewbonney | 0:07919e3d6c56 | 622 | mOwnedChild(0), |
andrewbonney | 0:07919e3d6c56 | 623 | mSelfDeleting(true) |
andrewbonney | 0:07919e3d6c56 | 624 | { |
andrewbonney | 0:07919e3d6c56 | 625 | if ( parent ) |
andrewbonney | 0:07919e3d6c56 | 626 | { |
andrewbonney | 0:07919e3d6c56 | 627 | RegisterWithParentXMLParser(); |
andrewbonney | 0:07919e3d6c56 | 628 | parent->AdoptChild(this); |
andrewbonney | 0:07919e3d6c56 | 629 | } |
andrewbonney | 0:07919e3d6c56 | 630 | else |
andrewbonney | 0:07919e3d6c56 | 631 | { |
andrewbonney | 0:07919e3d6c56 | 632 | // No parent - the expatpp constructor will have created a new mParser (expat parser) |
andrewbonney | 0:07919e3d6c56 | 633 | ::XML_SetElementHandler(mParser, nestedStartElementCallback, nestedEndElementCallback); |
andrewbonney | 0:07919e3d6c56 | 634 | } |
andrewbonney | 0:07919e3d6c56 | 635 | assert(mParser); // either we created above or expatpp |
andrewbonney | 0:07919e3d6c56 | 636 | } |
andrewbonney | 0:07919e3d6c56 | 637 | |
andrewbonney | 0:07919e3d6c56 | 638 | |
andrewbonney | 0:07919e3d6c56 | 639 | expatppNesting::~expatppNesting() |
andrewbonney | 0:07919e3d6c56 | 640 | { |
andrewbonney | 0:07919e3d6c56 | 641 | assert(!mParent); // if we are a sub-parser, should not delete without calling returnToParent |
andrewbonney | 0:07919e3d6c56 | 642 | DeleteChild(); |
andrewbonney | 0:07919e3d6c56 | 643 | } |
andrewbonney | 0:07919e3d6c56 | 644 | |
andrewbonney | 0:07919e3d6c56 | 645 | |
andrewbonney | 0:07919e3d6c56 | 646 | /** |
andrewbonney | 0:07919e3d6c56 | 647 | Call parent version then override same as in our ctor. |
andrewbonney | 0:07919e3d6c56 | 648 | */ |
andrewbonney | 0:07919e3d6c56 | 649 | void |
andrewbonney | 0:07919e3d6c56 | 650 | expatppNesting::SetupHandlers() |
andrewbonney | 0:07919e3d6c56 | 651 | { |
andrewbonney | 0:07919e3d6c56 | 652 | expatpp::SetupHandlers(); |
andrewbonney | 0:07919e3d6c56 | 653 | ::XML_SetElementHandler(mParser, nestedStartElementCallback, nestedEndElementCallback); |
andrewbonney | 0:07919e3d6c56 | 654 | } |
andrewbonney | 0:07919e3d6c56 | 655 | |
andrewbonney | 0:07919e3d6c56 | 656 | /** |
andrewbonney | 0:07919e3d6c56 | 657 | Must use if you have adopted a child parser and want to dispose of it early. |
andrewbonney | 0:07919e3d6c56 | 658 | */ |
andrewbonney | 0:07919e3d6c56 | 659 | void |
andrewbonney | 0:07919e3d6c56 | 660 | expatppNesting::DeleteChild() |
andrewbonney | 0:07919e3d6c56 | 661 | { |
andrewbonney | 0:07919e3d6c56 | 662 | delete mOwnedChild; |
andrewbonney | 0:07919e3d6c56 | 663 | mOwnedChild = 0; |
andrewbonney | 0:07919e3d6c56 | 664 | } |
andrewbonney | 0:07919e3d6c56 | 665 | |
andrewbonney | 0:07919e3d6c56 | 666 | |
andrewbonney | 0:07919e3d6c56 | 667 | /** |
andrewbonney | 0:07919e3d6c56 | 668 | Invoked as a callback from a child ctor when we pass in a parent pointer. |
andrewbonney | 0:07919e3d6c56 | 669 | OR used from switchToNewSubParser, in which case it may be the 2nd time |
andrewbonney | 0:07919e3d6c56 | 670 | we're called for a given child (see scenarios in expatppNesting class comment). |
andrewbonney | 0:07919e3d6c56 | 671 | */ |
andrewbonney | 0:07919e3d6c56 | 672 | void |
andrewbonney | 0:07919e3d6c56 | 673 | expatppNesting::AdoptChild(expatppNesting* adoptingChild) |
andrewbonney | 0:07919e3d6c56 | 674 | { |
andrewbonney | 0:07919e3d6c56 | 675 | if ( mOwnedChild != adoptingChild ) |
andrewbonney | 0:07919e3d6c56 | 676 | { |
andrewbonney | 0:07919e3d6c56 | 677 | delete mOwnedChild; |
andrewbonney | 0:07919e3d6c56 | 678 | mOwnedChild = adoptingChild; |
andrewbonney | 0:07919e3d6c56 | 679 | } |
andrewbonney | 0:07919e3d6c56 | 680 | } |
andrewbonney | 0:07919e3d6c56 | 681 | |
andrewbonney | 0:07919e3d6c56 | 682 | |
andrewbonney | 0:07919e3d6c56 | 683 | /** |
andrewbonney | 0:07919e3d6c56 | 684 | to use parent's underlying expat parser |
andrewbonney | 0:07919e3d6c56 | 685 | */ |
andrewbonney | 0:07919e3d6c56 | 686 | void |
andrewbonney | 0:07919e3d6c56 | 687 | expatppNesting::RegisterWithParentXMLParser() |
andrewbonney | 0:07919e3d6c56 | 688 | { |
andrewbonney | 0:07919e3d6c56 | 689 | mParser = mParent->mParser; |
andrewbonney | 0:07919e3d6c56 | 690 | ::XML_SetUserData(mParser, this); |
andrewbonney | 0:07919e3d6c56 | 691 | } |
andrewbonney | 0:07919e3d6c56 | 692 | |
andrewbonney | 0:07919e3d6c56 | 693 | |
andrewbonney | 0:07919e3d6c56 | 694 | /** |
andrewbonney | 0:07919e3d6c56 | 695 | User code (typically the startElement handler of user parsers derived from expatppNesting) |
andrewbonney | 0:07919e3d6c56 | 696 | may call |
andrewbonney | 0:07919e3d6c56 | 697 | switchToNewSubParser( new UserChildParser() ); |
andrewbonney | 0:07919e3d6c56 | 698 | to hand off the current document to a child parser that understands the next segment of XML. |
andrewbonney | 0:07919e3d6c56 | 699 | Control will be returned to the original (parent) parser when the end of the child element |
andrewbonney | 0:07919e3d6c56 | 700 | is reached. |
andrewbonney | 0:07919e3d6c56 | 701 | In its lifetime a 'parent' parser may switch control to several child parsers (one at a time |
andrewbonney | 0:07919e3d6c56 | 702 | of course) as it moves through the document encoutering various types of child element. |
andrewbonney | 0:07919e3d6c56 | 703 | |
andrewbonney | 0:07919e3d6c56 | 704 | A child to which older code (eg: OOFILE) has just switched control by |
andrewbonney | 0:07919e3d6c56 | 705 | new childParser(this) will be self-deleting and will clear our mOwnedChild in its dtor. |
andrewbonney | 0:07919e3d6c56 | 706 | */ |
andrewbonney | 0:07919e3d6c56 | 707 | void expatppNesting::switchToNewSubParser( expatppNesting* pAdoptedChild ) |
andrewbonney | 0:07919e3d6c56 | 708 | { |
andrewbonney | 0:07919e3d6c56 | 709 | assert(pAdoptedChild); |
andrewbonney | 0:07919e3d6c56 | 710 | AdoptChild(pAdoptedChild); |
andrewbonney | 0:07919e3d6c56 | 711 | pAdoptedChild->BeAdopted(this); |
andrewbonney | 0:07919e3d6c56 | 712 | } |
andrewbonney | 0:07919e3d6c56 | 713 | |
andrewbonney | 0:07919e3d6c56 | 714 | |
andrewbonney | 0:07919e3d6c56 | 715 | /** |
andrewbonney | 0:07919e3d6c56 | 716 | If this is root parser, nestedEndElementCallback won't call returnToParent. |
andrewbonney | 0:07919e3d6c56 | 717 | Therefore it is safe to put parsers on the stack. |
andrewbonney | 0:07919e3d6c56 | 718 | */ |
andrewbonney | 0:07919e3d6c56 | 719 | expatppNesting* |
andrewbonney | 0:07919e3d6c56 | 720 | expatppNesting::returnToParent() |
andrewbonney | 0:07919e3d6c56 | 721 | { |
andrewbonney | 0:07919e3d6c56 | 722 | expatppNesting* ret = mParent; |
andrewbonney | 0:07919e3d6c56 | 723 | ::XML_SetUserData(mParser, mParent); |
andrewbonney | 0:07919e3d6c56 | 724 | mParent=0; |
andrewbonney | 0:07919e3d6c56 | 725 | mParser=0; // prevent parser shutdown by expatpp::~expatpp!! |
andrewbonney | 0:07919e3d6c56 | 726 | if (mSelfDeleting) { |
andrewbonney | 0:07919e3d6c56 | 727 | ret->OwnedChildOrphansItself(this); |
andrewbonney | 0:07919e3d6c56 | 728 | delete this; // MUST BE LAST THING CALLED IN NON-VIRTUAL FUNCTION, NO MEMBER ACCESS |
andrewbonney | 0:07919e3d6c56 | 729 | } |
andrewbonney | 0:07919e3d6c56 | 730 | return ret; |
andrewbonney | 0:07919e3d6c56 | 731 | } |
andrewbonney | 0:07919e3d6c56 | 732 | |
andrewbonney | 0:07919e3d6c56 | 733 | |
andrewbonney | 0:07919e3d6c56 | 734 | void |
andrewbonney | 0:07919e3d6c56 | 735 | expatppNesting::nestedStartElementCallback(void *userData, const XML_Char* name, const XML_Char** atts) |
andrewbonney | 0:07919e3d6c56 | 736 | { |
andrewbonney | 0:07919e3d6c56 | 737 | assert(userData); |
andrewbonney | 0:07919e3d6c56 | 738 | expatppNesting* nestedParser = (expatppNesting*)userData; |
andrewbonney | 0:07919e3d6c56 | 739 | nestedParser->mDepth++; |
andrewbonney | 0:07919e3d6c56 | 740 | nestedParser->startElement(name, atts); // probably user override |
andrewbonney | 0:07919e3d6c56 | 741 | } |
andrewbonney | 0:07919e3d6c56 | 742 | |
andrewbonney | 0:07919e3d6c56 | 743 | |
andrewbonney | 0:07919e3d6c56 | 744 | /** |
andrewbonney | 0:07919e3d6c56 | 745 | If this is root parser, will never hit nestedEndElementCallback after closing element, |
andrewbonney | 0:07919e3d6c56 | 746 | except for when we call it. |
andrewbonney | 0:07919e3d6c56 | 747 | \param userData should be non-nil except for specific case of ending root |
andrewbonney | 0:07919e3d6c56 | 748 | */ |
andrewbonney | 0:07919e3d6c56 | 749 | void |
andrewbonney | 0:07919e3d6c56 | 750 | expatppNesting::nestedEndElementCallback(void *userData, const XML_Char* name) |
andrewbonney | 0:07919e3d6c56 | 751 | { |
andrewbonney | 0:07919e3d6c56 | 752 | if (!userData) |
andrewbonney | 0:07919e3d6c56 | 753 | return; // end tag for root |
andrewbonney | 0:07919e3d6c56 | 754 | |
andrewbonney | 0:07919e3d6c56 | 755 | expatppNesting* nestedParser = (expatppNesting*)userData; |
andrewbonney | 0:07919e3d6c56 | 756 | // we don't know until we hit a closing tag 'outside' us that our run is done |
andrewbonney | 0:07919e3d6c56 | 757 | if (nestedParser->mDepth==0) { |
andrewbonney | 0:07919e3d6c56 | 758 | expatppNesting* parentParser = nestedParser->returnToParent(); |
andrewbonney | 0:07919e3d6c56 | 759 | nestedEndElementCallback(parentParser, name); // callbacks for expatppNesting stay registered, so safe |
andrewbonney | 0:07919e3d6c56 | 760 | //if we don't invoke their callback, they will not balance their mDepth |
andrewbonney | 0:07919e3d6c56 | 761 | } |
andrewbonney | 0:07919e3d6c56 | 762 | else { |
andrewbonney | 0:07919e3d6c56 | 763 | // end of an element this parser has started - normal case |
andrewbonney | 0:07919e3d6c56 | 764 | nestedParser->endElement(name); // probably user override |
andrewbonney | 0:07919e3d6c56 | 765 | nestedParser->mDepth--; |
andrewbonney | 0:07919e3d6c56 | 766 | } |
andrewbonney | 0:07919e3d6c56 | 767 | } |
andrewbonney | 0:07919e3d6c56 | 768 | |
andrewbonney | 0:07919e3d6c56 | 769 | |
andrewbonney | 0:07919e3d6c56 | 770 | /** |
andrewbonney | 0:07919e3d6c56 | 771 | Called by switchToNewSubParser to indicate a newly created child parser |
andrewbonney | 0:07919e3d6c56 | 772 | is now the currently active child for adoptingParent and the child |
andrewbonney | 0:07919e3d6c56 | 773 | isn't expected to be self deleting. |
andrewbonney | 0:07919e3d6c56 | 774 | |
andrewbonney | 0:07919e3d6c56 | 775 | Normal code to create an owned child would be either |
andrewbonney | 0:07919e3d6c56 | 776 | switchToNewSubParser( new UserChildParser(this) ); |
andrewbonney | 0:07919e3d6c56 | 777 | where this is the currently active parser and you want to be deleting it, or |
andrewbonney | 0:07919e3d6c56 | 778 | new UserChildParser(this); |
andrewbonney | 0:07919e3d6c56 | 779 | to have a child parser self-delete |
andrewbonney | 0:07919e3d6c56 | 780 | |
andrewbonney | 0:07919e3d6c56 | 781 | \par Important Safety Note |
andrewbonney | 0:07919e3d6c56 | 782 | Copes with the situation of people forgetting to pass |
andrewbonney | 0:07919e3d6c56 | 783 | in the parent parser (and hence creating a new one by default) |
andrewbonney | 0:07919e3d6c56 | 784 | if invoked by switchToNewSubParser( new UserChildParser() ) |
andrewbonney | 0:07919e3d6c56 | 785 | by somewhat wastefully deleting the parser created in expatpp::expatpp |
andrewbonney | 0:07919e3d6c56 | 786 | by us being a root parser. |
andrewbonney | 0:07919e3d6c56 | 787 | */ |
andrewbonney | 0:07919e3d6c56 | 788 | void |
andrewbonney | 0:07919e3d6c56 | 789 | expatppNesting::BeAdopted(expatppNesting* adoptingParent) |
andrewbonney | 0:07919e3d6c56 | 790 | { |
andrewbonney | 0:07919e3d6c56 | 791 | if (mParent) { |
andrewbonney | 0:07919e3d6c56 | 792 | assert(mParent==adoptingParent); |
andrewbonney | 0:07919e3d6c56 | 793 | } |
andrewbonney | 0:07919e3d6c56 | 794 | else { // root parser being adopted, cleanup! |
andrewbonney | 0:07919e3d6c56 | 795 | ReleaseParser(); |
andrewbonney | 0:07919e3d6c56 | 796 | mParent = adoptingParent; |
andrewbonney | 0:07919e3d6c56 | 797 | RegisterWithParentXMLParser(); |
andrewbonney | 0:07919e3d6c56 | 798 | } |
andrewbonney | 0:07919e3d6c56 | 799 | mSelfDeleting = false; |
andrewbonney | 0:07919e3d6c56 | 800 | } |
andrewbonney | 0:07919e3d6c56 | 801 | |
andrewbonney | 0:07919e3d6c56 | 802 | |
andrewbonney | 0:07919e3d6c56 | 803 | |
andrewbonney | 0:07919e3d6c56 | 804 |