PIString::toFloat/Double/LDouble own fast implementation (. and , equivalent)

PICout ldouble support
PIEthernet small optimization
This commit is contained in:
2022-09-17 17:53:58 +03:00
parent eddef26b5e
commit 499ee386a7
8 changed files with 270 additions and 103 deletions

View File

@@ -20,6 +20,7 @@
#include "piincludes_p.h"
#include "pistring.h"
#include "pistringlist.h"
#include "pimathbase.h"
#ifdef PIP_ICU
# define U_NOEXCEPT
# include "unicode/ucnv.h"
@@ -78,6 +79,97 @@ const float PIString::ElideCenter = .5f;
const float PIString::ElideRight = 1.f;
inline float pow10(const int & e) {return powf(10.f, e);}
inline double pow10(const double & e) {return pow(10., e);}
inline ldouble pow10(const ldouble & e) {return powl(10.L, e);}
template <typename T>
T toDecimal(const PIString & s) {
int part = 0, exp = 0;
bool negative = false, negative_exp = false, err = false;
T ret = 0., frac = 0., frac_delim = 10.;
for (const PIChar pc: s) {
char c = pc.toAscii();
switch (part) {
case 0: // sign
if (pc.isSpace()) continue;
if (c >= '0' && c <= '9') {
ret = c - '0';
part = 1;
continue;
}
if (c == '+') {
part = 1;
continue;
}
if (c == '-') {
negative = true;
part = 1;
continue;
}
if (c == '.' || c == ',') {
part = 2;
continue;
}
err = true;
break;
case 1: // integer
if (c >= '0' && c <= '9') {
ret = ret * 10 + (c - '0');
continue;
}
if (c == '.' || c == ',') {
part = 2;
continue;
}
if (c == 'e' || c == 'E') {
part = 3;
continue;
}
err = true;
break;
case 2: // fractional
if (c >= '0' && c <= '9') {
frac += (c - '0') / frac_delim;
frac_delim *= 10;
continue;
}
if (c == 'e' || c == 'E') {
part = 3;
continue;
}
err = true;
break;
case 3: // exponent with sign
if (c == '+') {
part = 4;
continue;
}
if (c == '-') {
negative_exp = true;
part = 4;
continue;
}
case 4: // exponent
if (c >= '0' && c <= '9') {
exp = (exp * 10) + (c - '0');
continue;
}
err = true;
break;
}
if (err) break;
}
ret += frac;
if (negative) ret = -ret;
if (exp > 0) {
if (negative_exp) ret /= pow10((T)exp);
else ret *= pow10((T)exp);
}
return ret;
}
#define pisprintf(f, v) char ch[256]; memset(ch, 0, 256); snprintf(ch, 256, f, v); return PIStringAscii(ch);
PIString PIString::itos(const int num) {pisprintf("%d", num);}
@@ -1023,7 +1115,7 @@ bool PIString::toBool() const {
PIString s(*this);
s = s.trimmed().toLowerCase();
if (s == s_true || s == s_yes || s == s_on || s == s_ok) return true;
if (atof(s.toNativeDecimalPoints().data()) > 0.) return true;
if (toDouble() > 0.) return true;
return false;
}
@@ -1432,37 +1524,25 @@ PIString PIString::toLowerCase() const {
}
PIString PIString::toNativeDecimalPoints() const {
#ifdef HAS_LOCALE
PIString s(*this);
if (currentLocale == 0) return s;
return s.replaceAll('.', currentLocale->decimal_point).replaceAll(',', currentLocale->decimal_point);
#else
return PIString(*this).replaceAll(',', '.');
#endif
}
char PIString::toChar() const {
PIString s(toNativeDecimalPoints());
char v;
sscanf(s.data(), "%c", &v);
sscanf(dataAscii(), "%c", &v);
return v;
}
float PIString::toFloat() const {
return (float)atof(toNativeDecimalPoints().data());
return toDecimal<float>(*this);
}
double PIString::toDouble() const {
return atof(toNativeDecimalPoints().data());
return toDecimal<double>(*this);
}
ldouble PIString::toLDouble() const {
return atof(toNativeDecimalPoints().data());
return toDecimal<ldouble>(*this);
}