14 #include "math/ParaMath.h" 31 static char * cvt(
double arg,
int ndigits,
int* decpt,
int *sign,
int eflag)
35 register char *p, *p1;
36 static char buf[NDIG];
40 if (ndigits >= NDIG - 1)
57 fj = modf(fi / 10, &fi);
58 *--p1 = (int)((fj + .03) * 10) +
'0';
61 while (p1 < &buf[NDIG])
65 while ((fj = arg * 10) < 1) {
78 while (p <= p1 && p < &buf[NDIG]) {
83 if (p1 >= &buf[NDIG]) {
107 char * ecvt(
double arg,
int ndigits,
int *decpt,
int *sign)
109 return cvt(arg, ndigits, decpt, sign, 1);
112 char * fcvt(
double arg,
int ndigits,
int*decpt,
int * sign)
114 return cvt(arg, ndigits, decpt, sign, 0);
120 template <
class Char,
class FloatType>
121 void FloatToString(FloatType f, Char* sz)
123 Char* sBuffer = sz + 1;
124 static const int digitCount = 6;
128 char* end = ecvt(f, digitCount, &decimal, &sign);
130 if (sign != 0) (*sBuffer++) =
'-';
131 int count = digitCount;
132 if (decimal > digitCount)
135 (*sBuffer++) = (*end++);
139 for (--count; count > 0; --count)
if (end[count - 1] !=
'0')
break;
140 for (
int i = 0; i < count; ++i) (*sBuffer++) = (*end++);
141 if (sBuffer[-1] ==
'.') --sBuffer;
145 uint32 exponent = decimal - 1;
146 if (exponent >= 10) (*sBuffer++) = (Char)(
'0' + (exponent / 10));
147 (*sBuffer++) = (Char)(
'0' + (exponent % 10));
151 else if (decimal > 0)
154 for (
int i = 0; i < decimal; ++i) (*sBuffer++) = (*end++);
155 if (decimal < digitCount) (*sBuffer++) =
'.';
156 count = digitCount - decimal;
158 else if (decimal < -digitCount)
163 else if (decimal < 0 || (decimal == 0 && *end !=
'0'))
166 (*sBuffer++) =
'0'; (*sBuffer++) =
'.';
167 for (
int i = 0; i < -decimal; ++i) (*sBuffer++) =
'0';
168 count = digitCount + decimal;
170 for (; count > 0; --count)
if (end[count - 1] !=
'0')
break;
171 for (
int i = 0; i < count; ++i) (*sBuffer++) = (*end++);
172 if (decimal == 0 && count == 0) (*sBuffer++) =
'0';
173 if (sBuffer[-1] ==
'.') --sBuffer;
178 template <
typename UserAllocator>
181 this->m_buffer = NULL;
183 this->m_reserved = 0;
185 append(sz.c_str(), sz.size());
188 template <
typename UserAllocator>
191 this->m_buffer = NULL;
193 this->m_reserved = 0;
196 for (
const Char* p = sz; *p != 0; ++p) ++len;
200 template <
typename UserAllocator>
203 this->m_buffer = NULL;
205 this->m_reserved = 0;
208 for (
size_t i = 0; i < count; ++i) m_buffer[m_size++] = ch;
211 template <
typename UserAllocator>
214 this->m_buffer = NULL;
216 this->m_reserved = 0;
217 reserve(reservation);
220 template <
typename UserAllocator>
223 this->m_buffer = NULL;
225 this->m_reserved = 0;
228 template <
typename UserAllocator>
234 template <
typename UserAllocator>
237 reserve(max(m_reserved + minimum, 2 * m_reserved));
240 template <
typename UserAllocator>
246 template <
typename UserAllocator>
249 if (new_size > m_reserved)
256 template <
typename UserAllocator>
259 if (m_size + 1 >= m_reserved) enlarge(2);
261 m_buffer[m_size++] = c;
264 template <
typename UserAllocator>
266 template <
typename UserAllocator>
269 if (sz == NULL)
return;
272 for (; *sz != 0; ++sz)
274 if (m_size >= m_reserved) enlarge(32);
275 m_buffer[m_size++] = *sz;
278 template <
typename UserAllocator>
281 if (sz == NULL)
return;
283 if ((m_size + len) >= m_reserved)
285 enlarge(max((
size_t)32, m_size + len + 1));
287 memcpy(m_buffer + m_size, sz, len);
291 template <
typename UserAllocator>
294 if (sz == NULL || len == 0)
return;
296 if ((len + nIndex) > m_size)
298 if ((len + nIndex) >= m_reserved)
300 enlarge(max((
size_t)32, nIndex + len + 1));
302 m_size = nIndex + len;
304 memcpy(m_buffer + nIndex, sz, len);
308 template <
typename UserAllocator>
311 if (m_size + b.m_size >= m_reserved) enlarge(32 + m_size + b.m_size - m_reserved);
312 memcpy(m_buffer + m_size, b.m_buffer, b.m_size *
sizeof(Char));
316 template <
typename UserAllocator>
321 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))
323 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())
326 if (
Math::IsEquivalent(f, 0.0f, std::numeric_limits<float>::epsilon())) append((Char)
'0');
330 FloatToString(f, sz);
334 else if (f == std::numeric_limits<float>::infinity())
336 append((Char)
'I'); append((Char)
'N'); append((Char)
'F');
338 else if (f == -std::numeric_limits<float>::infinity())
340 append((Char)
'-'); append((Char)
'I'); append((Char)
'N'); append((Char)
'F');
344 append((Char)
'N'); append((Char)
'a'); append((Char)
'N');
348 template <
typename UserAllocator>
353 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))
355 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())
358 if (
Math::IsEquivalent(f, 0.0, std::numeric_limits<double>::epsilon())) append((Char)
'0');
362 FloatToString(f, sz);
366 else if (f == std::numeric_limits<double>::infinity())
368 append((Char)
'I'); append((Char)
'N'); append((Char)
'F');
370 else if (f == -std::numeric_limits<double>::infinity())
372 append((Char)
'-'); append((Char)
'I'); append((Char)
'N'); append((Char)
'F');
376 append((Char)
'N'); append((Char)
'a'); append((Char)
'N');
380 template <
typename UserAllocator>
387 template <
typename UserAllocator>
390 uint8 top = (i & 0xF0) >> 4;
392 if (top <= 0x9) append((Char)(
'0' + top));
393 else append((Char)(
'A' + (top - 0xA)));
394 if (bot <= 0x9) append((Char)(
'0' + bot));
395 else append((Char)(
'A' + (bot - 0xA)));
398 template <
typename UserAllocator>
401 if ((int32)m_size > start && start >= 0) m_size = start;
404 template <
typename UserAllocator>
407 int32 diff = end - start;
408 if ((int32)m_size >= end && start >= 0 && diff > 0)
410 const Char* stop = m_buffer + m_size - diff;
411 for (Char* p = m_buffer + start; p != stop; ++p)
419 template <
typename UserAllocator>
423 if (m_size + 1 > m_reserved) ncThis->enlarge(1);
424 ncThis->m_buffer[m_size] = 0;
428 template <
typename UserAllocator>
431 if (m_buffer != NULL && m_size > 0)
433 const Char* end = m_buffer + m_size + 1;
434 for (
const Char* p = m_buffer; p != end; ++p)
436 if (*p == c)
return (int32)(p - m_buffer);
442 template <
typename UserAllocator>
445 if (m_buffer != NULL && m_size > 0)
447 for (
const Char* p = m_buffer + m_size - 1; p != m_buffer; --p)
449 if (*p == c)
return (int32)(p - m_buffer);
455 template <
typename UserAllocator>
459 snprintf(sz, 128,
"%u", (
unsigned int)i);
463 template <
typename UserAllocator>
467 snprintf(sz, 128,
"%u", (
unsigned int)i);
471 template <
typename UserAllocator>
475 snprintf(sz, 128,
"%i", (
int)i);
479 template <
typename UserAllocator>
482 assert(m_size <= m_reserved);
487 user_allocator::deallocate(m_buffer, m_reserved);
490 m_size = m_reserved = 0;
492 else if (_length < m_reserved)
497 else if (_length > m_reserved)
502 _length = (size_t)(0x1 << n);
506 _length = (size_t)(0x1 << n);
509 Char* b =
static_cast<Char*
>(user_allocator::allocate(_length));
510 memcpy(b, m_buffer, m_size *
sizeof(Char));
513 user_allocator::deallocate(m_buffer, m_reserved);
516 m_reserved = _length;
StringBuilderT()
Creates a new builder with an empty buffer.
Definition: StringBuilder.hpp:221
void appendHex(uint8 i)
Appends the integer value, after converting it to a fm::string, in hexadecimal, to the content of the...
Definition: StringBuilder.hpp:388
int32 index(Char c) const
Retrieves the index of the first character within the content of the builder that is equivalent to th...
Definition: StringBuilder.hpp:429
different physics engine has different winding order.
Definition: EventBinding.h:32
int32 rindex(Char c) const
Retrieves the index of the last character within the content of the builder that is equivalent to the...
Definition: StringBuilder.hpp:443
void resize(size_t length)
resize the buffer
Definition: StringBuilder.hpp:247
void clear()
Clears the content of the builder.
Definition: StringBuilder.hpp:241
const Char * c_str() const
Converts the content of the builder to a character array.
Definition: StringBuilder.hpp:420
std::string string_type
The standard string object which correspond to the builder.
Definition: StringBuilder.h:35
void append(Char c)
Appends a character to the content of the builder.
Definition: StringBuilder.hpp:257
void remove(int32 start)
Removes a section of the content of the builder.
Definition: StringBuilder.hpp:399
void WriteAt(int nIndex, const TYPE &val)
this is useful for writing to a previous cached location.
Definition: StringBuilder.h:151
static bool IsEquivalent(float f1, float f2)
Returns whether two floating-point values are equivalent within a given tolerance.
Definition: ParaMath.h:417
void reserve(size_t length)
Reserves a given number of character slots.
Definition: StringBuilder.hpp:480
A NON-thread-safe, mutable sequence of characters(Binary is also possible).
Definition: StringBuilder.h:9
~StringBuilderT()
Deletes the builder.
Definition: StringBuilder.hpp:229
static int log2_ceil(unsigned int x)
this is a fast version of log2.
Definition: ParaMath.h:458
void appendLine(const Char *sz)
Appends a character array to the content of the builder.
Definition: StringBuilder.hpp:381