refactored to allow progressive parsing

pull/40/head
Matchman Green 2012-05-05 15:25:21 +08:00
parent 19c329836b
commit b89f7bb873
2 changed files with 47 additions and 23 deletions

View File

@ -25,20 +25,33 @@
#include <cassert> #include <cassert>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <stdexcept>
namespace gr { namespace xml { namespace gr { namespace xml {
TreeBuilder::TreeBuilder() : m_stack( 1, Node() ) struct TreeBuilder::Impl
{
std::vector<Node> stack ;
::XML_Parser psr ;
} ;
TreeBuilder::TreeBuilder() : m_impl( new Impl )
{
m_impl->stack.push_back( Node() ) ;
m_impl->psr = ::XML_ParserCreate( 0 ) ;
::XML_SetElementHandler( m_impl->psr, &TreeBuilder::StartElement, &TreeBuilder::EndElement ) ;
::XML_SetUserData( m_impl->psr , this ) ;
}
TreeBuilder::~TreeBuilder()
{ {
} }
Node TreeBuilder::ParseFile( const std::string& file ) Node TreeBuilder::ParseFile( const std::string& file )
{ {
::XML_Parser p = ::XML_ParserCreate( 0 ) ;
::XML_SetElementHandler( p, &TreeBuilder::StartElement, &TreeBuilder::EndElement ) ;
TreeBuilder tb ; TreeBuilder tb ;
::XML_SetUserData( p, &tb ) ; ::XML_Parser p = tb.m_impl->psr ;
std::ifstream f( file.c_str() ) ; std::ifstream f( file.c_str() ) ;
@ -48,22 +61,26 @@ Node TreeBuilder::ParseFile( const std::string& file )
XML_ParseBuffer( p, count, false ) ; XML_ParseBuffer( p, count, false ) ;
XML_ParseBuffer( p, 0, true ) ; XML_ParseBuffer( p, 0, true ) ;
assert( tb.m_stack.size() == 1 ) ; return tb.Result() ;
return tb.m_stack.front() ; }
void TreeBuilder::ParseData( const char *data, std::size_t count, bool last )
{
if ( ::XML_Parse( m_impl->psr, data, count, last ) == 0 )
throw std::runtime_error( "XML parse error" ) ;
} }
Node TreeBuilder::Parse( const std::string& xml ) Node TreeBuilder::Parse( const std::string& xml )
{ {
::XML_Parser p = ::XML_ParserCreate( 0 ) ;
::XML_SetElementHandler( p, &TreeBuilder::StartElement, &TreeBuilder::EndElement ) ;
TreeBuilder tb ; TreeBuilder tb ;
::XML_SetUserData( p, &tb ) ; tb.ParseData( xml.c_str(), xml.size(), true ) ;
return tb.Result() ;
}
XML_Parse( p, xml.c_str(), xml.size(), true ) ; Node TreeBuilder::Result() const
{
assert( tb.m_stack.size() == 1 ) ; assert( m_impl->stack.size() == 1 ) ;
return tb.m_stack.front() ; return m_impl->stack.front() ;
} }
void TreeBuilder::StartElement( void *pvthis, const char *name, const char **attr ) void TreeBuilder::StartElement( void *pvthis, const char *name, const char **attr )
@ -74,7 +91,7 @@ void TreeBuilder::StartElement( void *pvthis, const char *name, const char **att
TreeBuilder *pthis = reinterpret_cast<TreeBuilder*>(pvthis) ; TreeBuilder *pthis = reinterpret_cast<TreeBuilder*>(pvthis) ;
Node n = pthis->m_stack.back().AddElement( name ) ; Node n = pthis->m_impl->stack.back().AddElement( name ) ;
for ( std::size_t i = 0 ; attr[i] != 0 ; i += 2 ) for ( std::size_t i = 0 ; attr[i] != 0 ; i += 2 )
{ {
@ -82,15 +99,15 @@ void TreeBuilder::StartElement( void *pvthis, const char *name, const char **att
n.AddAttribute( attr[i], attr[i+1] ) ; n.AddAttribute( attr[i], attr[i+1] ) ;
} }
pthis->m_stack.push_back( n ) ; pthis->m_impl->stack.push_back( n ) ;
} }
void TreeBuilder::EndElement( void* pvthis, const char* name ) void TreeBuilder::EndElement( void* pvthis, const char* name )
{ {
TreeBuilder *pthis = reinterpret_cast<TreeBuilder*>(pvthis) ; TreeBuilder *pthis = reinterpret_cast<TreeBuilder*>(pvthis) ;
assert( pthis->m_stack.back().Name() == name ) ; assert( pthis->m_impl->stack.back().Name() == name ) ;
pthis->m_stack.pop_back() ; pthis->m_impl->stack.pop_back() ;
} }
} } // end of namespace } } // end of namespace

View File

@ -19,8 +19,8 @@
#pragma once #pragma once
#include <memory>
#include <string> #include <string>
#include <vector>
namespace gr { namespace xml { namespace gr { namespace xml {
@ -29,17 +29,24 @@ class Node ;
class TreeBuilder class TreeBuilder
{ {
public : public :
TreeBuilder() ;
~TreeBuilder() ;
void ParseData( const char *data, std::size_t count, bool last = false ) ;
Node Result( ) const ;
// one shot helpers
static Node ParseFile( const std::string& file ) ; static Node ParseFile( const std::string& file ) ;
static Node Parse( const std::string& xml ) ; static Node Parse( const std::string& xml ) ;
private : private :
TreeBuilder() ;
static void StartElement( void* pvthis, const char* name, const char** attr ) ; static void StartElement( void* pvthis, const char* name, const char** attr ) ;
static void EndElement( void* pvthis, const char* name ) ; static void EndElement( void* pvthis, const char* name ) ;
private : private :
std::vector<Node> m_stack ; struct Impl ;
std::auto_ptr<Impl> m_impl ;
} ; } ;
} } // end of namespace } } // end of namespace