diff --git a/Sources/Plasma/CoreLib/plString.cpp b/Sources/Plasma/CoreLib/plString.cpp index 369f1182..cd24209b 100644 --- a/Sources/Plasma/CoreLib/plString.cpp +++ b/Sources/Plasma/CoreLib/plString.cpp @@ -501,11 +501,11 @@ double plString::ToDouble() const plString plString::IFormat(const char *fmt, va_list vptr) { - char buffer[256]; + char buffer[STRING_STACK_SIZE]; va_list vptr_save; va_copy(vptr_save, vptr); - int chars = vsnprintf(buffer, 256, fmt, vptr); + int chars = vsnprintf(buffer, STRING_STACK_SIZE, fmt, vptr); if (chars < 0) { // We will need to try this multiple times until we get a // large enough buffer :( @@ -522,9 +522,8 @@ plString plString::IFormat(const char *fmt, va_list vptr) } size *= 2; - hsAssert(size > 0, "Formatted string output is waaaaay too long"); } - } else if (chars >= 256) { + } else if (chars >= STRING_STACK_SIZE) { va_copy(vptr, vptr_save); plStringBuffer bigbuffer; char *data = bigbuffer.CreateWritableBuffer(chars); @@ -823,14 +822,24 @@ plString operator+(const char *left, const plString &right) plStringStream &plStringStream::append(const char *data, size_t length) { - if (fLength + length > fBufSize) { - char *bigger = new char[fBufSize * 2]; - memcpy(bigger, fBuffer, fBufSize); - delete [] fBuffer; - fBuffer = bigger; - fBufSize *= 2; + size_t bufSize = ICanHasHeap() ? fBufSize : STRING_STACK_SIZE; + char *bufp = ICanHasHeap() ? fBuffer : fShort; + + if (fLength + length > bufSize) { + size_t bigSize = bufSize; + do { + bigSize *= 2; + } while (fLength + length > bigSize); + + char *bigger = new char[bigSize]; + memcpy(bigger, GetRawBuffer(), bufSize); + if (ICanHasHeap()) + delete [] fBuffer; + fBuffer = bufp = bigger; + fBufSize = bigSize; } - memcpy(fBuffer + fLength, data, length); + + memcpy(bufp + fLength, data, length); fLength += length; return *this; } @@ -855,6 +864,13 @@ plStringStream &plStringStream::operator<<(unsigned int num) return operator<<(buffer); } +plStringStream &plStringStream::operator<<(double num) +{ + char buffer[64]; + snprintf(buffer, 64, "%f", num); + return operator<<(buffer); +} + size_t ustrlen(const UniChar *ustr, size_t max) { size_t length = 0; diff --git a/Sources/Plasma/CoreLib/plString.h b/Sources/Plasma/CoreLib/plString.h index 598fd588..ecc77b5d 100644 --- a/Sources/Plasma/CoreLib/plString.h +++ b/Sources/Plasma/CoreLib/plString.h @@ -49,6 +49,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com typedef unsigned int UniChar; #define SSO_CHARS (16) +#define STRING_STACK_SIZE (256) #define WHITESPACE_CHARS " \t\n\r" template @@ -343,17 +344,16 @@ plString operator+(const char *left, const plString &right); class plStringStream { public: - plStringStream() : fBufSize(256), fLength(0) - { - fBuffer = new char[fBufSize]; - } - ~plStringStream() { delete [] fBuffer; } + plStringStream() : fLength(0) { } + ~plStringStream() { if (ICanHasHeap()) delete [] fBuffer; } plStringStream &append(const char *data, size_t length); plStringStream &operator<<(const char *text); plStringStream &operator<<(int num); plStringStream &operator<<(unsigned int num); + plStringStream &operator<<(float num) { return operator<<(static_cast(num)); } + plStringStream &operator<<(double num); plStringStream &operator<<(char ch) { return append(&ch, 1); } plStringStream &operator<<(const plString &text) @@ -361,13 +361,25 @@ public: return append(text.c_str(), text.GetSize()); } + const char *GetRawBuffer() const // WARNING: Not null-terminated! + { + return ICanHasHeap() ? fBuffer : fShort; + } + size_t GetLength() const { return fLength; } - plString GetString() { return plString::FromUtf8(fBuffer, fLength); } + plString GetString() { return plString::FromUtf8(GetRawBuffer(), fLength); } private: - char *fBuffer; - size_t fBufSize; + union { + struct { + char *fBuffer; + size_t fBufSize; + }; + char fShort[STRING_STACK_SIZE]; + }; size_t fLength; + + bool ICanHasHeap() const { return fLength > STRING_STACK_SIZE; } }; size_t ustrlen(const UniChar *ustr, size_t max = plString::kSizeAuto);