StringBuilder mockup

This commit is contained in:
mniip 2018-05-02 05:38:08 +03:00
parent ced7b0c993
commit f864f81a76
2 changed files with 200 additions and 0 deletions

View File

@ -2,6 +2,7 @@
#include <vector>
#include <locale>
#include <codecvt>
#include <limits>
#include "String.h"
@ -88,6 +89,164 @@ ByteString String::ToUtf8() const
}
}
inline String::value_type widen_wchar(wchar_t ch)
{
return std::make_unsigned<wchar_t>::type(ch);
}
inline bool representable_wchar(String::value_type ch)
{
return ch < String::value_type(std::make_unsigned<wchar_t>::type(std::numeric_limits<wchar_t>::max()));
}
inline wchar_t narrow_wchar(String::value_type ch)
{
return wchar_t(ch);
}
static thread_local struct LocaleImpl
{
std::basic_stringstream<char> stream;
std::basic_stringstream<wchar_t> 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<wchar_t> wstr = wstream.str();
std::vector<String::value_type> 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<wchar_t>());
}
}
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<char32_t>::~ctype()
{
}

View File

@ -3,9 +3,13 @@
#include <stdexcept>
#include <sstream>
#include <vector>
#include <string>
#include <ios>
class ByteStringBuilder;
class String;
class StringBuilder;
template<typename T> 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<String::value_type> buffer; // TODO: std::list<std::vector<String::value_type> > ?
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<typename T> StringBuilder &operator<<(T) = delete;
template<typename T, typename... Ts> StringBuilder &Add(T &&arg, Ts&&... args)
{
return (*this << std::forward<T>(arg)).Add(std::forward<Ts>(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<size_t N> StringBuilder &operator<<(StringBuilder &b, ByteString::value_type const (&data)[N]) { return b << ByteString(data).FromUtf8(); }
#endif