mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
144 lines
3.2 KiB
C++
144 lines
3.2 KiB
C++
template <typename CHAR, typename BYTE>
|
|
force_inline
|
|
void SkipSpaces__(const CHAR *&s)
|
|
{
|
|
while(*s && (BYTE)*s <= ' ') s++;
|
|
}
|
|
|
|
template <typename CHAR, typename BYTE>
|
|
force_inline
|
|
int ScanSgn__(const CHAR *&s)
|
|
{
|
|
int sign = 1;
|
|
if(*s == '+')
|
|
s++;
|
|
if(*s == '-') {
|
|
sign = -1;
|
|
s++;
|
|
}
|
|
SkipSpaces__<CHAR, BYTE>(s);
|
|
return sign;
|
|
}
|
|
|
|
template <typename CHAR, typename BYTE, typename UINT, int base>
|
|
force_inline
|
|
const CHAR *ScanUint0(UINT& result, const CHAR *s, bool& overflow)
|
|
{
|
|
auto Get = [&] (int i) -> int {
|
|
int c = (BYTE)s[i];
|
|
if(base > 10) {
|
|
if(c <= '9')
|
|
return c - '0';
|
|
if(c >= 'A' && c <= 'Z')
|
|
return c - 'A' + 10;
|
|
if(c >= 'a' && c <= 'z')
|
|
return c - 'a' + 10;
|
|
return -1;
|
|
}
|
|
return c - '0';
|
|
};
|
|
int c1 = Get(0);
|
|
if(c1 < 0 || c1 >= base)
|
|
return NULL;
|
|
UINT n = 0;
|
|
const int base2 = base * base;
|
|
const int base3 = base * base2;
|
|
const int base4 = base * base3;
|
|
for(;;) {
|
|
UINT n0 = n;
|
|
auto CheckOverflow = [&](UINT n1) { if(n0 > n1) overflow = true; };
|
|
if(c1 < 0 || c1 >= base) {
|
|
result = n;
|
|
return s;
|
|
}
|
|
int c2 = Get(1);
|
|
if(c2 < 0 || c2 >= base) {
|
|
result = base * n + c1;
|
|
CheckOverflow(result);
|
|
return s + 1;
|
|
}
|
|
int c3 = Get(2);
|
|
if(c3 < 0 || c3 >= base) {
|
|
result = base2 * n + base * c1 + c2;
|
|
CheckOverflow(result);
|
|
return s + 2;
|
|
}
|
|
int c4 = Get(3);
|
|
if(c4 < 0 || c4 >= base) {
|
|
result = base3 * n + base2 * c1 + base * c2 + c3;
|
|
CheckOverflow(result);
|
|
return s + 3;
|
|
}
|
|
n = base4 * n + base3 * c1 + base2 * c2 + base * c3 + c4;
|
|
CheckOverflow(n);
|
|
s += 4;
|
|
c1 = Get(0);
|
|
}
|
|
}
|
|
|
|
template <typename CHAR, typename BYTE, typename UINT, int base>
|
|
force_inline
|
|
const CHAR *ScanUint(UINT& result, const CHAR *s, bool& overflow)
|
|
{
|
|
SkipSpaces__<CHAR, BYTE>(s);
|
|
return ScanUint0<CHAR, BYTE, UINT, base>(result, s, overflow);
|
|
}
|
|
|
|
template <typename CHAR, typename BYTE, typename UINT, int base>
|
|
force_inline
|
|
const CHAR *ScanUint(UINT& result, const CHAR *s)
|
|
{
|
|
bool overflow = false;
|
|
s = ScanUint<CHAR, BYTE, UINT, base>(result, s, overflow);
|
|
return overflow ? NULL : s;
|
|
}
|
|
|
|
template <typename CHAR, typename BYTE, typename UINT, typename INT, int base>
|
|
force_inline
|
|
const CHAR *ScanInt(INT& result, const CHAR *s, bool& overflow)
|
|
{
|
|
SkipSpaces__<CHAR, BYTE>(s);
|
|
int sgn = ScanSgn__<CHAR, BYTE>(s);
|
|
UINT uresult;
|
|
s = ScanUint0<CHAR, BYTE, UINT, base>(uresult, s, overflow);
|
|
if(s) {
|
|
if(sgn < 0) {
|
|
result = INT(sgn * uresult);
|
|
if(result > 0) overflow = true;
|
|
}
|
|
else {
|
|
result = INT(uresult);
|
|
if(result < 0) overflow = true;
|
|
}
|
|
}
|
|
return s;
|
|
}
|
|
|
|
template <typename CHAR, typename BYTE, typename UINT, typename INT, int base>
|
|
force_inline
|
|
const CHAR *ScanInt(INT& result, const CHAR *s)
|
|
{
|
|
bool overflow = false;
|
|
s = ScanInt<CHAR, BYTE, UINT, INT, base>(result, s, overflow);
|
|
return overflow ? NULL : s;
|
|
}
|
|
|
|
inline
|
|
String FormatUnsigned(dword w)
|
|
{
|
|
return String::Make(12, [&](char *s) { return utoa32(w, s); });
|
|
}
|
|
|
|
inline
|
|
String FormatInt(int i)
|
|
{
|
|
return String::Make(12, [&](char *s) {
|
|
if(IsNull(i))
|
|
return 0;
|
|
if(i < 0) {
|
|
*s++ = '-';
|
|
return utoa32(-i, s) + 1;
|
|
}
|
|
return utoa32(i, s);
|
|
});
|
|
}
|