more refactoring. cleaning out container classes.
diff --git a/tinyxml2.h b/tinyxml2.h
index 4d2d70e..afd01f4 100644
--- a/tinyxml2.h
+++ b/tinyxml2.h
@@ -1,9 +1,23 @@
#ifndef 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 <ctype.h>
#include <stdio.h>
+#include <memory.h>
#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
#ifndef DEBUG
@@ -38,18 +52,6 @@
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
{
public:
@@ -70,6 +72,8 @@
const char* GetStr();
bool Empty() const { return start == end; }
+ void SetInternedStr( const char* str ) { this->start = (char*) str; this->end = 0; this->flags = 0; }
+
private:
enum {
NEEDS_FLUSH = 0x100
@@ -82,6 +86,121 @@
};
+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
{
public:
@@ -125,10 +244,16 @@
XMLNode* InsertEndChild( XMLNode* addThis );
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 XMLText* ToText() { 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
virtual char* ParseDeep( char* );
@@ -143,6 +268,7 @@
XMLDocument* document;
XMLNode* parent;
bool isTextParent;
+ mutable StrPair value;
XMLNode* firstChild;
XMLNode* lastChild;
@@ -157,29 +283,31 @@
class XMLText : public XMLNode
{
+ friend class XMLBase;
+ friend class XMLDocument;
public:
- XMLText( XMLDocument* doc ) : XMLNode( doc ) {}
virtual ~XMLText() {}
-
virtual void Print( XMLStreamer* streamer );
const char* Value() { return value.GetStr(); }
+ void SetValue( const char* );
+
virtual XMLText* ToText() { return this; }
char* ParseDeep( char* );
protected:
+ XMLText( XMLDocument* doc ) : XMLNode( doc ) {}
private:
- StrPair value;
};
class XMLComment : public XMLNode
{
+ friend class XMLBase;
+ friend class XMLDocument;
public:
- XMLComment( XMLDocument* doc );
virtual ~XMLComment();
-
virtual void Print( XMLStreamer* );
virtual XMLComment* ToComment() { return this; }
@@ -188,9 +316,10 @@
char* ParseDeep( char* );
protected:
+ XMLComment( XMLDocument* doc );
+
private:
- StrPair value;
};
@@ -213,24 +342,29 @@
class XMLElement : public XMLNode
{
+ friend class XMLBase;
+ friend class XMLDocument;
public:
- XMLElement( XMLDocument* doc );
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 XMLElement* ToElement() { return this; }
- virtual bool IsClosingElement() const { return closing; }
+ // internal:
+ virtual bool IsClosingElement() const { return closing; }
char* ParseDeep( char* p );
protected:
+ XMLElement( XMLDocument* doc );
private:
char* ParseAttributes( char* p, bool *closedElement );
- StrPair name;
+ mutable StrPair name;
bool closing;
XMLAttribute* rootAttribute;
XMLAttribute* lastAttribute;
@@ -249,6 +383,8 @@
void Print( XMLStreamer* streamer=0 );
+ XMLElement* NewElement( const char* name );
+
enum {
NO_ERROR = 0,
ERROR_ELEMENT_MISMATCH,
@@ -262,6 +398,8 @@
const char* GetErrorStr1() const { return errorStr1; }
const char* GetErrorStr2() const { return errorStr2; }
+// const char* Intern( const char* );
+
private:
XMLDocument( const XMLDocument& ); // intentionally not implemented
void InitDocument();
@@ -270,84 +408,7 @@
const char* errorStr1;
const char* errorStr2;
char* charBuffer;
-};
-
-
-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
+ //StringStack stringPool;
};
@@ -368,6 +429,13 @@
void SealElement();
void PrintSpace( int depth );
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;
int depth;
@@ -377,8 +445,8 @@
};
bool entityFlag[ENTITY_RANGE];
- DynArray< const char*, 40 > stack;
- StringStack text;
+ DynArray< const char*, 10 > stack;
+ DynArray< char, 10 > text;
};