diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9259e814..faf0ca27 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,7 +3,7 @@ cmake_policy(SET CMP0017 NEW) # need include() with .cmake
project(PIP)
set(PIP_MAJOR 3)
set(PIP_MINOR 1)
-set(PIP_REVISION 1)
+set(PIP_REVISION 2)
set(PIP_SUFFIX )
set(PIP_COMPANY SHS)
set(PIP_DOMAIN org.SHS)
diff --git a/libs/main/core/picout.cpp b/libs/main/core/picout.cpp
index a6e4ff2c..294114bf 100644
--- a/libs/main/core/picout.cpp
+++ b/libs/main/core/picout.cpp
@@ -392,6 +392,8 @@ PICout & PICout::operator <<(float v) {if (!act_) return *this; space(); PIFLOAT
PICout & PICout::operator <<(double v) {if (!act_) return *this; space(); PIFLOATCOUT(v)}
+PICout & PICout::operator <<(ldouble v) {if (!act_) return *this; space(); PIFLOATCOUT(v)}
+
PICout & PICout::operator <<(const void * v) {
if (!act_) return *this;
space();
diff --git a/libs/main/core/picout.h b/libs/main/core/picout.h
index 6f317365..381338c4 100644
--- a/libs/main/core/picout.h
+++ b/libs/main/core/picout.h
@@ -230,6 +230,10 @@ public:
//! \~russian Оператор вывода для "double" значений
PICout & operator <<(double v);
+ //! \~english Output operator for "ldouble" values
+ //! \~russian Оператор вывода для "ldouble" значений
+ PICout & operator <<(ldouble v);
+
//! \~english Output operator for pointers
//! \~russian Оператор вывода для указателей
PICout & operator <<(const void * v);
diff --git a/libs/main/core/pistring.cpp b/libs/main/core/pistring.cpp
index af2ca093..1b162921 100644
--- a/libs/main/core/pistring.cpp
+++ b/libs/main/core/pistring.cpp
@@ -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
+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(*this);
}
double PIString::toDouble() const {
- return atof(toNativeDecimalPoints().data());
+ return toDecimal(*this);
}
ldouble PIString::toLDouble() const {
- return atof(toNativeDecimalPoints().data());
+ return toDecimal(*this);
}
diff --git a/libs/main/core/pistring.h b/libs/main/core/pistring.h
index 1128157c..e6e08420 100644
--- a/libs/main/core/pistring.h
+++ b/libs/main/core/pistring.h
@@ -869,9 +869,6 @@ public:
//! \~english Convert each character in copied string to lower case.
//! \~russian Преобразует каждый символ в скопированной строке в нижний регистр.
PIString toLowerCase() const;
-
- // TODO: doxygen
- PIString toNativeDecimalPoints() const;
//! \~english Returns if string contains character "c".
diff --git a/libs/main/io_devices/piethernet.cpp b/libs/main/io_devices/piethernet.cpp
index bc30c465..a4592351 100644
--- a/libs/main/io_devices/piethernet.cpp
+++ b/libs/main/io_devices/piethernet.cpp
@@ -909,6 +909,17 @@ void PIEthernet::server_func(void * eth) {
}
+void PIEthernet::setType(Type t, bool reopen) {
+ eth_type = t;
+ setProperty("type", (int)t);
+ if (reopen && isOpened()) {
+ closeDevice();
+ init();
+ openDevice();
+ }
+}
+
+
bool PIEthernet::configureDevice(const void * e_main, const void * e_parent) {
PIConfig::Entry * em = (PIConfig::Entry * )e_main;
PIConfig::Entry * ep = (PIConfig::Entry * )e_parent;
diff --git a/libs/main/io_devices/piethernet.h b/libs/main/io_devices/piethernet.h
index 5cd1dcd4..f7f6d00f 100644
--- a/libs/main/io_devices/piethernet.h
+++ b/libs/main/io_devices/piethernet.h
@@ -213,7 +213,7 @@ public:
PIFlags parameters() const {return (PIFlags)(property("parameters").toInt());}
//! Returns %PIEthernet type
- Type type() const {return (Type)(property("type").toInt());}
+ Type type() const {return eth_type;}
//! Returns read timeout
double readTimeout() const {return property("readTimeout").toDouble();}
@@ -489,6 +489,7 @@ protected:
int sock, sock_s;
bool connected_, connecting_, listen_threaded, server_bounded;
mutable Address addr_r, addr_s, addr_lr;
+ Type eth_type;
PIThread server_thread_;
PIMutex clients_mutex;
PIVector clients_;
@@ -498,7 +499,7 @@ protected:
private:
EVENT_HANDLER1(void, clientDeleted, PIObject *, o);
static void server_func(void * eth);
- void setType(Type t, bool reopen = true) {setProperty("type", (int)t); if (reopen && isOpened()) {closeDevice(); init(); openDevice();}}
+ void setType(Type t, bool reopen = true);
static int ethErrorCore();
static PIString ethErrorString();
diff --git a/main.cpp b/main.cpp
index 5432cbf4..abbe7ab4 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,97 +1,169 @@
#include "pip.h"
#include "piiostream.h"
#include "pibytearray.h"
-#include
-#include
+#include "pimathbase.h"
using namespace PICoutManipulators;
-#define SZ 256
+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);}
-class A {
-public:
- A() : id_(666) {
- arr = new int[SZ];
- piCout << "def A()" << id_ << this << arr;
- }
- A(int id) : id_(id) {
- arr = new int[SZ];
- piCout << "A(int)" << id_ << this << arr;
- }
-
- A(const A & a) {
- arr = new int[SZ];
- id_ = a.id_;
- piCout << "A(A)" << id_ << this << arr;
- }
-
- A(A && a) {
- std::swap(id_, a.id_);
- std::swap(arr, a.arr);
- piCout << "move A(A)" << id_ << this << arr;
- }
-
- ~A() {
- if (arr) {
- memset(arr, 0, SZ * 4);
- delete arr;
+template
+T toDouble(const PIString & s) {
+ int part = 0;
+ bool negative = false, negative_exp = false, err = false;
+ T ret = 0., frac = 0., frac_delim = 10., exp = 0;
+ 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;
}
- piCout << "~A()" << id_ << this << arr;
- //id_ = 0;
+ if (err) break;
}
-
- inline A & operator =(const A & a) {
- id_ = a.id_;
- piCout << "A =" << id_ << this;
- return *this;
+ ret += frac;
+ if (negative) ret = -ret;
+ if (exp > 0) {
+ if (negative_exp) ret /= pow10(exp);
+ else ret *= pow10(exp);
}
+ return ret;
+}
- inline A & operator =(A && a) {
- std::swap(id_, a.id_);
- std::swap(arr, a.arr);
- piCout << "move A=" << id_ << this;
- return *this;
- }
-private:
- int id_ = -1;
- int * arr = 0;
-};
-
-
-//class B {
-//public:
-// B() {a_ = nullptr;}
-// ~B() {if (a_) delete a_;}
-
-// void setA(A && a) {
-// a_ = (A *)malloc(sizeof(a));
-// memcpy(a_, &a, sizeof(a));
-// operator delete(&a);
-// }
-// void setA(const A & a) {a_ = new A(a);}
-//private:
-// A * a_;
-//};
+inline void test(const PIString & s) {
+ double av = toDouble(s);
+ double v = s.toDouble();
+ piCout << s << "=" << v << av;
+}
int main(int argc, char * argv[]) {
- piCout << "pip 3.1";
- {
- PIDeque v;
- //A a;
- //v.push_back(a);
- //v.push_back(std::move(a));
- v.push_back(A(1));
- v.push_back(A(2));
- v.push_back(A(3));
- }
+ /*test(" 123 ");
+ test("\n123 ");
+ test("\t123 ");
+ test(" +123 ");
+ test(" ++123 ");
+ test(" + 123 ");
+ test(" -123 ");
+ test(" --123 ");
+ test(" - 123 ");
+ test("123.1");
+ test("123 .1");
+ test("123 . 1");
+ test("123.+1");
+ test("123.-1");
+ test("123E2");
+ test("123E+2");
+ test("123E +2");
+ test("123E+ 2");
+ test("123E + 2");
+ test("123 E+2");
+ test("123 E +2");
+ test("123 E+ 2");
+ test("123 E + 2");
+ test("123E+2.5");
+ test("123.4E+2");
+ test("123.4.5E+2");
+ test("123EE+2");
+ test("123e+2");
+ test("123e++2");
+ test("E+2");
+ test("1E+2");
+ test("1.E+2");
+ test(".E+2");
+ test(".1E-2");
+ test("+E2");
+ test("nan");
+ test("inf");*/
+ test("1.23");
+ test("1,23");
+ test(".23");
+ test(",23");
+ PITimeMeasurer tm;
+ PIString s("1E+600");
+ int cnt = 1000000;
+ int el_o = 0, el_n = 0;
+ ldouble v = 0.;
+ NO_UNUSED(v);
- piCout << "";
- piCout << "std";
- {
- std::vector v;
- v.push_back(A(1));
- v.push_back(A(2));
- v.push_back(A(3));
+ tm.reset();
+ piForTimes (cnt) {
+ v = s.toLDouble();
}
+ el_o = tm.elapsed_u();
+ piCout << v << el_o;
+
+ tm.reset();
+ piForTimes (cnt) {
+ v = toDouble(s);
+ }
+ el_n = tm.elapsed_u();
+ piCout << v << el_n;
+
+ piCout << (double)el_o / el_n;
return 0;
}