From 5dbc8f155b16759b4ebb82aceb3759c686489e3b Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Thu, 4 Sep 2008 22:09:51 +0000 Subject: XML is important, I guess... --- src/fstring.h | 21 ++++++- src/unit/xml.cpp | 39 +++++++++++++ src/xmlreader.cpp | 165 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/xmlreader.h | 54 ++++++++++++++++++ 4 files changed, 278 insertions(+), 1 deletion(-) create mode 100644 src/unit/xml.cpp create mode 100644 src/xmlreader.cpp create mode 100644 src/xmlreader.h (limited to 'src') diff --git a/src/fstring.h b/src/fstring.h index 8b22160..fb4bf55 100644 --- a/src/fstring.h +++ b/src/fstring.h @@ -187,7 +187,26 @@ namespace Bu append( &cData, 1 ); } } - + + /** + * Append another FString to this one. + *@param sData (MyType &) The FString to append. + */ + void append( const MyType & sData ) + { + append( sData.getStr(), sData.getSize() ); + } + + /** + * Append another FString to this one. + *@param sData (MyType &) The FString to append. + *@param nLen How much data to append. + */ + void append( const MyType & sData, long nLen ) + { + append( sData.getStr(), nLen ); + } + /** * Prepend another FString to this one. *@param sData (MyType &) The FString to prepend. diff --git a/src/unit/xml.cpp b/src/unit/xml.cpp new file mode 100644 index 0000000..e845cc1 --- /dev/null +++ b/src/unit/xml.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2007-2008 Xagasoft, All rights reserved. + * + * This file is part of the libbu++ library and is released under the + * terms of the license contained in the file LICENSE. + */ + +#include "bu/fstring.h" +#include "bu/unitsuite.h" +#include "bu/xmlreader.h" +#include "bu/membuf.h" + +class Unit : public Bu::UnitSuite +{ +public: + Unit() + { + setName("Xml"); + addTest( Unit::declaration ); + } + + virtual ~Unit() + { + } + + void declaration() + { + Bu::FString sXml(" "); + Bu::MemBuf buf( sXml ); + Bu::XmlReader xr( buf ); + } + +}; + +int main( int argc, char *argv[] ) +{ + return Unit().run( argc, argv ); +} + diff --git a/src/xmlreader.cpp b/src/xmlreader.cpp new file mode 100644 index 0000000..9d299e6 --- /dev/null +++ b/src/xmlreader.cpp @@ -0,0 +1,165 @@ +#include "bu/xmlreader.h" +#include "bu/stream.h" +#include "bu/exceptions.h" + +Bu::XmlReader::XmlReader( Stream &rInput ) : + rInput( rInput ), + iCurToken( 0 ), + iNextToken( 0 ), + bIgnoreWS( true ) +{ + nextToken(); + stDocument(); +} + +Bu::XmlReader::~XmlReader() +{ +} + +void Bu::XmlReader::fillBuffer() +{ + if( rInput.isEOS() ) + return; + char buf[1024]; + int iSize = rInput.read( buf, 1024 ); + sBuf.append( buf, iSize ); +} + +void Bu::XmlReader::cleanupBuffer( int iUsed ) +{ + for( int j = 0; j < iUsed; j++ ) + { + if( sBuf[j] == '\n' ) + { + spNextToken.iLine++; + spNextToken.iChar = 1; + } + else + { + spNextToken.iChar++; + } + } + + printf("--Deleting %d bytes from front of buffer.\n", iUsed ); + sBuf.trimFront( iUsed ); +} + +int Bu::XmlReader::nextToken() +{ + fillBuffer(); + + int iUsed = 1; + + iCurToken = iNextToken; + spCurToken = spNextToken; + + switch( sBuf[0] ) + { + case '<': + if( !strncmp( sBuf.getStr(), "' ) + { + iNextToken = tokXmlDeclEnd; + iUsed = 2; + } + else + { + iNextToken = '?'; + } + break; + + case ' ': + case '\t': + case '\n': + case '\r': + for( int j = 1;; j++ ) + { + if( j == sBuf.getSize() ) + { + if( rInput.isEOS() ) + error("Reached end of input while waiting for whitespace to end."); + + fillBuffer(); + } + if( sBuf[j] == ' ' || sBuf[j] == '\t' || + sBuf[j] == '\n' || sBuf[j] == '\r' ) + iUsed++; + else + break; + } + sStr.clear(); + sStr.append( sBuf, iUsed ); + iNextToken = tokWS; + break; + + case '=': + iNextToken = sBuf[0]; + break; + + default: + if( (sBuf[0] >= 'a' && sBuf[0] <= 'z') || + (sBuf[0] >= 'A' && sBuf[0] <= 'Z') ) + { + for( int j = 1;; j++ ) + { + if( j == sBuf.getSize() ) + { + if( rInput.isEOS() ) + error("Reached end of input while waiting for a string to end."); + + fillBuffer(); + } + if( (sBuf[j] >= 'a' && sBuf[j] <= 'z') || + (sBuf[j] >= 'A' && sBuf[j] <= 'Z') ) + iUsed++; + else + break; + } + sStr.clear(); + sStr.append( sBuf, iUsed ); + iNextToken = tokIdent; + } + } + + cleanupBuffer( iUsed ); + + return iCurToken; +} + +void Bu::XmlReader::error( const char *sMessage ) +{ + throw Bu::XmlException("%d:%d: %s", + spCurToken.iLine, spCurToken.iChar, sMessage ); +} + +void Bu::XmlReader::stDocument() +{ + stProlog(); +} + +void Bu::XmlReader::stProlog() +{ + stXmlDecl(); +} + +void Bu::XmlReader::stXmlDecl() +{ + if( nextToken() != tokXmlDeclHead ) + error("You must begin your xml file with a declaration: "); + if( nextToken() != tokIdent ) + error("A version comes first!"); + if( sStr != "version" ) + error("No, a version!"); +} + diff --git a/src/xmlreader.h b/src/xmlreader.h new file mode 100644 index 0000000..375dfe3 --- /dev/null +++ b/src/xmlreader.h @@ -0,0 +1,54 @@ +#ifndef BU_XML_READER_H +#define BU_XML_READER_H + +#include "bu/fstring.h" + +namespace Bu +{ + class Stream; + + class XmlReader + { + public: + XmlReader( Stream &rInput ); + virtual ~XmlReader(); + + private: + Stream &rInput; + int iCurToken; + int iNextToken; + Bu::FString sBuf; + Bu::FString sStr; + bool bIgnoreWS; + typedef struct StreamPos + { + StreamPos() : iLine( 1 ), iChar( 1 ) { } + int iLine; + int iChar; + } StreamPos; + StreamPos spCurToken; + StreamPos spNextToken; + + + enum + { + tokXmlDeclHead = 0x100, + tokXmlDeclEnd, + tokWS, + tokIdent, + tokString + }; + + void fillBuffer(); + void cleanupBuffer( int iUsed ); + int nextToken(); + + void stDocument(); + void stProlog(); + void stXmlDecl(); + + void error( const char *sMessage ); + }; +}; + +#endif -- cgit v1.2.3