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; }