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