FUtils/FUStringBuilder.hpp

00001 /*
00002     Copyright (C) 2005-2006 Feeling Software Inc.
00003     MIT License: http://www.opensource.org/licenses/mit-license.php
00004 */
00005 /*
00006     Based on the FS Import classes:
00007     Copyright (C) 2005-2006 Feeling Software Inc
00008     Copyright (C) 2005-2006 Autodesk Media Entertainment
00009     MIT License: http://www.opensource.org/licenses/mit-license.php
00010 */
00011 
00012 #include <limits>
00013 
00014 #ifdef WIN32
00015 #include <float.h>
00016 #endif
00017 
00018 #ifndef SAFE_DELETE_ARRAY
00019 #define SAFE_DELETE_ARRAY(ptr) if (ptr != NULL) { delete [] ptr; ptr = NULL; }
00020 #endif
00021 
00022 template <class Char, class SPrintF>
00023 FUStringBuilderT<Char,SPrintF>::FUStringBuilderT(const String& sz)
00024 {
00025     this->buffer = NULL;
00026     this->size = 0;
00027     this->reserved = 0;
00028     
00029     reserve(sz.size() + 32);
00030     append(sz.c_str());
00031 }
00032 
00033 template <class Char, class SPrintF>
00034 FUStringBuilderT<Char,SPrintF>::FUStringBuilderT(const Char* sz)
00035 {
00036     this->buffer = NULL;
00037     this->size = 0;
00038     this->reserved = 0;
00039 
00040     SPrintF s;
00041     reserve(s.StrLen(sz) + 32);
00042     append(sz);
00043 }
00044 
00045 template <class Char, class SPrintF>
00046 FUStringBuilderT<Char,SPrintF>::FUStringBuilderT(Char ch, size_t count)
00047 {
00048     this->buffer = NULL;
00049     this->size = 0;
00050     this->reserved = 0;
00051 
00052     reserve(count + 32);
00053     for (size_t i = 0; i < count; ++i) buffer[size++] = ch;
00054 }
00055 
00056 template <class Char, class SPrintF>
00057 FUStringBuilderT<Char,SPrintF>::FUStringBuilderT(size_t reservation)
00058 {
00059     this->buffer = NULL;
00060     this->size = 0;
00061     this->reserved = 0;
00062 
00063     reserve(reservation);
00064 }
00065 
00066 template <class Char, class SPrintF>
00067 FUStringBuilderT<Char,SPrintF>::FUStringBuilderT()
00068 {
00069     this->buffer = NULL;
00070     this->size = 0;
00071     this->reserved = 0;
00072 
00073 #ifndef _DEBUG
00074     reserve(32);
00075 #endif
00076 }
00077 
00078 template <class Char, class SPrintF>
00079 FUStringBuilderT<Char,SPrintF>::~FUStringBuilderT()
00080 {
00081     reserve(0);
00082 }
00083 
00084 template <class Char, class SPrintF>
00085 void FUStringBuilderT<Char,SPrintF>::enlarge(size_t minimum)
00086 {
00087     reserve(max(reserved + minimum + 32, 2 * reserved + 32));
00088 }
00089 
00090 template <class Char, class SPrintF>
00091 void FUStringBuilderT<Char,SPrintF>::clear()
00092 {
00093     size = 0;
00094 }
00095 
00096 template <class Char, class SPrintF>
00097 void FUStringBuilderT<Char,SPrintF>::reserve(size_t _length)
00098 {
00099     FUAssert(size <= reserved, );
00100     if (_length > reserved)
00101     {
00102         Char* b = new Char[_length];
00103         memcpy(b, buffer, size * sizeof(Char));
00104         SAFE_DELETE_ARRAY(buffer);
00105         buffer = b;
00106         reserved = _length;
00107     }
00108     else if (_length == 0)
00109     {
00110         SAFE_DELETE_ARRAY(buffer);
00111         size = reserved = 0;
00112     }
00113     else if (_length < reserved)
00114     {
00115         size_t realSize = min(size, _length);
00116         Char* b = new Char[_length];
00117         memcpy(b, buffer, realSize * sizeof(Char));
00118         SAFE_DELETE_ARRAY(buffer);
00119         buffer = b;
00120         reserved = _length;
00121         size = realSize;
00122     }
00123 }
00124 
00125 template <class Char, class SPrintF>
00126 void FUStringBuilderT<Char,SPrintF>::append(Char c)
00127 {
00128     if (size + 1 >= reserved) enlarge(2);
00129 
00130     buffer[size++] = c;
00131 }
00132 
00133 template <class Char, class SPrintF>
00134 void FUStringBuilderT<Char,SPrintF>::append(const String& sz) { append(sz.c_str()); }
00135 template <class Char, class SPrintF>
00136 void FUStringBuilderT<Char,SPrintF>::append(const Char* sz)
00137 {
00138     // This is optimized for SMALL strings.
00139     for (; *sz != 0; ++sz)
00140     {
00141         if (size >= reserved) enlarge(64);
00142         buffer[size++] = *sz;
00143     }
00144 }
00145 template <class Char, class SPrintF>
00146 void FUStringBuilderT<Char,SPrintF>::append(const FUStringBuilderT& b)
00147 {
00148     if (size + b.size >= reserved) enlarge(64 + size + b.size - reserved);
00149     memcpy(buffer + size, b.buffer, b.size * sizeof(Char));
00150     size += b.size;
00151 }
00152 
00153 template <class Char, class SPrintF>
00154 void FUStringBuilderT<Char,SPrintF>::append(uint32 i)
00155 {
00156     Char sz[128];
00157     SPrintF writer; writer.PrintUInt32(sz, 128, i);
00158     append(sz);
00159 }
00160 
00161 template <class Char, class SPrintF>
00162 void FUStringBuilderT<Char,SPrintF>::append(uint64 i)
00163 {
00164     Char sz[128];
00165     SPrintF writer; writer.PrintUInt64(sz, 128, i);
00166     append(sz);
00167 }
00168 
00169 template <class Char, class SPrintF>
00170 void FUStringBuilderT<Char,SPrintF>::append(int32 i)
00171 {
00172     Char sz[128];
00173     SPrintF writer; writer.PrintInt32(sz, 128, i);
00174     append(sz);
00175 }
00176 
00177 template <class Char, class SPrintF>
00178 void FUStringBuilderT<Char,SPrintF>::append(float f)
00179 {
00180     if (f != std::numeric_limits<float>::infinity() && f != -std::numeric_limits<float>::infinity() && f != std::numeric_limits<float>::quiet_NaN() && f != std::numeric_limits<float>::signaling_NaN())
00181     {
00182         if (IsEquivalent(f, 0.0f, std::numeric_limits<float>::epsilon())) append('0');
00183         else
00184         {
00185             Char sz[128];
00186             SPrintF writer; writer.PrintFloat(sz, 128, f);
00187             append(sz);
00188         }
00189     }
00190     else if (f == std::numeric_limits<float>::infinity())
00191     { append('I'); append('N'); append('F'); }
00192     else if (f == -std::numeric_limits<float>::infinity())
00193     { append('-'); append('I'); append('N'); append('F'); }
00194     else
00195     { append('N'); append('a'); append('N'); }
00196 }
00197 
00198 template <class Char, class SPrintF>
00199 void FUStringBuilderT<Char,SPrintF>::append(double f)
00200 {
00201     if (f != std::numeric_limits<double>::infinity() && f != -std::numeric_limits<double>::infinity() && f != std::numeric_limits<double>::quiet_NaN() && f != std::numeric_limits<double>::signaling_NaN())
00202     {
00203         if (IsEquivalent(f, 0.0, std::numeric_limits<double>::epsilon())) append('0');
00204         else
00205         {
00206             Char sz[128];
00207             SPrintF writer; writer.PrintFloat(sz, 128, f);
00208             append(sz);
00209         }
00210     }
00211     else if (f == std::numeric_limits<double>::infinity())
00212     { append('I'); append('N'); append('F'); }
00213     else if (f == -std::numeric_limits<double>::infinity())
00214     { append('-'); append('I'); append('N'); append('F'); }
00215     else
00216     { append('N'); append('a'); append('N'); }
00217 }
00218 
00219 template <class Char, class SPrintF>
00220 void FUStringBuilderT<Char,SPrintF>::appendLine(const Char* sz)
00221 {
00222     append(sz);
00223     append("\n");
00224 }
00225 
00226 template <class Char, class SPrintF>
00227 void FUStringBuilderT<Char,SPrintF>::remove(int32 start)
00228 {
00229     if ((int32)size > start && start >= 0) size = start;
00230 }
00231 
00232 template <class Char, class SPrintF>
00233 void FUStringBuilderT<Char,SPrintF>::remove(int32 start, int32 end)
00234 {
00235     int32 diff = end - start;
00236     if ((int32)size >= end && start >= 0 && diff > 0)
00237     {
00238         const Char* stop = buffer + size - diff;
00239         for (Char* p = buffer + start; p != stop; ++p)
00240         {
00241             *p = *(p + diff);
00242         }
00243         size -= diff;
00244     }
00245 }
00246 
00247 template <class Char, class SPrintF> 
00248 typename FUStringBuilderT<Char,SPrintF>::String FUStringBuilderT<Char,SPrintF>::ToString()
00249 {
00250     return String((const Char*)*this);
00251 }
00252 
00253 template <class Char, class SPrintF> 
00254 const Char* FUStringBuilderT<Char,SPrintF>::ToCharPtr()
00255 {
00256     if (size + 1 > reserved) enlarge(1);
00257     buffer[size] = 0;
00258     return buffer;
00259 }
00260 
00261 template <class Char, class SPrintF>
00262 int32 FUStringBuilderT<Char,SPrintF>::index(Char c)
00263 {
00264     if (buffer != NULL && size > 0)
00265     {
00266         const Char* end = buffer + size + 1;
00267         for (const Char* p = buffer; p != end; ++p)
00268         {
00269             if (*p == c) return (int32)(p - buffer);
00270         }
00271     }
00272     return -1;
00273 }
00274 
00275 template <class Char, class SPrintF>
00276 int32 FUStringBuilderT<Char,SPrintF>::rindex(Char c)
00277 {
00278     if (buffer != NULL && size > 0)
00279     {
00280         for (const Char* p = buffer + size - 1; p != buffer; --p)
00281         {
00282             if (*p == c) return (int32)(p - buffer);
00283         }
00284     }
00285     return -1;
00286 }

Generated on Fri May 12 16:44:39 2006 for FCollada by  doxygen 1.4.6-NO