#pragma once #include "GpVector.h" #include #include template class GpString { public: explicit GpString(IGpAllocator *alloc); GpString(GpString &&other); bool Set(const TChar *str); bool Set(const TChar *str, size_t len); bool Set(const GpString &other); bool Append(const TChar *str); bool Append(const TChar *str, size_t len); bool Append(const GpString &other); TChar *Buffer(); const TChar *Buffer() const ; private: static const size_t kStaticSize = 32; GpVector m_chars; size_t m_length; }; typedef GpString GpCString; typedef GpString GpWString; #include #include template GpString::GpString(IGpAllocator *alloc) : m_chars(alloc) , m_length(0) { (void)m_chars.Resize(1); m_chars[0] = static_cast(0); } template GpString::GpString(GpString &&other) : m_chars(static_cast&&>(other.m_chars)) , m_length(other.m_length) { other.m_length = 0; } template bool GpString::Set(const TChar *str) { size_t len = 0; while (str[len] != static_cast(0)) len++; return this->Set(str, len); } template bool GpString::Set(const TChar *str, size_t len) { if (!m_chars.ResizeNoConstruct(len + 1)) return false; TChar *chars = m_chars.Buffer(); memcpy(chars, str, sizeof(TChar) * len); chars[len] = static_cast(0); m_length = len; return true; } template bool GpString::Set(const GpString &other) { if (&other == this) return true; return this->Set(other.Buffer(), other.m_length); } template bool GpString::Append(const TChar *str) { size_t len = 0; while (str[len] != static_cast(0)) len++; return this->Append(str, len); } template bool GpString::Append(const TChar *str, size_t len) { // This is a special path in case we're appending the string to itself and the resize relocates the buffer if (len == 0) return true; assert(str != this->Buffer()); if (!m_chars.ResizeNoConstruct(m_length + len + 1)) return false; memcpy(m_chars.Buffer() + m_length, str, sizeof(TChar) * len); m_chars[m_length + len] = static_cast(0); m_length += len; return true; } template bool GpString::Append(const GpString &other) { // This is a special path in case we're appending the string to itself and the resize relocates the buffer if (other.m_length == 0) return true; if (!m_chars.ResizeNoConstruct(m_length + other.m_length)) return false; memcpy(m_chars.Buffer() + m_length, other.Buffer(), sizeof(TChar) * other.m_length); m_chars[m_length + other.m_length] = static_cast(0); m_length += other.m_length; return true; } template TChar *GpString::Buffer() { return m_chars.Buffer(); } template const TChar *GpString::Buffer() const { return m_chars.Buffer(); }