/* Copyright (C) 2005-2006 Feeling Software Inc. MIT License: http://www.opensource.org/licenses/mit-license.php */ /* Based on the FS Import classes: Copyright (C) 2005-2006 Feeling Software Inc Copyright (C) 2005-2006 Autodesk Media Entertainment MIT License: http://www.opensource.org/licenses/mit-license.php */ #include #ifdef WIN32 #include #endif #ifndef SAFE_DELETE_ARRAY #define SAFE_DELETE_ARRAY(ptr) if (ptr != NULL) { delete [] ptr; ptr = NULL; } #endif template FUStringBuilderT::FUStringBuilderT(const String& sz) { this->buffer = NULL; this->size = 0; this->reserved = 0; reserve(sz.size() + 32); append(sz.c_str()); } template FUStringBuilderT::FUStringBuilderT(const Char* sz) { this->buffer = NULL; this->size = 0; this->reserved = 0; SPrintF s; reserve(s.StrLen(sz) + 32); append(sz); } template FUStringBuilderT::FUStringBuilderT(Char ch, size_t count) { this->buffer = NULL; this->size = 0; this->reserved = 0; reserve(count + 32); for (size_t i = 0; i < count; ++i) buffer[size++] = ch; } template FUStringBuilderT::FUStringBuilderT(size_t reservation) { this->buffer = NULL; this->size = 0; this->reserved = 0; reserve(reservation); } template FUStringBuilderT::FUStringBuilderT() { this->buffer = NULL; this->size = 0; this->reserved = 0; #ifndef _DEBUG reserve(32); #endif } template FUStringBuilderT::~FUStringBuilderT() { reserve(0); } template void FUStringBuilderT::enlarge(size_t minimum) { reserve(max(reserved + minimum + 32, 2 * reserved + 32)); } template void FUStringBuilderT::clear() { size = 0; } template void FUStringBuilderT::reserve(size_t _length) { FUAssert(size <= reserved, ); if (_length > reserved) { Char* b = new Char[_length]; memcpy(b, buffer, size * sizeof(Char)); SAFE_DELETE_ARRAY(buffer); buffer = b; reserved = _length; } else if (_length == 0) { SAFE_DELETE_ARRAY(buffer); size = reserved = 0; } else if (_length < reserved) { size_t realSize = min(size, _length); Char* b = new Char[_length]; memcpy(b, buffer, realSize * sizeof(Char)); SAFE_DELETE_ARRAY(buffer); buffer = b; reserved = _length; size = realSize; } } template void FUStringBuilderT::append(Char c) { if (size + 1 >= reserved) enlarge(2); buffer[size++] = c; } template void FUStringBuilderT::append(const String& sz) { append(sz.c_str()); } template void FUStringBuilderT::append(const Char* sz) { // This is optimized for SMALL strings. for (; *sz != 0; ++sz) { if (size >= reserved) enlarge(64); buffer[size++] = *sz; } } template void FUStringBuilderT::append(const FUStringBuilderT& b) { if (size + b.size >= reserved) enlarge(64 + size + b.size - reserved); memcpy(buffer + size, b.buffer, b.size * sizeof(Char)); size += b.size; } template void FUStringBuilderT::append(uint32 i) { Char sz[128]; SPrintF writer; writer.PrintUInt32(sz, 128, i); append(sz); } template void FUStringBuilderT::append(uint64 i) { Char sz[128]; SPrintF writer; writer.PrintUInt64(sz, 128, i); append(sz); } template void FUStringBuilderT::append(int32 i) { Char sz[128]; SPrintF writer; writer.PrintInt32(sz, 128, i); append(sz); } template void FUStringBuilderT::append(float f) { if (f != std::numeric_limits::infinity() && f != -std::numeric_limits::infinity() && f != std::numeric_limits::quiet_NaN() && f != std::numeric_limits::signaling_NaN()) { if (IsEquivalent(f, 0.0f, std::numeric_limits::epsilon())) append('0'); else { Char sz[128]; SPrintF writer; writer.PrintFloat(sz, 128, f); append(sz); } } else if (f == std::numeric_limits::infinity()) { append('I'); append('N'); append('F'); } else if (f == -std::numeric_limits::infinity()) { append('-'); append('I'); append('N'); append('F'); } else { append('N'); append('a'); append('N'); } } template void FUStringBuilderT::append(double f) { if (f != std::numeric_limits::infinity() && f != -std::numeric_limits::infinity() && f != std::numeric_limits::quiet_NaN() && f != std::numeric_limits::signaling_NaN()) { if (IsEquivalent(f, 0.0, std::numeric_limits::epsilon())) append('0'); else { Char sz[128]; SPrintF writer; writer.PrintFloat(sz, 128, f); append(sz); } } else if (f == std::numeric_limits::infinity()) { append('I'); append('N'); append('F'); } else if (f == -std::numeric_limits::infinity()) { append('-'); append('I'); append('N'); append('F'); } else { append('N'); append('a'); append('N'); } } template void FUStringBuilderT::appendLine(const Char* sz) { append(sz); append("\n"); } template void FUStringBuilderT::remove(int32 start) { if ((int32)size > start && start >= 0) size = start; } template void FUStringBuilderT::remove(int32 start, int32 end) { int32 diff = end - start; if ((int32)size >= end && start >= 0 && diff > 0) { const Char* stop = buffer + size - diff; for (Char* p = buffer + start; p != stop; ++p) { *p = *(p + diff); } size -= diff; } } template typename FUStringBuilderT::String FUStringBuilderT::ToString() { return String((const Char*)*this); } template const Char* FUStringBuilderT::ToCharPtr() { if (size + 1 > reserved) enlarge(1); buffer[size] = 0; return buffer; } template int32 FUStringBuilderT::index(Char c) { if (buffer != NULL && size > 0) { const Char* end = buffer + size + 1; for (const Char* p = buffer; p != end; ++p) { if (*p == c) return (int32)(p - buffer); } } return -1; } template int32 FUStringBuilderT::rindex(Char c) { if (buffer != NULL && size > 0) { for (const Char* p = buffer + size - 1; p != buffer; --p) { if (*p == c) return (int32)(p - buffer); } } return -1; }