Browse Source

Merge pull request #253 from zrax/plString

Fix a major plStringStream bug, and add an SSO-like optimization to it.
Joseph Davies 12 years ago
parent
commit
3bfb6b5850
  1. 38
      Sources/Plasma/CoreLib/plString.cpp
  2. 28
      Sources/Plasma/CoreLib/plString.h

38
Sources/Plasma/CoreLib/plString.cpp

@ -501,11 +501,11 @@ double plString::ToDouble() const
plString plString::IFormat(const char *fmt, va_list vptr) plString plString::IFormat(const char *fmt, va_list vptr)
{ {
char buffer[256]; char buffer[STRING_STACK_SIZE];
va_list vptr_save; va_list vptr_save;
va_copy(vptr_save, vptr); va_copy(vptr_save, vptr);
int chars = vsnprintf(buffer, 256, fmt, vptr); int chars = vsnprintf(buffer, STRING_STACK_SIZE, fmt, vptr);
if (chars < 0) { if (chars < 0) {
// We will need to try this multiple times until we get a // We will need to try this multiple times until we get a
// large enough buffer :( // large enough buffer :(
@ -522,9 +522,8 @@ plString plString::IFormat(const char *fmt, va_list vptr)
} }
size *= 2; 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); va_copy(vptr, vptr_save);
plStringBuffer<char> bigbuffer; plStringBuffer<char> bigbuffer;
char *data = bigbuffer.CreateWritableBuffer(chars); 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) plStringStream &plStringStream::append(const char *data, size_t length)
{ {
if (fLength + length > fBufSize) { size_t bufSize = ICanHasHeap() ? fBufSize : STRING_STACK_SIZE;
char *bigger = new char[fBufSize * 2]; char *bufp = ICanHasHeap() ? fBuffer : fShort;
memcpy(bigger, fBuffer, fBufSize);
delete [] fBuffer; if (fLength + length > bufSize) {
fBuffer = bigger; size_t bigSize = bufSize;
fBufSize *= 2; 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; fLength += length;
return *this; return *this;
} }
@ -855,6 +864,13 @@ plStringStream &plStringStream::operator<<(unsigned int num)
return operator<<(buffer); 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 ustrlen(const UniChar *ustr, size_t max)
{ {
size_t length = 0; size_t length = 0;

28
Sources/Plasma/CoreLib/plString.h

@ -49,6 +49,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
typedef unsigned int UniChar; typedef unsigned int UniChar;
#define SSO_CHARS (16) #define SSO_CHARS (16)
#define STRING_STACK_SIZE (256)
#define WHITESPACE_CHARS " \t\n\r" #define WHITESPACE_CHARS " \t\n\r"
template <typename _Ch> template <typename _Ch>
@ -343,17 +344,16 @@ plString operator+(const char *left, const plString &right);
class plStringStream class plStringStream
{ {
public: public:
plStringStream() : fBufSize(256), fLength(0) plStringStream() : fLength(0) { }
{ ~plStringStream() { if (ICanHasHeap()) delete [] fBuffer; }
fBuffer = new char[fBufSize];
}
~plStringStream() { delete [] fBuffer; }
plStringStream &append(const char *data, size_t length); plStringStream &append(const char *data, size_t length);
plStringStream &operator<<(const char *text); plStringStream &operator<<(const char *text);
plStringStream &operator<<(int num); plStringStream &operator<<(int num);
plStringStream &operator<<(unsigned int num); plStringStream &operator<<(unsigned int num);
plStringStream &operator<<(float num) { return operator<<(static_cast<double>(num)); }
plStringStream &operator<<(double num);
plStringStream &operator<<(char ch) { return append(&ch, 1); } plStringStream &operator<<(char ch) { return append(&ch, 1); }
plStringStream &operator<<(const plString &text) plStringStream &operator<<(const plString &text)
@ -361,13 +361,25 @@ public:
return append(text.c_str(), text.GetSize()); 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; } size_t GetLength() const { return fLength; }
plString GetString() { return plString::FromUtf8(fBuffer, fLength); } plString GetString() { return plString::FromUtf8(GetRawBuffer(), fLength); }
private: private:
char *fBuffer; union {
size_t fBufSize; struct {
char *fBuffer;
size_t fBufSize;
};
char fShort[STRING_STACK_SIZE];
};
size_t fLength; size_t fLength;
bool ICanHasHeap() const { return fLength > STRING_STACK_SIZE; }
}; };
size_t ustrlen(const UniChar *ustr, size_t max = plString::kSizeAuto); size_t ustrlen(const UniChar *ustr, size_t max = plString::kSizeAuto);

Loading…
Cancel
Save