tinystr.h

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

Generated on Sun May 6 15:41:22 2007 for TinyXml by  doxygen 1.4.7