From f864f81a7617bdd0a2355eb400aaf8c96ccf363d Mon Sep 17 00:00:00 2001 From: mniip Date: Wed, 2 May 2018 05:38:08 +0300 Subject: [PATCH] StringBuilder mockup --- src/common/String.cpp | 159 ++++++++++++++++++++++++++++++++++++++++++ src/common/String.h | 41 +++++++++++ 2 files changed, 200 insertions(+) diff --git a/src/common/String.cpp b/src/common/String.cpp index 41bbe0136..87f133327 100644 --- a/src/common/String.cpp +++ b/src/common/String.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "String.h" @@ -88,6 +89,164 @@ ByteString String::ToUtf8() const } } +inline String::value_type widen_wchar(wchar_t ch) +{ + return std::make_unsigned::type(ch); +} + +inline bool representable_wchar(String::value_type ch) +{ + return ch < String::value_type(std::make_unsigned::type(std::numeric_limits::max())); +} + +inline wchar_t narrow_wchar(String::value_type ch) +{ + return wchar_t(ch); +} + +static thread_local struct LocaleImpl +{ + std::basic_stringstream stream; + std::basic_stringstream wstream; + + LocaleImpl() + { + stream.imbue(std::locale::classic()); + wstream.imbue(std::locale::classic()); + } + + inline void PrepareWStream(StringBuilder &b) + { + wstream.flags(b.flags); + wstream.width(b.width); + wstream.precision(b.precision); + wstream.fill(b.fill); + } + + inline void FlushWStream(StringBuilder &b) + { + std::basic_string wstr = wstream.str(); + std::vector chars; // operator new? + chars.reserve(wstr.size()); + for(wchar_t ch : wstream.str()) + chars.push_back(widen_wchar(ch)); + b.AddChars(chars.data(), chars.size()); + wstream.str(std::basic_string()); + } +} +LocaleImpl; + +String StringBuilder::Build() const +{ + return String(buffer.begin(), buffer.end()); +} + +void StringBuilder::AddChars(String::value_type const *data, size_t count) +{ + buffer.reserve(buffer.size() + count); + buffer.insert(buffer.end(), data, data + count); +} + +StringBuilder &operator<<(StringBuilder &b, short int data) +{ + LocaleImpl.PrepareWStream(b); + LocaleImpl.wstream << data; + LocaleImpl.FlushWStream(b); + return b; +} + +StringBuilder &operator<<(StringBuilder &b, int data) +{ + LocaleImpl.PrepareWStream(b); + LocaleImpl.wstream << data; + LocaleImpl.FlushWStream(b); + return b; +} + +StringBuilder &operator<<(StringBuilder &b, long int data) +{ + LocaleImpl.PrepareWStream(b); + LocaleImpl.wstream << data; + LocaleImpl.FlushWStream(b); + return b; +} + +StringBuilder &operator<<(StringBuilder &b, long long int data) +{ + LocaleImpl.PrepareWStream(b); + LocaleImpl.wstream << data; + LocaleImpl.FlushWStream(b); + return b; +} + +StringBuilder &operator<<(StringBuilder &b, unsigned short int data) +{ + LocaleImpl.PrepareWStream(b); + LocaleImpl.wstream << data; + LocaleImpl.FlushWStream(b); + return b; +} + +StringBuilder &operator<<(StringBuilder &b, unsigned int data) +{ + LocaleImpl.PrepareWStream(b); + LocaleImpl.wstream << data; + LocaleImpl.FlushWStream(b); + return b; +} + +StringBuilder &operator<<(StringBuilder &b, unsigned long int data) +{ + LocaleImpl.PrepareWStream(b); + LocaleImpl.wstream << data; + LocaleImpl.FlushWStream(b); + return b; +} + +StringBuilder &operator<<(StringBuilder &b, unsigned long long int data) +{ + LocaleImpl.PrepareWStream(b); + LocaleImpl.wstream << data; + LocaleImpl.FlushWStream(b); + return b; +} + +StringBuilder &operator<<(StringBuilder &b, ByteString::value_type data) +{ + String::value_type ch = data; + b.AddChars(&ch, 1); + return b; +} + +StringBuilder &operator<<(StringBuilder &b, String::value_type data) +{ + b.AddChars(&data, 1); + return b; +} + +StringBuilder &operator<<(StringBuilder &b, String const &data) +{ + b.AddChars(data.data(), data.size()); + return b; +} + +StringBuilder &operator<<(StringBuilder &b, float data) +{ + LocaleImpl.PrepareWStream(b); + LocaleImpl.wstream << data; + LocaleImpl.FlushWStream(b); + return b; +} + +StringBuilder &operator<<(StringBuilder &b, double data) +{ + LocaleImpl.PrepareWStream(b); + LocaleImpl.wstream << data; + LocaleImpl.FlushWStream(b); + return b; +} + + template<> std::ctype::~ctype() { } diff --git a/src/common/String.h b/src/common/String.h index 706f270e0..9b6eb2696 100644 --- a/src/common/String.h +++ b/src/common/String.h @@ -3,9 +3,13 @@ #include #include +#include #include +#include +class ByteStringBuilder; class String; +class StringBuilder; template class SplitBase { @@ -244,4 +248,41 @@ public: inline ConversionError(bool to): std::runtime_error(to ? "Could not convert to UTF-8" : "Could not convert from UTF-8") {} }; +class StringBuilder +{ + std::vector buffer; // TODO: std::list > ? +public: + std::ios_base::fmtflags flags; + String::value_type fill; + size_t width, precision; + inline StringBuilder(): flags(std::ios_base::skipws | std::ios_base::dec), fill(' '), width(0), precision(6) {} + + void AddChars(String::value_type const *, size_t); + size_t Size() const { return buffer.size(); } + String Build() const; + + template StringBuilder &operator<<(T) = delete; + + template StringBuilder &Add(T &&arg, Ts&&... args) + { + return (*this << std::forward(arg)).Add(std::forward(args)...); + } + StringBuilder &Add() { return *this; } +}; + +StringBuilder &operator<<(StringBuilder &, short int); +StringBuilder &operator<<(StringBuilder &, int); +StringBuilder &operator<<(StringBuilder &, long int); +StringBuilder &operator<<(StringBuilder &, long long int); +StringBuilder &operator<<(StringBuilder &, unsigned short int); +StringBuilder &operator<<(StringBuilder &, unsigned int); +StringBuilder &operator<<(StringBuilder &, unsigned long int); +StringBuilder &operator<<(StringBuilder &, unsigned long long int); +StringBuilder &operator<<(StringBuilder &, ByteString::value_type); +StringBuilder &operator<<(StringBuilder &, String::value_type); +StringBuilder &operator<<(StringBuilder &, String const &); +StringBuilder &operator<<(StringBuilder &, float); +StringBuilder &operator<<(StringBuilder &, double); +template StringBuilder &operator<<(StringBuilder &b, ByteString::value_type const (&data)[N]) { return b << ByteString(data).FromUtf8(); } + #endif