mirror of https://github.com/AxioDL/tinyxml2.git
more refactoring. cleaning out container classes.
This commit is contained in:
parent
1270ae58e4
commit
2c85a711f1
64
tinyxml2.cpp
64
tinyxml2.cpp
|
@ -95,6 +95,32 @@ const char* StrPair::GetStr()
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
const char* StringPool::Intern( const char* str )
|
||||||
|
{
|
||||||
|
// Treat the array as a linear, inplace hash table.
|
||||||
|
// Nothing can get deleted, so that's handy.
|
||||||
|
if ( size > pool.Size()*3/4 ) {
|
||||||
|
DynArray< const char*, 20 > store;
|
||||||
|
for( int i=0; i<pool.Size(); ++i ) {
|
||||||
|
if ( pool[i] != 0 ) {
|
||||||
|
store.Push( pool[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int newSize = pool.Size() * 2;
|
||||||
|
pool.PopArr( pool.Size() );
|
||||||
|
|
||||||
|
const char** mem = pool.PushArr( newSize );
|
||||||
|
memset( (void*)mem, 0, sizeof(char)*newSize );
|
||||||
|
|
||||||
|
while ( !store.Empty() ) {
|
||||||
|
Intern( store.Pop() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
// --------- XMLBase ----------- //
|
// --------- XMLBase ----------- //
|
||||||
// fixme: should take in the entity/newline flags as param
|
// fixme: should take in the entity/newline flags as param
|
||||||
|
@ -279,6 +305,20 @@ XMLNode* XMLNode::InsertEndChild( XMLNode* addThis )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
XMLElement* XMLNode::FirstChildElement( const char* value )
|
||||||
|
{
|
||||||
|
for( XMLNode* node=firstChild; node; node=node->next ) {
|
||||||
|
XMLElement* element = node->ToElement();
|
||||||
|
if ( element ) {
|
||||||
|
if ( !value || StringEqual( element->Name(), value ) ) {
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void XMLNode::Print( XMLStreamer* streamer )
|
void XMLNode::Print( XMLStreamer* streamer )
|
||||||
{
|
{
|
||||||
for( XMLNode* node = firstChild; node; node=node->next ) {
|
for( XMLNode* node = firstChild; node; node=node->next ) {
|
||||||
|
@ -530,6 +570,14 @@ void XMLDocument::InitDocument()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
XMLElement* XMLDocument::NewElement( const char* name )
|
||||||
|
{
|
||||||
|
XMLElement* ele = new XMLElement( this );
|
||||||
|
ele->SetName( name );
|
||||||
|
return ele;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int XMLDocument::Parse( const char* p )
|
int XMLDocument::Parse( const char* p )
|
||||||
{
|
{
|
||||||
ClearChildren();
|
ClearChildren();
|
||||||
|
@ -568,6 +616,7 @@ void XMLDocument::SetError( int error, const char* str1, const char* str2 )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
StringStack::StringStack()
|
StringStack::StringStack()
|
||||||
{
|
{
|
||||||
nPositive = 0;
|
nPositive = 0;
|
||||||
|
@ -602,6 +651,7 @@ const char* StringStack::Pop() {
|
||||||
mem.PopArr( strlen(p)+1 );
|
mem.PopArr( strlen(p)+1 );
|
||||||
return p+1;
|
return p+1;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
XMLStreamer::XMLStreamer( FILE* file ) : fp( file ), depth( 0 ), elementJustOpened( false )
|
XMLStreamer::XMLStreamer( FILE* file ) : fp( file ), depth( 0 ), elementJustOpened( false )
|
||||||
|
@ -664,11 +714,11 @@ void XMLStreamer::OpenElement( const char* name, bool textParent )
|
||||||
if ( elementJustOpened ) {
|
if ( elementJustOpened ) {
|
||||||
SealElement();
|
SealElement();
|
||||||
}
|
}
|
||||||
if ( text.NumPositive() == 0 ) {
|
if ( !TextOnStack() ) {
|
||||||
PrintSpace( depth );
|
PrintSpace( depth );
|
||||||
}
|
}
|
||||||
stack.Push( name );
|
stack.Push( name );
|
||||||
text.Push( textParent ? "T" : "" );
|
text.Push( textParent ? 'T' : 'e' );
|
||||||
|
|
||||||
// fixme: can names have entities?
|
// fixme: can names have entities?
|
||||||
fprintf( fp, "<%s", name );
|
fprintf( fp, "<%s", name );
|
||||||
|
@ -690,22 +740,22 @@ void XMLStreamer::CloseElement()
|
||||||
{
|
{
|
||||||
--depth;
|
--depth;
|
||||||
const char* name = stack.Pop();
|
const char* name = stack.Pop();
|
||||||
int wasPositive = text.NumPositive();
|
bool wasText = TextOnStack();
|
||||||
text.Pop();
|
text.Pop();
|
||||||
|
|
||||||
if ( elementJustOpened ) {
|
if ( elementJustOpened ) {
|
||||||
fprintf( fp, "/>" );
|
fprintf( fp, "/>" );
|
||||||
if ( text.NumPositive() == 0 ) {
|
if ( !wasText ) {
|
||||||
fprintf( fp, "\n" );
|
fprintf( fp, "\n" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ( wasPositive == 0 ) {
|
if ( !wasText ) {
|
||||||
PrintSpace( depth );
|
PrintSpace( depth );
|
||||||
}
|
}
|
||||||
// fixme can names have entities?
|
// fixme can names have entities?
|
||||||
fprintf( fp, "</%s>", name );
|
fprintf( fp, "</%s>", name );
|
||||||
if ( text.NumPositive() == 0 ) {
|
if ( !TextOnStack() ) {
|
||||||
fprintf( fp, "\n" );
|
fprintf( fp, "\n" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -717,7 +767,7 @@ void XMLStreamer::SealElement()
|
||||||
{
|
{
|
||||||
elementJustOpened = false;
|
elementJustOpened = false;
|
||||||
fprintf( fp, ">" );
|
fprintf( fp, ">" );
|
||||||
if ( text.NumPositive() == 0 ) {
|
if ( !TextOnStack() ) {
|
||||||
fprintf( fp, "\n" );
|
fprintf( fp, "\n" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
272
tinyxml2.h
272
tinyxml2.h
|
@ -1,9 +1,23 @@
|
||||||
#ifndef TINYXML2_INCLUDED
|
#ifndef TINYXML2_INCLUDED
|
||||||
#define TINYXML2_INCLUDED
|
#define TINYXML2_INCLUDED
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO
|
||||||
|
- const and non-const versions of API
|
||||||
|
- memory pool the class construction
|
||||||
|
- attribute accessors
|
||||||
|
- node navigation
|
||||||
|
- handles
|
||||||
|
- visit pattern - change streamer?
|
||||||
|
- make constructors protected
|
||||||
|
- hide copy constructor
|
||||||
|
- hide = operator
|
||||||
|
*/
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <memory.h>
|
||||||
|
|
||||||
#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
|
#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
|
||||||
#ifndef DEBUG
|
#ifndef DEBUG
|
||||||
|
@ -38,18 +52,6 @@ class XMLText;
|
||||||
|
|
||||||
class XMLStreamer;
|
class XMLStreamer;
|
||||||
|
|
||||||
/*
|
|
||||||
// internal - move to separate namespace
|
|
||||||
struct CharBuffer
|
|
||||||
{
|
|
||||||
size_t length;
|
|
||||||
char mem[1];
|
|
||||||
|
|
||||||
static CharBuffer* Construct( const char* in );
|
|
||||||
static void Free( CharBuffer* );
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
class StrPair
|
class StrPair
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -70,6 +72,8 @@ public:
|
||||||
const char* GetStr();
|
const char* GetStr();
|
||||||
bool Empty() const { return start == end; }
|
bool Empty() const { return start == end; }
|
||||||
|
|
||||||
|
void SetInternedStr( const char* str ) { this->start = (char*) str; this->end = 0; this->flags = 0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum {
|
enum {
|
||||||
NEEDS_FLUSH = 0x100
|
NEEDS_FLUSH = 0x100
|
||||||
|
@ -82,6 +86,121 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class T, int INIT>
|
||||||
|
class DynArray
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DynArray< T, INIT >()
|
||||||
|
{
|
||||||
|
mem = pool;
|
||||||
|
allocated = INIT;
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
~DynArray()
|
||||||
|
{
|
||||||
|
if ( mem != pool ) {
|
||||||
|
delete mem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Push( T t )
|
||||||
|
{
|
||||||
|
EnsureCapacity( size+1 );
|
||||||
|
mem[size++] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* PushArr( int count )
|
||||||
|
{
|
||||||
|
EnsureCapacity( size+count );
|
||||||
|
T* ret = &mem[size];
|
||||||
|
size += count;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
T Pop() {
|
||||||
|
return mem[--size];
|
||||||
|
}
|
||||||
|
void PopArr( int count )
|
||||||
|
{
|
||||||
|
TIXMLASSERT( size >= count );
|
||||||
|
size -= count;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Empty() const { return size == 0; }
|
||||||
|
T& operator[](int i) { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
|
||||||
|
const T& operator[](int i) const { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
|
||||||
|
int Size() const { return size; }
|
||||||
|
const T* Mem() const { return mem; }
|
||||||
|
T* Mem() { return mem; }
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
void EnsureCapacity( int cap ) {
|
||||||
|
if ( cap > allocated ) {
|
||||||
|
int newAllocated = cap * 2;
|
||||||
|
T* newMem = new T[newAllocated];
|
||||||
|
memcpy( newMem, mem, sizeof(T)*size ); // warning: not using constructors, only works for PODs
|
||||||
|
if ( mem != pool ) delete [] mem;
|
||||||
|
mem = newMem;
|
||||||
|
allocated = newAllocated;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T* mem;
|
||||||
|
T pool[INIT];
|
||||||
|
int allocated; // objects allocated
|
||||||
|
int size; // number objects in use
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
class StringStack
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
StringStack();
|
||||||
|
virtual ~StringStack();
|
||||||
|
|
||||||
|
void Push( const char* str );
|
||||||
|
const char* Pop();
|
||||||
|
|
||||||
|
int NumPositive() const { return nPositive; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
DynArray< char, 50 > mem;
|
||||||
|
int nPositive; // number of strings with len > 0
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
class StringPool
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum { INIT_SIZE=20 };
|
||||||
|
|
||||||
|
StringPool() : size( 0 ) {
|
||||||
|
const char** mem = pool.PushArr( INIT_SIZE );
|
||||||
|
memset( (void*)mem, 0, sizeof(char)*INIT_SIZE );
|
||||||
|
}
|
||||||
|
~StringPool() {}
|
||||||
|
|
||||||
|
const char* Intern( const char* str );
|
||||||
|
|
||||||
|
private:
|
||||||
|
// FNV hash
|
||||||
|
int Hash( const char* s ) {
|
||||||
|
#define FNV_32_PRIME ((int)0x01000193)
|
||||||
|
int hval = 0;
|
||||||
|
while (*s) {
|
||||||
|
hval *= FNV_32_PRIME;
|
||||||
|
hval ^= (int)*s++;
|
||||||
|
}
|
||||||
|
return hval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int size;
|
||||||
|
DynArray< const char*, INIT_SIZE > pool; // the hash table
|
||||||
|
StringStack store; // memory for the interned strings
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
class XMLBase
|
class XMLBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -125,10 +244,16 @@ public:
|
||||||
XMLNode* InsertEndChild( XMLNode* addThis );
|
XMLNode* InsertEndChild( XMLNode* addThis );
|
||||||
virtual void Print( XMLStreamer* streamer );
|
virtual void Print( XMLStreamer* streamer );
|
||||||
|
|
||||||
|
const char* Value() const { return value.GetStr(); }
|
||||||
|
void SetValue( const char* val ) { value.SetInternedStr( val ); }
|
||||||
|
|
||||||
virtual XMLElement* ToElement() { return 0; }
|
virtual XMLElement* ToElement() { return 0; }
|
||||||
virtual XMLText* ToText() { return 0; }
|
virtual XMLText* ToText() { return 0; }
|
||||||
virtual XMLComment* ToComment() { return 0; }
|
virtual XMLComment* ToComment() { return 0; }
|
||||||
|
|
||||||
|
XMLNode* FirstChild() { return firstChild; }
|
||||||
|
XMLElement* FirstChildElement( const char* value=0 );
|
||||||
|
|
||||||
// fixme: guarentee null terminator to avoid internal checks
|
// fixme: guarentee null terminator to avoid internal checks
|
||||||
virtual char* ParseDeep( char* );
|
virtual char* ParseDeep( char* );
|
||||||
|
|
||||||
|
@ -143,6 +268,7 @@ protected:
|
||||||
XMLDocument* document;
|
XMLDocument* document;
|
||||||
XMLNode* parent;
|
XMLNode* parent;
|
||||||
bool isTextParent;
|
bool isTextParent;
|
||||||
|
mutable StrPair value;
|
||||||
|
|
||||||
XMLNode* firstChild;
|
XMLNode* firstChild;
|
||||||
XMLNode* lastChild;
|
XMLNode* lastChild;
|
||||||
|
@ -157,29 +283,31 @@ private:
|
||||||
|
|
||||||
class XMLText : public XMLNode
|
class XMLText : public XMLNode
|
||||||
{
|
{
|
||||||
|
friend class XMLBase;
|
||||||
|
friend class XMLDocument;
|
||||||
public:
|
public:
|
||||||
XMLText( XMLDocument* doc ) : XMLNode( doc ) {}
|
|
||||||
virtual ~XMLText() {}
|
virtual ~XMLText() {}
|
||||||
|
|
||||||
virtual void Print( XMLStreamer* streamer );
|
virtual void Print( XMLStreamer* streamer );
|
||||||
const char* Value() { return value.GetStr(); }
|
const char* Value() { return value.GetStr(); }
|
||||||
|
void SetValue( const char* );
|
||||||
|
|
||||||
virtual XMLText* ToText() { return this; }
|
virtual XMLText* ToText() { return this; }
|
||||||
|
|
||||||
char* ParseDeep( char* );
|
char* ParseDeep( char* );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
XMLText( XMLDocument* doc ) : XMLNode( doc ) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StrPair value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class XMLComment : public XMLNode
|
class XMLComment : public XMLNode
|
||||||
{
|
{
|
||||||
|
friend class XMLBase;
|
||||||
|
friend class XMLDocument;
|
||||||
public:
|
public:
|
||||||
XMLComment( XMLDocument* doc );
|
|
||||||
virtual ~XMLComment();
|
virtual ~XMLComment();
|
||||||
|
|
||||||
virtual void Print( XMLStreamer* );
|
virtual void Print( XMLStreamer* );
|
||||||
virtual XMLComment* ToComment() { return this; }
|
virtual XMLComment* ToComment() { return this; }
|
||||||
|
|
||||||
|
@ -188,9 +316,10 @@ public:
|
||||||
char* ParseDeep( char* );
|
char* ParseDeep( char* );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
XMLComment( XMLDocument* doc );
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StrPair value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -213,24 +342,29 @@ private:
|
||||||
|
|
||||||
class XMLElement : public XMLNode
|
class XMLElement : public XMLNode
|
||||||
{
|
{
|
||||||
|
friend class XMLBase;
|
||||||
|
friend class XMLDocument;
|
||||||
public:
|
public:
|
||||||
XMLElement( XMLDocument* doc );
|
|
||||||
virtual ~XMLElement();
|
virtual ~XMLElement();
|
||||||
|
|
||||||
const char* Name() { return name.GetStr(); }
|
const char* Name() const { return Value(); }
|
||||||
|
void SetName( const char* str ) { SetValue( str ); }
|
||||||
|
|
||||||
virtual void Print( XMLStreamer* );
|
virtual void Print( XMLStreamer* );
|
||||||
|
|
||||||
virtual XMLElement* ToElement() { return this; }
|
virtual XMLElement* ToElement() { return this; }
|
||||||
virtual bool IsClosingElement() const { return closing; }
|
|
||||||
|
|
||||||
|
// internal:
|
||||||
|
virtual bool IsClosingElement() const { return closing; }
|
||||||
char* ParseDeep( char* p );
|
char* ParseDeep( char* p );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
XMLElement( XMLDocument* doc );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char* ParseAttributes( char* p, bool *closedElement );
|
char* ParseAttributes( char* p, bool *closedElement );
|
||||||
|
|
||||||
StrPair name;
|
mutable StrPair name;
|
||||||
bool closing;
|
bool closing;
|
||||||
XMLAttribute* rootAttribute;
|
XMLAttribute* rootAttribute;
|
||||||
XMLAttribute* lastAttribute;
|
XMLAttribute* lastAttribute;
|
||||||
|
@ -249,6 +383,8 @@ public:
|
||||||
|
|
||||||
void Print( XMLStreamer* streamer=0 );
|
void Print( XMLStreamer* streamer=0 );
|
||||||
|
|
||||||
|
XMLElement* NewElement( const char* name );
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
NO_ERROR = 0,
|
NO_ERROR = 0,
|
||||||
ERROR_ELEMENT_MISMATCH,
|
ERROR_ELEMENT_MISMATCH,
|
||||||
|
@ -262,6 +398,8 @@ public:
|
||||||
const char* GetErrorStr1() const { return errorStr1; }
|
const char* GetErrorStr1() const { return errorStr1; }
|
||||||
const char* GetErrorStr2() const { return errorStr2; }
|
const char* GetErrorStr2() const { return errorStr2; }
|
||||||
|
|
||||||
|
// const char* Intern( const char* );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
XMLDocument( const XMLDocument& ); // intentionally not implemented
|
XMLDocument( const XMLDocument& ); // intentionally not implemented
|
||||||
void InitDocument();
|
void InitDocument();
|
||||||
|
@ -270,84 +408,7 @@ private:
|
||||||
const char* errorStr1;
|
const char* errorStr1;
|
||||||
const char* errorStr2;
|
const char* errorStr2;
|
||||||
char* charBuffer;
|
char* charBuffer;
|
||||||
};
|
//StringStack stringPool;
|
||||||
|
|
||||||
|
|
||||||
template <class T, int INIT>
|
|
||||||
class DynArray
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DynArray< T, INIT >()
|
|
||||||
{
|
|
||||||
mem = pool;
|
|
||||||
allocated = INIT;
|
|
||||||
size = 0;
|
|
||||||
}
|
|
||||||
~DynArray()
|
|
||||||
{
|
|
||||||
if ( mem != pool ) {
|
|
||||||
delete mem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void Push( T t )
|
|
||||||
{
|
|
||||||
EnsureCapacity( size+1 );
|
|
||||||
mem[size++] = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
T* PushArr( int count )
|
|
||||||
{
|
|
||||||
EnsureCapacity( size+count );
|
|
||||||
T* ret = &mem[size];
|
|
||||||
size += count;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
T Pop() {
|
|
||||||
return mem[--size];
|
|
||||||
}
|
|
||||||
void PopArr( int count )
|
|
||||||
{
|
|
||||||
TIXMLASSERT( size >= count );
|
|
||||||
size -= count;
|
|
||||||
}
|
|
||||||
int Size() const { return size; }
|
|
||||||
const T* Mem() const { return mem; }
|
|
||||||
T* Mem() { return mem; }
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
void EnsureCapacity( int cap ) {
|
|
||||||
if ( cap > allocated ) {
|
|
||||||
int newAllocated = cap * 2;
|
|
||||||
T* newMem = new T[newAllocated];
|
|
||||||
memcpy( newMem, mem, sizeof(T)*size ); // warning: not using constructors, only works for PODs
|
|
||||||
if ( mem != pool ) delete [] mem;
|
|
||||||
mem = newMem;
|
|
||||||
allocated = newAllocated;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
T* mem;
|
|
||||||
T pool[INIT];
|
|
||||||
int allocated; // objects allocated
|
|
||||||
int size; // number objects in use
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class StringStack
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
StringStack();
|
|
||||||
virtual ~StringStack();
|
|
||||||
|
|
||||||
void Push( const char* str );
|
|
||||||
const char* Pop();
|
|
||||||
|
|
||||||
int NumPositive() const { return nPositive; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
DynArray< char, 50 > mem;
|
|
||||||
int nPositive; // number of strings with len > 0
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -368,6 +429,13 @@ private:
|
||||||
void SealElement();
|
void SealElement();
|
||||||
void PrintSpace( int depth );
|
void PrintSpace( int depth );
|
||||||
void PrintString( const char* ); // prints out, after detecting entities.
|
void PrintString( const char* ); // prints out, after detecting entities.
|
||||||
|
bool TextOnStack() const {
|
||||||
|
for( int i=0; i<text.Size(); ++i ) {
|
||||||
|
if ( text[i] == 'T' )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
FILE* fp;
|
FILE* fp;
|
||||||
int depth;
|
int depth;
|
||||||
|
@ -377,8 +445,8 @@ private:
|
||||||
};
|
};
|
||||||
bool entityFlag[ENTITY_RANGE];
|
bool entityFlag[ENTITY_RANGE];
|
||||||
|
|
||||||
DynArray< const char*, 40 > stack;
|
DynArray< const char*, 10 > stack;
|
||||||
StringStack text;
|
DynArray< char, 10 > text;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -52,5 +52,14 @@ int main( int argc, const char* argv )
|
||||||
printf( "----------------------------------------------\n" );
|
printf( "----------------------------------------------\n" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
static const char* test = "<element>Text before.</element>";
|
||||||
|
XMLDocument doc;
|
||||||
|
doc.Parse( test );
|
||||||
|
XMLElement* root = doc.FirstChildElement();
|
||||||
|
XMLElement* newElement = doc.NewElement( "Subelement" );
|
||||||
|
root->InsertEndChild( newElement );
|
||||||
|
doc.Print();
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
Loading…
Reference in New Issue