mirror of
https://github.com/The-Powder-Toy/The-Powder-Toy.git
synced 2025-08-11 10:54:15 +02:00
Add Number parsing facilities
This commit is contained in:
@@ -62,8 +62,10 @@ namespace Format
|
|||||||
template<typename T> inline FlagsOverride<T, std::ios_base::fmtflags{}, std::ios_base::showpoint> NoShowPoint(T value) { return FlagsOverride<T, std::ios_base::fmtflags{}, std::ios_base::showpoint>(value); }
|
template<typename T> inline FlagsOverride<T, std::ios_base::fmtflags{}, std::ios_base::showpoint> NoShowPoint(T value) { return FlagsOverride<T, std::ios_base::fmtflags{}, std::ios_base::showpoint>(value); }
|
||||||
inline FlagsOverride<void, std::ios_base::uppercase, std::ios_base::uppercase> Uppercase() { return FlagsOverride<void, std::ios_base::uppercase, std::ios_base::uppercase>(); }
|
inline FlagsOverride<void, std::ios_base::uppercase, std::ios_base::uppercase> Uppercase() { return FlagsOverride<void, std::ios_base::uppercase, std::ios_base::uppercase>(); }
|
||||||
inline FlagsOverride<void, std::ios_base::showpoint, std::ios_base::showpoint> ShowPoint() { return FlagsOverride<void, std::ios_base::showpoint, std::ios_base::showpoint>(); }
|
inline FlagsOverride<void, std::ios_base::showpoint, std::ios_base::showpoint> ShowPoint() { return FlagsOverride<void, std::ios_base::showpoint, std::ios_base::showpoint>(); }
|
||||||
|
inline FlagsOverride<void, std::ios_base::skipws, std::ios_base::skipws> SkipWS() { return FlagsOverride<void, std::ios_base::skipws, std::ios_base::skipws>(); }
|
||||||
inline FlagsOverride<void, std::ios_base::fmtflags{}, std::ios_base::uppercase> NoUppercase() { return FlagsOverride<void, std::ios_base::fmtflags{}, std::ios_base::uppercase>(); }
|
inline FlagsOverride<void, std::ios_base::fmtflags{}, std::ios_base::uppercase> NoUppercase() { return FlagsOverride<void, std::ios_base::fmtflags{}, std::ios_base::uppercase>(); }
|
||||||
inline FlagsOverride<void, std::ios_base::fmtflags{}, std::ios_base::showpoint> NoShowPoint() { return FlagsOverride<void, std::ios_base::fmtflags{}, std::ios_base::showpoint>(); }
|
inline FlagsOverride<void, std::ios_base::fmtflags{}, std::ios_base::showpoint> NoShowPoint() { return FlagsOverride<void, std::ios_base::fmtflags{}, std::ios_base::showpoint>(); }
|
||||||
|
inline FlagsOverride<void, std::ios_base::fmtflags{}, std::ios_base::skipws> NoSkipWS() { return FlagsOverride<void, std::ios_base::fmtflags{}, std::ios_base::skipws>(); }
|
||||||
|
|
||||||
template<typename T> inline FlagsOverride<T, std::ios_base::fixed, std::ios_base::floatfield> Fixed(T value) { return FlagsOverride<T, std::ios_base::fixed, std::ios_base::floatfield>(value); }
|
template<typename T> inline FlagsOverride<T, std::ios_base::fixed, std::ios_base::floatfield> Fixed(T value) { return FlagsOverride<T, std::ios_base::fixed, std::ios_base::floatfield>(value); }
|
||||||
template<typename T> inline FlagsOverride<T, std::ios_base::scientific, std::ios_base::floatfield> Scientific(T value) { return FlagsOverride<T, std::ios_base::scientific, std::ios_base::floatfield>(value); }
|
template<typename T> inline FlagsOverride<T, std::ios_base::scientific, std::ios_base::floatfield> Scientific(T value) { return FlagsOverride<T, std::ios_base::scientific, std::ios_base::floatfield>(value); }
|
||||||
|
@@ -234,6 +234,8 @@ inline wchar_t narrow_wchar(String::value_type ch)
|
|||||||
return wchar_t(ch);
|
return wchar_t(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String numberChars = "-.+0123456789ABCDEFXabcdefx";
|
||||||
|
|
||||||
static thread_local struct LocaleImpl
|
static thread_local struct LocaleImpl
|
||||||
{
|
{
|
||||||
std::basic_stringstream<char> stream;
|
std::basic_stringstream<char> stream;
|
||||||
@@ -253,6 +255,16 @@ static thread_local struct LocaleImpl
|
|||||||
wstream.fill(b.fill);
|
wstream.fill(b.fill);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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]))
|
||||||
|
wstr.push_back(narrow_wchar(str[pos++]));
|
||||||
|
wstream.str(wstr);
|
||||||
|
wstream.clear();
|
||||||
|
}
|
||||||
|
|
||||||
inline void FlushWStream(StringBuilder &b)
|
inline void FlushWStream(StringBuilder &b)
|
||||||
{
|
{
|
||||||
std::basic_string<wchar_t> wstr = wstream.str();
|
std::basic_string<wchar_t> wstr = wstream.str();
|
||||||
@@ -263,6 +275,11 @@ static thread_local struct LocaleImpl
|
|||||||
b.AddChars(chars.data(), chars.size());
|
b.AddChars(chars.data(), chars.size());
|
||||||
wstream.str(std::basic_string<wchar_t>());
|
wstream.str(std::basic_string<wchar_t>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void FlushWStream()
|
||||||
|
{
|
||||||
|
wstream.str(std::basic_string<wchar_t>());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
LocaleImpl;
|
LocaleImpl;
|
||||||
|
|
||||||
@@ -376,6 +393,50 @@ StringBuilder &operator<<(StringBuilder &b, double data)
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String::Split String::SplitSigned(long long int &value, size_t pos, std::ios_base::fmtflags set, std::ios_base::fmtflags reset) const
|
||||||
|
{
|
||||||
|
LocaleImpl.PrepareWStream(*this, pos, set, reset);
|
||||||
|
LocaleImpl.wstream >> value;
|
||||||
|
if(LocaleImpl.wstream.fail())
|
||||||
|
{
|
||||||
|
LocaleImpl.FlushWStream();
|
||||||
|
return Split(*this, pos, npos, 0, false);
|
||||||
|
}
|
||||||
|
LocaleImpl.wstream.clear();
|
||||||
|
Split split(*this, pos, pos + LocaleImpl.wstream.tellg(), 0, false);
|
||||||
|
LocaleImpl.FlushWStream();
|
||||||
|
return split;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::Split String::SplitUnsigned(unsigned long long int &value, size_t pos, std::ios_base::fmtflags set, std::ios_base::fmtflags reset) const
|
||||||
|
{
|
||||||
|
LocaleImpl.PrepareWStream(*this, pos, set, reset);
|
||||||
|
LocaleImpl.wstream >> value;
|
||||||
|
if(LocaleImpl.wstream.fail())
|
||||||
|
{
|
||||||
|
LocaleImpl.FlushWStream();
|
||||||
|
return Split(*this, pos, npos, 0, false);
|
||||||
|
}
|
||||||
|
LocaleImpl.wstream.clear();
|
||||||
|
Split split(*this, pos, pos + LocaleImpl.wstream.tellg(), 0, false);
|
||||||
|
LocaleImpl.FlushWStream();
|
||||||
|
return split;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::Split String::SplitFloat(double &value, size_t pos, std::ios_base::fmtflags set, std::ios_base::fmtflags reset) const
|
||||||
|
{
|
||||||
|
LocaleImpl.PrepareWStream(*this, pos, set, reset);
|
||||||
|
LocaleImpl.wstream >> value;
|
||||||
|
if(LocaleImpl.wstream.fail())
|
||||||
|
{
|
||||||
|
LocaleImpl.FlushWStream();
|
||||||
|
return Split(*this, pos, npos, 0, false);
|
||||||
|
}
|
||||||
|
LocaleImpl.wstream.clear();
|
||||||
|
Split split(*this, pos, pos + LocaleImpl.wstream.tellg(), 0, false);
|
||||||
|
LocaleImpl.FlushWStream();
|
||||||
|
return split;
|
||||||
|
}
|
||||||
|
|
||||||
template<> std::ctype<char32_t>::~ctype()
|
template<> std::ctype<char32_t>::~ctype()
|
||||||
{
|
{
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
class ByteStringBuilder;
|
class ByteStringBuilder;
|
||||||
class String;
|
class String;
|
||||||
class StringBuilder;
|
class StringBuilder;
|
||||||
|
namespace Format { template<typename T, std::ios_base::fmtflags set, std::ios_base::fmtflags reset> struct FlagsOverride; }
|
||||||
|
|
||||||
template<typename T> class SplitBase
|
template<typename T> class SplitBase
|
||||||
{
|
{
|
||||||
@@ -179,6 +180,71 @@ public:
|
|||||||
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 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); }
|
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:
|
||||||
|
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() const
|
||||||
|
{
|
||||||
|
T value = T();
|
||||||
|
Split split = SplitNumber(value);
|
||||||
|
if(split.PositionBefore() != size())
|
||||||
|
return T();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
template<typename T, std::ios_base::fmtflags set, std::ios_base::fmtflags reset> inline T ToNumber(Format::FlagsOverride<void, set, reset> fmt) const
|
||||||
|
{
|
||||||
|
T value = T();
|
||||||
|
Split split = SplitNumber(value, fmt);
|
||||||
|
if(split.PositionBefore() != size())
|
||||||
|
return T();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<String> PartitionBy(value_type ch, bool includeEmpty = false) const;
|
std::vector<String> PartitionBy(value_type ch, bool includeEmpty = false) const;
|
||||||
std::vector<String> PartitionBy(String const &str, bool includeEmpty = false) const;
|
std::vector<String> PartitionBy(String const &str, bool includeEmpty = false) const;
|
||||||
|
Reference in New Issue
Block a user