Mbed port of the Simple Plain Xml parser. See http://code.google.com/p/spxml/ for more details. This library uses less memory and is much better suited to streaming data than TinyXML (doesn\'t use as much C++ features, and especially works without streams). See http://mbed.org/users/hlipka/notebook/xml-parsing/ for usage examples.
Dependents: spxmltest_weather VFD_fontx2_weather weather_LCD_display News_LCD_display ... more
Diff: spxmlstag.cpp
- Revision:
- 0:3fa97f2c0505
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spxmlstag.cpp Wed Nov 24 20:52:14 2010 +0000 @@ -0,0 +1,254 @@ +/* + * Copyright 2007 Stephen Liu + * LGPL, see http://code.google.com/p/spxml/ + * For license terms, see the file COPYING along with this library. + */ + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <typeinfo> + +#include "mstring.h" + +#include "spxmlstag.hpp" +#include "spxmlutils.hpp" +#include "spxmlevent.hpp" +#include "spxmlcodec.hpp" + +SP_XmlSTagParser :: SP_XmlSTagParser( const char * encoding ) +{ + mEvent = new SP_XmlStartTagEvent(); + mReader = new SP_XmlSTagNameReader(); + mStartTagName = new SP_XmlStringBuffer(); + mError = NULL; + + snprintf( mEncoding, sizeof( mEncoding ), "%s", encoding ); +} + +SP_XmlSTagParser :: ~SP_XmlSTagParser() +{ + if( NULL != mEvent ) delete mEvent; + mEvent = NULL; + + if( NULL != mReader ) delete mReader; + mReader = NULL; + + if( NULL != mStartTagName ) delete mStartTagName; + mStartTagName = NULL; + + if( NULL != mError ) free( mError ); + mError = NULL; +} + +const char * SP_XmlSTagParser :: getEncoding() +{ + return mEncoding; +} + +SP_XmlStartTagEvent * SP_XmlSTagParser :: takeEvent() +{ + SP_XmlStartTagEvent * event = mEvent; + + mEvent = NULL; + + return event; +} + +const char * SP_XmlSTagParser :: getError() +{ + return mError; +} + +void SP_XmlSTagParser :: changeReader( SP_XmlSTagReader * reader ) +{ + delete mReader; + mReader = reader; +} + +void SP_XmlSTagParser :: setError( const char * error ) +{ + if( NULL != error ) { + if( NULL != mError ) free( mError ); + mError = strdup( error ); + } +} + +void SP_XmlSTagParser :: append( const char * source, int len ) +{ + for( int i = 0; i < len && NULL == mError; i++ ) { + mReader->read( this, source[ i ] ); + } +} + +//========================================================= + +SP_XmlSTagReader :: SP_XmlSTagReader() +{ + mBuffer = new SP_XmlStringBuffer(); +} + +SP_XmlSTagReader :: ~SP_XmlSTagReader() +{ + delete mBuffer; + mBuffer = NULL; +} + +void SP_XmlSTagReader :: changeReader( SP_XmlSTagParser * parser, + SP_XmlSTagReader * reader ) +{ + //printf( "\nchange: %s\n", typeid( *reader ).name() ); + parser->changeReader( reader ); +} + +void SP_XmlSTagReader :: setError( SP_XmlSTagParser * parser, const char * error ) +{ + parser->setError( error ); +} + +void SP_XmlSTagReader :: setName( SP_XmlSTagParser * parser, const char * name ) +{ + parser->mEvent->setName( name ); +} + +void SP_XmlSTagReader :: addAttrName( SP_XmlSTagParser * parser, const char * name ) +{ + parser->mStartTagName->append( name ); +} + +void SP_XmlSTagReader :: addAttrValue( SP_XmlSTagParser * parser, const char * value ) +{ + SP_XmlStringBuffer decodeValue; + SP_XmlStringCodec::decode( parser->getEncoding(), value, &decodeValue ); + + parser->mEvent->addAttr( parser->mStartTagName->getBuffer(), decodeValue.getBuffer() ); + parser->mStartTagName->clean(); +} + +//========================================================= + +SP_XmlSTagNameReader :: SP_XmlSTagNameReader() +{ +} + +SP_XmlSTagNameReader :: ~SP_XmlSTagNameReader() +{ +} + +void SP_XmlSTagNameReader :: read( SP_XmlSTagParser * parser, char c ) +{ + if( isspace( c ) ) { + if( 0 == mBuffer->getSize() ) { + //leading space, skip + } else { + setName( parser, mBuffer->getBuffer() ); + changeReader( parser, new SP_XmlSTagAttrNameReader() ); + } + } else { + mBuffer->append( c ); + } +} + +//========================================================= + +SP_XmlSTagAttrNameReader :: SP_XmlSTagAttrNameReader() +{ + mWait4Quot = 0; +} + +SP_XmlSTagAttrNameReader :: ~SP_XmlSTagAttrNameReader() +{ +} + +void SP_XmlSTagAttrNameReader :: read( SP_XmlSTagParser * parser, char c ) +{ + if( 1 == mWait4Quot ) { + if( '"' == c ) { + addAttrName( parser, mBuffer->getBuffer() ); + changeReader( parser, new SP_XmlSTagEqualMarkReader() ); + } else { + mBuffer->append( c ); + } + } else { + if( isspace( c ) ) { + if( 0 == mBuffer->getSize() ) { + //leading space, skip + } else { + addAttrName( parser, mBuffer->getBuffer() ); + changeReader( parser, new SP_XmlSTagEqualMarkReader() ); + } + } else { + if( '"' == c && 0 == mBuffer->getSize() ) { + mWait4Quot = 1; + } else if( '=' == c ) { + addAttrName( parser, mBuffer->getBuffer() ); + SP_XmlSTagReader * reader = new SP_XmlSTagEqualMarkReader(); + changeReader( parser, reader ); + reader->read( parser, c ); + } else { + mBuffer->append( c ); + } + } + } +} + +//========================================================= + +SP_XmlSTagEqualMarkReader :: SP_XmlSTagEqualMarkReader() +{ +} + +SP_XmlSTagEqualMarkReader :: ~SP_XmlSTagEqualMarkReader() +{ +} + +void SP_XmlSTagEqualMarkReader :: read( SP_XmlSTagParser * parser, char c ) +{ + if( isspace( c ) ) { + //skip + } else if( '=' == c ) { + changeReader( parser, new SP_XmlSTagAttrValueReader() ); + } else { + addAttrValue( parser, "" ); + SP_XmlSTagReader * reader = new SP_XmlSTagAttrNameReader(); + changeReader( parser, reader ); + reader->read( parser, c ); + + //setError( parser, "miss '=' between name & value" ); + } +} + +//========================================================= + +SP_XmlSTagAttrValueReader :: SP_XmlSTagAttrValueReader() +{ + mHasReadQuot = 0; +} + +SP_XmlSTagAttrValueReader :: ~SP_XmlSTagAttrValueReader() +{ +} + +void SP_XmlSTagAttrValueReader :: read( SP_XmlSTagParser * parser, char c ) +{ + if( 0 == mHasReadQuot ) { + if( isspace( c ) ) { + //skip + } else if( '"' == c ) { + mHasReadQuot = 1; + } else if( '\'' == c ) { + mHasReadQuot = 2; + } else { + setError( parser, "unknown attribute value start" ); + } + } else { + if( ( 1 == mHasReadQuot && '"' == c ) + || ( 2 == mHasReadQuot && '\'' == c ) ) { + addAttrValue( parser, mBuffer->getBuffer() ); + changeReader( parser, new SP_XmlSTagAttrNameReader() ); + } else { + mBuffer->append( c ); + } + } +} +