00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <limits>
00016
00017 #ifdef WIN32
00018 #include <float.h>
00019 #endif
00020
00021 #ifdef WIN32
00022 #define ecvt _ecvt
00023 #endif // WIN32
00024
00025 #ifndef SAFE_DELETE_ARRAY
00026 #define SAFE_DELETE_ARRAY(ptr) if (ptr != NULL) { delete [] ptr; ptr = NULL; }
00027 #endif
00028
00029 template <class Char, class FloatType>
00030 void FloatToString(FloatType f, Char* sz)
00031 {
00032 Char* buffer = sz + 1;
00033 static const int digitCount = 6;
00034 int decimal, sign;
00035
00036
00037 char* end = ecvt(f, digitCount, &decimal, &sign);
00038
00039 if (sign != 0) (*buffer++) = '-';
00040 int count = digitCount;
00041 if (decimal > digitCount)
00042 {
00043
00044 (*buffer++) = (*end++);
00045 (*buffer++) = '.';
00046
00047
00048 for (--count; count > 0; --count) if (end[count - 1] != '0') break;
00049 for (int i = 0; i < count; ++i) (*buffer++) = (*end++);
00050 if (buffer[-1] == '.') --buffer;
00051
00052
00053 (*buffer++) = 'e';
00054 uint32 exponent = decimal - 1;
00055 if (exponent >= 10) (*buffer++) = (Char) ('0' + (exponent / 10));
00056 (*buffer++) = (Char) ('0' + (exponent % 10));
00057 (*buffer) = 0;
00058 return;
00059 }
00060 else if (decimal > 0)
00061 {
00062
00063 for (int i = 0; i < decimal; ++i) (*buffer++) = (*end++);
00064 if (decimal < digitCount) (*buffer++) = '.';
00065 count = digitCount - decimal;
00066 }
00067 else if (decimal < -digitCount)
00068 {
00069
00070 decimal = count = 0;
00071 }
00072 else if (decimal < 0 || (decimal == 0 && *end != '0'))
00073 {
00074
00075 (*buffer++) = '0'; (*buffer++) = '.';
00076 for (int i = 0; i < -decimal; ++i) (*buffer++) = '0';
00077 count = digitCount + decimal;
00078 }
00079 for (; count > 0; --count) if (end[count - 1] != '0') break;
00080 for (int i = 0; i < count; ++i) (*buffer++) = (*end++);
00081 if (decimal == 0 && count == 0) (*buffer++) = '0';
00082 if (buffer[-1] == '.') --buffer;
00083 (*buffer) = 0;
00084 }
00085
00086 template <class Char>
00087 FUStringBuilderT<Char>::FUStringBuilderT(const String& sz)
00088 {
00089 this->buffer = NULL;
00090 this->size = 0;
00091 this->reserved = 0;
00092
00093 reserve(sz.size() + 32);
00094 append(sz.c_str());
00095 }
00096
00097 template <class Char>
00098 FUStringBuilderT<Char>::FUStringBuilderT(const Char* sz)
00099 {
00100 this->buffer = NULL;
00101 this->size = 0;
00102 this->reserved = 0;
00103
00104 size_t len = 0;
00105 for (const Char* p = sz; *p != 0; ++p) ++len;
00106 reserve(len + 32);
00107 append(sz);
00108 }
00109
00110 template <class Char>
00111 FUStringBuilderT<Char>::FUStringBuilderT(Char ch, size_t count)
00112 {
00113 this->buffer = NULL;
00114 this->size = 0;
00115 this->reserved = 0;
00116
00117 reserve(count + 32);
00118 for (size_t i = 0; i < count; ++i) buffer[size++] = ch;
00119 }
00120
00121 template <class Char>
00122 FUStringBuilderT<Char>::FUStringBuilderT(size_t reservation)
00123 {
00124 this->buffer = NULL;
00125 this->size = 0;
00126 this->reserved = 0;
00127
00128 reserve(reservation);
00129 }
00130
00131 template <class Char>
00132 FUStringBuilderT<Char>::FUStringBuilderT()
00133 {
00134 this->buffer = NULL;
00135 this->size = 0;
00136 this->reserved = 0;
00137
00138 #ifndef _DEBUG
00139 reserve(32);
00140 #endif
00141 }
00142
00143 template <class Char>
00144 FUStringBuilderT<Char>::~FUStringBuilderT()
00145 {
00146 reserve(0);
00147 }
00148
00149 template <class Char>
00150 void FUStringBuilderT<Char>::enlarge(size_t minimum)
00151 {
00152 reserve(max(reserved + minimum + 32, 2 * reserved + 32));
00153 }
00154
00155 template <class Char>
00156 void FUStringBuilderT<Char>::clear()
00157 {
00158 size = 0;
00159 }
00160
00161 template <class Char>
00162 void FUStringBuilderT<Char>::reserve(size_t _length)
00163 {
00164 FUAssert(size <= reserved,);
00165 if (_length > reserved)
00166 {
00167 Char* b = new Char[_length];
00168 memcpy(b, buffer, size * sizeof(Char));
00169 SAFE_DELETE_ARRAY(buffer);
00170 buffer = b;
00171 reserved = _length;
00172 }
00173 else if (_length == 0)
00174 {
00175 SAFE_DELETE_ARRAY(buffer);
00176 size = reserved = 0;
00177 }
00178 else if (_length < reserved)
00179 {
00180 size_t realSize = min(size, _length);
00181 Char* b = new Char[_length];
00182 memcpy(b, buffer, realSize * sizeof(Char));
00183 SAFE_DELETE_ARRAY(buffer);
00184 buffer = b;
00185 reserved = _length;
00186 size = realSize;
00187 }
00188 }
00189
00190 template <class Char>
00191 void FUStringBuilderT<Char>::append(Char c)
00192 {
00193 if (size + 1 >= reserved) enlarge(2);
00194
00195 buffer[size++] = c;
00196 }
00197
00198 template <class Char>
00199 void FUStringBuilderT<Char>::append(const String& sz) { append(sz.c_str()); }
00200 template <class Char>
00201 void FUStringBuilderT<Char>::append(const Char* sz)
00202 {
00203 if (sz == NULL) return;
00204
00205
00206 for (; *sz != 0; ++sz)
00207 {
00208 if (size >= reserved) enlarge(64);
00209 buffer[size++] = *sz;
00210 }
00211 }
00212 template <class Char>
00213 void FUStringBuilderT<Char>::append(const Char* sz, size_t len)
00214 {
00215 if (sz == NULL) return;
00216
00217 if (size + len >= reserved)
00218 {
00219 enlarge(max((size_t)64, size + len + 1));
00220 }
00221 memcpy(buffer + size, sz, len);
00222 size += len;
00223 }
00224
00225
00226 template <class Char>
00227 void FUStringBuilderT<Char>::append(const FUStringBuilderT& b)
00228 {
00229 if (size + b.size >= reserved) enlarge(64 + size + b.size - reserved);
00230 memcpy(buffer + size, b.buffer, b.size * sizeof(Char));
00231 size += b.size;
00232 }
00233
00234 template <class Char>
00235 void FUStringBuilderT<Char>::append(float f)
00236 {
00237 #ifdef WIN32
00238
00239 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() && !_isnan((double)f))
00240 #else
00241 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())
00242 #endif
00243 {
00244 if (IsEquivalent(f, 0.0f, std::numeric_limits<float>::epsilon())) append((Char)'0');
00245 else
00246 {
00247 Char sz[128];
00248 FloatToString(f, sz);
00249 append(sz + 1);
00250 }
00251 }
00252 else if (f == std::numeric_limits<float>::infinity())
00253 { append((Char)'I'); append((Char)'N'); append((Char)'F'); }
00254 else if (f == -std::numeric_limits<float>::infinity())
00255 { append((Char)'-'); append((Char)'I'); append((Char)'N'); append((Char)'F'); }
00256 else
00257 { append((Char)'N'); append((Char)'a'); append((Char)'N'); }
00258 }
00259
00260 template <class Char>
00261 void FUStringBuilderT<Char>::append(double f)
00262 {
00263 #ifdef WIN32
00264
00265 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() && !_isnan(f))
00266 #else
00267 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())
00268 #endif
00269 {
00270 if (IsEquivalent(f, 0.0, std::numeric_limits<double>::epsilon())) append((Char)'0');
00271 else
00272 {
00273 Char sz[128];
00274 FloatToString(f, sz);
00275 append(sz + 1);
00276 }
00277 }
00278 else if (f == std::numeric_limits<double>::infinity())
00279 { append((Char)'I'); append((Char)'N'); append((Char)'F'); }
00280 else if (f == -std::numeric_limits<double>::infinity())
00281 { append((Char)'-'); append((Char)'I'); append((Char)'N'); append((Char)'F'); }
00282 else
00283 { append((Char)'N'); append((Char)'a'); append((Char)'N'); }
00284 }
00285
00286 template <class Char>
00287 void FUStringBuilderT<Char>::append(const FMVector2& v)
00288 {
00289 if (!empty() && (back() != (Char) ' ' || back() != (Char) '\t' || back() != (Char) '\n' || back() != (Char) '\r'))
00290 {
00291 append((Char)' ');
00292 }
00293 append(v.x); append((Char)' '); append(v.y);
00294 }
00295
00296 template <class Char>
00297 void FUStringBuilderT<Char>::append(const FMVector3& v)
00298 {
00299 if (!empty() && (back() != (Char) ' ' || back() != (Char) '\t' || back() != (Char) '\n' || back() != (Char) '\r'))
00300 {
00301 append((Char)' ');
00302 }
00303 append(v.x); append((Char)' '); append(v.y); append((Char)' '); append(v.z);
00304 }
00305
00306 template <class Char>
00307 void FUStringBuilderT<Char>::append(const FMVector4& v)
00308 {
00309 if (!empty() && (back() != (Char) ' ' || back() != (Char) '\t' || back() != (Char) '\n' || back() != (Char) '\r'))
00310 {
00311 append((Char)' ');
00312 }
00313 append(v.x); append((Char)' '); append(v.y); append((Char)' '); append(v.z); append((Char)' '); append(v.w);
00314 }
00315
00316 template <class Char>
00317 void FUStringBuilderT<Char>::appendLine(const Char* sz)
00318 {
00319 append(sz);
00320 append((Char)'\n');
00321 }
00322
00323 template <class Char>
00324 void FUStringBuilderT<Char>::appendHex(uint8 i)
00325 {
00326 uint8 top = (i & 0xF0) >> 4;
00327 uint8 bot = i & 0xF;
00328 if (top <= 0x9) append((Char) ('0' + top));
00329 else append((Char) ('A' + (top - 0xA)));
00330 if (bot <= 0x9) append((Char) ('0' + bot));
00331 else append((Char) ('A' + (bot - 0xA)));
00332 }
00333
00334 template <class Char>
00335 void FUStringBuilderT<Char>::remove(int32 start)
00336 {
00337 if ((int32)size > start && start >= 0) size = start;
00338 }
00339
00340 template <class Char>
00341 void FUStringBuilderT<Char>::remove(int32 start, int32 end)
00342 {
00343 int32 diff = end - start;
00344 if ((int32)size >= end && start >= 0 && diff > 0)
00345 {
00346 const Char* stop = buffer + size - diff;
00347 for (Char* p = buffer + start; p != stop; ++p)
00348 {
00349 *p = *(p + diff);
00350 }
00351 size -= diff;
00352 }
00353 }
00354
00355 template <class Char>
00356 const Char* FUStringBuilderT<Char>::ToCharPtr() const
00357 {
00358 FUStringBuilderT<Char>* ncThis = const_cast< FUStringBuilderT<Char>* >(this);
00359 if (size + 1 > reserved) ncThis->enlarge(1);
00360 ncThis->buffer[size] = 0;
00361 return buffer;
00362 }
00363
00364 template <class Char>
00365 int32 FUStringBuilderT<Char>::index(Char c) const
00366 {
00367 if (buffer != NULL && size > 0)
00368 {
00369 const Char* end = buffer + size + 1;
00370 for (const Char* p = buffer; p != end; ++p)
00371 {
00372 if (*p == c) return (int32)(p - buffer);
00373 }
00374 }
00375 return -1;
00376 }
00377
00378 template <class Char>
00379 int32 FUStringBuilderT<Char>::rindex(Char c) const
00380 {
00381 if (buffer != NULL && size > 0)
00382 {
00383 for (const Char* p = buffer + size - 1; p != buffer; --p)
00384 {
00385 if (*p == c) return (int32)(p - buffer);
00386 }
00387 }
00388 return -1;
00389 }