You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
306 lines
8.0 KiB
C
306 lines
8.0 KiB
C
7 months ago
|
/*
|
||
|
www.sourceforge.net/projects/tinyxml
|
||
|
|
||
|
This software is provided 'as-is', without any express or implied
|
||
|
warranty. In no event will the authors be held liable for any
|
||
|
damages arising from the use of this software.
|
||
|
|
||
|
Permission is granted to anyone to use this software for any
|
||
|
purpose, including commercial applications, and to alter it and
|
||
|
redistribute it freely, subject to the following restrictions:
|
||
|
|
||
|
1. The origin of this software must not be misrepresented; you must
|
||
|
not claim that you wrote the original software. If you use this
|
||
|
software in a product, an acknowledgment in the product documentation
|
||
|
would be appreciated but is not required.
|
||
|
|
||
|
2. Altered source versions must be plainly marked as such, and
|
||
|
must not be misrepresented as being the original software.
|
||
|
|
||
|
3. This notice may not be removed or altered from any source
|
||
|
distribution.
|
||
|
*/
|
||
|
|
||
|
|
||
|
#ifndef TIXML_USE_STL
|
||
|
|
||
|
#ifndef TIXML_STRING_INCLUDED
|
||
|
#define TIXML_STRING_INCLUDED
|
||
|
|
||
|
#include <assert.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
/* The support for explicit isn't that universal, and it isn't really
|
||
|
required - it is used to check that the TiXmlString class isn't incorrectly
|
||
|
used. Be nice to old compilers and macro it here:
|
||
|
*/
|
||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200 )
|
||
|
// Microsoft visual studio, version 6 and higher.
|
||
|
#define TIXML_EXPLICIT explicit
|
||
|
#elif defined(__GNUC__) && (__GNUC__ >= 3 )
|
||
|
// GCC version 3 and higher.s
|
||
|
#define TIXML_EXPLICIT explicit
|
||
|
#else
|
||
|
#define TIXML_EXPLICIT
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/*
|
||
|
TiXmlString is an emulation of a subset of the std::string template.
|
||
|
Its purpose is to allow compiling TinyXML on compilers with no or poor STL support.
|
||
|
Only the member functions relevant to the TinyXML project have been implemented.
|
||
|
The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase
|
||
|
a string and there's no more room, we allocate a buffer twice as big as we need.
|
||
|
*/
|
||
|
class TiXmlString
|
||
|
{
|
||
|
public :
|
||
|
// The size type used
|
||
|
typedef size_t size_type;
|
||
|
|
||
|
// Error value for find primitive
|
||
|
static const size_type npos; // = -1;
|
||
|
|
||
|
|
||
|
// TiXmlString empty constructor
|
||
|
TiXmlString () : rep_(&nullrep_)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
// TiXmlString copy constructor
|
||
|
TiXmlString ( const TiXmlString & copy) : rep_(0)
|
||
|
{
|
||
|
init(copy.length());
|
||
|
memcpy(start(), copy.data(), length());
|
||
|
}
|
||
|
|
||
|
// TiXmlString constructor, based on a string
|
||
|
TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0)
|
||
|
{
|
||
|
init( static_cast<size_type>( strlen(copy) ));
|
||
|
memcpy(start(), copy, length());
|
||
|
}
|
||
|
|
||
|
// TiXmlString constructor, based on a string
|
||
|
TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0)
|
||
|
{
|
||
|
init(len);
|
||
|
memcpy(start(), str, len);
|
||
|
}
|
||
|
|
||
|
// TiXmlString destructor
|
||
|
~TiXmlString ()
|
||
|
{
|
||
|
quit();
|
||
|
}
|
||
|
|
||
|
TiXmlString& operator = (const char * copy)
|
||
|
{
|
||
|
return assign( copy, (size_type)strlen(copy));
|
||
|
}
|
||
|
|
||
|
TiXmlString& operator = (const TiXmlString & copy)
|
||
|
{
|
||
|
return assign(copy.start(), copy.length());
|
||
|
}
|
||
|
|
||
|
|
||
|
// += operator. Maps to append
|
||
|
TiXmlString& operator += (const char * suffix)
|
||
|
{
|
||
|
return append(suffix, static_cast<size_type>( strlen(suffix) ));
|
||
|
}
|
||
|
|
||
|
// += operator. Maps to append
|
||
|
TiXmlString& operator += (char single)
|
||
|
{
|
||
|
return append(&single, 1);
|
||
|
}
|
||
|
|
||
|
// += operator. Maps to append
|
||
|
TiXmlString& operator += (const TiXmlString & suffix)
|
||
|
{
|
||
|
return append(suffix.data(), suffix.length());
|
||
|
}
|
||
|
|
||
|
|
||
|
// Convert a TiXmlString into a null-terminated char *
|
||
|
const char * c_str () const { return rep_->str; }
|
||
|
|
||
|
// Convert a TiXmlString into a char * (need not be null terminated).
|
||
|
const char * data () const { return rep_->str; }
|
||
|
|
||
|
// Return the length of a TiXmlString
|
||
|
size_type length () const { return rep_->size; }
|
||
|
|
||
|
// Alias for length()
|
||
|
size_type size () const { return rep_->size; }
|
||
|
|
||
|
// Checks if a TiXmlString is empty
|
||
|
bool empty () const { return rep_->size == 0; }
|
||
|
|
||
|
// Return capacity of string
|
||
|
size_type capacity () const { return rep_->capacity; }
|
||
|
|
||
|
|
||
|
// single char extraction
|
||
|
const char& at (size_type index) const
|
||
|
{
|
||
|
assert( index < length() );
|
||
|
return rep_->str[ index ];
|
||
|
}
|
||
|
|
||
|
// [] operator
|
||
|
char& operator [] (size_type index) const
|
||
|
{
|
||
|
assert( index < length() );
|
||
|
return rep_->str[ index ];
|
||
|
}
|
||
|
|
||
|
// find a char in a string. Return TiXmlString::npos if not found
|
||
|
size_type find (char lookup) const
|
||
|
{
|
||
|
return find(lookup, 0);
|
||
|
}
|
||
|
|
||
|
// find a char in a string from an offset. Return TiXmlString::npos if not found
|
||
|
size_type find (char tofind, size_type offset) const
|
||
|
{
|
||
|
if (offset >= length()) return npos;
|
||
|
|
||
|
for (const char* p = c_str() + offset; *p != '\0'; ++p)
|
||
|
{
|
||
|
if (*p == tofind) return static_cast< size_type >( p - c_str() );
|
||
|
}
|
||
|
return npos;
|
||
|
}
|
||
|
|
||
|
void clear ()
|
||
|
{
|
||
|
//Lee:
|
||
|
//The original was just too strange, though correct:
|
||
|
// TiXmlString().swap(*this);
|
||
|
//Instead use the quit & re-init:
|
||
|
quit();
|
||
|
init(0,0);
|
||
|
}
|
||
|
|
||
|
/* Function to reserve a big amount of data when we know we'll need it. Be aware that this
|
||
|
function DOES NOT clear the content of the TiXmlString if any exists.
|
||
|
*/
|
||
|
void reserve (size_type cap);
|
||
|
|
||
|
TiXmlString& assign (const char* str, size_type len);
|
||
|
|
||
|
TiXmlString& append (const char* str, size_type len);
|
||
|
|
||
|
void swap (TiXmlString& other)
|
||
|
{
|
||
|
Rep* r = rep_;
|
||
|
rep_ = other.rep_;
|
||
|
other.rep_ = r;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
void init(size_type sz) { init(sz, sz); }
|
||
|
void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; }
|
||
|
char* start() const { return rep_->str; }
|
||
|
char* finish() const { return rep_->str + rep_->size; }
|
||
|
|
||
|
struct Rep
|
||
|
{
|
||
|
size_type size, capacity;
|
||
|
char str[1];
|
||
|
};
|
||
|
|
||
|
void init(size_type sz, size_type cap)
|
||
|
{
|
||
|
if (cap)
|
||
|
{
|
||
|
// Lee: the original form:
|
||
|
// rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap));
|
||
|
// doesn't work in some cases of new being overloaded. Switching
|
||
|
// to the normal allocation, although use an 'int' for systems
|
||
|
// that are overly picky about structure alignment.
|
||
|
const size_type bytesNeeded = sizeof(Rep) + cap;
|
||
|
const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int );
|
||
|
rep_ = reinterpret_cast<Rep*>( new int[ intsNeeded ] );
|
||
|
|
||
|
rep_->str[ rep_->size = sz ] = '\0';
|
||
|
rep_->capacity = cap;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
rep_ = &nullrep_;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void quit()
|
||
|
{
|
||
|
if (rep_ != &nullrep_)
|
||
|
{
|
||
|
// The rep_ is really an array of ints. (see the allocator, above).
|
||
|
// Cast it back before delete, so the compiler won't incorrectly call destructors.
|
||
|
delete [] ( reinterpret_cast<int*>( rep_ ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Rep * rep_;
|
||
|
static Rep nullrep_;
|
||
|
|
||
|
} ;
|
||
|
|
||
|
|
||
|
inline bool operator == (const TiXmlString & a, const TiXmlString & b)
|
||
|
{
|
||
|
return ( a.length() == b.length() ) // optimization on some platforms
|
||
|
&& ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare
|
||
|
}
|
||
|
inline bool operator < (const TiXmlString & a, const TiXmlString & b)
|
||
|
{
|
||
|
return strcmp(a.c_str(), b.c_str()) < 0;
|
||
|
}
|
||
|
|
||
|
inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); }
|
||
|
inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; }
|
||
|
inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); }
|
||
|
inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); }
|
||
|
|
||
|
inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; }
|
||
|
inline bool operator == (const char* a, const TiXmlString & b) { return b == a; }
|
||
|
inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); }
|
||
|
inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); }
|
||
|
|
||
|
TiXmlString operator + (const TiXmlString & a, const TiXmlString & b);
|
||
|
TiXmlString operator + (const TiXmlString & a, const char* b);
|
||
|
TiXmlString operator + (const char* a, const TiXmlString & b);
|
||
|
|
||
|
|
||
|
/*
|
||
|
TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString.
|
||
|
Only the operators that we need for TinyXML have been developped.
|
||
|
*/
|
||
|
class TiXmlOutStream : public TiXmlString
|
||
|
{
|
||
|
public :
|
||
|
|
||
|
// TiXmlOutStream << operator.
|
||
|
TiXmlOutStream & operator << (const TiXmlString & in)
|
||
|
{
|
||
|
*this += in;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
// TiXmlOutStream << operator.
|
||
|
TiXmlOutStream & operator << (const char * in)
|
||
|
{
|
||
|
*this += in;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
} ;
|
||
|
|
||
|
#endif // TIXML_STRING_INCLUDED
|
||
|
#endif // TIXML_USE_STL
|