mirror of
https://github.com/The-Powder-Toy/The-Powder-Toy.git
synced 2025-03-21 06:40:02 +01:00
Copy the String interface to ByteString
This commit is contained in:
parent
7f5c164d22
commit
d6a92bdab5
@ -234,7 +234,9 @@ inline wchar_t narrow_wchar(String::value_type ch)
|
||||
return wchar_t(ch);
|
||||
}
|
||||
|
||||
String numberChars = "-.+0123456789ABCDEFXabcdefx";
|
||||
char const numberChars[] = "-.+0123456789ABCDEFXabcdefx";
|
||||
ByteString numberByteString(numberChars);
|
||||
String numberString(numberChars);
|
||||
|
||||
static thread_local struct LocaleImpl
|
||||
{
|
||||
@ -247,19 +249,51 @@ static thread_local struct LocaleImpl
|
||||
wstream.imbue(std::locale::classic());
|
||||
}
|
||||
|
||||
inline void PrepareStream(ByteStringBuilder &b)
|
||||
{
|
||||
stream.flags(b.flags);
|
||||
stream.width(b.width);
|
||||
stream.precision(b.precision);
|
||||
stream.fill(b.fill);
|
||||
stream.clear();
|
||||
}
|
||||
|
||||
inline void PrepareStream(ByteString const &str, size_t pos, std::ios_base::fmtflags set, std::ios_base::fmtflags reset)
|
||||
{
|
||||
stream.flags((std::ios_base::dec & ~ reset) | set);
|
||||
std::basic_string<char> bstr;
|
||||
while(pos < str.size() && numberByteString.Contains(str[pos]))
|
||||
bstr.push_back(narrow_wchar(str[pos++]));
|
||||
stream.str(bstr);
|
||||
stream.clear();
|
||||
}
|
||||
|
||||
inline void FlushStream(ByteStringBuilder &b)
|
||||
{
|
||||
std::basic_string<char> str = stream.str();
|
||||
b.AddChars(str.data(), str.size());
|
||||
stream.str(std::basic_string<char>());
|
||||
}
|
||||
|
||||
inline void FlushStream()
|
||||
{
|
||||
stream.str(std::basic_string<char>());
|
||||
}
|
||||
|
||||
inline void PrepareWStream(StringBuilder &b)
|
||||
{
|
||||
wstream.flags(b.flags);
|
||||
wstream.width(b.width);
|
||||
wstream.precision(b.precision);
|
||||
wstream.fill(b.fill);
|
||||
wstream.clear();
|
||||
}
|
||||
|
||||
inline void PrepareWStream(String const &str, size_t pos, std::ios_base::fmtflags set, std::ios_base::fmtflags reset)
|
||||
{
|
||||
wstream.flags((std::ios_base::dec & ~ reset) | set);
|
||||
std::basic_string<wchar_t> wstr;
|
||||
while(pos < str.size() && representable_wchar(str[pos]) && numberChars.Contains(str[pos]))
|
||||
while(pos < str.size() && representable_wchar(str[pos]) && numberString.Contains(str[pos]))
|
||||
wstr.push_back(narrow_wchar(str[pos++]));
|
||||
wstream.str(wstr);
|
||||
wstream.clear();
|
||||
@ -283,6 +317,159 @@ static thread_local struct LocaleImpl
|
||||
}
|
||||
LocaleImpl;
|
||||
|
||||
ByteString ByteStringBuilder::Build() const
|
||||
{
|
||||
return ByteString(buffer.begin(), buffer.end());
|
||||
}
|
||||
|
||||
void ByteStringBuilder::AddChars(ByteString::value_type const *data, size_t count)
|
||||
{
|
||||
buffer.reserve(buffer.size() + count);
|
||||
buffer.insert(buffer.end(), data, data + count);
|
||||
}
|
||||
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &b, short int data)
|
||||
{
|
||||
LocaleImpl.PrepareStream(b);
|
||||
LocaleImpl.stream << data;
|
||||
LocaleImpl.FlushStream(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &b, int data)
|
||||
{
|
||||
LocaleImpl.PrepareStream(b);
|
||||
LocaleImpl.stream << data;
|
||||
LocaleImpl.FlushStream(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &b, long int data)
|
||||
{
|
||||
LocaleImpl.PrepareStream(b);
|
||||
LocaleImpl.stream << data;
|
||||
LocaleImpl.FlushStream(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &b, long long int data)
|
||||
{
|
||||
LocaleImpl.PrepareStream(b);
|
||||
LocaleImpl.stream << data;
|
||||
LocaleImpl.FlushStream(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &b, unsigned short int data)
|
||||
{
|
||||
LocaleImpl.PrepareStream(b);
|
||||
LocaleImpl.stream << data;
|
||||
LocaleImpl.FlushStream(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &b, unsigned int data)
|
||||
{
|
||||
LocaleImpl.PrepareStream(b);
|
||||
LocaleImpl.stream << data;
|
||||
LocaleImpl.FlushStream(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &b, unsigned long int data)
|
||||
{
|
||||
LocaleImpl.PrepareStream(b);
|
||||
LocaleImpl.stream << data;
|
||||
LocaleImpl.FlushStream(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &b, unsigned long long int data)
|
||||
{
|
||||
LocaleImpl.PrepareStream(b);
|
||||
LocaleImpl.stream << data;
|
||||
LocaleImpl.FlushStream(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &b, ByteString::value_type data)
|
||||
{
|
||||
b.AddChars(&data, 1);
|
||||
return b;
|
||||
}
|
||||
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &b, ByteString::value_type const *data)
|
||||
{
|
||||
return b << ByteString(data);
|
||||
}
|
||||
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &b, ByteString const &data)
|
||||
{
|
||||
b.AddChars(data.data(), data.size());
|
||||
return b;
|
||||
}
|
||||
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &b, float data)
|
||||
{
|
||||
LocaleImpl.PrepareStream(b);
|
||||
LocaleImpl.stream << data;
|
||||
LocaleImpl.FlushStream(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &b, double data)
|
||||
{
|
||||
LocaleImpl.PrepareStream(b);
|
||||
LocaleImpl.stream << data;
|
||||
LocaleImpl.FlushStream(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
ByteString::Split ByteString::SplitSigned(long long int &value, size_t pos, std::ios_base::fmtflags set, std::ios_base::fmtflags reset) const
|
||||
{
|
||||
LocaleImpl.PrepareStream(*this, pos, set, reset);
|
||||
LocaleImpl.stream >> value;
|
||||
if(LocaleImpl.stream.fail())
|
||||
{
|
||||
LocaleImpl.FlushStream();
|
||||
return Split(*this, pos, npos, 0, false);
|
||||
}
|
||||
LocaleImpl.stream.clear();
|
||||
Split split(*this, pos, pos + LocaleImpl.stream.tellg(), 0, false);
|
||||
LocaleImpl.FlushStream();
|
||||
return split;
|
||||
}
|
||||
|
||||
ByteString::Split ByteString::SplitUnsigned(unsigned long long int &value, size_t pos, std::ios_base::fmtflags set, std::ios_base::fmtflags reset) const
|
||||
{
|
||||
LocaleImpl.PrepareStream(*this, pos, set, reset);
|
||||
LocaleImpl.stream >> value;
|
||||
if(LocaleImpl.stream.fail())
|
||||
{
|
||||
LocaleImpl.FlushStream();
|
||||
return Split(*this, pos, npos, 0, false);
|
||||
}
|
||||
LocaleImpl.stream.clear();
|
||||
Split split(*this, pos, pos + LocaleImpl.stream.tellg(), 0, false);
|
||||
LocaleImpl.FlushStream();
|
||||
return split;
|
||||
}
|
||||
|
||||
ByteString::Split ByteString::SplitFloat(double &value, size_t pos, std::ios_base::fmtflags set, std::ios_base::fmtflags reset) const
|
||||
{
|
||||
LocaleImpl.PrepareStream(*this, pos, set, reset);
|
||||
LocaleImpl.stream >> value;
|
||||
if(LocaleImpl.stream.fail())
|
||||
{
|
||||
LocaleImpl.FlushStream();
|
||||
return Split(*this, pos, npos, 0, false);
|
||||
}
|
||||
LocaleImpl.stream.clear();
|
||||
Split split(*this, pos, pos + LocaleImpl.stream.tellg(), 0, false);
|
||||
LocaleImpl.FlushStream();
|
||||
return split;
|
||||
}
|
||||
|
||||
String StringBuilder::Build() const
|
||||
{
|
||||
return String(buffer.begin(), buffer.end());
|
||||
@ -371,6 +558,11 @@ StringBuilder &operator<<(StringBuilder &b, String::value_type data)
|
||||
return b;
|
||||
}
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &b, String::value_type const *data)
|
||||
{
|
||||
return b << String(data);
|
||||
}
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &b, String const &data)
|
||||
{
|
||||
b.AddChars(data.data(), data.size());
|
||||
@ -399,7 +591,6 @@ String::Split String::SplitSigned(long long int &value, size_t pos, std::ios_bas
|
||||
LocaleImpl.wstream >> value;
|
||||
if(LocaleImpl.wstream.fail())
|
||||
{
|
||||
LocaleImpl.wstream.clear();
|
||||
LocaleImpl.FlushWStream();
|
||||
return Split(*this, pos, npos, 0, false);
|
||||
}
|
||||
@ -415,7 +606,6 @@ String::Split String::SplitUnsigned(unsigned long long int &value, size_t pos, s
|
||||
LocaleImpl.wstream >> value;
|
||||
if(LocaleImpl.wstream.fail())
|
||||
{
|
||||
LocaleImpl.wstream.clear();
|
||||
LocaleImpl.FlushWStream();
|
||||
return Split(*this, pos, npos, 0, false);
|
||||
}
|
||||
@ -431,7 +621,6 @@ String::Split String::SplitFloat(double &value, size_t pos, std::ios_base::fmtfl
|
||||
LocaleImpl.wstream >> value;
|
||||
if(LocaleImpl.wstream.fail())
|
||||
{
|
||||
LocaleImpl.wstream.clear();
|
||||
LocaleImpl.FlushWStream();
|
||||
return Split(*this, pos, npos, 0, false);
|
||||
}
|
||||
|
@ -72,10 +72,10 @@ public:
|
||||
|
||||
inline ByteString Substr(size_t pos = 0, size_t count = npos) const { return super::substr(pos, count); }
|
||||
inline ByteString SubstrFromEnd(size_t rpos = 0, size_t rcount = npos) const { return super::substr(rcount == npos || rcount > rpos ? 0 : rpos - rcount, size() - rpos); }
|
||||
inline ByteString Between(size_t from, size_t to) const { return from >= to ? ByteString() : super::substr(from, to - from); }
|
||||
inline ByteString Between(size_t from, size_t to) const { return to == npos ? super::substr(from) : from >= to ? ByteString() : super::substr(from, to - from); }
|
||||
|
||||
inline bool Contains(value_type ch) const { return super::find(ch) != npos; }
|
||||
inline bool Contains(ByteString const &other) { return super::find(other) != npos; }
|
||||
inline bool Contains(ByteString const &other) const { return super::find(other) != npos; }
|
||||
|
||||
inline bool BeginsWith(ByteString const &other) const { return !super::compare(0, other.size(), other); }
|
||||
inline bool EndsWith(ByteString const &other) const { return !super::compare(size() - other.size(), other.size(), other); }
|
||||
@ -89,6 +89,71 @@ public:
|
||||
inline Split SplitFromEndBy(ByteString const &str, size_t pos = npos) const { return Split(*this, pos, super::find(str, pos), str.size(), true); }
|
||||
inline Split SplitFromEndByAny(ByteString const &str, size_t pos = npos) const { return Split(*this, pos, super::find_last_of(str, pos), 1, true); }
|
||||
inline Split SplitFromEndByNot(ByteString const &str, size_t pos = npos) const { return Split(*this, pos, super::find_last_not_of(str, pos), 1, true); }
|
||||
private:
|
||||
Split SplitSigned(long long int &, size_t, std::ios_base::fmtflags, std::ios_base::fmtflags) const;
|
||||
Split SplitUnsigned(unsigned long long int &, size_t, std::ios_base::fmtflags, std::ios_base::fmtflags) const;
|
||||
Split SplitFloat(double &, size_t, std::ios_base::fmtflags, std::ios_base::fmtflags) const;
|
||||
public:
|
||||
template<typename T> inline Split SplitSigned(T &ref, size_t pos, std::ios_base::fmtflags set, std::ios_base::fmtflags reset) const
|
||||
{
|
||||
long long int value = 0;
|
||||
Split split = SplitSigned(value, pos, set, reset);
|
||||
ref = value;
|
||||
return split;
|
||||
}
|
||||
template<typename T> inline Split SplitUnsigned(T &ref, size_t pos, std::ios_base::fmtflags set, std::ios_base::fmtflags reset) const
|
||||
{
|
||||
unsigned long long int value = 0;
|
||||
Split split = SplitUnsigned(value, pos, set, reset);
|
||||
ref = value;
|
||||
return split;
|
||||
}
|
||||
template<typename T> inline Split SplitFloat(T &ref, size_t pos, std::ios_base::fmtflags set, std::ios_base::fmtflags reset) const
|
||||
{
|
||||
double value = 0;
|
||||
Split split = SplitFloat(value, pos, set, reset);
|
||||
ref = value;
|
||||
return split;
|
||||
}
|
||||
|
||||
inline Split SplitNumber(short int &ref, size_t pos = 0) const { return SplitSigned(ref, pos, std::ios_base::fmtflags(), std::ios_base::fmtflags()); }
|
||||
inline Split SplitNumber(int &ref, size_t pos = 0) const { return SplitSigned(ref, pos, std::ios_base::fmtflags(), std::ios_base::fmtflags()); }
|
||||
inline Split SplitNumber(long int &ref, size_t pos = 0) const { return SplitSigned(ref, pos, std::ios_base::fmtflags(), std::ios_base::fmtflags()); }
|
||||
inline Split SplitNumber(long long int &ref, size_t pos = 0) const { return SplitSigned(ref, pos, std::ios_base::fmtflags(), std::ios_base::fmtflags()); }
|
||||
inline Split SplitNumber(unsigned short int &ref, size_t pos = 0) const { return SplitUnsigned(ref, pos, std::ios_base::fmtflags(), std::ios_base::fmtflags()); }
|
||||
inline Split SplitNumber(unsigned int &ref, size_t pos = 0) const { return SplitUnsigned(ref, pos, std::ios_base::fmtflags(), std::ios_base::fmtflags()); }
|
||||
inline Split SplitNumber(unsigned long int &ref, size_t pos = 0) const { return SplitUnsigned(ref, pos, std::ios_base::fmtflags(), std::ios_base::fmtflags()); }
|
||||
inline Split SplitNumber(unsigned long long int &ref, size_t pos = 0) const { return SplitUnsigned(ref, pos, std::ios_base::fmtflags(), std::ios_base::fmtflags()); }
|
||||
inline Split SplitNumber(float &ref, size_t pos = 0) const { return SplitFloat(ref, pos, std::ios_base::fmtflags(), std::ios_base::fmtflags()); }
|
||||
inline Split SplitNumber(double &ref, size_t pos = 0) const { return SplitFloat(ref, pos, std::ios_base::fmtflags(), std::ios_base::fmtflags()); }
|
||||
|
||||
template<std::ios_base::fmtflags set, std::ios_base::fmtflags reset> inline Split SplitNumber(short int &ref, Format::FlagsOverride<void, set, reset>, size_t pos = 0) const { return SplitSigned(ref, pos, set, reset); }
|
||||
template<std::ios_base::fmtflags set, std::ios_base::fmtflags reset> inline Split SplitNumber(int &ref, Format::FlagsOverride<void, set, reset>, size_t pos = 0) const { return SplitSigned(ref, pos, set, reset); }
|
||||
template<std::ios_base::fmtflags set, std::ios_base::fmtflags reset> inline Split SplitNumber(long int &ref, Format::FlagsOverride<void, set, reset>, size_t pos = 0) const { return SplitSigned(ref, pos, set, reset); }
|
||||
template<std::ios_base::fmtflags set, std::ios_base::fmtflags reset> inline Split SplitNumber(long long int &ref, Format::FlagsOverride<void, set, reset>, size_t pos = 0) const { return SplitSigned(ref, pos, set, reset); }
|
||||
template<std::ios_base::fmtflags set, std::ios_base::fmtflags reset> inline Split SplitNumber(unsigned short int &ref, Format::FlagsOverride<void, set, reset>, size_t pos = 0) const { return SplitUnsigned(ref, pos, set, reset); }
|
||||
template<std::ios_base::fmtflags set, std::ios_base::fmtflags reset> inline Split SplitNumber(unsigned int &ref, Format::FlagsOverride<void, set, reset>, size_t pos = 0) const { return SplitUnsigned(ref, pos, set, reset); }
|
||||
template<std::ios_base::fmtflags set, std::ios_base::fmtflags reset> inline Split SplitNumber(unsigned long int &ref, Format::FlagsOverride<void, set, reset>, size_t pos = 0) const { return SplitUnsigned(ref, pos, set, reset); }
|
||||
template<std::ios_base::fmtflags set, std::ios_base::fmtflags reset> inline Split SplitNumber(unsigned long long int &ref, Format::FlagsOverride<void, set, reset>, size_t pos = 0) const { return SplitUnsigned(ref, pos, set, reset); }
|
||||
template<std::ios_base::fmtflags set, std::ios_base::fmtflags reset> inline Split SplitNumber(float &ref, Format::FlagsOverride<void, set, reset>, size_t pos = 0) const { return SplitFloat(ref, pos, set, reset); }
|
||||
template<std::ios_base::fmtflags set, std::ios_base::fmtflags reset> inline Split SplitNumber(double &ref, Format::FlagsOverride<void, set, reset>, size_t pos = 0) const { return SplitFloat(ref, pos, set, reset); }
|
||||
|
||||
template<typename T> T ToNumber(bool noThrow = false) const
|
||||
{
|
||||
T value = T();
|
||||
Split split = SplitNumber(value);
|
||||
if(split.PositionBefore() != size())
|
||||
return noThrow ? T() : throw std::runtime_error("Not a number");
|
||||
return value;
|
||||
}
|
||||
template<typename T, std::ios_base::fmtflags set, std::ios_base::fmtflags reset> inline T ToNumber(Format::FlagsOverride<void, set, reset> fmt, bool noThrow = false) const
|
||||
{
|
||||
T value = T();
|
||||
Split split = SplitNumber(value, fmt);
|
||||
if(split.PositionBefore() != size())
|
||||
return noThrow ? T() : throw std::runtime_error("Not a number");
|
||||
return value;
|
||||
}
|
||||
|
||||
std::vector<ByteString> PartitionBy(value_type ch, bool includeEmpty = false) const;
|
||||
std::vector<ByteString> PartitionBy(ByteString const &str, bool includeEmpty = false) const;
|
||||
@ -102,6 +167,7 @@ public:
|
||||
|
||||
String FromUtf8(bool ignoreError = true) const;
|
||||
inline String FromAscii() const;
|
||||
template<typename... Ts> static ByteString Build(Ts&&... args);
|
||||
|
||||
using Stream = std::basic_stringstream<value_type>;
|
||||
};
|
||||
@ -177,7 +243,7 @@ public:
|
||||
inline Split SplitByAny(String const &str, size_t pos = 0) const { return Split(*this, pos, super::find_first_of(str, pos), 1, false); }
|
||||
inline Split SplitByNot(String const &str, size_t pos = 0) const { return Split(*this, pos, super::find_first_not_of(str, pos), 1, false); }
|
||||
inline Split SplitFromEndBy(value_type ch, size_t pos = npos) const { return Split(*this, pos, super::rfind(ch, pos), 1, true); }
|
||||
inline Split SplitFromEndBy(String const &str, size_t pos = npos) const { return Split(*this, pos,super::find(str, pos), str.size(), true); }
|
||||
inline Split SplitFromEndBy(String const &str, size_t pos = npos) const { return Split(*this, pos, super::find(str, pos), str.size(), true); }
|
||||
inline Split SplitFromEndByAny(String const &str, size_t pos = npos) const { return Split(*this, pos, super::find_last_of(str, pos), 1, true); }
|
||||
inline Split SplitFromEndByNot(String const &str, size_t pos = npos) const { return Split(*this, pos, super::find_last_not_of(str, pos), 1, true); }
|
||||
private:
|
||||
@ -251,7 +317,7 @@ public:
|
||||
std::vector<String> PartitionByAny(String const &str, bool includeEmpty = false) const;
|
||||
|
||||
String &Substitute(String const &needle, String const &replacement);
|
||||
|
||||
|
||||
inline String &Insert(size_t pos, String const &str) { super::insert(pos, str); return *this; }
|
||||
inline String &Erase(size_t pos, size_t count) { super::erase(pos, count); return *this; }
|
||||
inline String &EraseBetween(size_t from, size_t to) { if(from < to) super::erase(from, to - from); return *this; }
|
||||
@ -326,9 +392,52 @@ public:
|
||||
inline ConversionError(bool to): std::runtime_error(to ? "Could not convert to UTF-8" : "Could not convert from UTF-8") {}
|
||||
};
|
||||
|
||||
class ByteStringBuilder
|
||||
{
|
||||
std::vector<ByteString::value_type> buffer;
|
||||
public:
|
||||
std::ios_base::fmtflags flags;
|
||||
ByteString::value_type fill;
|
||||
size_t width, precision;
|
||||
inline ByteStringBuilder(): flags(std::ios_base::skipws | std::ios_base::dec), fill(' '), width(0), precision(6) {}
|
||||
|
||||
void AddChars(ByteString::value_type const *, size_t);
|
||||
size_t Size() const { return buffer.size(); }
|
||||
ByteString Build() const;
|
||||
|
||||
template<typename T> ByteStringBuilder &operator<<(T) = delete;
|
||||
|
||||
template<typename T, typename... Ts> ByteStringBuilder &Add(T &&arg, Ts&&... args)
|
||||
{
|
||||
return (*this << std::forward<T>(arg)).Add(std::forward<Ts>(args)...);
|
||||
}
|
||||
ByteStringBuilder &Add() { return *this; }
|
||||
};
|
||||
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &, short int);
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &, int);
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &, long int);
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &, long long int);
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &, unsigned short int);
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &, unsigned int);
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &, unsigned long int);
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &, unsigned long long int);
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &, ByteString::value_type);
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &, ByteString::value_type const *);
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &, ByteString const &);
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &, float);
|
||||
ByteStringBuilder &operator<<(ByteStringBuilder &, double);
|
||||
|
||||
template<typename... Ts> ByteString ByteString::Build(Ts&&... args)
|
||||
{
|
||||
ByteStringBuilder b;
|
||||
b.Add(std::forward<Ts>(args)...);
|
||||
return b.Build();
|
||||
}
|
||||
|
||||
class StringBuilder
|
||||
{
|
||||
std::vector<String::value_type> buffer; // TODO: std::list<std::vector<String::value_type> > ?
|
||||
std::vector<String::value_type> buffer;
|
||||
public:
|
||||
std::ios_base::fmtflags flags;
|
||||
String::value_type fill;
|
||||
@ -358,6 +467,7 @@ 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::value_type const *);
|
||||
StringBuilder &operator<<(StringBuilder &, String const &);
|
||||
StringBuilder &operator<<(StringBuilder &, float);
|
||||
StringBuilder &operator<<(StringBuilder &, double);
|
||||
|
Loading…
x
Reference in New Issue
Block a user