mirror of
https://github.com/The-Powder-Toy/The-Powder-Toy.git
synced 2025-03-21 06:40:02 +01:00
Add Number parsing facilities
This commit is contained in:
parent
4b92926f0d
commit
1ea7a035d1
@ -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); }
|
||||
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::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::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::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);
|
||||
}
|
||||
|
||||
String numberChars = "-.+0123456789ABCDEFXabcdefx";
|
||||
|
||||
static thread_local struct LocaleImpl
|
||||
{
|
||||
std::basic_stringstream<char> stream;
|
||||
@ -253,6 +255,16 @@ static thread_local struct LocaleImpl
|
||||
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)
|
||||
{
|
||||
std::basic_string<wchar_t> wstr = wstream.str();
|
||||
@ -263,6 +275,11 @@ static thread_local struct LocaleImpl
|
||||
b.AddChars(chars.data(), chars.size());
|
||||
wstream.str(std::basic_string<wchar_t>());
|
||||
}
|
||||
|
||||
inline void FlushWStream()
|
||||
{
|
||||
wstream.str(std::basic_string<wchar_t>());
|
||||
}
|
||||
}
|
||||
LocaleImpl;
|
||||
|
||||
@ -376,6 +393,50 @@ StringBuilder &operator<<(StringBuilder &b, double data)
|
||||
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()
|
||||
{
|
||||
|
@ -9,6 +9,7 @@
|
||||
class ByteStringBuilder;
|
||||
class String;
|
||||
class StringBuilder;
|
||||
namespace Format { template<typename T, std::ios_base::fmtflags set, std::ios_base::fmtflags reset> struct FlagsOverride; }
|
||||
|
||||
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 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:
|
||||
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(String const &str, bool includeEmpty = false) const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user