TinyXML
|
00001 /* 00002 www.sourceforge.net/projects/tinyxml 00003 00004 This software is provided 'as-is', without any express or implied 00005 warranty. In no event will the authors be held liable for any 00006 damages arising from the use of this software. 00007 00008 Permission is granted to anyone to use this software for any 00009 purpose, including commercial applications, and to alter it and 00010 redistribute it freely, subject to the following restrictions: 00011 00012 1. The origin of this software must not be misrepresented; you must 00013 not claim that you wrote the original software. If you use this 00014 software in a product, an acknowledgment in the product documentation 00015 would be appreciated but is not required. 00016 00017 2. Altered source versions must be plainly marked as such, and 00018 must not be misrepresented as being the original software. 00019 00020 3. This notice may not be removed or altered from any source 00021 distribution. 00022 */ 00023 00024 00025 #ifndef TIXML_USE_STL 00026 00027 #ifndef TIXML_STRING_INCLUDED 00028 #define TIXML_STRING_INCLUDED 00029 00030 #include <assert.h> 00031 #include <string.h> 00032 00033 /* The support for explicit isn't that universal, and it isn't really 00034 required - it is used to check that the TiXmlString class isn't incorrectly 00035 used. Be nice to old compilers and macro it here: 00036 */ 00037 #if defined(_MSC_VER) && (_MSC_VER >= 1200 ) 00038 // Microsoft visual studio, version 6 and higher. 00039 #define TIXML_EXPLICIT explicit 00040 #elif defined(__GNUC__) && (__GNUC__ >= 3 ) 00041 // GCC version 3 and higher.s 00042 #define TIXML_EXPLICIT explicit 00043 #else 00044 #define TIXML_EXPLICIT 00045 #endif 00046 00047 00048 /* 00049 TiXmlString is an emulation of a subset of the std::string template. 00050 Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. 00051 Only the member functions relevant to the TinyXML project have been implemented. 00052 The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase 00053 a string and there's no more room, we allocate a buffer twice as big as we need. 00054 */ 00055 class TiXmlString 00056 { 00057 public : 00058 // The size type used 00059 typedef size_t size_type; 00060 00061 // Error value for find primitive 00062 static const size_type npos; // = -1; 00063 00064 00065 // TiXmlString empty constructor 00066 TiXmlString () : rep_(&nullrep_) 00067 { 00068 } 00069 00070 // TiXmlString copy constructor 00071 TiXmlString ( const TiXmlString & copy) : rep_(0) 00072 { 00073 init(copy.length()); 00074 memcpy(start(), copy.data(), length()); 00075 } 00076 00077 // TiXmlString constructor, based on a string 00078 TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) 00079 { 00080 init( static_cast<size_type>( strlen(copy) )); 00081 memcpy(start(), copy, length()); 00082 } 00083 00084 // TiXmlString constructor, based on a string 00085 TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) 00086 { 00087 init(len); 00088 memcpy(start(), str, len); 00089 } 00090 00091 // TiXmlString destructor 00092 ~TiXmlString () 00093 { 00094 quit(); 00095 } 00096 00097 TiXmlString& operator = (const char * copy) 00098 { 00099 return assign( copy, (size_type)strlen(copy)); 00100 } 00101 00102 TiXmlString& operator = (const TiXmlString & copy) 00103 { 00104 return assign(copy.start(), copy.length()); 00105 } 00106 00107 00108 // += operator. Maps to append 00109 TiXmlString& operator += (const char * suffix) 00110 { 00111 return append(suffix, static_cast<size_type>( strlen(suffix) )); 00112 } 00113 00114 // += operator. Maps to append 00115 TiXmlString& operator += (char single) 00116 { 00117 return append(&single, 1); 00118 } 00119 00120 // += operator. Maps to append 00121 TiXmlString& operator += (const TiXmlString & suffix) 00122 { 00123 return append(suffix.data(), suffix.length()); 00124 } 00125 00126 00127 // Convert a TiXmlString into a null-terminated char * 00128 const char * c_str () const { return rep_->str; } 00129 00130 // Convert a TiXmlString into a char * (need not be null terminated). 00131 const char * data () const { return rep_->str; } 00132 00133 // Return the length of a TiXmlString 00134 size_type length () const { return rep_->size; } 00135 00136 // Alias for length() 00137 size_type size () const { return rep_->size; } 00138 00139 // Checks if a TiXmlString is empty 00140 bool empty () const { return rep_->size == 0; } 00141 00142 // Return capacity of string 00143 size_type capacity () const { return rep_->capacity; } 00144 00145 00146 // single char extraction 00147 const char& at (size_type index) const 00148 { 00149 assert( index < length() ); 00150 return rep_->str[ index ]; 00151 } 00152 00153 // [] operator 00154 char& operator [] (size_type index) const 00155 { 00156 assert( index < length() ); 00157 return rep_->str[ index ]; 00158 } 00159 00160 // find a char in a string. Return TiXmlString::npos if not found 00161 size_type find (char lookup) const 00162 { 00163 return find(lookup, 0); 00164 } 00165 00166 // find a char in a string from an offset. Return TiXmlString::npos if not found 00167 size_type find (char tofind, size_type offset) const 00168 { 00169 if (offset >= length()) return npos; 00170 00171 for (const char* p = c_str() + offset; *p != '\0'; ++p) 00172 { 00173 if (*p == tofind) return static_cast< size_type >( p - c_str() ); 00174 } 00175 return npos; 00176 } 00177 00178 void clear () 00179 { 00180 //Lee: 00181 //The original was just too strange, though correct: 00182 // TiXmlString().swap(*this); 00183 //Instead use the quit & re-init: 00184 quit(); 00185 init(0,0); 00186 } 00187 00188 /* Function to reserve a big amount of data when we know we'll need it. Be aware that this 00189 function DOES NOT clear the content of the TiXmlString if any exists. 00190 */ 00191 void reserve (size_type cap); 00192 00193 TiXmlString& assign (const char* str, size_type len); 00194 00195 TiXmlString& append (const char* str, size_type len); 00196 00197 void swap (TiXmlString& other) 00198 { 00199 Rep* r = rep_; 00200 rep_ = other.rep_; 00201 other.rep_ = r; 00202 } 00203 00204 private: 00205 00206 void init(size_type sz) { init(sz, sz); } 00207 void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } 00208 char* start() const { return rep_->str; } 00209 char* finish() const { return rep_->str + rep_->size; } 00210 00211 struct Rep 00212 { 00213 size_type size, capacity; 00214 char str[1]; 00215 }; 00216 00217 void init(size_type sz, size_type cap) 00218 { 00219 if (cap) 00220 { 00221 // Lee: the original form: 00222 // rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap)); 00223 // doesn't work in some cases of new being overloaded. Switching 00224 // to the normal allocation, although use an 'int' for systems 00225 // that are overly picky about structure alignment. 00226 const size_type bytesNeeded = sizeof(Rep) + cap; 00227 const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); 00228 rep_ = reinterpret_cast<Rep*>( new int[ intsNeeded ] ); 00229 00230 rep_->str[ rep_->size = sz ] = '\0'; 00231 rep_->capacity = cap; 00232 } 00233 else 00234 { 00235 rep_ = &nullrep_; 00236 } 00237 } 00238 00239 void quit() 00240 { 00241 if (rep_ != &nullrep_) 00242 { 00243 // The rep_ is really an array of ints. (see the allocator, above). 00244 // Cast it back before delete, so the compiler won't incorrectly call destructors. 00245 delete [] ( reinterpret_cast<int*>( rep_ ) ); 00246 } 00247 } 00248 00249 Rep * rep_; 00250 static Rep nullrep_; 00251 00252 } ; 00253 00254 00255 inline bool operator == (const TiXmlString & a, const TiXmlString & b) 00256 { 00257 return ( a.length() == b.length() ) // optimization on some platforms 00258 && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare 00259 } 00260 inline bool operator < (const TiXmlString & a, const TiXmlString & b) 00261 { 00262 return strcmp(a.c_str(), b.c_str()) < 0; 00263 } 00264 00265 inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } 00266 inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } 00267 inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } 00268 inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } 00269 00270 inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } 00271 inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } 00272 inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } 00273 inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } 00274 00275 TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); 00276 TiXmlString operator + (const TiXmlString & a, const char* b); 00277 TiXmlString operator + (const char* a, const TiXmlString & b); 00278 00279 00280 /* 00281 TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. 00282 Only the operators that we need for TinyXML have been developped. 00283 */ 00284 class TiXmlOutStream : public TiXmlString 00285 { 00286 public : 00287 00288 // TiXmlOutStream << operator. 00289 TiXmlOutStream & operator << (const TiXmlString & in) 00290 { 00291 *this += in; 00292 return *this; 00293 } 00294 00295 // TiXmlOutStream << operator. 00296 TiXmlOutStream & operator << (const char * in) 00297 { 00298 *this += in; 00299 return *this; 00300 } 00301 00302 } ; 00303 00304 #endif // TIXML_STRING_INCLUDED 00305 #endif // TIXML_USE_STL