Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 0:37e8c5cd04e8, committed 2009-12-11
- Comitter:
- rolf
- Date:
- Fri Dec 11 15:32:41 2009 +0000
- Commit message:
Changed in this revision
diff -r 000000000000 -r 37e8c5cd04e8 fastxml/fastxml.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/fastxml/fastxml.cpp Fri Dec 11 15:32:41 2009 +0000
@@ -0,0 +1,330 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "fastxml.h"
+
+/*!
+**
+** Copyright (c) 2009 by John W. Ratcliff mailto:jratcliffscarab@gmail.com
+**
+** The MIT license:
+**
+** Permission is hereby granted, MEMALLOC_FREE of charge, to any person obtaining a copy
+** of this software and associated documentation files (the "Software"), to deal
+** in the Software without restriction, including without limitation the rights
+** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+** copies of the Software, and to permit persons to whom the Software is furnished
+** to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in all
+** copies or substantial portions of the Software.
+
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+** WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+
+class MyFastXml : public FastXml {
+public:
+ enum CharType {
+ CT_DATA,
+ CT_EOF,
+ CT_SOFT,
+ CT_END_OF_ELEMENT, // either a forward slash or a greater than symbol
+ CT_END_OF_LINE,
+ };
+
+ MyFastXml(void) {
+ mInputData = 0;
+ memset(mTypes,CT_DATA,256);
+ mTypes[0] = CT_EOF;
+ mTypes[32] = CT_SOFT;
+ mTypes[9] = CT_SOFT;
+ mTypes['/'] = CT_END_OF_ELEMENT;
+ mTypes['>'] = CT_END_OF_ELEMENT;
+ mTypes['?'] = CT_END_OF_ELEMENT;
+ mTypes[10] = CT_END_OF_LINE;
+ mTypes[13] = CT_END_OF_LINE;
+ mError = 0;
+ }
+ ~MyFastXml(void) {
+ release();
+ }
+
+ void release(void) {
+ if(mInputData) {
+ free(mInputData);
+ mInputData = 0;
+ }
+ mError = 0;
+ }
+
+ inline char *nextSoft(char *scan) {
+ while ( *scan && mTypes[*scan] != CT_SOFT ) scan++;
+ return scan;
+ }
+
+ inline char *nextSoftOrClose(char *scan,bool &close) {
+ while ( *scan && mTypes[*scan] != CT_SOFT && *scan != '>' ) scan++;
+ close = *scan == '>';
+ return scan;
+ }
+
+ inline char *nextSep(char *scan) {
+ while ( *scan && mTypes[*scan] != CT_SOFT && *scan != '=' ) scan++;
+ return scan;
+ }
+
+ inline char * skipNextData(char *scan) {
+ // while we have data, and we encounter soft seperators or line feeds...
+ while ( *scan && mTypes[*scan] == CT_SOFT || mTypes[*scan] == CT_END_OF_LINE ) {
+ if ( *scan == 13 ) mLineNo++;
+ scan++;
+ }
+ return scan;
+ }
+
+ char * processClose(char c,const char *element,char *scan,int argc,const char **argv,FastXmlInterface *iface) {
+ if ( c == '/' || c == '?' ) {
+ if ( *scan != '>' ) { // unexepected character!
+ mError = "Expected an element close character immediately after the '/' or '?' character.";
+ return 0;
+ }
+ scan++;
+ bool ok = iface->processElement(element,argc,argv,0,mLineNo);
+ if ( !ok )
+ {
+ mError = "User aborted the parsing process";
+ return 0;
+ }
+ }
+ else
+ {
+ scan = skipNextData(scan);
+ char *data = scan; // this is the data portion of the element, only copies memory if we encounter line feeds
+ char *dest_data = 0;
+ while ( *scan && *scan != '<' )
+ {
+ if ( mTypes[*scan] == CT_END_OF_LINE )
+ {
+ if ( *scan == 13 ) mLineNo++;
+ dest_data = scan;
+ *dest_data++ = 32; // replace the linefeed with a space...
+ scan = skipNextData(scan);
+ while ( *scan && *scan != '<' )
+ {
+ if ( mTypes[*scan] == CT_END_OF_LINE )
+ {
+ if ( *scan == 13 ) mLineNo++;
+ *dest_data++ = 32; // replace the linefeed with a space...
+ scan = skipNextData(scan);
+ }
+ else
+ {
+ *dest_data++ = *scan++;
+ }
+ }
+ break;
+ }
+ else
+ scan++;
+ }
+ if ( *scan == '<' )
+ {
+ if ( dest_data )
+ {
+ *dest_data = 0;
+ }
+ else
+ {
+ *scan = 0;
+ }
+ scan++; // skip it..
+ if ( *data == 0 ) data = 0;
+ bool ok = iface->processElement(element,argc,argv,data,mLineNo);
+ if ( !ok )
+ {
+ mError = "User aborted the parsing process";
+ return 0;
+ }
+ if ( *scan == '/' )
+ {
+ while ( *scan && *scan != '>' ) scan++;
+ scan++;
+ }
+ }
+ else
+ {
+ mError = "Data portion of an element wasn't terminated properly";
+ return 0;
+ }
+ }
+ return scan;
+ }
+
+ virtual bool processXml(const char *inputData,unsigned int dataLen,FastXmlInterface *iface)
+ {
+ bool ret = true;
+
+ #define MAX_ATTRIBUTE 2048 // can't imagine having more than 2,048 attributes in a single element right?
+
+ release();
+ mInputData = (char *)malloc(dataLen+1);
+ memcpy(mInputData,inputData,dataLen);
+ mInputData[dataLen] = 0;
+
+ mLineNo = 1;
+
+ char *element;
+
+ char *scan = mInputData;
+ if ( *scan == '<' )
+ {
+ scan++;
+ while ( *scan )
+ {
+ scan = skipNextData(scan);
+ if ( *scan == 0 ) return ret;
+ if ( *scan == '<' )
+ {
+ scan++;
+ }
+ if ( *scan == '/' || *scan == '?' )
+ {
+ while ( *scan && *scan != '>' ) scan++;
+ scan++;
+ }
+ else
+ {
+ element = scan;
+ int argc = 0;
+ const char *argv[MAX_ATTRIBUTE];
+ bool close;
+ scan = nextSoftOrClose(scan,close);
+ if ( close )
+ {
+ char c = *(scan-1);
+ if ( c != '?' && c != '/' )
+ {
+ c = '>';
+ }
+ *scan = 0;
+ scan++;
+ scan = processClose(c,element,scan,argc,argv,iface);
+ if ( !scan ) return false;
+ }
+ else
+ {
+ if ( *scan == 0 ) return ret;
+ *scan = 0; // place a zero byte to indicate the end of the element name...
+ scan++;
+
+ while ( *scan )
+ {
+ scan = skipNextData(scan); // advance past any soft seperators (tab or space)
+
+ if ( mTypes[*scan] == CT_END_OF_ELEMENT )
+ {
+ char c = *scan++;
+ scan = processClose(c,element,scan,argc,argv,iface);
+ if ( !scan ) return false;
+ break;
+ }
+ else
+ {
+ if ( argc >= MAX_ATTRIBUTE )
+ {
+ mError = "encountered too many attributes";
+ return false;
+ }
+ argv[argc] = scan;
+ scan = nextSep(scan); // scan up to a space, or an equal
+ if ( *scan )
+ {
+ if ( *scan != '=' )
+ {
+ *scan = 0;
+ scan++;
+ while ( *scan && *scan != '=' ) scan++;
+ if ( *scan == '=' ) scan++;
+ }
+ else
+ {
+ *scan=0;
+ scan++;
+ }
+ if ( *scan ) // if not eof...
+ {
+ scan = skipNextData(scan);
+ if ( *scan == 34 )
+ {
+ scan++;
+ argc++;
+ argv[argc] = scan;
+ argc++;
+ while ( *scan && *scan != 34 ) scan++;
+ if ( *scan == 34 )
+ {
+ *scan = 0;
+ scan++;
+ }
+ else
+ {
+ mError = "Failed to find closing quote for attribute";
+ return false;
+ }
+ }
+ else
+ {
+ mError = "Expected quote to begin attribute";
+ return false;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ mError = "Expected the start of an element '<' at this location.";
+ ret = false; // unexpected character!?
+ }
+
+ return ret;
+ }
+
+ virtual const char *getError(int &lineno) {
+ const char *ret = mError;
+ lineno = mLineNo;
+ mError = 0;
+ return ret;
+ }
+
+private:
+ char mTypes[256];
+ char *mInputData;
+ int mLineNo;
+ const char *mError;
+};
+
+
+
+FastXml *createFastXml(void) {
+ MyFastXml *f = new MyFastXml;
+ return static_cast< FastXml *>(f);
+}
+
+void releaseFastXml(FastXml *f) {
+ MyFastXml *m = static_cast< MyFastXml *>(f);
+ delete m;
+}
diff -r 000000000000 -r 37e8c5cd04e8 fastxml/fastxml.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/fastxml/fastxml.h Fri Dec 11 15:32:41 2009 +0000
@@ -0,0 +1,81 @@
+#ifndef FAST_XML_H
+#define FAST_XML_H
+
+/*!
+**
+** Copyright (c) 2009 by John W. Ratcliff mailto:jratcliff@infiniplex.net
+**
+** The MIT license:
+**
+** Permission is hereby granted, MEMALLOC_FREE of charge, to any person obtaining a copy
+** of this software and associated documentation files (the "Software"), to deal
+** in the Software without restriction, including without limitation the rights
+** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+** copies of the Software, and to permit persons to whom the Software is furnished
+** to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in all
+** copies or substantial portions of the Software.
+
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+** WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+
+// This code snippet provides an extremely lightweight and fast XML parser.
+// This parser only handles data elements as if they were streamed data.
+// It is important to note that all pointers returned by this parser are
+// persistent for the lifetime of the FastXml class. This means you can cache
+// copies of the pointers (rather than copying any data) if this matches your
+// needs.
+
+
+// Simpy call createFastXml to get a copy of the FastXml parsing interface
+// To parse an XML file, have your application inherit the pure virtual
+// interface called 'FastXmlInterface' and implement the single method 'processElement'
+//
+// For each element in the XML file you will get a callback with the following
+// data.
+//
+// 'elementName' the name of the element (this pointer is persistent)
+// 'argc' The total number of attributes and values for this element.
+// The number of attribute/value pairs is equal to argc/2
+// 'argv' The attribute/value pairs in the form of attribute/value, attribute/value..
+// These pointers are persistent and can be cached if needed (until FastXml is released)
+// 'elementData' optional data (i.e. text) associated with the element. If this is a null pointer
+// then the element had no data. This pointer is persistent.
+// 'lineno' The line number in the source XML file.
+//
+// After calling your routine 'processElement' you must return 'true' to continue parsing
+// If you want to stop parsing early, return false.
+//
+// If the call to process an XML file fails, it will return false.
+// You can then call the method 'getError' to get a description of why it failed
+// and on what line number of the source XML file it occurred.
+
+class FastXmlInterface {
+ public:
+ // return true to continue processing the XML document, false to skip.
+ virtual bool processElement(const char *elementName, // name of the element
+ int argc, // number of attributes
+ const char **argv, // list of attributes.
+ const char *elementData, // element data, null if none
+ int lineno) = 0; // line number in the source XML file
+
+};
+
+class FastXml {
+ public:
+ virtual bool processXml(const char *inputData,unsigned int dataLen,FastXmlInterface *iface) = 0;
+ virtual const char * getError(int &lineno) = 0; // report the reason for a parsing error, and the line number where it occurred.
+};
+
+FastXml *createFastXml(void);
+void releaseFastXml(FastXml *f);
+
+#endif
diff -r 000000000000 -r 37e8c5cd04e8 main.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Fri Dec 11 15:32:41 2009 +0000
@@ -0,0 +1,38 @@
+#include "mbed.h"
+#include "fastxml.h"
+
+DigitalOut myled(LED1);
+
+class tmpr : public FastXmlInterface {
+ public:
+ virtual bool processElement(const char *name, int argc, const char **argv, const char *data, int lineno) {
+ printf("::%s\n", name);
+ if(strncmp(name, "tmpr", 4)==0) {
+ printf("tmpr: %s\n", data);
+ }
+ return true;
+ }
+};
+
+const char *code = {
+ "<root>\r\n"
+ " <chan1>\r\n"
+ " <tmpr>23.7</tmpr>\r\n"
+ " </chan1>\r\n"
+ " <chan2>\r\n"
+ " <tmpr>23.7</tmpr>\r\n"
+ " </chan2>\r\n"
+ "</root>\r\n"
+};
+
+int main() {
+ FastXml *xml = createFastXml();
+ FastXmlInterface *tmp = new tmpr();
+ xml->processXml(code, strlen(code), tmp);
+ while(1) {
+ myled = 1;
+ wait(0.2);
+ myled = 0;
+ wait(0.2);
+ }
+}
diff -r 000000000000 -r 37e8c5cd04e8 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Fri Dec 11 15:32:41 2009 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/49a220cc26e0