|
@@ -70,6 +70,29 @@ StrPair::~StrPair()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+void StrPair::TransferTo( StrPair& other )
|
|
|
|
|
+{
|
|
|
|
|
+ if ( this == &other ) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ // This in effect implements the assignment operator by "moving"
|
|
|
|
|
+ // ownership (as in auto_ptr).
|
|
|
|
|
+
|
|
|
|
|
+ TIXMLASSERT( other._flags == 0 );
|
|
|
|
|
+ TIXMLASSERT( other._start == 0 );
|
|
|
|
|
+ TIXMLASSERT( other._end == 0 );
|
|
|
|
|
+
|
|
|
|
|
+ other.Reset();
|
|
|
|
|
+
|
|
|
|
|
+ other._flags = _flags;
|
|
|
|
|
+ other._start = _start;
|
|
|
|
|
+ other._end = _end;
|
|
|
|
|
+
|
|
|
|
|
+ _flags = 0;
|
|
|
|
|
+ _start = 0;
|
|
|
|
|
+ _end = 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
void StrPair::Reset()
|
|
void StrPair::Reset()
|
|
|
{
|
|
{
|
|
|
if ( _flags & NEEDS_DELETE ) {
|
|
if ( _flags & NEEDS_DELETE ) {
|
|
@@ -212,12 +235,13 @@ const char* StrPair::GetStr()
|
|
|
else {
|
|
else {
|
|
|
int i=0;
|
|
int i=0;
|
|
|
for(; i<NUM_ENTITIES; ++i ) {
|
|
for(; i<NUM_ENTITIES; ++i ) {
|
|
|
- if ( strncmp( p+1, entities[i].pattern, entities[i].length ) == 0
|
|
|
|
|
- && *(p+entities[i].length+1) == ';' ) {
|
|
|
|
|
- // Found an entity convert;
|
|
|
|
|
- *q = entities[i].value;
|
|
|
|
|
|
|
+ const Entity& entity = entities[i];
|
|
|
|
|
+ if ( strncmp( p + 1, entity.pattern, entity.length ) == 0
|
|
|
|
|
+ && *( p + entity.length + 1 ) == ';' ) {
|
|
|
|
|
+ // Found an entity - convert.
|
|
|
|
|
+ *q = entity.value;
|
|
|
++q;
|
|
++q;
|
|
|
- p += entities[i].length + 2;
|
|
|
|
|
|
|
+ p += entity.length + 2;
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -823,7 +847,7 @@ char* XMLNode::ParseDeep( char* p, StrPair* parentEnd )
|
|
|
// We read the end tag. Return it to the parent.
|
|
// We read the end tag. Return it to the parent.
|
|
|
if ( ele && ele->ClosingType() == XMLElement::CLOSING ) {
|
|
if ( ele && ele->ClosingType() == XMLElement::CLOSING ) {
|
|
|
if ( parentEnd ) {
|
|
if ( parentEnd ) {
|
|
|
- *parentEnd = ele->_value;
|
|
|
|
|
|
|
+ ele->_value.TransferTo( *parentEnd );
|
|
|
}
|
|
}
|
|
|
node->_memPool->SetTracked(); // created and then immediately deleted.
|
|
node->_memPool->SetTracked(); // created and then immediately deleted.
|
|
|
DeleteNode( node );
|
|
DeleteNode( node );
|
|
@@ -1257,7 +1281,7 @@ const char* XMLElement::Attribute( const char* name, const char* value ) const
|
|
|
const char* XMLElement::GetText() const
|
|
const char* XMLElement::GetText() const
|
|
|
{
|
|
{
|
|
|
if ( FirstChild() && FirstChild()->ToText() ) {
|
|
if ( FirstChild() && FirstChild()->ToText() ) {
|
|
|
- return FirstChild()->ToText()->Value();
|
|
|
|
|
|
|
+ return FirstChild()->Value();
|
|
|
}
|
|
}
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
@@ -1317,7 +1341,7 @@ void XMLElement::SetText( double v )
|
|
|
XMLError XMLElement::QueryIntText( int* ival ) const
|
|
XMLError XMLElement::QueryIntText( int* ival ) const
|
|
|
{
|
|
{
|
|
|
if ( FirstChild() && FirstChild()->ToText() ) {
|
|
if ( FirstChild() && FirstChild()->ToText() ) {
|
|
|
- const char* t = FirstChild()->ToText()->Value();
|
|
|
|
|
|
|
+ const char* t = FirstChild()->Value();
|
|
|
if ( XMLUtil::ToInt( t, ival ) ) {
|
|
if ( XMLUtil::ToInt( t, ival ) ) {
|
|
|
return XML_SUCCESS;
|
|
return XML_SUCCESS;
|
|
|
}
|
|
}
|
|
@@ -1330,7 +1354,7 @@ XMLError XMLElement::QueryIntText( int* ival ) const
|
|
|
XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const
|
|
XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const
|
|
|
{
|
|
{
|
|
|
if ( FirstChild() && FirstChild()->ToText() ) {
|
|
if ( FirstChild() && FirstChild()->ToText() ) {
|
|
|
- const char* t = FirstChild()->ToText()->Value();
|
|
|
|
|
|
|
+ const char* t = FirstChild()->Value();
|
|
|
if ( XMLUtil::ToUnsigned( t, uval ) ) {
|
|
if ( XMLUtil::ToUnsigned( t, uval ) ) {
|
|
|
return XML_SUCCESS;
|
|
return XML_SUCCESS;
|
|
|
}
|
|
}
|
|
@@ -1343,7 +1367,7 @@ XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const
|
|
|
XMLError XMLElement::QueryBoolText( bool* bval ) const
|
|
XMLError XMLElement::QueryBoolText( bool* bval ) const
|
|
|
{
|
|
{
|
|
|
if ( FirstChild() && FirstChild()->ToText() ) {
|
|
if ( FirstChild() && FirstChild()->ToText() ) {
|
|
|
- const char* t = FirstChild()->ToText()->Value();
|
|
|
|
|
|
|
+ const char* t = FirstChild()->Value();
|
|
|
if ( XMLUtil::ToBool( t, bval ) ) {
|
|
if ( XMLUtil::ToBool( t, bval ) ) {
|
|
|
return XML_SUCCESS;
|
|
return XML_SUCCESS;
|
|
|
}
|
|
}
|
|
@@ -1356,7 +1380,7 @@ XMLError XMLElement::QueryBoolText( bool* bval ) const
|
|
|
XMLError XMLElement::QueryDoubleText( double* dval ) const
|
|
XMLError XMLElement::QueryDoubleText( double* dval ) const
|
|
|
{
|
|
{
|
|
|
if ( FirstChild() && FirstChild()->ToText() ) {
|
|
if ( FirstChild() && FirstChild()->ToText() ) {
|
|
|
- const char* t = FirstChild()->ToText()->Value();
|
|
|
|
|
|
|
+ const char* t = FirstChild()->Value();
|
|
|
if ( XMLUtil::ToDouble( t, dval ) ) {
|
|
if ( XMLUtil::ToDouble( t, dval ) ) {
|
|
|
return XML_SUCCESS;
|
|
return XML_SUCCESS;
|
|
|
}
|
|
}
|
|
@@ -1369,7 +1393,7 @@ XMLError XMLElement::QueryDoubleText( double* dval ) const
|
|
|
XMLError XMLElement::QueryFloatText( float* fval ) const
|
|
XMLError XMLElement::QueryFloatText( float* fval ) const
|
|
|
{
|
|
{
|
|
|
if ( FirstChild() && FirstChild()->ToText() ) {
|
|
if ( FirstChild() && FirstChild()->ToText() ) {
|
|
|
- const char* t = FirstChild()->ToText()->Value();
|
|
|
|
|
|
|
+ const char* t = FirstChild()->Value();
|
|
|
if ( XMLUtil::ToFloat( t, fval ) ) {
|
|
if ( XMLUtil::ToFloat( t, fval ) ) {
|
|
|
return XML_SUCCESS;
|
|
return XML_SUCCESS;
|
|
|
}
|
|
}
|
|
@@ -1622,24 +1646,7 @@ XMLDocument::XMLDocument( bool processEntities, Whitespace whitespace ) :
|
|
|
|
|
|
|
|
XMLDocument::~XMLDocument()
|
|
XMLDocument::~XMLDocument()
|
|
|
{
|
|
{
|
|
|
- DeleteChildren();
|
|
|
|
|
- delete [] _charBuffer;
|
|
|
|
|
-
|
|
|
|
|
-#if 0
|
|
|
|
|
- _textPool.Trace( "text" );
|
|
|
|
|
- _elementPool.Trace( "element" );
|
|
|
|
|
- _commentPool.Trace( "comment" );
|
|
|
|
|
- _attributePool.Trace( "attribute" );
|
|
|
|
|
-#endif
|
|
|
|
|
-
|
|
|
|
|
-#ifdef DEBUG
|
|
|
|
|
- if ( Error() == false ) {
|
|
|
|
|
- TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() );
|
|
|
|
|
- TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() );
|
|
|
|
|
- TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() );
|
|
|
|
|
- TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() );
|
|
|
|
|
- }
|
|
|
|
|
-#endif
|
|
|
|
|
|
|
+ Clear();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1653,6 +1660,22 @@ void XMLDocument::Clear()
|
|
|
|
|
|
|
|
delete [] _charBuffer;
|
|
delete [] _charBuffer;
|
|
|
_charBuffer = 0;
|
|
_charBuffer = 0;
|
|
|
|
|
+
|
|
|
|
|
+#if 0
|
|
|
|
|
+ _textPool.Trace( "text" );
|
|
|
|
|
+ _elementPool.Trace( "element" );
|
|
|
|
|
+ _commentPool.Trace( "comment" );
|
|
|
|
|
+ _attributePool.Trace( "attribute" );
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+#ifdef DEBUG
|
|
|
|
|
+ if ( Error() == false ) {
|
|
|
|
|
+ TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() );
|
|
|
|
|
+ TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() );
|
|
|
|
|
+ TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() );
|
|
|
|
|
+ TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() );
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1820,6 +1843,16 @@ XMLError XMLDocument::Parse( const char* p, size_t len )
|
|
|
|
|
|
|
|
ptrdiff_t delta = p - start; // skip initial whitespace, BOM, etc.
|
|
ptrdiff_t delta = p - start; // skip initial whitespace, BOM, etc.
|
|
|
ParseDeep( _charBuffer+delta, 0 );
|
|
ParseDeep( _charBuffer+delta, 0 );
|
|
|
|
|
+ if (_errorID) {
|
|
|
|
|
+ // clean up now essentially dangling memory.
|
|
|
|
|
+ // and the parse fail can put objects in the
|
|
|
|
|
+ // pools that are dead and inaccessible.
|
|
|
|
|
+ DeleteChildren();
|
|
|
|
|
+ _elementPool.Clear();
|
|
|
|
|
+ _attributePool.Clear();
|
|
|
|
|
+ _textPool.Clear();
|
|
|
|
|
+ _commentPool.Clear();
|
|
|
|
|
+ }
|
|
|
return _errorID;
|
|
return _errorID;
|
|
|
}
|
|
}
|
|
|
|
|
|