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

Files at this revision

API Documentation at this revision

Comitter:
rolf
Date:
Fri Dec 11 15:32:41 2009 +0000
Commit message:

Changed in this revision

fastxml/fastxml.cpp Show annotated file Show diff for this revision Revisions of this file
fastxml/fastxml.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /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;
+}
--- /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
--- /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);
+    }
+}
--- /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