From 11558b8301d7a8a943e968a3b7c9b29fa74ca665 Mon Sep 17 00:00:00 2001 From: Michael Hansen Date: Sun, 6 Jan 2013 16:19:30 -0800 Subject: [PATCH] Fix a major plStringStream bug, and add an SSO-like optimization to it --- Sources/Plasma/CoreLib/plString.cpp | 32 ++++++++++++++++++++++------- Sources/Plasma/CoreLib/plString.h | 26 +++++++++++++++++------ 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/Sources/Plasma/CoreLib/plString.cpp b/Sources/Plasma/CoreLib/plString.cpp index 57c0c422..8718aa19 100644 --- a/Sources/Plasma/CoreLib/plString.cpp +++ b/Sources/Plasma/CoreLib/plString.cpp @@ -800,14 +800,25 @@ 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 : 256; + char *bufp = ICanHasHeap() ? fBuffer : fShort; + + if (fLength + length > bufSize) { + size_t bigSize = bufSize; + do { + hsAssert(bigSize * 2, "plStringStream buffer too large"); + 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; } @@ -832,6 +843,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 bfecb1de..53827e00 100644 --- a/Sources/Plasma/CoreLib/plString.h +++ b/Sources/Plasma/CoreLib/plString.h @@ -341,17 +341,19 @@ plString operator+(const char *left, const plString &right); class plStringStream { public: - plStringStream() : fBufSize(256), fLength(0) + plStringStream() : fLength(0) { - fBuffer = new char[fBufSize]; + fShort[0] = 0; } - ~plStringStream() { delete [] fBuffer; } + ~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) @@ -359,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[256]; + }; size_t fLength; + + bool ICanHasHeap() const { return fLength > 256; } }; size_t ustrlen(const UniChar *ustr, size_t max = plString::kSizeAuto);