This demo contains a port of the FastXML library. FastXML was hosted on geocities and is offline now. The library itself is contained into two files header and cpp and very easy to use. I don't know how many RAM it eats up but XML is probably not the best thing to use on an microcontroler. Decide your self but be warned. I told you so!!

Dependencies:   mbed

Committer:
rolf
Date:
Fri Dec 11 15:32:41 2009 +0000
Revision:
0:37e8c5cd04e8

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rolf 0:37e8c5cd04e8 1 #include <stdio.h>
rolf 0:37e8c5cd04e8 2 #include <stdlib.h>
rolf 0:37e8c5cd04e8 3 #include <string.h>
rolf 0:37e8c5cd04e8 4 #include <assert.h>
rolf 0:37e8c5cd04e8 5
rolf 0:37e8c5cd04e8 6 #include "fastxml.h"
rolf 0:37e8c5cd04e8 7
rolf 0:37e8c5cd04e8 8 /*!
rolf 0:37e8c5cd04e8 9 **
rolf 0:37e8c5cd04e8 10 ** Copyright (c) 2009 by John W. Ratcliff mailto:jratcliffscarab@gmail.com
rolf 0:37e8c5cd04e8 11 **
rolf 0:37e8c5cd04e8 12 ** The MIT license:
rolf 0:37e8c5cd04e8 13 **
rolf 0:37e8c5cd04e8 14 ** Permission is hereby granted, MEMALLOC_FREE of charge, to any person obtaining a copy
rolf 0:37e8c5cd04e8 15 ** of this software and associated documentation files (the "Software"), to deal
rolf 0:37e8c5cd04e8 16 ** in the Software without restriction, including without limitation the rights
rolf 0:37e8c5cd04e8 17 ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
rolf 0:37e8c5cd04e8 18 ** copies of the Software, and to permit persons to whom the Software is furnished
rolf 0:37e8c5cd04e8 19 ** to do so, subject to the following conditions:
rolf 0:37e8c5cd04e8 20 **
rolf 0:37e8c5cd04e8 21 ** The above copyright notice and this permission notice shall be included in all
rolf 0:37e8c5cd04e8 22 ** copies or substantial portions of the Software.
rolf 0:37e8c5cd04e8 23
rolf 0:37e8c5cd04e8 24 ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
rolf 0:37e8c5cd04e8 25 ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
rolf 0:37e8c5cd04e8 26 ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
rolf 0:37e8c5cd04e8 27 ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
rolf 0:37e8c5cd04e8 28 ** WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
rolf 0:37e8c5cd04e8 29 ** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
rolf 0:37e8c5cd04e8 30
rolf 0:37e8c5cd04e8 31 */
rolf 0:37e8c5cd04e8 32
rolf 0:37e8c5cd04e8 33
rolf 0:37e8c5cd04e8 34 class MyFastXml : public FastXml {
rolf 0:37e8c5cd04e8 35 public:
rolf 0:37e8c5cd04e8 36 enum CharType {
rolf 0:37e8c5cd04e8 37 CT_DATA,
rolf 0:37e8c5cd04e8 38 CT_EOF,
rolf 0:37e8c5cd04e8 39 CT_SOFT,
rolf 0:37e8c5cd04e8 40 CT_END_OF_ELEMENT, // either a forward slash or a greater than symbol
rolf 0:37e8c5cd04e8 41 CT_END_OF_LINE,
rolf 0:37e8c5cd04e8 42 };
rolf 0:37e8c5cd04e8 43
rolf 0:37e8c5cd04e8 44 MyFastXml(void) {
rolf 0:37e8c5cd04e8 45 mInputData = 0;
rolf 0:37e8c5cd04e8 46 memset(mTypes,CT_DATA,256);
rolf 0:37e8c5cd04e8 47 mTypes[0] = CT_EOF;
rolf 0:37e8c5cd04e8 48 mTypes[32] = CT_SOFT;
rolf 0:37e8c5cd04e8 49 mTypes[9] = CT_SOFT;
rolf 0:37e8c5cd04e8 50 mTypes['/'] = CT_END_OF_ELEMENT;
rolf 0:37e8c5cd04e8 51 mTypes['>'] = CT_END_OF_ELEMENT;
rolf 0:37e8c5cd04e8 52 mTypes['?'] = CT_END_OF_ELEMENT;
rolf 0:37e8c5cd04e8 53 mTypes[10] = CT_END_OF_LINE;
rolf 0:37e8c5cd04e8 54 mTypes[13] = CT_END_OF_LINE;
rolf 0:37e8c5cd04e8 55 mError = 0;
rolf 0:37e8c5cd04e8 56 }
rolf 0:37e8c5cd04e8 57 ~MyFastXml(void) {
rolf 0:37e8c5cd04e8 58 release();
rolf 0:37e8c5cd04e8 59 }
rolf 0:37e8c5cd04e8 60
rolf 0:37e8c5cd04e8 61 void release(void) {
rolf 0:37e8c5cd04e8 62 if(mInputData) {
rolf 0:37e8c5cd04e8 63 free(mInputData);
rolf 0:37e8c5cd04e8 64 mInputData = 0;
rolf 0:37e8c5cd04e8 65 }
rolf 0:37e8c5cd04e8 66 mError = 0;
rolf 0:37e8c5cd04e8 67 }
rolf 0:37e8c5cd04e8 68
rolf 0:37e8c5cd04e8 69 inline char *nextSoft(char *scan) {
rolf 0:37e8c5cd04e8 70 while ( *scan && mTypes[*scan] != CT_SOFT ) scan++;
rolf 0:37e8c5cd04e8 71 return scan;
rolf 0:37e8c5cd04e8 72 }
rolf 0:37e8c5cd04e8 73
rolf 0:37e8c5cd04e8 74 inline char *nextSoftOrClose(char *scan,bool &close) {
rolf 0:37e8c5cd04e8 75 while ( *scan && mTypes[*scan] != CT_SOFT && *scan != '>' ) scan++;
rolf 0:37e8c5cd04e8 76 close = *scan == '>';
rolf 0:37e8c5cd04e8 77 return scan;
rolf 0:37e8c5cd04e8 78 }
rolf 0:37e8c5cd04e8 79
rolf 0:37e8c5cd04e8 80 inline char *nextSep(char *scan) {
rolf 0:37e8c5cd04e8 81 while ( *scan && mTypes[*scan] != CT_SOFT && *scan != '=' ) scan++;
rolf 0:37e8c5cd04e8 82 return scan;
rolf 0:37e8c5cd04e8 83 }
rolf 0:37e8c5cd04e8 84
rolf 0:37e8c5cd04e8 85 inline char * skipNextData(char *scan) {
rolf 0:37e8c5cd04e8 86 // while we have data, and we encounter soft seperators or line feeds...
rolf 0:37e8c5cd04e8 87 while ( *scan && mTypes[*scan] == CT_SOFT || mTypes[*scan] == CT_END_OF_LINE ) {
rolf 0:37e8c5cd04e8 88 if ( *scan == 13 ) mLineNo++;
rolf 0:37e8c5cd04e8 89 scan++;
rolf 0:37e8c5cd04e8 90 }
rolf 0:37e8c5cd04e8 91 return scan;
rolf 0:37e8c5cd04e8 92 }
rolf 0:37e8c5cd04e8 93
rolf 0:37e8c5cd04e8 94 char * processClose(char c,const char *element,char *scan,int argc,const char **argv,FastXmlInterface *iface) {
rolf 0:37e8c5cd04e8 95 if ( c == '/' || c == '?' ) {
rolf 0:37e8c5cd04e8 96 if ( *scan != '>' ) { // unexepected character!
rolf 0:37e8c5cd04e8 97 mError = "Expected an element close character immediately after the '/' or '?' character.";
rolf 0:37e8c5cd04e8 98 return 0;
rolf 0:37e8c5cd04e8 99 }
rolf 0:37e8c5cd04e8 100 scan++;
rolf 0:37e8c5cd04e8 101 bool ok = iface->processElement(element,argc,argv,0,mLineNo);
rolf 0:37e8c5cd04e8 102 if ( !ok )
rolf 0:37e8c5cd04e8 103 {
rolf 0:37e8c5cd04e8 104 mError = "User aborted the parsing process";
rolf 0:37e8c5cd04e8 105 return 0;
rolf 0:37e8c5cd04e8 106 }
rolf 0:37e8c5cd04e8 107 }
rolf 0:37e8c5cd04e8 108 else
rolf 0:37e8c5cd04e8 109 {
rolf 0:37e8c5cd04e8 110 scan = skipNextData(scan);
rolf 0:37e8c5cd04e8 111 char *data = scan; // this is the data portion of the element, only copies memory if we encounter line feeds
rolf 0:37e8c5cd04e8 112 char *dest_data = 0;
rolf 0:37e8c5cd04e8 113 while ( *scan && *scan != '<' )
rolf 0:37e8c5cd04e8 114 {
rolf 0:37e8c5cd04e8 115 if ( mTypes[*scan] == CT_END_OF_LINE )
rolf 0:37e8c5cd04e8 116 {
rolf 0:37e8c5cd04e8 117 if ( *scan == 13 ) mLineNo++;
rolf 0:37e8c5cd04e8 118 dest_data = scan;
rolf 0:37e8c5cd04e8 119 *dest_data++ = 32; // replace the linefeed with a space...
rolf 0:37e8c5cd04e8 120 scan = skipNextData(scan);
rolf 0:37e8c5cd04e8 121 while ( *scan && *scan != '<' )
rolf 0:37e8c5cd04e8 122 {
rolf 0:37e8c5cd04e8 123 if ( mTypes[*scan] == CT_END_OF_LINE )
rolf 0:37e8c5cd04e8 124 {
rolf 0:37e8c5cd04e8 125 if ( *scan == 13 ) mLineNo++;
rolf 0:37e8c5cd04e8 126 *dest_data++ = 32; // replace the linefeed with a space...
rolf 0:37e8c5cd04e8 127 scan = skipNextData(scan);
rolf 0:37e8c5cd04e8 128 }
rolf 0:37e8c5cd04e8 129 else
rolf 0:37e8c5cd04e8 130 {
rolf 0:37e8c5cd04e8 131 *dest_data++ = *scan++;
rolf 0:37e8c5cd04e8 132 }
rolf 0:37e8c5cd04e8 133 }
rolf 0:37e8c5cd04e8 134 break;
rolf 0:37e8c5cd04e8 135 }
rolf 0:37e8c5cd04e8 136 else
rolf 0:37e8c5cd04e8 137 scan++;
rolf 0:37e8c5cd04e8 138 }
rolf 0:37e8c5cd04e8 139 if ( *scan == '<' )
rolf 0:37e8c5cd04e8 140 {
rolf 0:37e8c5cd04e8 141 if ( dest_data )
rolf 0:37e8c5cd04e8 142 {
rolf 0:37e8c5cd04e8 143 *dest_data = 0;
rolf 0:37e8c5cd04e8 144 }
rolf 0:37e8c5cd04e8 145 else
rolf 0:37e8c5cd04e8 146 {
rolf 0:37e8c5cd04e8 147 *scan = 0;
rolf 0:37e8c5cd04e8 148 }
rolf 0:37e8c5cd04e8 149 scan++; // skip it..
rolf 0:37e8c5cd04e8 150 if ( *data == 0 ) data = 0;
rolf 0:37e8c5cd04e8 151 bool ok = iface->processElement(element,argc,argv,data,mLineNo);
rolf 0:37e8c5cd04e8 152 if ( !ok )
rolf 0:37e8c5cd04e8 153 {
rolf 0:37e8c5cd04e8 154 mError = "User aborted the parsing process";
rolf 0:37e8c5cd04e8 155 return 0;
rolf 0:37e8c5cd04e8 156 }
rolf 0:37e8c5cd04e8 157 if ( *scan == '/' )
rolf 0:37e8c5cd04e8 158 {
rolf 0:37e8c5cd04e8 159 while ( *scan && *scan != '>' ) scan++;
rolf 0:37e8c5cd04e8 160 scan++;
rolf 0:37e8c5cd04e8 161 }
rolf 0:37e8c5cd04e8 162 }
rolf 0:37e8c5cd04e8 163 else
rolf 0:37e8c5cd04e8 164 {
rolf 0:37e8c5cd04e8 165 mError = "Data portion of an element wasn't terminated properly";
rolf 0:37e8c5cd04e8 166 return 0;
rolf 0:37e8c5cd04e8 167 }
rolf 0:37e8c5cd04e8 168 }
rolf 0:37e8c5cd04e8 169 return scan;
rolf 0:37e8c5cd04e8 170 }
rolf 0:37e8c5cd04e8 171
rolf 0:37e8c5cd04e8 172 virtual bool processXml(const char *inputData,unsigned int dataLen,FastXmlInterface *iface)
rolf 0:37e8c5cd04e8 173 {
rolf 0:37e8c5cd04e8 174 bool ret = true;
rolf 0:37e8c5cd04e8 175
rolf 0:37e8c5cd04e8 176 #define MAX_ATTRIBUTE 2048 // can't imagine having more than 2,048 attributes in a single element right?
rolf 0:37e8c5cd04e8 177
rolf 0:37e8c5cd04e8 178 release();
rolf 0:37e8c5cd04e8 179 mInputData = (char *)malloc(dataLen+1);
rolf 0:37e8c5cd04e8 180 memcpy(mInputData,inputData,dataLen);
rolf 0:37e8c5cd04e8 181 mInputData[dataLen] = 0;
rolf 0:37e8c5cd04e8 182
rolf 0:37e8c5cd04e8 183 mLineNo = 1;
rolf 0:37e8c5cd04e8 184
rolf 0:37e8c5cd04e8 185 char *element;
rolf 0:37e8c5cd04e8 186
rolf 0:37e8c5cd04e8 187 char *scan = mInputData;
rolf 0:37e8c5cd04e8 188 if ( *scan == '<' )
rolf 0:37e8c5cd04e8 189 {
rolf 0:37e8c5cd04e8 190 scan++;
rolf 0:37e8c5cd04e8 191 while ( *scan )
rolf 0:37e8c5cd04e8 192 {
rolf 0:37e8c5cd04e8 193 scan = skipNextData(scan);
rolf 0:37e8c5cd04e8 194 if ( *scan == 0 ) return ret;
rolf 0:37e8c5cd04e8 195 if ( *scan == '<' )
rolf 0:37e8c5cd04e8 196 {
rolf 0:37e8c5cd04e8 197 scan++;
rolf 0:37e8c5cd04e8 198 }
rolf 0:37e8c5cd04e8 199 if ( *scan == '/' || *scan == '?' )
rolf 0:37e8c5cd04e8 200 {
rolf 0:37e8c5cd04e8 201 while ( *scan && *scan != '>' ) scan++;
rolf 0:37e8c5cd04e8 202 scan++;
rolf 0:37e8c5cd04e8 203 }
rolf 0:37e8c5cd04e8 204 else
rolf 0:37e8c5cd04e8 205 {
rolf 0:37e8c5cd04e8 206 element = scan;
rolf 0:37e8c5cd04e8 207 int argc = 0;
rolf 0:37e8c5cd04e8 208 const char *argv[MAX_ATTRIBUTE];
rolf 0:37e8c5cd04e8 209 bool close;
rolf 0:37e8c5cd04e8 210 scan = nextSoftOrClose(scan,close);
rolf 0:37e8c5cd04e8 211 if ( close )
rolf 0:37e8c5cd04e8 212 {
rolf 0:37e8c5cd04e8 213 char c = *(scan-1);
rolf 0:37e8c5cd04e8 214 if ( c != '?' && c != '/' )
rolf 0:37e8c5cd04e8 215 {
rolf 0:37e8c5cd04e8 216 c = '>';
rolf 0:37e8c5cd04e8 217 }
rolf 0:37e8c5cd04e8 218 *scan = 0;
rolf 0:37e8c5cd04e8 219 scan++;
rolf 0:37e8c5cd04e8 220 scan = processClose(c,element,scan,argc,argv,iface);
rolf 0:37e8c5cd04e8 221 if ( !scan ) return false;
rolf 0:37e8c5cd04e8 222 }
rolf 0:37e8c5cd04e8 223 else
rolf 0:37e8c5cd04e8 224 {
rolf 0:37e8c5cd04e8 225 if ( *scan == 0 ) return ret;
rolf 0:37e8c5cd04e8 226 *scan = 0; // place a zero byte to indicate the end of the element name...
rolf 0:37e8c5cd04e8 227 scan++;
rolf 0:37e8c5cd04e8 228
rolf 0:37e8c5cd04e8 229 while ( *scan )
rolf 0:37e8c5cd04e8 230 {
rolf 0:37e8c5cd04e8 231 scan = skipNextData(scan); // advance past any soft seperators (tab or space)
rolf 0:37e8c5cd04e8 232
rolf 0:37e8c5cd04e8 233 if ( mTypes[*scan] == CT_END_OF_ELEMENT )
rolf 0:37e8c5cd04e8 234 {
rolf 0:37e8c5cd04e8 235 char c = *scan++;
rolf 0:37e8c5cd04e8 236 scan = processClose(c,element,scan,argc,argv,iface);
rolf 0:37e8c5cd04e8 237 if ( !scan ) return false;
rolf 0:37e8c5cd04e8 238 break;
rolf 0:37e8c5cd04e8 239 }
rolf 0:37e8c5cd04e8 240 else
rolf 0:37e8c5cd04e8 241 {
rolf 0:37e8c5cd04e8 242 if ( argc >= MAX_ATTRIBUTE )
rolf 0:37e8c5cd04e8 243 {
rolf 0:37e8c5cd04e8 244 mError = "encountered too many attributes";
rolf 0:37e8c5cd04e8 245 return false;
rolf 0:37e8c5cd04e8 246 }
rolf 0:37e8c5cd04e8 247 argv[argc] = scan;
rolf 0:37e8c5cd04e8 248 scan = nextSep(scan); // scan up to a space, or an equal
rolf 0:37e8c5cd04e8 249 if ( *scan )
rolf 0:37e8c5cd04e8 250 {
rolf 0:37e8c5cd04e8 251 if ( *scan != '=' )
rolf 0:37e8c5cd04e8 252 {
rolf 0:37e8c5cd04e8 253 *scan = 0;
rolf 0:37e8c5cd04e8 254 scan++;
rolf 0:37e8c5cd04e8 255 while ( *scan && *scan != '=' ) scan++;
rolf 0:37e8c5cd04e8 256 if ( *scan == '=' ) scan++;
rolf 0:37e8c5cd04e8 257 }
rolf 0:37e8c5cd04e8 258 else
rolf 0:37e8c5cd04e8 259 {
rolf 0:37e8c5cd04e8 260 *scan=0;
rolf 0:37e8c5cd04e8 261 scan++;
rolf 0:37e8c5cd04e8 262 }
rolf 0:37e8c5cd04e8 263 if ( *scan ) // if not eof...
rolf 0:37e8c5cd04e8 264 {
rolf 0:37e8c5cd04e8 265 scan = skipNextData(scan);
rolf 0:37e8c5cd04e8 266 if ( *scan == 34 )
rolf 0:37e8c5cd04e8 267 {
rolf 0:37e8c5cd04e8 268 scan++;
rolf 0:37e8c5cd04e8 269 argc++;
rolf 0:37e8c5cd04e8 270 argv[argc] = scan;
rolf 0:37e8c5cd04e8 271 argc++;
rolf 0:37e8c5cd04e8 272 while ( *scan && *scan != 34 ) scan++;
rolf 0:37e8c5cd04e8 273 if ( *scan == 34 )
rolf 0:37e8c5cd04e8 274 {
rolf 0:37e8c5cd04e8 275 *scan = 0;
rolf 0:37e8c5cd04e8 276 scan++;
rolf 0:37e8c5cd04e8 277 }
rolf 0:37e8c5cd04e8 278 else
rolf 0:37e8c5cd04e8 279 {
rolf 0:37e8c5cd04e8 280 mError = "Failed to find closing quote for attribute";
rolf 0:37e8c5cd04e8 281 return false;
rolf 0:37e8c5cd04e8 282 }
rolf 0:37e8c5cd04e8 283 }
rolf 0:37e8c5cd04e8 284 else
rolf 0:37e8c5cd04e8 285 {
rolf 0:37e8c5cd04e8 286 mError = "Expected quote to begin attribute";
rolf 0:37e8c5cd04e8 287 return false;
rolf 0:37e8c5cd04e8 288 }
rolf 0:37e8c5cd04e8 289 }
rolf 0:37e8c5cd04e8 290 }
rolf 0:37e8c5cd04e8 291 }
rolf 0:37e8c5cd04e8 292 }
rolf 0:37e8c5cd04e8 293 }
rolf 0:37e8c5cd04e8 294 }
rolf 0:37e8c5cd04e8 295 }
rolf 0:37e8c5cd04e8 296 }
rolf 0:37e8c5cd04e8 297 else
rolf 0:37e8c5cd04e8 298 {
rolf 0:37e8c5cd04e8 299 mError = "Expected the start of an element '<' at this location.";
rolf 0:37e8c5cd04e8 300 ret = false; // unexpected character!?
rolf 0:37e8c5cd04e8 301 }
rolf 0:37e8c5cd04e8 302
rolf 0:37e8c5cd04e8 303 return ret;
rolf 0:37e8c5cd04e8 304 }
rolf 0:37e8c5cd04e8 305
rolf 0:37e8c5cd04e8 306 virtual const char *getError(int &lineno) {
rolf 0:37e8c5cd04e8 307 const char *ret = mError;
rolf 0:37e8c5cd04e8 308 lineno = mLineNo;
rolf 0:37e8c5cd04e8 309 mError = 0;
rolf 0:37e8c5cd04e8 310 return ret;
rolf 0:37e8c5cd04e8 311 }
rolf 0:37e8c5cd04e8 312
rolf 0:37e8c5cd04e8 313 private:
rolf 0:37e8c5cd04e8 314 char mTypes[256];
rolf 0:37e8c5cd04e8 315 char *mInputData;
rolf 0:37e8c5cd04e8 316 int mLineNo;
rolf 0:37e8c5cd04e8 317 const char *mError;
rolf 0:37e8c5cd04e8 318 };
rolf 0:37e8c5cd04e8 319
rolf 0:37e8c5cd04e8 320
rolf 0:37e8c5cd04e8 321
rolf 0:37e8c5cd04e8 322 FastXml *createFastXml(void) {
rolf 0:37e8c5cd04e8 323 MyFastXml *f = new MyFastXml;
rolf 0:37e8c5cd04e8 324 return static_cast< FastXml *>(f);
rolf 0:37e8c5cd04e8 325 }
rolf 0:37e8c5cd04e8 326
rolf 0:37e8c5cd04e8 327 void releaseFastXml(FastXml *f) {
rolf 0:37e8c5cd04e8 328 MyFastXml *m = static_cast< MyFastXml *>(f);
rolf 0:37e8c5cd04e8 329 delete m;
rolf 0:37e8c5cd04e8 330 }