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
spxmlparser.cpp
- Committer:
- hlipka
- Date:
- 2010-11-24
- Revision:
- 0:3fa97f2c0505
File content as of revision 0:3fa97f2c0505:
/* * 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 <assert.h> #include <typeinfo> #include "mstring.h" #include "spxmlparser.hpp" #include "spxmlreader.hpp" #include "spxmlutils.hpp" #include "spxmlevent.hpp" #include "spxmlcodec.hpp" SP_XmlPullParser :: SP_XmlPullParser() { mReaderPool = new SP_XmlReaderPool(); mReader = getReader( SP_XmlReader::eLBracket ); mEventQueue = new SP_XmlPullEventQueue(); mEventQueue->enqueue( new SP_XmlStartDocEvent() ); mRootTagState = eRootNone; mTagNameStack = new SP_XmlArrayList(); mLevel = 0; mIgnoreWhitespace = 1; mError = NULL; memset( mErrorSegment, 0, sizeof( mErrorSegment ) ); mErrorIndex = 0; mRowIndex = mColIndex = 0; memset( mEncoding, 0, sizeof( mEncoding ) ); } SP_XmlPullParser :: ~SP_XmlPullParser() { mReaderPool->save( mReader ); for( int i = 0; i < mTagNameStack->getCount(); i++ ) { free( (char*)mTagNameStack->getItem( i ) ); } delete mTagNameStack; delete mEventQueue; delete mReaderPool; if( NULL != mError ) free( mError ); } const char * SP_XmlPullParser :: getEncoding() { if( '\0' == mEncoding[0] ) { return SP_XmlStringCodec::DEFAULT_ENCODING; } return mEncoding; } int SP_XmlPullParser :: append( const char * source, int len ) { if( NULL != mError ) return 0; int consumed = 0; for( int i = 0; i < len && NULL == mError; i++ ) { consumed++; char c = source[ i ]; mErrorSegment[ mErrorIndex++ % sizeof( mErrorSegment ) ] = c; mReader->read( this, c ); if( '\n' == c ) { mRowIndex++; mColIndex = 0; } else { mColIndex++; } } return consumed; } SP_XmlPullEvent * SP_XmlPullParser :: getNext() { SP_XmlPullEvent * event = mEventQueue->dequeue(); if( NULL != event ) { if( SP_XmlPullEvent::eStartTag == event->getEventType() ) mLevel++; if( SP_XmlPullEvent::eEndTag == event->getEventType() ) mLevel--; } return event; } int SP_XmlPullParser :: getLevel() { return mLevel; } void SP_XmlPullParser :: setIgnoreWhitespace( int ignoreWhitespace ) { mIgnoreWhitespace = ignoreWhitespace; } int SP_XmlPullParser :: getIgnoreWhitespace() { return mIgnoreWhitespace; } const char * SP_XmlPullParser :: getError() { return mError; } void SP_XmlPullParser :: changeReader( SP_XmlReader * reader ) { SP_XmlPullEvent * event = mReader->getEvent( this ); if( NULL != event ) { if( SP_XmlPullEvent::eStartTag == event->getEventType() ) { if( eRootNone == mRootTagState ) mRootTagState = eRootStart; const char * name = ((SP_XmlStartTagEvent*)event)->getName(); mTagNameStack->append( strdup( name ) ); } if( SP_XmlPullEvent::eEndTag == event->getEventType() ) { char error[ 256 ] = { 0 }; const char * etag = ((SP_XmlEndTagEvent*)event)->getText(); char * stag = (char*)mTagNameStack->takeItem( SP_XmlArrayList::LAST_INDEX ); if( NULL != stag ) { if( 0 != strcmp( stag, etag ) ) { snprintf( error, sizeof( error ), "mismatched tag, start-tag <%s>, end-tag <%s>", stag, etag ); } free( stag ); } else { snprintf( error, sizeof( error ), "mismatched tag, start-tag <NULL>, end-tag <%s>", etag ); } if( '\0' != *error ) { setError( error ); delete event; event = NULL; } } if( NULL != event ) { if( SP_XmlPullEvent::eDocDecl == event->getEventType() ) { snprintf( mEncoding, sizeof( mEncoding ), "%s", ((SP_XmlDocDeclEvent*)event)->getEncoding() ); } mEventQueue->enqueue( event ); if( mTagNameStack->getCount() <= 0 && eRootStart == mRootTagState ) { mRootTagState = eRootEnd; mEventQueue->enqueue( new SP_XmlEndDocEvent() ); } } } //printf( "\nchange: %s -> %s\n", typeid( *mReader ).name(), typeid( *reader ).name() ); mReaderPool->save( mReader ); mReader = reader; } SP_XmlReader * SP_XmlPullParser :: getReader( int type ) { return mReaderPool->borrow( type ); } void SP_XmlPullParser :: setError( const char * error ) { if( NULL != error ) { if( NULL != mError ) free( mError ); char segment[ 2 * sizeof( mErrorSegment ) + 1 ]; { memset( segment, 0, sizeof( segment ) ); char temp[ sizeof( mErrorSegment ) + 1 ]; memset( temp, 0, sizeof( temp ) ); if( mErrorIndex < (int)sizeof( mErrorSegment ) ) { strncpy( temp, mErrorSegment, mErrorIndex ); } else { int offset = mErrorIndex % sizeof( mErrorSegment ); strncpy( temp, mErrorSegment + offset, sizeof( mErrorSegment ) - offset ); strncpy( temp + sizeof( mErrorSegment ) - offset, mErrorSegment, offset ); } for( char * pos = temp, * dest = segment; '\0' != *pos; pos++ ) { if( '\r' == *pos ) { *dest++ = '\\'; *dest++ = 'r'; } else if( '\n' == *pos ) { *dest++ = '\\'; *dest++ = 'n'; } else if( '\t' == *pos ) { *dest++ = '\\'; *dest++ = 't'; } else { *dest++ = *pos; } } } char msg[ 512 ]; snprintf( msg, sizeof( msg), "%s ( occured at row(%d), col(%d) : %s )", error, mRowIndex + 1, mColIndex + 1, segment ); mError = strdup( msg ); } }