diff --git a/doc/doxygen_sqlite3.db b/doc/doxygen_sqlite3.db new file mode 100644 index 00000000..838dc510 Binary files /dev/null and b/doc/doxygen_sqlite3.db differ diff --git a/doc/events_handlers.odp b/doc/events_handlers.odp new file mode 100644 index 00000000..09be151b Binary files /dev/null and b/doc/events_handlers.odp differ diff --git a/doc/packet_detection.odp b/doc/packet_detection.odp new file mode 100644 index 00000000..a80ffb1f Binary files /dev/null and b/doc/packet_detection.odp differ diff --git a/doc/piconnection.odg b/doc/piconnection.odg new file mode 100644 index 00000000..0bcdb024 Binary files /dev/null and b/doc/piconnection.odg differ diff --git a/doc/piconnection_conf.odg b/doc/piconnection_conf.odg new file mode 100644 index 00000000..8428ed7c Binary files /dev/null and b/doc/piconnection_conf.odg differ diff --git a/doc/piconnection_filters.odg b/doc/piconnection_filters.odg new file mode 100644 index 00000000..57a5df56 Binary files /dev/null and b/doc/piconnection_filters.odg differ diff --git a/doc/piconnection_senders.odg b/doc/piconnection_senders.odg new file mode 100644 index 00000000..5a1fee1b Binary files /dev/null and b/doc/piconnection_senders.odg differ diff --git a/doc/piconsole_layout.odp b/doc/piconsole_layout.odp new file mode 100644 index 00000000..e94ce3e0 Binary files /dev/null and b/doc/piconsole_layout.odp differ diff --git a/src/_unsused/pigeometry.h b/src/_unsused/pigeometry.h new file mode 100755 index 00000000..dd8c25f6 --- /dev/null +++ b/src/_unsused/pigeometry.h @@ -0,0 +1,137 @@ +/* + PIP - Platform Independent Primitives + Geometry + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIGEOMETRY_H +#define PIGEOMETRY_H + +#include "pimath.h" + +template +class PIP_EXPORT PIPoint { +public: + Type x; + Type y; + + PIPoint() {x = y = 0;}; + PIPoint(Type x_, Type y_) {set(x_, y_);} + + PIPoint & set(Type x_, Type y_) {x = x_; y = y_; return *this;} + PIPoint & move(Type x_, Type y_) {x += x_; y += y_; return *this;} + PIPoint & move(const PIPoint & p) {x += p.x; y += p.y; return *this;} + double angleRad() const {return atan2(y, x);} + int angleDeg() const {return round(atan2(y, x) * 180. / M_PI);} + PIPoint toPolar(bool isDeg = false) const {return PIPoint(sqrt(x*x + y*y), isDeg ? angleDeg() : angleRad());} + static PIPoint fromPolar(const PIPoint & p) {return PIPoint(p.y * cos(p.x), p.y * sin(p.x));} + + PIPoint operator +(const PIPoint & p) {return PIPoint(x + p.x, y + p.y);} + PIPoint operator +(const Type & p) {return PIPoint(x + p, y + p);} + PIPoint operator -(const PIPoint & p) {return PIPoint(x - p.x, y - p.y);} + PIPoint operator -(const Type & p) {return PIPoint(x - p, y - p);} + PIPoint operator -() {return PIPoint(-x, -y);} + PIPoint operator *(const Type & d) {return PIPoint(x * d, y * d);} + PIPoint operator /(const Type & d) {return PIPoint(x / d, y / d);} + bool operator ==(const PIPoint & p) const {return (x == p.x && y == p.y);} + bool operator !=(const PIPoint & p) const {return (x != p.x || y != p.y);} + +}; + +template +std::ostream & operator <<(std::ostream & s, const PIPoint & v) {s << '{' << v.x << ", " << v.y << '}'; return s;} + +template +class PIP_EXPORT PIRect { +public: + Type x0; + Type y0; + Type x1; + Type y1; + + PIRect() {x0 = y0 = x1 = y1 = 0;}; + PIRect(Type x, Type y, Type w, Type h) {set(x, y, w, h);} + PIRect(const PIPoint & tl, const PIPoint & br) {set(tl.x, tl.y, br.x, br.y);} + PIRect(const PIPoint & p0, const PIPoint & p1, const PIPoint & p2) {set(piMin(p0.x, p1.x, p2.x), piMin(p0.y, p1.y, p2.y), + piMax(p0.x, p1.x, p2.x), piMax(p0.y, p1.y, p2.y));} + + PIRect & set(Type x, Type y, Type w, Type h) {x0 = x; y0 = y; x1 = x + w; y1 = y + h; return *this;} + bool pointIn(Type x, Type y) const {return (x <= x1 && x >= x0 && y <= y1 && y >= y0);} + bool pointIn(const PIPoint & p) const {return pointIn(p.x, p.y);} + bool isEmpty() const {return (x1 - x0 == 0 && y1 - y0 == 0);} + PIRect & translate(Type x, Type y) {x0 += x; x1 += x; y0 += y; y1 += y; return *this;} + PIRect & translate(const PIPoint & p) {x0 += p.x; x1 += p.x; y0 += p.y; y1 += p.y; return *this;} + PIRect translated(Type x, Type y) {PIRect r(*this); r.translate(x, y); return r;} + PIRect translated(const PIPoint & p) {PIRect r(*this); r.translate(p); return r;} + PIRect & scale(Type x, Type y) {setWidth(width() * x); setHeight(height() * y); return *this;} + PIRect & scale(const PIPoint & p) {setWidth(width() * p.x); setHeight(height() * p.y); return *this;} + PIRect scaled(Type x, Type y) {PIRect r(*this); r.scale(x, y); return r;} + PIRect scaled(const PIPoint & p) {PIRect r(*this); r.scale(p); return r;} + PIRect & normalize() {if (x0 > x1) piSwap(x0, x1); if (y0 > y1) piSwap(y0, y1); return *this;} + PIRect normalized() {PIRect r(*this); r.normalize(); return r;} + PIRect & unite(const PIRect & r) {x0 = piMin(x0, r.x0); y0 = piMin(y0, r.y0); x1 = piMax(x1, r.x1); y1 = piMax(y1, r.y1); return *this;} + PIRect united(const PIRect & rect) {PIRect r(*this); r.unite(rect); return r;} + PIRect & intersect(const PIRect & r) {x0 = piMax(x0, r.x0); y0 = piMax(y0, r.y0); x1 = piMin(x1, r.x1); y1 = piMin(y1, r.y1); if (x0 > x1 || y0 > y1) x0 = x1 = y0 = y1 = Type(0); return *this;} + PIRect intersected(const PIRect & rect) {PIRect r(*this); r.intersect(rect); return r;} + Type top() const {return y0;} + Type left() const {return x0;} + Type right() const {return x1;} + Type bottom() const {return y1;} + Type width() const {return x1 - x0;} + Type height() const {return y1 - y0;} + PIPoint topLeft() {return PIPoint(x0, y0);} + PIPoint topRigth() {return PIPoint(x1, y0);} + PIPoint bottomLeft() {return PIPoint(x0, y1);} + PIPoint bottomRight() {return PIPoint(x1, y1);} + void setTop(Type v) {y0 = v;} + void setLeft(Type v) {x0 = v;} + void setRigth(Type v) {x1 = v;} + void setBottom(Type v) {y1 = v;} + void setWidth(Type v) {x1 = x0 + v;} + void setHeight(Type v) {y1 = y0 + v;} + + PIRect operator -() {return PIRect(-x0, -y0, -width(), -height());} + void operator +=(Type x) {translate(x, x);} + void operator +=(const PIPoint & p) {translate(p);} + void operator -=(Type x) {translate(-x, -x);} + void operator -=(const PIPoint & p) {translate(-p);} + void operator *=(Type p) {x0 *= p; x1 *= p; y0 *= p; y1 *= p;} + void operator /=(Type p) {x0 /= p; x1 /= p; y0 /= p; y1 /= p;} + void operator |=(const PIRect & r) {unite(r);} + void operator &=(const PIRect & r) {intersect(r);} + PIRect operator +(const PIPoint & p) {return PIRect(*this).translated(p);} + PIRect operator -(const PIPoint & p) {return PIRect(*this).translated(-p);} + PIRect operator |(const PIRect & r) {return PIRect(*this).united(r);} + PIRect operator &(const PIRect & r) {return PIRect(*this).intersected(r);} + bool operator ==(const PIRect & r) const {return (x0 == r.x0 && y0 == r.y0 && x1 == r.x1 && y1 == r.y10);} + bool operator !=(const PIRect & r) const {return (x0 != r.x0 || y0 != r.y0 || x1 != r.x1 || y1 != r.y10);} + +}; + +template +std::ostream & operator <<(std::ostream & s, const PIRect & v) {s << '{' << v.x0 << ", " << v.y0 << "; " << v.x1 - v.x0 << ", " << v.y1 - v.y0 << '}'; return s;} + +typedef PIPoint PIPointi; +typedef PIPoint PIPointu; +typedef PIPoint PIPointf; +typedef PIPoint PIPointd; + +typedef PIRect PIRecti; +typedef PIRect PIRectu; +typedef PIRect PIRectf; +typedef PIRect PIRectd; + +#endif // PIGEOMETRY_H diff --git a/src/_unsused/pivariable.cpp b/src/_unsused/pivariable.cpp new file mode 100755 index 00000000..f39d806a --- /dev/null +++ b/src/_unsused/pivariable.cpp @@ -0,0 +1,249 @@ +/* + PIP - Platform Independent Primitives + Variable, Struct (simple serialization) + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pivariable.h" + + +bool PIVariant::operator ==(const PIVariant & v) const { + if (type != v.type) return false; + switch (type) { + case PIVariant::Bool: return vBool == v.vBool; + case PIVariant::Char: return vChar == v.vChar; + case PIVariant::Short: return vShort == v.vShort; + case PIVariant::Int: return vInt == v.vInt; + case PIVariant::Long: return vLong == v.vLong; + case PIVariant::LLong: return vLLong == v.vLLong; + case PIVariant::UChar: return vUChar == v.vUChar; + case PIVariant::UShort: return vUShort == v.vUShort; + case PIVariant::UInt: return vUInt == v.vUInt; + case PIVariant::ULong: return vULong == v.vULong; + case PIVariant::ULLong: return vULLong == v.vULLong; + case PIVariant::Float: return vFloat == v.vFloat; + case PIVariant::Double: return vDouble == v.vDouble; + case PIVariant::LDouble: return vLDouble == v.vLDouble; + case PIVariant::String: return vString == v.vString; + case PIVariant::StringList: return vStringList == v.vStringList; + }; + return false; +} + + +void PIVariant::setValueOnly(const PIString & s) { + switch (type) { + case PIVariant::Bool: vBool = s.toBool(); break; + case PIVariant::Char: vChar = s.toChar(); break; + case PIVariant::Short: vShort = s.toShort(); break; + case PIVariant::Int: vInt = s.toInt(); break; + case PIVariant::Long: vLong = s.toLong(); break; + case PIVariant::LLong: vLLong = s.toLLong(); break; + case PIVariant::UChar: vUChar = s.toChar(); break; + case PIVariant::UShort: vUShort = s.toShort(); break; + case PIVariant::UInt: vUInt = s.toInt(); break; + case PIVariant::ULong: vULong = s.toLong(); break; + case PIVariant::ULLong: vULLong = s.toLLong(); break; + case PIVariant::Float: vFloat = s.toFloat(); break; + case PIVariant::Double: vDouble = s.toDouble(); break; + case PIVariant::LDouble: vLDouble = s.toLDouble(); break; + case PIVariant::String: vString = s; break; + case PIVariant::StringList: vStringList = s.split("%|%"); break; + }; +} + + +PIString PIVariant::stringValue() const { + switch (type) { + case PIVariant::Bool: return (vBool ? "true" : "false"); + case PIVariant::Char: return PIString::fromNumber(vChar); + case PIVariant::Short: return PIString::fromNumber(vShort); + case PIVariant::Int: return PIString::fromNumber(vInt); + case PIVariant::Long: return PIString::fromNumber(vLong); + case PIVariant::LLong: return PIString::fromNumber(static_cast(vLLong)); + case PIVariant::UChar: return PIString::fromNumber(vUChar); + case PIVariant::UShort: return PIString::fromNumber(vUShort); + case PIVariant::UInt: return PIString::fromNumber(vUInt); + case PIVariant::ULong: return PIString::fromNumber(static_cast(vULong)); + case PIVariant::ULLong: return PIString::fromNumber(static_cast(vULLong)); + case PIVariant::Float: return PIString::fromNumber(vFloat); + case PIVariant::Double: return PIString::fromNumber(vDouble); + case PIVariant::LDouble: return PIString::fromNumber(vLDouble); + case PIVariant::String: return vString; + case PIVariant::StringList: return vStringList.join("%|%"); + }; + return vString; +} + + +PIVariant PIVariant::readFromString(const PIString & s) { + int i = s.find(':'); + if (i < 0 || s.length() < 2) return PIVariant(s); + PIVariant ret; + ret.type = PIVariant::fromString(s.left(i)); + ret.setValueOnly(s.right(s.length() - i - 1)); + return ret; +} + + +PIVariant::Type PIVariant::fromString(const PIString & str) { + PIString s = str.trimmed().toLowerCase().replace(" ", ""); + if (s == "bool") return PIVariant::Bool; + if (s == "char" || s == "sbyte") return PIVariant::Char; + if (s == "short" || s == "short int" || s == "signed short" || s == "signed short int" || s == "sword") return PIVariant::Short; + if (s == "int" || s == "signed" || s == "signed int") return PIVariant::Int; + if (s == "long" || s == "long int" || s == "signed long" || s == "signed long int" || s == "sdword") return PIVariant::Long; + if (s == "llong" || s == "long long" || s == "long long int" || s == "signed long long" || s == "signed long long int" || s == "sqword") return PIVariant::LLong; + if (s == "uchar" || s == "byte") return PIVariant::UChar; + if (s == "ushort" || s == "unsigned short" || s == "unsigned short int" || s == "word") return PIVariant::UShort; + if (s == "uint" || s == "unsigned" || s == "unsigned int") return PIVariant::UInt; + if (s == "ulong" || s == "unsigned long" || s == "unsigned long int" || s == "dword") return PIVariant::ULong; + if (s == "ullong" || s == "unsigned long long" || s == "unsigned long long int" || s == "qword") return PIVariant::ULLong; + if (s == "float") return PIVariant::Float; + if (s == "double" || s == "real") return PIVariant::Double; + if (s == "ldouble" || s == "long double") return PIVariant::LDouble; + if (s == "pistring" || s == "string") return PIVariant::String; + if (s == "pistringlist" || s == "vector" || s == "vector" || s == "pivector" || s == "pivector") return PIVariant::StringList; + return PIVariant::Double; +} + + +PIString PIVariant::toString(const PIVariant::Type & var) { + switch (var) { + case PIVariant::Bool: return "bool"; + case PIVariant::Char: return "char"; + case PIVariant::Short: return "short"; + case PIVariant::Int: return "int"; + case PIVariant::Long: return "long"; + case PIVariant::LLong: return "llong"; + case PIVariant::UChar: return "uchar"; + case PIVariant::UShort: return "ushort"; + case PIVariant::UInt: return "uint"; + case PIVariant::ULong: return "ulong"; + case PIVariant::ULLong: return "ullong"; + case PIVariant::Float: return "float"; + case PIVariant::Double: return "double"; + case PIVariant::LDouble: return "ldouble"; + case PIVariant::String: return "string"; + case PIVariant::StringList: return "stringlist"; + } + return "double"; +} + + +uint PIVariant::variableSize(const PIVariant::Type & var) { + switch (var) { + case PIVariant::Bool: return sizeof(bool); + case PIVariant::Char: return sizeof(char); + case PIVariant::Short: return sizeof(short); + case PIVariant::Int: return sizeof(int); + case PIVariant::Long: return sizeof(long); + case PIVariant::LLong: return sizeof(llong); + case PIVariant::UChar: return sizeof(uchar); + case PIVariant::UShort: return sizeof(ushort); + case PIVariant::UInt: return sizeof(uint); + case PIVariant::ULong: return sizeof(ulong); + case PIVariant::ULLong: return sizeof(ullong); + case PIVariant::Float: return sizeof(float); + case PIVariant::Double: return sizeof(double); + case PIVariant::LDouble: return sizeof(ldouble); + default: break; + } + return 0; +} + + +double PIVariant::variableValue(const void * var_ptr, const PIVariant::Type & var) { + switch (var) { + case PIVariant::Bool: return (double)(*((bool * )var_ptr)); + case PIVariant::Char: return (double)(*((char * )var_ptr)); + case PIVariant::Short: return (double)(*((short * )var_ptr)); + case PIVariant::Int: return (double)(*((int * )var_ptr)); + case PIVariant::Long: return (double)(*((long * )var_ptr)); + case PIVariant::LLong: return (double)(*((llong * )var_ptr)); + case PIVariant::UChar: return (double)(*((uchar * )var_ptr)); + case PIVariant::UShort: return (double)(*((ushort * )var_ptr)); + case PIVariant::UInt: return (double)(*((uint * )var_ptr)); + case PIVariant::ULong: return (double)(*((ulong * )var_ptr)); + case PIVariant::ULLong: return (double)(*((ullong * )var_ptr)); + case PIVariant::Float: return (double)(*((float * )var_ptr)); + case PIVariant::Double: return (double)(*((double * )var_ptr)); + case PIVariant::LDouble: return (ldouble)(*((ldouble * )var_ptr)); + default: break; + } + return 0.; +} + + +void PIVariable::setVariable(const PIString & str) { + type_ = PIVariant::fromString(str); + size_ = PIVariant::variableSize(type_); +} + + +void PIVariable::writeVariable(void * dest) { + switch (type_) { + case PIVariant::Bool: *((bool * )((ullong)dest + offset)) = value_ > 0.; return; + case PIVariant::Char: *((char * )((ullong)dest + offset)) = char(value_); return; + case PIVariant::Short: *((short * )((ullong)dest + offset)) = short(value_); return; + case PIVariant::Int: *((int * )((ullong)dest + offset)) = int(value_); return; + case PIVariant::Long: *((long * )((ullong)dest + offset)) = long(value_); return; + case PIVariant::LLong: *((llong * )((ullong)dest + offset)) = llong(value_); return; + case PIVariant::UChar: *((uchar * )((ullong)dest + offset)) = uchar(value_); return; + case PIVariant::UShort: *((ushort * )((ullong)dest + offset)) = ushort(value_); return; + case PIVariant::UInt: *((uint * )((ullong)dest + offset)) = uint(value_); return; + case PIVariant::ULong: *((ulong * )((ullong)dest + offset)) = ulong(value_); return; + case PIVariant::ULLong: *((ullong * )((ullong)dest + offset)) = ullong(value_); return; + case PIVariant::Float: *((float * )((ullong)dest + offset)) = float(value_); return; + case PIVariant::Double: *((double * )((ullong)dest + offset)) = value_; return; + case PIVariant::LDouble: *((ldouble * )((ullong)dest + offset)) = ldouble(value_); return; + default: break; + } +} + + +void PIStruct::parseFile(const PIString & file) { + PIConfig conf(file, PIIODevice::ReadOnly); + PIVariable var; + PIString ts; + uint sz = 0; + vars.clear(); + for (int i = 0; i < conf.entriesCount(); ++i) { + var.setVariable(conf.getValue(i)); + var.setName(conf.getName(i)); + var.offset = sz; + sz += var.size(); + ts = conf.getComment(i); + if (ts.length() > 0) + var.setValue(ts.toDouble()); + else var.setValue(0.); + vars.push_back(var); + } + size_ = sz; +} + + +void PIStruct::readData(const void * data) { + for (uint i = 0; i < vars.size(); ++i) + vars[i].readVariable(data); +} + + +void PIStruct::writeData(void * data) { + for (uint i = 0; i < vars.size(); ++i) + vars[i].writeVariable(data); +} + diff --git a/src/_unsused/pivariable.cpp_ b/src/_unsused/pivariable.cpp_ new file mode 100644 index 00000000..f39d806a --- /dev/null +++ b/src/_unsused/pivariable.cpp_ @@ -0,0 +1,249 @@ +/* + PIP - Platform Independent Primitives + Variable, Struct (simple serialization) + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pivariable.h" + + +bool PIVariant::operator ==(const PIVariant & v) const { + if (type != v.type) return false; + switch (type) { + case PIVariant::Bool: return vBool == v.vBool; + case PIVariant::Char: return vChar == v.vChar; + case PIVariant::Short: return vShort == v.vShort; + case PIVariant::Int: return vInt == v.vInt; + case PIVariant::Long: return vLong == v.vLong; + case PIVariant::LLong: return vLLong == v.vLLong; + case PIVariant::UChar: return vUChar == v.vUChar; + case PIVariant::UShort: return vUShort == v.vUShort; + case PIVariant::UInt: return vUInt == v.vUInt; + case PIVariant::ULong: return vULong == v.vULong; + case PIVariant::ULLong: return vULLong == v.vULLong; + case PIVariant::Float: return vFloat == v.vFloat; + case PIVariant::Double: return vDouble == v.vDouble; + case PIVariant::LDouble: return vLDouble == v.vLDouble; + case PIVariant::String: return vString == v.vString; + case PIVariant::StringList: return vStringList == v.vStringList; + }; + return false; +} + + +void PIVariant::setValueOnly(const PIString & s) { + switch (type) { + case PIVariant::Bool: vBool = s.toBool(); break; + case PIVariant::Char: vChar = s.toChar(); break; + case PIVariant::Short: vShort = s.toShort(); break; + case PIVariant::Int: vInt = s.toInt(); break; + case PIVariant::Long: vLong = s.toLong(); break; + case PIVariant::LLong: vLLong = s.toLLong(); break; + case PIVariant::UChar: vUChar = s.toChar(); break; + case PIVariant::UShort: vUShort = s.toShort(); break; + case PIVariant::UInt: vUInt = s.toInt(); break; + case PIVariant::ULong: vULong = s.toLong(); break; + case PIVariant::ULLong: vULLong = s.toLLong(); break; + case PIVariant::Float: vFloat = s.toFloat(); break; + case PIVariant::Double: vDouble = s.toDouble(); break; + case PIVariant::LDouble: vLDouble = s.toLDouble(); break; + case PIVariant::String: vString = s; break; + case PIVariant::StringList: vStringList = s.split("%|%"); break; + }; +} + + +PIString PIVariant::stringValue() const { + switch (type) { + case PIVariant::Bool: return (vBool ? "true" : "false"); + case PIVariant::Char: return PIString::fromNumber(vChar); + case PIVariant::Short: return PIString::fromNumber(vShort); + case PIVariant::Int: return PIString::fromNumber(vInt); + case PIVariant::Long: return PIString::fromNumber(vLong); + case PIVariant::LLong: return PIString::fromNumber(static_cast(vLLong)); + case PIVariant::UChar: return PIString::fromNumber(vUChar); + case PIVariant::UShort: return PIString::fromNumber(vUShort); + case PIVariant::UInt: return PIString::fromNumber(vUInt); + case PIVariant::ULong: return PIString::fromNumber(static_cast(vULong)); + case PIVariant::ULLong: return PIString::fromNumber(static_cast(vULLong)); + case PIVariant::Float: return PIString::fromNumber(vFloat); + case PIVariant::Double: return PIString::fromNumber(vDouble); + case PIVariant::LDouble: return PIString::fromNumber(vLDouble); + case PIVariant::String: return vString; + case PIVariant::StringList: return vStringList.join("%|%"); + }; + return vString; +} + + +PIVariant PIVariant::readFromString(const PIString & s) { + int i = s.find(':'); + if (i < 0 || s.length() < 2) return PIVariant(s); + PIVariant ret; + ret.type = PIVariant::fromString(s.left(i)); + ret.setValueOnly(s.right(s.length() - i - 1)); + return ret; +} + + +PIVariant::Type PIVariant::fromString(const PIString & str) { + PIString s = str.trimmed().toLowerCase().replace(" ", ""); + if (s == "bool") return PIVariant::Bool; + if (s == "char" || s == "sbyte") return PIVariant::Char; + if (s == "short" || s == "short int" || s == "signed short" || s == "signed short int" || s == "sword") return PIVariant::Short; + if (s == "int" || s == "signed" || s == "signed int") return PIVariant::Int; + if (s == "long" || s == "long int" || s == "signed long" || s == "signed long int" || s == "sdword") return PIVariant::Long; + if (s == "llong" || s == "long long" || s == "long long int" || s == "signed long long" || s == "signed long long int" || s == "sqword") return PIVariant::LLong; + if (s == "uchar" || s == "byte") return PIVariant::UChar; + if (s == "ushort" || s == "unsigned short" || s == "unsigned short int" || s == "word") return PIVariant::UShort; + if (s == "uint" || s == "unsigned" || s == "unsigned int") return PIVariant::UInt; + if (s == "ulong" || s == "unsigned long" || s == "unsigned long int" || s == "dword") return PIVariant::ULong; + if (s == "ullong" || s == "unsigned long long" || s == "unsigned long long int" || s == "qword") return PIVariant::ULLong; + if (s == "float") return PIVariant::Float; + if (s == "double" || s == "real") return PIVariant::Double; + if (s == "ldouble" || s == "long double") return PIVariant::LDouble; + if (s == "pistring" || s == "string") return PIVariant::String; + if (s == "pistringlist" || s == "vector" || s == "vector" || s == "pivector" || s == "pivector") return PIVariant::StringList; + return PIVariant::Double; +} + + +PIString PIVariant::toString(const PIVariant::Type & var) { + switch (var) { + case PIVariant::Bool: return "bool"; + case PIVariant::Char: return "char"; + case PIVariant::Short: return "short"; + case PIVariant::Int: return "int"; + case PIVariant::Long: return "long"; + case PIVariant::LLong: return "llong"; + case PIVariant::UChar: return "uchar"; + case PIVariant::UShort: return "ushort"; + case PIVariant::UInt: return "uint"; + case PIVariant::ULong: return "ulong"; + case PIVariant::ULLong: return "ullong"; + case PIVariant::Float: return "float"; + case PIVariant::Double: return "double"; + case PIVariant::LDouble: return "ldouble"; + case PIVariant::String: return "string"; + case PIVariant::StringList: return "stringlist"; + } + return "double"; +} + + +uint PIVariant::variableSize(const PIVariant::Type & var) { + switch (var) { + case PIVariant::Bool: return sizeof(bool); + case PIVariant::Char: return sizeof(char); + case PIVariant::Short: return sizeof(short); + case PIVariant::Int: return sizeof(int); + case PIVariant::Long: return sizeof(long); + case PIVariant::LLong: return sizeof(llong); + case PIVariant::UChar: return sizeof(uchar); + case PIVariant::UShort: return sizeof(ushort); + case PIVariant::UInt: return sizeof(uint); + case PIVariant::ULong: return sizeof(ulong); + case PIVariant::ULLong: return sizeof(ullong); + case PIVariant::Float: return sizeof(float); + case PIVariant::Double: return sizeof(double); + case PIVariant::LDouble: return sizeof(ldouble); + default: break; + } + return 0; +} + + +double PIVariant::variableValue(const void * var_ptr, const PIVariant::Type & var) { + switch (var) { + case PIVariant::Bool: return (double)(*((bool * )var_ptr)); + case PIVariant::Char: return (double)(*((char * )var_ptr)); + case PIVariant::Short: return (double)(*((short * )var_ptr)); + case PIVariant::Int: return (double)(*((int * )var_ptr)); + case PIVariant::Long: return (double)(*((long * )var_ptr)); + case PIVariant::LLong: return (double)(*((llong * )var_ptr)); + case PIVariant::UChar: return (double)(*((uchar * )var_ptr)); + case PIVariant::UShort: return (double)(*((ushort * )var_ptr)); + case PIVariant::UInt: return (double)(*((uint * )var_ptr)); + case PIVariant::ULong: return (double)(*((ulong * )var_ptr)); + case PIVariant::ULLong: return (double)(*((ullong * )var_ptr)); + case PIVariant::Float: return (double)(*((float * )var_ptr)); + case PIVariant::Double: return (double)(*((double * )var_ptr)); + case PIVariant::LDouble: return (ldouble)(*((ldouble * )var_ptr)); + default: break; + } + return 0.; +} + + +void PIVariable::setVariable(const PIString & str) { + type_ = PIVariant::fromString(str); + size_ = PIVariant::variableSize(type_); +} + + +void PIVariable::writeVariable(void * dest) { + switch (type_) { + case PIVariant::Bool: *((bool * )((ullong)dest + offset)) = value_ > 0.; return; + case PIVariant::Char: *((char * )((ullong)dest + offset)) = char(value_); return; + case PIVariant::Short: *((short * )((ullong)dest + offset)) = short(value_); return; + case PIVariant::Int: *((int * )((ullong)dest + offset)) = int(value_); return; + case PIVariant::Long: *((long * )((ullong)dest + offset)) = long(value_); return; + case PIVariant::LLong: *((llong * )((ullong)dest + offset)) = llong(value_); return; + case PIVariant::UChar: *((uchar * )((ullong)dest + offset)) = uchar(value_); return; + case PIVariant::UShort: *((ushort * )((ullong)dest + offset)) = ushort(value_); return; + case PIVariant::UInt: *((uint * )((ullong)dest + offset)) = uint(value_); return; + case PIVariant::ULong: *((ulong * )((ullong)dest + offset)) = ulong(value_); return; + case PIVariant::ULLong: *((ullong * )((ullong)dest + offset)) = ullong(value_); return; + case PIVariant::Float: *((float * )((ullong)dest + offset)) = float(value_); return; + case PIVariant::Double: *((double * )((ullong)dest + offset)) = value_; return; + case PIVariant::LDouble: *((ldouble * )((ullong)dest + offset)) = ldouble(value_); return; + default: break; + } +} + + +void PIStruct::parseFile(const PIString & file) { + PIConfig conf(file, PIIODevice::ReadOnly); + PIVariable var; + PIString ts; + uint sz = 0; + vars.clear(); + for (int i = 0; i < conf.entriesCount(); ++i) { + var.setVariable(conf.getValue(i)); + var.setName(conf.getName(i)); + var.offset = sz; + sz += var.size(); + ts = conf.getComment(i); + if (ts.length() > 0) + var.setValue(ts.toDouble()); + else var.setValue(0.); + vars.push_back(var); + } + size_ = sz; +} + + +void PIStruct::readData(const void * data) { + for (uint i = 0; i < vars.size(); ++i) + vars[i].readVariable(data); +} + + +void PIStruct::writeData(void * data) { + for (uint i = 0; i < vars.size(); ++i) + vars[i].writeVariable(data); +} + diff --git a/src/_unsused/pivariable.h b/src/_unsused/pivariable.h new file mode 100755 index 00000000..44ba5fd8 --- /dev/null +++ b/src/_unsused/pivariable.h @@ -0,0 +1,196 @@ +/* + PIP - Platform Independent Primitives + Variable, Struct (simple serialization) + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIVARIABLE_H +#define PIVARIABLE_H + +#include "piconfig.h" + +class PIP_EXPORT PIVariant { + friend class PIVariable; +public: + enum Type {Bool, Char, Short, Int, Long, LLong, UChar, UShort, UInt, ULong, ULLong, Float, Double, LDouble, String, StringList}; + + PIVariant() {setValue(0.);} + PIVariant(const char * v) {setValue(v);} + PIVariant(const bool & v) {setValue(v);} + PIVariant(const char & v) {setValue(v);} + PIVariant(const short & v) {setValue(v);} + PIVariant(const int & v) {setValue(v);} + PIVariant(const long & v) {setValue(v);} + PIVariant(const llong & v) {setValue(v);} + PIVariant(const uchar & v) {setValue(v);} + PIVariant(const ushort & v) {setValue(v);} + PIVariant(const uint & v) {setValue(v);} + PIVariant(const ulong & v) {setValue(v);} + PIVariant(const ullong & v) {setValue(v);} + PIVariant(const float & v) {setValue(v);} + PIVariant(const double & v) {setValue(v);} + PIVariant(const ldouble & v) {setValue(v);} + PIVariant(const PIString & v) {setValue(v);} + PIVariant(const PIStringList & v) {setValue(v);} + + void setValue(const char * v) {setValue(PIString(v));} + void setValue(const bool & v) {type = PIVariant::Bool; vBool = v;} + void setValue(const char & v) {type = PIVariant::Char; vChar = v;} + void setValue(const short & v) {type = PIVariant::Short; vShort = v;} + void setValue(const int & v) {type = PIVariant::Int; vInt = v;} + void setValue(const long & v) {type = PIVariant::Long; vLong = v;} + void setValue(const llong & v) {type = PIVariant::LLong; vLLong = v;} + void setValue(const uchar & v) {type = PIVariant::UChar; vUChar = v;} + void setValue(const ushort & v) {type = PIVariant::UShort; vUShort = v;} + void setValue(const uint & v) {type = PIVariant::UInt; vUInt = v;} + void setValue(const ulong & v) {type = PIVariant::ULong; vULong = v;} + void setValue(const ullong & v) {type = PIVariant::ULLong; vULLong = v;} + void setValue(const float & v) {type = PIVariant::Float; vFloat = v;} + void setValue(const double & v) {type = PIVariant::Double; vDouble = v;} + void setValue(const ldouble & v) {type = PIVariant::LDouble; vLDouble = v;} + void setValue(const PIString & v) {type = PIVariant::String; vString = v;} + void setValue(const PIStringList & v) {type = PIVariant::StringList; vStringList = v;} + void setValueOnly(const PIString & v); + PIString typeName() const {return PIVariant::toString(type);} + double doubleValue() const {return PIVariant::variableValue(&vChar, type);} + PIString stringValue() const; + void typeFromString(const PIString & str) {type = PIVariant::fromString(str);} + PIString typeToString() const {return PIVariant::toString(type);} + uint size() {if (type != PIVariant::String && type != PIVariant::StringList) return PIVariant::variableSize(type); if (type == PIVariant::String) return vString.size(); else return vStringList.contentSize();} + PIString writeToString() const {return typeName() + ":" + stringValue();} + +#ifdef QNX + void operator =(const PIVariant & v) {type = v.type; vLDouble = v.vLDouble; vString = v.vString; vStringList = v.vStringList;} +#endif + void operator =(const char * v) {setValue(PIString(v));} + void operator =(const bool & v) {type = PIVariant::Bool; vBool = v;} + void operator =(const char & v) {type = PIVariant::Char; vChar = v;} + void operator =(const short & v) {type = PIVariant::Short; vShort = v;} + void operator =(const int & v) {type = PIVariant::Int; vInt = v;} + void operator =(const long & v) {type = PIVariant::Long; vLong = v;} + void operator =(const llong & v) {type = PIVariant::LLong; vLLong = v;} + void operator =(const uchar & v) {type = PIVariant::UChar; vUChar = v;} + void operator =(const ushort & v) {type = PIVariant::UShort; vUShort = v;} + void operator =(const uint & v) {type = PIVariant::UInt; vUInt = v;} + void operator =(const ulong & v) {type = PIVariant::ULong; vULong = v;} + void operator =(const ullong & v) {type = PIVariant::ULLong; vULLong = v;} + void operator =(const float & v) {type = PIVariant::Float; vFloat = v;} + void operator =(const double & v) {type = PIVariant::Double; vDouble = v;} + void operator =(const ldouble & v) {type = PIVariant::LDouble; vLDouble = v;} + void operator =(const PIString & v) {type = PIVariant::String; vString = v;} + void operator =(const PIStringList & v) {type = PIVariant::StringList; vStringList = v;} + + bool operator ==(const PIVariant & v) const; + bool operator !=(const PIVariant & v) const {return !(*this == v);} + + PIVariant::Type type; + union { + bool vBool; + char vChar; + short vShort; + int vInt; + long vLong; + llong vLLong; + uchar vUChar; + ushort vUShort; + uint vUInt; + ulong vULong; + ullong vULLong; + float vFloat; + double vDouble; + ldouble vLDouble; + }; + PIString vString; + PIStringList vStringList; + + static PIVariant readFromString(const PIString & s); + +private: + static PIVariant::Type fromString(const PIString & str); + static PIString toString(const PIVariant::Type & var); + static uint variableSize(const PIVariant::Type & var); + static double variableValue(const void * var_ptr, const PIVariant::Type & var); + +}; + +inline std::ostream & operator <<(std::ostream & s, const PIVariant & v) {s << v.typeName() << ": " << v.stringValue(); return s;} + +class PIP_EXPORT PIVariable { +public: + PIVariable() {;} + PIVariable(const PIString & str) {setVariable(str);} + ~PIVariable() {;} + + void setVariable(const PIString & str); + void writeVariable(void * dest); + void readVariable(const void * var_ptr) {value_ = PIVariant::variableValue((char * )((long)var_ptr + offset), type_);} + PIVariant::Type type() const {return type_;} + uint size() const {return size_;} + const PIString & name() {return name_;} + void setName(const PIString & str) {name_ = str;} + double value() const {return value_;} + void setValue(const double & val) {value_ = val;} + + int offset; + +private: + PIVariant::Type type_; + uint size_; + PIString name_; + double value_; + +}; + + +/* + * PIStruct is abstract structure, described by *.conf file with format of each line: + * " = # ". + * e.g. "pi = double #f 3.1418" + * + * You can write or read binary content of this struct + * by functions "writeData" and "readData", e.g. + * "char * data = new char[struct.size()]; + * struct.writeData(data);" + * + * Access to each variable in struct is looks like + * "double value = struct["pi"].value();" +*/ + +class PIP_EXPORT PIStruct { +public: + PIStruct() {;} + PIStruct(const PIString & str) {parseFile(str);} + + void parseFile(const PIString & file); + void readData(const void * data); + void writeData(void * data); + void clear() {vars.clear(); size_ = 0;} + uint count() const {return vars.size();} + uint size() const {return size_;} + const PIString & name() {return name_;} + void setName(const PIString & str) {name_ = str;} + PIVariable & operator[](const uint & index) {return vars[index];} + PIVariable & operator[](const PIString & name) {for (uint i = 0; i < vars.size(); ++i) if (vars[i].name() == name) return vars[i]; return def;} + +private: + uint size_; + PIString name_; + PIVariable def; + PIVector vars; + +}; + +#endif // PIVARIABLE_H diff --git a/src/_unsused/pivariable.h_ b/src/_unsused/pivariable.h_ new file mode 100644 index 00000000..44ba5fd8 --- /dev/null +++ b/src/_unsused/pivariable.h_ @@ -0,0 +1,196 @@ +/* + PIP - Platform Independent Primitives + Variable, Struct (simple serialization) + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIVARIABLE_H +#define PIVARIABLE_H + +#include "piconfig.h" + +class PIP_EXPORT PIVariant { + friend class PIVariable; +public: + enum Type {Bool, Char, Short, Int, Long, LLong, UChar, UShort, UInt, ULong, ULLong, Float, Double, LDouble, String, StringList}; + + PIVariant() {setValue(0.);} + PIVariant(const char * v) {setValue(v);} + PIVariant(const bool & v) {setValue(v);} + PIVariant(const char & v) {setValue(v);} + PIVariant(const short & v) {setValue(v);} + PIVariant(const int & v) {setValue(v);} + PIVariant(const long & v) {setValue(v);} + PIVariant(const llong & v) {setValue(v);} + PIVariant(const uchar & v) {setValue(v);} + PIVariant(const ushort & v) {setValue(v);} + PIVariant(const uint & v) {setValue(v);} + PIVariant(const ulong & v) {setValue(v);} + PIVariant(const ullong & v) {setValue(v);} + PIVariant(const float & v) {setValue(v);} + PIVariant(const double & v) {setValue(v);} + PIVariant(const ldouble & v) {setValue(v);} + PIVariant(const PIString & v) {setValue(v);} + PIVariant(const PIStringList & v) {setValue(v);} + + void setValue(const char * v) {setValue(PIString(v));} + void setValue(const bool & v) {type = PIVariant::Bool; vBool = v;} + void setValue(const char & v) {type = PIVariant::Char; vChar = v;} + void setValue(const short & v) {type = PIVariant::Short; vShort = v;} + void setValue(const int & v) {type = PIVariant::Int; vInt = v;} + void setValue(const long & v) {type = PIVariant::Long; vLong = v;} + void setValue(const llong & v) {type = PIVariant::LLong; vLLong = v;} + void setValue(const uchar & v) {type = PIVariant::UChar; vUChar = v;} + void setValue(const ushort & v) {type = PIVariant::UShort; vUShort = v;} + void setValue(const uint & v) {type = PIVariant::UInt; vUInt = v;} + void setValue(const ulong & v) {type = PIVariant::ULong; vULong = v;} + void setValue(const ullong & v) {type = PIVariant::ULLong; vULLong = v;} + void setValue(const float & v) {type = PIVariant::Float; vFloat = v;} + void setValue(const double & v) {type = PIVariant::Double; vDouble = v;} + void setValue(const ldouble & v) {type = PIVariant::LDouble; vLDouble = v;} + void setValue(const PIString & v) {type = PIVariant::String; vString = v;} + void setValue(const PIStringList & v) {type = PIVariant::StringList; vStringList = v;} + void setValueOnly(const PIString & v); + PIString typeName() const {return PIVariant::toString(type);} + double doubleValue() const {return PIVariant::variableValue(&vChar, type);} + PIString stringValue() const; + void typeFromString(const PIString & str) {type = PIVariant::fromString(str);} + PIString typeToString() const {return PIVariant::toString(type);} + uint size() {if (type != PIVariant::String && type != PIVariant::StringList) return PIVariant::variableSize(type); if (type == PIVariant::String) return vString.size(); else return vStringList.contentSize();} + PIString writeToString() const {return typeName() + ":" + stringValue();} + +#ifdef QNX + void operator =(const PIVariant & v) {type = v.type; vLDouble = v.vLDouble; vString = v.vString; vStringList = v.vStringList;} +#endif + void operator =(const char * v) {setValue(PIString(v));} + void operator =(const bool & v) {type = PIVariant::Bool; vBool = v;} + void operator =(const char & v) {type = PIVariant::Char; vChar = v;} + void operator =(const short & v) {type = PIVariant::Short; vShort = v;} + void operator =(const int & v) {type = PIVariant::Int; vInt = v;} + void operator =(const long & v) {type = PIVariant::Long; vLong = v;} + void operator =(const llong & v) {type = PIVariant::LLong; vLLong = v;} + void operator =(const uchar & v) {type = PIVariant::UChar; vUChar = v;} + void operator =(const ushort & v) {type = PIVariant::UShort; vUShort = v;} + void operator =(const uint & v) {type = PIVariant::UInt; vUInt = v;} + void operator =(const ulong & v) {type = PIVariant::ULong; vULong = v;} + void operator =(const ullong & v) {type = PIVariant::ULLong; vULLong = v;} + void operator =(const float & v) {type = PIVariant::Float; vFloat = v;} + void operator =(const double & v) {type = PIVariant::Double; vDouble = v;} + void operator =(const ldouble & v) {type = PIVariant::LDouble; vLDouble = v;} + void operator =(const PIString & v) {type = PIVariant::String; vString = v;} + void operator =(const PIStringList & v) {type = PIVariant::StringList; vStringList = v;} + + bool operator ==(const PIVariant & v) const; + bool operator !=(const PIVariant & v) const {return !(*this == v);} + + PIVariant::Type type; + union { + bool vBool; + char vChar; + short vShort; + int vInt; + long vLong; + llong vLLong; + uchar vUChar; + ushort vUShort; + uint vUInt; + ulong vULong; + ullong vULLong; + float vFloat; + double vDouble; + ldouble vLDouble; + }; + PIString vString; + PIStringList vStringList; + + static PIVariant readFromString(const PIString & s); + +private: + static PIVariant::Type fromString(const PIString & str); + static PIString toString(const PIVariant::Type & var); + static uint variableSize(const PIVariant::Type & var); + static double variableValue(const void * var_ptr, const PIVariant::Type & var); + +}; + +inline std::ostream & operator <<(std::ostream & s, const PIVariant & v) {s << v.typeName() << ": " << v.stringValue(); return s;} + +class PIP_EXPORT PIVariable { +public: + PIVariable() {;} + PIVariable(const PIString & str) {setVariable(str);} + ~PIVariable() {;} + + void setVariable(const PIString & str); + void writeVariable(void * dest); + void readVariable(const void * var_ptr) {value_ = PIVariant::variableValue((char * )((long)var_ptr + offset), type_);} + PIVariant::Type type() const {return type_;} + uint size() const {return size_;} + const PIString & name() {return name_;} + void setName(const PIString & str) {name_ = str;} + double value() const {return value_;} + void setValue(const double & val) {value_ = val;} + + int offset; + +private: + PIVariant::Type type_; + uint size_; + PIString name_; + double value_; + +}; + + +/* + * PIStruct is abstract structure, described by *.conf file with format of each line: + * " = # ". + * e.g. "pi = double #f 3.1418" + * + * You can write or read binary content of this struct + * by functions "writeData" and "readData", e.g. + * "char * data = new char[struct.size()]; + * struct.writeData(data);" + * + * Access to each variable in struct is looks like + * "double value = struct["pi"].value();" +*/ + +class PIP_EXPORT PIStruct { +public: + PIStruct() {;} + PIStruct(const PIString & str) {parseFile(str);} + + void parseFile(const PIString & file); + void readData(const void * data); + void writeData(void * data); + void clear() {vars.clear(); size_ = 0;} + uint count() const {return vars.size();} + uint size() const {return size_;} + const PIString & name() {return name_;} + void setName(const PIString & str) {name_ = str;} + PIVariable & operator[](const uint & index) {return vars[index];} + PIVariable & operator[](const PIString & name) {for (uint i = 0; i < vars.size(); ++i) if (vars[i].name() == name) return vars[i]; return def;} + +private: + uint size_; + PIString name_; + PIVariable def; + PIVector vars; + +}; + +#endif // PIVARIABLE_H diff --git a/src/code/picodeinfo.cpp b/src/code/picodeinfo.cpp new file mode 100755 index 00000000..ef2801b3 --- /dev/null +++ b/src/code/picodeinfo.cpp @@ -0,0 +1,42 @@ +/* + PIP - Platform Independent Primitives + C++ code info structs + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "picodeinfo.h" + + +PIString PICodeInfo::EnumInfo::memberName(int value_) const { + piForeachC (PICodeInfo::EnumeratorInfo & e, members) + if (e.value == value_) + return e.name; + return PIString(); +} + + +int PICodeInfo::EnumInfo::memberValue(const PIString & name_) const { + piForeachC (PICodeInfo::EnumeratorInfo & e, members) + if (e.name == name_) + return e.value; + return -1; +} + + +PIMap * PICodeInfo::classesInfo; +PIMap * PICodeInfo::enumsInfo; + +bool __PICodeInfoInitializer__::_inited_ = false; diff --git a/src/code/picodeinfo.h b/src/code/picodeinfo.h new file mode 100755 index 00000000..c6f45125 --- /dev/null +++ b/src/code/picodeinfo.h @@ -0,0 +1,158 @@ +/*! \file picodeinfo.h + * \brief C++ code info structs +*/ +/* + PIP - Platform Independent Primitives + C++ code info structs + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +#ifndef PICODEINFO_H +#define PICODEINFO_H + +#include "pistring.h" + +namespace PICodeInfo { + +enum TypeFlag { + NoFlag, + Const = 0x01, + Static = 0x02, + Mutable = 0x04, + Volatile = 0x08, + Inline = 0x10, + Virtual = 0x20, + Extern = 0x40 +}; + +typedef PIFlags TypeFlags; + +struct TypeInfo { + TypeInfo(const PIString & n = PIString(), const PIString & t = PIString(), PICodeInfo::TypeFlags f = 0) {name = n; type = t; flags = f;} + PIString name; + PIString type; + PICodeInfo::TypeFlags flags; +}; + +struct FunctionInfo { + PIString name; + TypeInfo return_type; + PIVector arguments; +}; + +struct ClassInfo { + PIString name; + PIStringList parents; + PIVector variables; + PIVector functions; +}; + +struct EnumeratorInfo { + EnumeratorInfo(const PIString & n = PIString(), int v = 0) {name = n; value = v;} + PIString name; + int value; +}; + +struct EnumInfo { + PIString memberName(int value) const; + int memberValue(const PIString & name) const; + PIString name; + PIVector members; +}; + + +inline PICout operator <<(PICout s, const PICodeInfo::TypeInfo & v) { + if (v.flags[Inline]) s << "inline "; + if (v.flags[Virtual]) s << "virtual "; + if (v.flags[Mutable]) s << "mutable "; + if (v.flags[Volatile]) s << "volatile "; + if (v.flags[Static]) s << "static "; + if (v.flags[Const]) s << "const "; + s << v.type; + if (!v.name.isEmpty()) + s << " " << v.name; + return s; +} + +inline PICout operator <<(PICout s, const PICodeInfo::EnumeratorInfo & v) {s << v.name << " = " << v.value; return s;} + +inline PICout operator <<(PICout s, const PICodeInfo::ClassInfo & v) { + s.setControl(0, true); + s << "class " << v.name; + if (!v.parents.isEmpty()) { + s << ": "; + bool first = true; + piForeachC (PIString & i, v.parents) { + if (first) first = false; + else s << ", "; + s << i; + } + } + s << " {\n"; + piForeachC (FunctionInfo & i, v.functions) { + s << Tab << i.return_type << " " << i.name << "("; + bool fa = true; + piForeachC (TypeInfo & a, i.arguments) { + if (fa) fa = false; + else s << ", "; + s << a; + } + s << ");\n"; + } + if (!v.functions.isEmpty() && !v.variables.isEmpty()) + s << "\n"; + piForeachC (TypeInfo & i, v.variables) { + s << Tab << i << ";\n"; + } + s << "}\n"; + s.restoreControl(); + return s; +} + +inline PICout operator <<(PICout s, const PICodeInfo::EnumInfo & v) { + s.setControl(0, true); + s << "enum " << v.name << " {\n"; + piForeachC (EnumeratorInfo & i, v.members) { + bool f = true; + if (f) f = false; + else s << ", "; + s << Tab << i << "\n"; + } + s << "}\n"; + s.restoreControl(); + return s; +} + +extern PIMap * classesInfo; +extern PIMap * enumsInfo; + +} + +class __PICodeInfoInitializer__ { +public: + __PICodeInfoInitializer__() { + if (_inited_) return; + _inited_ = true; + PICodeInfo::classesInfo = new PIMap; + PICodeInfo::enumsInfo = new PIMap; + } + static bool _inited_; +}; + +static __PICodeInfoInitializer__ __picodeinfoinitializer__; + +#endif // PICODEINFO_H diff --git a/src/code/picodeparser.cpp b/src/code/picodeparser.cpp new file mode 100755 index 00000000..36722d2e --- /dev/null +++ b/src/code/picodeparser.cpp @@ -0,0 +1,846 @@ +/* + PIP - Platform Independent Primitives + C++ code parser + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "picodeparser.h" + + + +PIString PICodeParser::Macro::expand(PIString args_, bool * ok) const { + PIStringList arg_vals; + while (!args_.isEmpty()) { + int ci = args_.find(","), bi = args_.find("("); + if (ci < 0) { + arg_vals << args_; + break; + } + PIString ca; + if (bi >= 0 && bi < ci) { + ca = args_.left(args_.takeLeft(bi)); + ci -= ca.size_s(); bi -= ca.size_s(); + ca += "(" + args_.takeRange("(", ")") + ")"; + } else { + ca = args_.takeLeft(ci); + } + arg_vals << ca; + args_.trim(); args_.takeLeft(1); args_.trim(); + } + if (args.size() != arg_vals.size()) { + piCout << ("Error: in expansion of macro \"" + name + "(" + args.join(", ") + ")\": expect") + << args.size() << "arguments but takes" << arg_vals.size() << "!"; + if (ok != 0) *ok = false; + return PIString(); + } + PIString ret = value; + for (int i = 0; i < args.size_s(); ++i) { + const PIString & an(args[i]), av(arg_vals[i]); + int ind(-1); + while ((ind = ret.find(an, ind + 1)) >= 0) { + PIChar ppc(0), pc(0), nc(0); + if (ind > 1) ppc = ret[ind - 2]; + if (ind > 0) pc = ret[ind - 1]; + if (ind + an.size_s() < ret.size_s()) nc = ret[ind + an.size_s()]; + if (ppc != '#' && pc == '#' && !_isCChar(nc)) { // to chars + ind--; + ret.replace(ind, an.size_s() + 1, "\"" + av + "\""); + ind -= an.size_s() - av.size_s() - 1; + continue; + } + if (_isCChar(pc) || _isCChar(nc)) continue; + ret.replace(ind, an.size_s(), av); + ind -= an.size_s() - av.size_s(); + } + } + ret.replaceAll("##", ""); + if (ok != 0) *ok = true; + return ret; +} + + + +PICodeParser::PICodeParser() { + macros_iter = 32; + with_includes = true; + clear(); + includes << ""; +} + + +void PICodeParser::parseFile(const PIString & file, bool follow_includes) { + clear(); + parseFileInternal(file, follow_includes); + /*piCout << "\n\nDefines:"; + piForeachC (Define & m, defines) + piCout << "define" << m.first << m.second; + piCout << "\n\nMacros:"; + piForeachC (Macro & m, macros) + piCout << "Macro:" << m.name << m.args << m.value; + piCout << "\n\nClasses:"; + piForeachC (Entity * c, entities) + piCout << "class" << c->name << c->parents; + piCout << "\n\nEnums:"; + piForeachC (Enum & c, enums) + piCout << "enum" << c.name << c.members; + piCout << "\n\nTypedefs:"; + piForeachC (Typedef & c, typedefs) + piCout << "typedef" << c;*/ +} + + +void PICodeParser::parseFiles(const PIStringList & files, bool follow_includes) { + clear(); + piForeachC (PIString & f, files) + parseFileInternal(f, follow_includes); + /*piCout << "\n\nDefines:"; + piForeachC (Define & m, defines) + piCout << "define" << m.first << m.second; + piCout << "\n\nMacros:"; + piForeachC (Macro & m, macros) + piCout << "Macro:" << m.name << m.args << m.value; + piCout << "\n\nClasses:"; + piForeachC (Entity * c, entities) + piCout << "class" << c->name << c->parents; + piCout << "\n\nEnums:"; + piForeachC (Enum & c, enums) + piCout << "enum" << c.name << c.members; + piCout << "\n\nTypedefs:"; + piForeachC (Typedef & c, typedefs) + piCout << "typedef" << c;*/ +} + + +bool PICodeParser::isEnum(const PIString & name) { + piForeachC (Enum & e, enums) + if (e.name == name) + return true; + return false; +} + + +bool PICodeParser::parseFileInternal(const PIString & file, bool follow_includes) { + if (proc_files[file]) return true; + with_includes = follow_includes; + cur_file = file; + PIFile f(file, PIIODevice::ReadOnly); + int ii = 0; + while (!f.isOpened() && ii < (includes.size_s() - 1)) { + f.setPath(includes[++ii] + "/" + file); + //piCout << "try" << f.path(); + f.open(PIIODevice::ReadOnly); + } + if (!f.isOpened()) { + //piCout << ("Error: can`t open file \"" + file + "\"!"); + return false; + } + //piCout << "add" << file; + proc_files << f.path(); + PIString fc = f.readAll(); + piCout << "parsing" << f.path() << "..."; + bool is_main = isMainFile(fc); + if (is_main) main_file = f.path(); + bool ret = parseFileContent(fc, is_main); + piCout << "parsing" << f.path() << "done"; + return ret; +} + + +void PICodeParser::clear() { + piForeach (Entity * i, entities) delete i; + defines.clear(); + macros.clear(); + enums.clear(); + typedefs.clear(); + entities.clear(); + proc_files.clear(); + cur_namespace.clear(); + main_file.clear(); + evaluator.clearCustomVariables(); + defines << Define("PICODE", "") << custom_defines; +} + + +bool PICodeParser::parseFileContent(PIString & fc, bool main) { + bool mlc = false, cc = false; + int mls = 0, ole = -1, /*ccs = 0,*/ end = 0; + char c = 0, pc = 0; + PIString pfc, line, ccmn, tmp; + PIMap cchars; + + /// Remove comments, join multiline "*" and replace "*" to $n (cchars) + fc.replaceAll("\r\n", "\n"); + fc.replaceAll("\r", "\n"); + for (int i = 0; i < fc.size_s() - 1; ++i) { + if (i > 0) pc = c; + c = fc[i].toAscii(); + if (c == '"' && !mlc && pc != '\'') { + if (i > 0) if (fc[i - 1] == '\\') continue; + cc = !cc; + /*if (cc) ccs = i; + if (!cc) { + ccmn = "$" + PIString::fromNumber(cchars.size()); + cchars[ccmn] = fc.mid(ccs, i - ccs + 1); + fc.replace(ccs, i - ccs + 1, ccmn); + i = ccs - 1 + ccmn.size_s(); + }*/ + continue; + } + if (i > 0) + if (c == '\\' && fc[i - 1].toAscii() != '\\') { + fc.cutMid(i, 2); + --i; + continue; + } + if (cc) continue; + if (fc.mid(i, 2) == "/*") {mlc = true; mls = i; ++i; continue;} + if (fc.mid(i, 2) == "*/" && mlc) {mlc = false; fc.cutMid(mls, i - mls + 2); i = mls - 1; continue;} + if (fc.mid(i, 2) == "//" && !mlc) {ole = fc.find('\n', i); fc.cutMid(i, ole < 0 ? -1 : ole - i); --i; continue;} + } + //piCout << fc; + pfc = procMacros(fc); + + if (main) return true; + + bool replaced = true; + int replaced_cnt = 0; + while (replaced) { + //piCout << "MACRO iter" << replaced_cnt; + if (replaced_cnt >= macros_iter) { + piCout << "Error: recursive macros detected!"; + break;//return false; + } + replaced_cnt++; + replaced = false; + piForeachC (Define & d, defines) { + int ind(-1); + while ((ind = pfc.find(d.first, ind + 1)) >= 0) { + PIChar pc(0), nc(0); + if (ind > 0) pc = pfc[ind - 1]; + if (ind + d.first.size_s() < pfc.size_s()) nc = pfc[ind + d.first.size_s()]; + if (_isCChar(pc) || _isCChar(nc) || nc.isDigit()) continue; + pfc.replace(ind, d.first.size_s(), d.second); + ind -= d.first.size_s() - d.second.size_s(); + replaced = true; + } + } + piForeachC (Macro & m, macros) { + int ind(-1); + while ((ind = pfc.find(m.name, ind + 1)) >= 0) { + PIChar pc(0), nc(0); + if (ind > 0) pc = pfc[ind - 1]; + if (ind + m.name.size_s() < pfc.size_s()) nc = pfc[ind + m.name.size_s()]; + if (_isCChar(pc) || _isCChar(nc) || nc.isDigit()) continue; + PIString ret, range; bool ok(false); + range = pfc.mid(ind + m.name.size_s()).takeRange("(", ")"); + ret = m.expand(range, &ok); + if (!ok) return false; + int rlen = pfc.find(range, ind + m.name.size_s()) + range.size_s() + 1 - ind; + pfc.replace(ind, rlen, ret); + ind -= rlen - ret.size_s(); + replaced = true; + } + } + } + + //piCout << NewLine << "file" << cur_file << pfc; + int pl = -1; + while (!pfc.isEmpty()) { + pfc.trim(); + int nl = pfc.size_s(); + if (pl == nl) break; + pl = nl; + if (pfc.left(9) == "namespace") { + pfc.cutLeft(pfc.find("{") + 1); + continue; + } + if (pfc.left(8) == "template") { + pfc.cutLeft(8); + pfc.takeRange("<", ">"); + bool def = !isDeclaration(pfc, 0, &end); + pfc.cutLeft(end); + if (def) pfc.takeRange("{", "}"); + else pfc.takeSymbol(); + continue; + } + if (pfc.left(5) == "class" || pfc.left(6) == "struct") { + int dind = pfc.find("{", 0), find = pfc.find(";", 0); + if (dind < 0 && find < 0) {pfc.cutLeft(6); continue;} + if (dind < 0 || find < dind) {pfc.cutLeft(6); continue;} + ccmn = pfc.left(dind) + "{\n" + pfc.mid(dind).takeRange('{', '}') + "\n}\n"; + pfc.remove(0, ccmn.size()); + parseClass(ccmn); + continue; + } + if (pfc.left(4) == "enum") { + pfc.cutLeft(4); + tmp = pfc.takeCWord(); + parseEnum(cur_namespace + tmp, pfc.takeRange("{", "}")); + pfc.takeSymbol(); + continue; + } + if (pfc.left(7) == "typedef") { + pfc.cutLeft(7); + typedefs << parseTypedef(pfc.takeLeft(pfc.find(";"))); + if (typedefs.back().first.isEmpty()) typedefs.pop_back(); + else root_.typedefs << typedefs.back(); + pfc.takeSymbol(); + continue; + } + int sci = pfc.find(";", 0), obi = pfc.find("{", 0); + if (sci < 0 && obi < 0) { + pfc.takeLeft(1); + continue; + } + PIString str; + if (sci < obi) { + str = pfc.takeLeft(sci + 1); + } else { + str = pfc.takeLeft(obi); + pfc.cutLeft(pfc.takeRange("{", "}")); + } + parseMember(&root_, str); + } + + return true; +} + + +PICodeParser::Entity * PICodeParser::parseClassDeclaration(const PIString & fc) { + PIString cd = fc.trimmed().removeAll('\n').replaceAll("\t", " ").replaceAll(" ", " "), pn; + //piCout << "found class <****\n" << cd << "\n****>"; + int ind = cd.find(":"); + PIVector parents; + if (ind > 0) { + PIStringList pl = cd.takeMid(ind + 1).trim().split(","); + cd.cutRight(1); + Entity * pe = 0; + piForeachC (PIString & p, pl) { + if (p.contains(" ")) pn = p.mid(p.find(" ") + 1); + else pn = p; + pe = findEntityByName(pn); + if (pe == 0) ;//{piCout << "Error: can`t find" << pn;} + else parents << pe; + } + } + bool is_class = cd.left(5) == "class"; + cur_def_vis = (is_class ? Private : Public); + PIString cn = cd.mid(6).trim(); + if (cn.isEmpty()) return 0; + Entity * e = new Entity(); + e->name = cur_namespace + cn; + e->type = (is_class ? "class" : "struct"); + e->parents = parents; + e->file = cur_file; + entities << e; + return e; +} + + +PIString PICodeParser::parseClass(PIString & fc) { + Visibility prev_vis = cur_def_vis; + int dind = fc.find("{"), find = fc.find(";"), end = 0; + if (dind < 0 && find < 0) return PIString(); + if (dind < 0 || find < dind) return fc.left(find); + Entity * ce = parseClassDeclaration(fc.takeLeft(dind)); + fc.trim().cutLeft(1).cutRight(1).trim(); + //piCout << "found class <****\n" << fc << "\n****>"; + if (!ce) return PIString(); + int ps = -1; + bool def = false; + PIString prev_namespace = cur_namespace, stmp; + cur_namespace = ce->name + "::"; + //piCout << "parse class" << ce->name << "namespace" << cur_namespace; + //piCout << "\nparse class" << ce->name << "namespace" << cur_namespace; + while (!fc.isEmpty()) { + PIString cw = fc.takeCWord(), tmp; + //piCout << "\ntaked word" << cw; + if (cw == "public") {cur_def_vis = Public; fc.cutLeft(1); continue;} + if (cw == "protected") {cur_def_vis = Protected; fc.cutLeft(1); continue;} + if (cw == "private") {cur_def_vis = Private; fc.cutLeft(1); continue;} + if (cw == "class") {if (isDeclaration(fc, 0, &end)) {fc.cutLeft(end); fc.takeSymbol(); continue;} tmp = fc.takeLeft(fc.find("{")); stmp = fc.takeRange("{", "}"); fc.takeSymbol(); stmp = "class " + tmp + "{" + stmp + "}"; parseClass(stmp); continue;} + if (cw == "struct") {if (isDeclaration(fc, 0, &end)) {fc.cutLeft(end); fc.takeSymbol(); continue;} tmp = fc.takeLeft(fc.find("{")); stmp = fc.takeRange("{", "}"); fc.takeSymbol(); stmp = "struct " + tmp + "{" + stmp + "}"; parseClass(stmp); continue;} + if (cw == "enum") {tmp = fc.takeCWord(); parseEnum(cur_namespace + tmp, fc.takeRange("{", "}")); fc.takeSymbol(); continue;} + if (cw == "friend") {fc.cutLeft(fc.find(";") + 1); continue;} + if (cw == "typedef") {ce->typedefs << parseTypedef(fc.takeLeft(fc.find(";"))); typedefs << ce->typedefs.back(); typedefs.back().first.insert(0, cur_namespace); if (ce->typedefs.back().first.isEmpty()) ce->typedefs.pop_back(); fc.takeSymbol(); continue;} + if (cw == "template") { + fc.takeRange("<", ">"); + def = !isDeclaration(fc, 0, &end); + fc.cutLeft(end); + if (def) fc.takeRange("{", "}"); + else fc.takeSymbol(); + continue; + } + def = !isDeclaration(fc, 0, &end); + tmp = (cw + fc.takeLeft(end)).trim(); + if (!tmp.isEmpty()) + parseMember(ce, tmp); + if (def) fc.takeRange("{", "}"); + else fc.takeSymbol(); + if (ps == fc.size_s()) {/*cur_namespace = prev_namespace;*/ fc.cutLeft(1);/*return false*/;} + ps = fc.size_s(); + } + cur_def_vis = prev_vis; + cur_namespace = prev_namespace; + return ce->name; +} + + +bool PICodeParser::parseEnum(const PIString & name, PIString fc) { + //piCout << "enum" << name << fc; + Enum e(name); + PIStringList vl(fc.split(",")); + PIString vn; + int cv = -1, ind = 0; + piForeachC (PIString & v, vl) { + vn = v; ind = v.find("="); + if (ind > 0) {cv = v.right(v.size_s() - ind - 1).toInt(); vn = v.left(ind);} + if (ind < 0) ++cv; + e.members << Enumerator(vn.trim(), cv); + } + enums << e; + return true; +} + + +PICodeParser::Typedef PICodeParser::parseTypedef(PIString fc) { + //piCout << "parse typedef" << fc; + Typedef td; + fc.replaceAll("\t", " "); + + if (fc.contains("(")) { + int start = fc.find("("), end = fc.find(")"); + td.first = fc.takeMid(start + 1, end - start - 1).trim(); + if (td.first.left(1) == "*") {td.first.cutLeft(1).trim(); fc.insert(start + 1, "*");} + td.second = fc.trim(); + } else { + td.first = fc.takeMid(fc.findLast(" ")).trim(); + td.second = fc.trim(); + } + //piCout << "found typedef" << td; + return td; +} + + +bool PICodeParser::parseMember(Entity * parent, PIString & fc) { + if (fc.trim().isEmpty()) return true; + if (fc.find("operator") >= 0) return true; + tmp_temp.clear(); + //piCout << "parse member" << fc; + int ts = fc.find("<"), te = 0; + PIString ctemp, crepl; + while (ts >= 0) { + ctemp = fc.mid(ts).takeRange("<", ">"); + if (ctemp.isEmpty()) {te = ts + 1; ts = fc.find("<", te); continue;} + crepl = "$" + PIString::fromNumber(tmp_temp.size_s()).expandLeftTo(3, "0"); + fc.replace(ts, ctemp.size_s() + 2, crepl); + tmp_temp[crepl] = "<" + ctemp + ">"; + ts = fc.find("<", te); + } + fc.replaceAll("\n", " ").replaceAll("\t", " ").replaceAll(" ", " ").replaceAll(", ", ","); + PIStringList tl, al; + Member me; + //piCout << fc; + if (fc.contains("(")) { + fc.cutRight(fc.size_s() - fc.findLast(")") - 1); + te = fc.find("("); + //piCout << fc; + for (ts = te - 1; ts >= 0; --ts) + if (!_isCChar(fc[ts]) && !(fc[ts].isDigit())) break; + //piCout << "takeMid" << ts + 1 << te - ts - 1; + me.name = fc.takeMid(ts + 1, te - ts - 1); + if (me.name == parent->name) return true; + me.arguments_full = fc.takeMid(ts + 2).cutRight(1).split(","); + me.type = fc.cutRight(1).trim(); + me.visibility = cur_def_vis; + if (me.type.find("inline ") >= 0) { + me.attributes |= Inline; + me.type.removeAll("inline "); + } + if (me.type.find("static ") >= 0) { + me.attributes |= Static; + me.type.removeAll("static "); + } + if (me.type.find("virtual ") >= 0) { + me.attributes |= Virtual; + me.type.removeAll("virtual "); + } + normalizeEntityNamespace(me.type); + int i = 0; + //piCout << me.arguments_full; + piForeach (PIString & a, me.arguments_full) + if ((i = a.find("=")) > 0) + a.cutRight(a.size_s() - i).trim(); + for (int j = 0; j < me.arguments_full.size_s(); ++j) + if (me.arguments_full[j] == "void") { + me.arguments_full.remove(j); + --j; + } + me.arguments_type = me.arguments_full; + piForeach (PIString & a, me.arguments_type) { + crepl.clear(); + if (a.contains("[")) + crepl = a.takeMid(a.find("["), a.findLast("]") - a.find("[") + 1); + for (ts = a.size_s() - 1; ts >= 0; --ts) + if (!_isCChar(a[ts]) && !(a[ts].isDigit())) break; + a.cutRight(a.size_s() - ts - 1); + normalizeEntityNamespace(a); + a += crepl; + a.trim(); + } + restoreTmpTemp(&me); + //piCout << "func" << me.type << me.name << me.arguments_full << me.arguments_type; + parent->functions << me; + } else { + if (fc.endsWith(";")) fc.cutRight(1); + if (fc.startsWith("using") || !(fc.contains(' ') || fc.contains('\t') || fc.contains('\n'))) return true; + tl = fc.split(","); + //piCout << "\tmember" << fc; + if (tl.isEmpty()) return true; + bool vn = true; + ctemp = tl.front(); + for (ts = ctemp.size_s() - 1; ts > 0; --ts) { + if (vn) {if (!_isCChar(ctemp[ts]) && !ctemp[ts].isDigit() && ctemp[ts] != '[' && ctemp[ts] != ']') vn = false;} + else {if (_isCChar(ctemp[ts]) || ctemp[ts].isDigit()) break;} + } + me.type = ctemp.takeLeft(ts + 1); + me.visibility = cur_def_vis; + restoreTmpTemp(&me); + PIString type = " " + me.type; + if (type.find(" const ") >= 0) { + me.attributes |= Const; + type.replaceAll(" const ", " "); + } + if (type.find(" static ") >= 0) { + me.attributes |= Static; + type.replaceAll(" static ", " "); + } + if (type.find(" mutable ") >= 0) { + me.attributes |= Mutable; + type.replaceAll(" mutable ", " "); + } + if (type.find(" volatile ") >= 0) { + me.attributes |= Volatile; + type.replaceAll(" volatile ", " "); + } + if (type.find(" extern ") >= 0) { + me.attributes |= Extern; + type.replaceAll(" extern ", " "); + } + type.trim(); + normalizeEntityNamespace(type); + tl[0] = ctemp.trim(); + piForeachC (PIString & v, tl) { + crepl.clear(); + me.name = v.trimmed(); + me.type = type; + if (me.name.isEmpty()) continue; + if (me.name.contains("[")) + crepl = me.name.takeMid(me.name.find("["), me.name.findLast("]") - me.name.find("[") + 1); + while (!me.name.isEmpty()) { + if (me.name.front() == "*" || me.name.front() == "&") { + me.type += me.name.takeLeft(1); + me.name.trim(); + } else break; + } + me.is_type_ptr = (me.type.right(1) == "]" || me.type.right(1) == "*"); + me.type += crepl; + //piCout << "var" << me.type << me.name << me.is_const << me.is_static; + parent->members << me; + } + } + //piCout << "parse member" << fc; + return true; +} + + +void PICodeParser::normalizeEntityNamespace(PIString & n) { + PIString suff, pref; + for (int i = n.size_s() - 1; i > 0; --i) + if (_isCChar(n[i]) || n[i].isDigit()) { + suff = n.right(n.size_s() - i - 1); + n.cutRight(suff.size_s()); + break; + } + n.push_front(" "); + if (n.find(" static ") >= 0) {n.replaceAll(" static ", ""); pref += "static ";} + if (n.find(" const ") >= 0) {n.replaceAll(" const ", ""); pref += "const ";} + if (n.find(" mutable ") >= 0) {n.replaceAll(" mutable ", ""); pref += "mutable ";} + if (n.find(" volatile ") >= 0) {n.replaceAll(" volatile ", ""); pref += "volatile ";} + n.trim(); + int f = 0; + piForeachC (Entity * e, entities) { + if (e->name == n) { + n = (pref + n + suff).trim(); + return; + } + if ((f = e->name.find(n)) >= 0) + if (e->name.mid(f - 1, 1) == ":") + if (e->name.find(cur_namespace) >= 0) { + n = pref + e->name + suff; + return; + } + } + piForeachC (Enum & e, enums) + if ((f = e.name.find(n)) >= 0) + if (e.name.mid(f - 1, 1) == ":") + if (e.name.find(cur_namespace) >= 0) { + //piCout << "change" << n << "to" << e.name + suff; + n = pref + e.name + suff; + return; + } + piForeachC (Typedef & e, typedefs) + if ((f = e.first.find(n)) >= 0) + if (e.first.mid(f - 1, 1) == ":") + if (e.first.find(cur_namespace) >= 0) { + //piCout << "change" << n << "to" << e.name + suff; + n = pref + e.first + suff; + return; + } + n = (pref + n + suff).trim(); +} + + +void PICodeParser::restoreTmpTemp(Member * e) { + int i = 0; + piForeach (PIString & a, e->arguments_full) { + while ((i = a.find("$")) >= 0) + a.replace(i, 4, tmp_temp[a.mid(i, 4)]); + } + piForeach (PIString & a, e->arguments_type) { + while ((i = a.find("$")) >= 0) + a.replace(i, 4, tmp_temp[a.mid(i, 4)]); + } + while ((i = e->type.find("$")) >= 0) + e->type.replace(i, 4, tmp_temp[e->type.mid(i, 4)]); +} + + +bool PICodeParser::macroCondition(const PIString & mif, PIString mifcond) { + //piCout << "macroCondition" << mif << mifcond; + if (mif == "ifdef") return isDefineExists(mifcond); + if (mif == "ifndef") return !isDefineExists(mifcond); + if (mif == "if" || mif == "elif") { + mifcond.removeAll(" ").removeAll("\t"); + return procMacrosCond(mifcond) > 0.; + } + return false; +} + + +double PICodeParser::procMacrosCond(PIString fc) { + bool neg = false, first = true, br = false; + double ret = 0., brv = 0.; + int oper = 0, ps = -1; + char cc, nc; + PIString ce; + fc.removeAll("defined"); + //piCout << "procMacrosCond" << fc; + while (!fc.isEmpty()) { + cc = fc[0].toAscii(); + nc = (fc.size() > 1 ? fc[1].toAscii() : 0); + if (cc == '!') {neg = true; fc.pop_front(); continue;} + if (cc == '(') {br = true; brv = procMacrosCond(fc.takeRange('(', ')'));} + if (cc == '&' && nc == '&') {fc.remove(0, 2); oper = 1; continue;} + if (cc == '|' && nc == '|') {fc.remove(0, 2); oper = 2; continue;} + if (!br) { + ce = fc.takeCWord(); + if (ce.isEmpty()) ce = fc.takeNumber(); + } + if (first) { + first = false; + ret = br ? brv : defineValue(ce); + if (neg) ret = -ret; + } else { + //piCout << "oper" << oper << "with" << ce; + if (!br) brv = defineValue(ce); + switch (oper) { + case 1: ret = ret && (neg ? -brv : brv); break; + case 2: ret = ret || (neg ? -brv : brv); break; + } + } + if (ps == fc.size_s()) fc.cutLeft(1); + ps = fc.size_s(); + br = neg = false; + } + //piCout << "return" << ret; + return ret; +} + + +bool PICodeParser::isDefineExists(const PIString & dn) { + piForeachC (Define & d, defines) { + if (d.first == dn) + return true; + } + return false; +} + + +double PICodeParser::defineValue(const PIString & dn) { + piForeachC (Define & d, defines) { + if (d.first == dn) + return d.second.isEmpty() ? 1. : d.second.toDouble(); + } + return dn.toDouble(); +} + + +PICodeParser::Entity * PICodeParser::findEntityByName(const PIString & en) { + piForeach (Entity * e, entities) + if (e->name == en) + return e; + return 0; +} + + +bool PICodeParser::isDeclaration(const PIString & fc, int start, int * end) { + int dind = fc.find("{", start), find = fc.find(";", start); + //piCout << "isDeclaration" << dind << find; + if (dind < 0 && find < 0) {if (end) *end = -1; return true;} + if (dind < 0 || find < dind) {if (end) *end = find; return true;} + if (end) *end = dind; + return false; +} + + +bool PICodeParser::isMainFile(const PIString & fc) { + int si = 0; + while (si >= 0) { + int csi = fc.find(" main", si); + if (csi < 0) csi = fc.find("\tmain", si); + if (csi < 0) csi = fc.find("\nmain", si); + if (csi < 0) return false; + si = csi; + int fi = fc.find("(", si + 5); + if (fi < 0) return false; + if (fi - si < 10) { + PIString ms(fc.mid(si, fi - si + 1)); + ms.removeAll(" ").removeAll("\t").removeAll("\n"); + if (ms == "main(") return true; + } + si += 5; + } + return false; +} + + +PIString PICodeParser::procMacros(PIString fc) { + if (fc.isEmpty()) return PIString(); + int ifcnt = 0; + bool grab = false, skip = false, cond_ok = false; + PIString pfc, nfc, line, mif, mifcond; + //piCout << "procMacros\n<******" << fc << "\n******>"; + fc += "\n"; + while (!fc.isEmpty()) { + line = fc.takeLine().trimmed(); + if (line.left(1) == "#") { + mifcond = line.mid(1); + mif = mifcond.takeCWord(); + //piCout << "mif mifcond" << mif << mifcond << ifcnt; + if (skip || grab) { + if (mif.left(2) == "if") ifcnt++; + if (mif.left(5) == "endif") { + if (ifcnt > 0) ifcnt--; + else { + //piCout << "main endif" << skip << grab; + if (grab) pfc << procMacros(nfc); + skip = grab = false; + continue; + } + } + if (mif.left(4) == "elif" && ifcnt == 0) { + //piCout << "main elif" << skip << grab << cond_ok; + if (cond_ok) { + if (grab) { + pfc << procMacros(nfc); + skip = true; grab = false; + } + continue; + } + if (skip) { + //piCout << "check elif" << skip << grab << cond_ok; + if (!macroCondition(mif, mifcond.trimmed())) continue; + //piCout << "check elif ok"; + skip = false; grab = cond_ok = true; + continue; + } + continue; + } + if (mif.left(4) == "else" && ifcnt == 0) { + //piCout << "main else" << skip << grab; + if (grab) pfc << procMacros(nfc); + if (skip && !cond_ok) {skip = false; grab = true;} + else {skip = true; grab = false;} + continue; + } + if (grab) nfc << line << "\n"; + continue; + } + if (mif.left(2) == "if") { + //piCout << "main if"; + skip = grab = cond_ok = false; + if (macroCondition(mif, mifcond.trimmed())) grab = cond_ok = true; + else skip = true; + ifcnt = 0; + nfc.clear(); + } else { + if (!parseDirective(line.cutLeft(1).trim())) + ;//return false; /// WARNING + } + } else { + if (grab) nfc << line << "\n"; + else if (!skip) pfc << line << "\n"; + } + } + return pfc; +} + + +bool PICodeParser::parseDirective(PIString d) { + if (d.isEmpty()) return true; + PIString dname = d.takeCWord(); + //piCout << "parseDirective" << d; + if (dname == "include") { + d.replaceAll("<", "\"").replaceAll(">", "\""); + PIString cf = cur_file, ifc = d.takeRange("\"", "\""); + if (with_includes) { + bool ret = parseFileInternal(ifc, with_includes); + cur_file = cf; + return ret; + } + } + if (dname == "define") { + PIString mname = d.takeCWord(); + if (d.left(1) == "(") { // macro + PIStringList args = d.takeRange("(", ")").split(",").trim(); + macros << Macro(mname, d.trim(), args); + } else { // define + d.trim(); + //if (mname == d) d.clear(); + defines << Define(mname, d); + evaluator.setVariable(mname, complexd_1); + } + return true; + } + if (dname == "undef") { + PIString mname = d.takeCWord(); + for (int i = 0; i < defines.size_s(); ++i) + if (defines[i].first == mname) {defines.remove(i); --i;} + return true; + } + return true; +} diff --git a/src/code/picodeparser.h b/src/code/picodeparser.h new file mode 100755 index 00000000..133361ca --- /dev/null +++ b/src/code/picodeparser.h @@ -0,0 +1,162 @@ +/*! \file picodeparser.h + * \brief C++ code parser +*/ +/* + PIP - Platform Independent Primitives + C++ code parser + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +#ifndef PICODEPARSER_H +#define PICODEPARSER_H + +#include "pifile.h" +#include "pievaluator.h" + +inline bool _isCChar(const PIChar & c) {return (c.isAlpha() || (c.toAscii() == '_'));} +inline bool _isCChar(const PIString & c) {if (c.isEmpty()) return false; return _isCChar(c[0]);} + +class PIP_EXPORT PICodeParser { +public: + PICodeParser(); + + enum PIP_EXPORT Visibility {Global, Public, Protected, Private}; + enum PIP_EXPORT Attribute { + NoAttributes = 0x0, + Const = 0x01, + Static = 0x02, + Mutable = 0x04, + Volatile = 0x08, + Inline = 0x10, + Virtual = 0x20, + Extern = 0x40 + }; + + typedef PIFlags Attributes; + typedef PIPair Define; + typedef PIPair Typedef; + typedef PIPair Enumerator; + + struct PIP_EXPORT Macro { + Macro(const PIString & n = PIString(), const PIString & v = PIString(), const PIStringList & a = PIStringList()) { + name = n; + value = v; + args = a; + } + PIString expand(PIString args_, bool * ok = 0) const; + PIString name; + PIString value; + PIStringList args; + }; + + struct PIP_EXPORT Member { + Member() { + visibility = Global; + size = 0; + is_type_ptr = false; + attributes = NoAttributes; + } + PIString type; + PIString name; + PIStringList arguments_full; + PIStringList arguments_type; + Visibility visibility; + Attributes attributes; + bool is_type_ptr; + int size; + }; + + struct PIP_EXPORT Entity { + Entity() { + visibility = Global; + size = 0; + } + PIString type; + PIString name; + PIString file; + Visibility visibility; + int size; + PIVector parents; + //PIVector children; + PIVector functions; + PIVector members; + PIVector typedefs; + }; + + struct PIP_EXPORT Enum { + Enum(const PIString & n = PIString()) { + name = n; + } + PIString name; + PIVector members; + }; + + void parseFile(const PIString & file, bool follow_includes = true); + void parseFiles(const PIStringList & files, bool follow_includes = true); + + void includeDirectory(const PIString & dir) {includes << dir;} + void addDefine(const PIString & def_name, const PIString & def_value) {custom_defines << Define(def_name, def_value);} + bool isEnum(const PIString & name); + Entity * findEntityByName(const PIString & en); + PIStringList parsedFiles() const {return PIStringList(proc_files.toVector());} + PIString mainFile() const {return main_file;} + const PICodeParser::Entity * global() const {return &root_;} + + int macrosSubstitutionMaxIterations() const {return macros_iter;} + void setMacrosSubstitutionMaxIterations(int value) {macros_iter = value;} + + PIVector defines, custom_defines; + PIVector macros; + PIVector enums; + PIVector typedefs; + PIVector entities; + +private: + void clear(); + bool parseFileInternal(const PIString & file, bool follow_includes); + bool parseFileContent(PIString & fc, bool main); + bool parseDirective(PIString d); + Entity * parseClassDeclaration(const PIString & fc); + PIString parseClass(PIString & fc); + bool parseEnum(const PIString & name, PIString fc); + Typedef parseTypedef(PIString fc); + bool parseMember(Entity * parent, PIString & fc); + void restoreTmpTemp(Member * e); + bool macroCondition(const PIString & mif, PIString mifcond); + bool isDefineExists(const PIString & dn); + double defineValue(const PIString & dn); + PIString procMacros(PIString fc); + double procMacrosCond(PIString fc); + bool isDeclaration(const PIString & fc, int start, int * end); + bool isMainFile(const PIString & fc); + void normalizeEntityNamespace(PIString & n); + + int macros_iter; + bool with_includes; + PIEvaluator evaluator; + //PIVector tree; + PISet proc_files; + PIString cur_file, main_file; + PIStringList includes; + Entity root_; + Visibility cur_def_vis; + PIString cur_namespace; + PIMap tmp_temp; + +}; + +#endif // PICODEPARSER_H diff --git a/src/containers/picontainers.cpp b/src/containers/picontainers.cpp new file mode 100755 index 00000000..0c4dd3a0 --- /dev/null +++ b/src/containers/picontainers.cpp @@ -0,0 +1,175 @@ +/* + PIP - Platform Independent Primitives + Generic containers + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// * This class based on std::vector, expanding his functionality + +/** \class PIVector + * \brief Dynamic array of any type + * \details This class used to store dynamic array of any + * type of data. In memory data stored linear. You can insert + * item in any place of remove some items from any place. + * For quick add elements this is stream operator <<. + + * \fn PIVector::PIVector(); + * Contructs an empty vector + + * \fn PIVector::PIVector(ullong size, const Type & value = Type()); + * \brief Contructs vector with size "size" filled elements "value" + * \details Example: \snippet picontainers.cpp PIVector::PIVector + + * \fn const Type & PIVector::at(ullong index) const; + * \brief Read-only access to element by index "index" + * \details Example: \snippet picontainers.cpp PIVector::at_c + * \sa \a operator[] + + * \fn Type & PIVector::at(ullong index); + * \brief Full access to element by index "index" + * \details Example: \snippet picontainers.cpp PIVector::at + * \sa \a operator[] + + * \fn const Type * PIVector::data(ullong index = 0) const; + * \brief Read-only pointer to element by index "index" + * \details Example: \snippet picontainers.cpp PIVector::data_c + + * \fn Type * PIVector::data(ullong index = 0); + * \brief Pointer to element by index "index" + * \details Example: \snippet picontainers.cpp PIVector::data + + * \fn ullong PIVector::size() const; + * \brief Elements count + + * \fn int PIVector::size_s() const; + * \brief Elements count + + * \fn bool PIVector::isEmpty() const; + * \brief Return \c "true" if vector is empty, i.e. size = 0 + + * \fn bool PIVector::has(const Type & t) const; + + * \fn bool PIVector::contains(const Type & v) const; + * \brief Return \c "true" if vector has at least one element equal "t" + + * \fn int PIVector::etries(const Type & t) const; + * \brief Return how many times element "t" appears in vector + + * \fn static int PIVector::compare_func(const Type * t0, const Type * t1); + * \brief Standard compare function for type "Type". Return 0 if t0 = t1, -1 if t0 < t1 and 1 if t0 > t1. + + * \fn void PIVector::resize(ullong size, const Type & new_type = Type()); + * \brief Resize vector to size "size" + * \details Elements removed from end of vector if new size < old size, or added new elements = "new_type" if new size > old size.\n + * Example: \snippet picontainers.cpp PIVector::resize + * \sa \a size(), \a clear() + + * \fn PIVector & PIVector::enlarge(ullong size); + * \brief Increase vector size with "size" elements + + * \fn void PIVector::clear(); + * \brief Clear vector. Equivalent to call "resize(0)" + + * \fn PIVector & PIVector::sort(CompareFunc compare = compare_func); + * \brief Sort vector using quick sort algorithm and standard compare function + * \details Example: \snippet picontainers.cpp PIVector::sort_0 + * With custom compare function: \snippet picontainers.cpp PIVector::sort_1 + + * \fn PIVector & PIVector::fill(const Type & t); + * \brief Fill vector with elements "t" leave size is unchanged and return reference to vector + * \details Example: \snippet picontainers.cpp PIVector::fill + + * \fn Type & PIVector::back(); + * \brief Last element of the vector + + * \fn const Type & PIVector::back() const; + * \brief Last element of the vector + + * \fn Type & PIVector::front(); + * \brief First element of the vector + + * \fn const Type & PIVector::front() const; + * \brief First element of the vector + + * \fn PIVector & PIVector::push_back(const Type & t); + * \brief Add new element "t" at the end of vector and return reference to vector + + * \fn PIVector & PIVector::push_front(const Type & t); + * \brief Add new element "t" at the beginning of vector and return reference to vector + + * \fn PIVector & PIVector::pop_back(); + * \brief Remove one element from the end of vector and return reference to vector + + * \fn PIVector & PIVector::pop_front(); + * \brief Remove one element from the beginning of vector and return reference to vector + + * \fn Type PIVector::take_back(); + * \brief Remove one element from the end of vector and return it + + * \fn Type PIVector::take_front(); + * \brief Remove one element from the beginning of vector and return it + + * \fn PIVector & PIVector::remove(uint index); + * \brief Remove one element by index "index" and return reference to vector + * \details Example: \snippet picontainers.cpp PIVector::remove_0 + * \sa \a removeOne(), \a removeAll() + + * \fn PIVector & PIVector::remove(uint index, uint count); + * \brief Remove "count" elements by first index "index" and return reference to vector + * \details Example: \snippet picontainers.cpp PIVector::remove_1 + * \sa \a removeOne(), \a removeAll() + + * \fn PIVector & PIVector::removeOne(const Type & v); + * \brief Remove no more than one element equal "v" and return reference to vector + * \details Example: \snippet picontainers.cpp PIVector::removeOne + * \sa \a remove(), \a removeAll() + + * \fn PIVector & PIVector::removeAll(const Type & v); + * \brief Remove all elements equal "v" and return reference to vector + * \details Example: \snippet picontainers.cpp PIVector::removeAll + * \sa \a remove(), \a removeOne() + + * \fn PIVector & PIVector::insert(uint pos, const Type & t); + * \brief Insert element "t" after index "pos" and return reference to vector + * \details Example: \snippet picontainers.cpp PIVector::insert_0 + + * \fn PIVector & PIVector::insert(uint pos, const PIVector & t); + * \brief Insert other vector "t" after index "pos" and return reference to vector + * \details Example: \snippet picontainers.cpp PIVector::insert_1 + + * \fn Type & PIVector::operator [](uint index); + * \brief Full access to element by index "index" + * \details Example: \snippet picontainers.cpp PIVector::() + * \sa \a at() + + * \fn const Type & PIVector::operator [](uint index) const; + * \brief Read-only access to element by index "index" + * \details Example: \snippet picontainers.cpp PIVector::()_c + * \sa \a at() + + * \fn PIVector & PIVector::operator <<(const Type & t); + * \brief Add new element "t" at the end of vector and return reference to vector + + * \fn PIVector & PIVector::operator <<(const PIVector & t); + * \brief Add vector "t" at the end of vector and return reference to vector + + * \fn bool PIVector::operator ==(const PIVector & t); + * \brief Compare with vector "t" + + * \fn bool PIVector::operator !=(const PIVector & t); + * \brief Compare with vector "t" + + * */ diff --git a/src/containers/picontainers.h b/src/containers/picontainers.h new file mode 100755 index 00000000..6be2bf61 --- /dev/null +++ b/src/containers/picontainers.h @@ -0,0 +1,286 @@ +/*! \file picontainers.h + * \brief Generic containers + * + * This file declare all containers and useful macros + * to use them +*/ +/* + PIP - Platform Independent Primitives + Generic containers + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PICONTAINERS_H +#define PICONTAINERS_H + +#include "picout.h" + +template +class PIP_EXPORT PIPair { +public: + PIPair() {first = Type0(); second = Type1();} + PIPair(const Type0 & value0, const Type1 & value1) {first = value0; second = value1;} + Type0 first; + Type1 second; +}; +template +inline bool operator <(const PIPair & value0, const PIPair & value1) {return value0.first < value1.first;} +template +inline bool operator ==(const PIPair & value0, const PIPair & value1) {return (value0.first == value1.first) && (value0.second == value1.second);} +template +inline bool operator !=(const PIPair & value0, const PIPair & value1) {return (value0.first != value1.first) || (value0.second != value1.second);} +template +inline std::ostream & operator <<(std::ostream & s, const PIPair & v) {s << "(" << v.first << ", " << v.second << ")"; return s;} +template +inline PICout operator <<(PICout s, const PIPair & v) {s.space(); s.setControl(0, true); s << "(" << v.first << ", " << v.second << ")"; s.restoreControl(); return s;} + +#include "pivector.h" +#include "pistack.h" +#include "piqueue.h" +#include "pideque.h" +#include "pimap.h" +#include "piset.h" + +#ifdef DOXYGEN + +/*!\brief Macro for iterate any container + * \details Use this macros instead of standard "for" + * to get read/write access to each element of container. + * Pass direction is direct \n + * Example: \snippet picontainers.cpp foreach + */ +# define piForeach(i,c) + +/*!\brief Macro for iterate any container only for read + * \details Use this macros instead of standard "for" + * to get read access to each element of container. + * Pass direction is direct \n + * Example: \snippet picontainers.cpp foreachC + */ +# define piForeachC(i,c) + +/*!\brief Macro for iterate any container with reverse direction + * \details Use this macros instead of standard "for" + * to get read/write access to each element of container. + * Pass direction is reverse \n + * Example: \snippet picontainers.cpp foreachR + */ +# define piForeachR(i,c) + +/*!\brief Macro for iterate any container only for read with reverse direction + * \details Use this macros instead of standard "for" + * to get read access to each element of container. + * Pass direction is reverse \n + * Example: \snippet picontainers.cpp foreachCR + */ +# define piForeachCR(i,c) + +/*!\brief Macro for break from any piForeach* loop + * \details \warning C++ ordinary "break" doesn`t work inside piForeach* + * loops! Always use "piBreak" instead! + */ +# define piBreak + +#else + +# define piBreak {_for._end = true; break;} + +# define piForTimes(c) for(int _i##c = 0; _i##c < c; ++_i##c) + +#ifdef CC_GCC + +template +class _PIForeach { +public: + _PIForeach(Type & t): _t(t), _break(false), _end(false) {_it = _t.begin();} + typename Type::value_type _var; + typename Type::iterator _it; + Type & _t; + bool _break, _end; + inline bool isEnd() {return _it == _t.end();} + inline void operator ++() {if (_end) _it = _t.end(); else _it++; _break = false;} +}; + +template +class _PIForeachR { +public: + _PIForeachR(Type & t): _t(t), _break(false), _end(false) {_rit = _t.rbegin();} + typename Type::value_type _var; + typename Type::reverse_iterator _rit; + Type & _t; + bool _break, _end; + inline bool isEnd() {return _rit == _t.rend();} + inline void operator ++() {if (_end) _rit = _t.rend(); else _rit++; _break = false;} +}; + +template +class _PIForeachC { +public: + _PIForeachC(const Type & t): _t(t), _break(false), _end(false) {_it = _t.begin();} + typename Type::value_type _var; + typename Type::const_iterator _it; + const Type & _t; + bool _break, _end; + inline bool isEnd() {return _it == _t.end();} + inline void operator ++() {if (_end) _it = _t.end(); else _it++; _break = false;} +}; + +template +class _PIForeachCR { +public: + _PIForeachCR(const Type & t): _t(t), _break(false), _end(false) {_rit = _t.rbegin();} + typename Type::value_type _var; + typename Type::const_reverse_iterator _rit; + const Type & _t; + bool _break, _end; + inline bool isEnd() {return _rit == _t.rend();} + inline void operator ++() {if (_end) _rit = _t.rend(); else _rit++; _break = false;} +}; + +#define piForeach(i,c) for(_PIForeach _for(c); !_for.isEnd(); ++_for) \ + for(i(*_for._it); !_for._break; _for._break = true) +#define piForeachR(i,c) for(_PIForeachR _for(c); !_for.isEnd(); ++_for) \ + for(i(*_for._rit); !_for._break; _for._break = true) +#define piForeachA(i,c) for(_PIForeach _for(c); !_for.isEnd(); ++_for) \ + for(typeof(_for._var) & i(*_for._it); !_for._break; _for._break = true) +#define piForeachAR(i,c) for(_PIForeachR _for(c); !_for.isEnd(); ++_for) \ + for(typeof(_for._var) & i(*_for._rit); !_for._break; _for._break = true) +#define piForeachC(i,c) for(_PIForeachC _for(c); !_for.isEnd(); ++_for) \ + for(const i(*_for._it); !_for._break; _for._break = true) +#define piForeachCR(i,c) for(_PIForeachCR _for(c); !_for.isEnd(); ++_for) \ + for(const i(*_for._rit); !_for._break; _for._break = true) +#define piForeachCA(i,c) for(_PIForeachC _for(c); !_for.isEnd(); ++_for) \ + for(const typeof(_for._var) & i(*_for._it); !_for._break; _for._break = true) +#define piForeachCAR(i,c) for(_PIForeachCR _for(c); !_for.isEnd(); ++_for) \ + for(const typeof(_for._var) & i(*_for._rit); !_for._break; _for._break = true) + +#define piForeachRA piForeachAR +#define piForeachAC piForeachCA +#define piForeachCRA piForeachCAR +#define piForeachARC piForeachCAR +#define piForeachACR piForeachCAR +#define piForeachRCA piForeachCAR +#define piForeachRAC piForeachCAR + +#else + +struct _PIForeachBase {mutable bool _break, _end;}; + +template +class _PIForeach: public _PIForeachBase { +public: + _PIForeach(Type & t, bool i = false): _break(false), _end(false), _t(t), _inv(i) {if (_inv) _rit = _t.rbegin(); else _it = _t.begin();} + mutable typename Type::value_type _var; + mutable typename Type::iterator _it; + mutable typename Type::reverse_iterator _rit; + Type & _t; + bool _inv; + bool isEnd() {if (_inv) return _rit == _t.rend(); else return _it == _t.end();} + void operator ++() {if (_inv) {if (_end) _rit = _t.rend(); else _rit++;} else {if (_end) _it = _t.end(); else _it++;} _break = false;} +}; + +template +class _PIForeachC: public _PIForeachBase { +public: + _PIForeachC(const Type & t, bool i = false): _break(false), _end(false), _t(t), _inv(i) {if (_inv) _rit = _t.rbegin(); else _it = _t.begin();} + mutable typename Type::value_type _var; + mutable typename Type::const_iterator _it; + mutable typename Type::const_reverse_iterator _rit; + const Type & _t; + bool _inv; + bool isEnd() {if (_inv) return _rit == _t.rend(); else return _it == _t.end();} + void operator ++() {if (_inv) {if (_end) _rit = _t.rend(); else _rit++;} else {if (_end) _it = _t.end(); else _it++;} _break = false;} +}; + +template inline _PIForeach _PIForeachNew(T & t, bool i = false) {return _PIForeach(t, i);} +template inline _PIForeach * _PIForeachCast(_PIForeachBase & c, T & ) {return static_cast<_PIForeach * >(&c);} + +template inline _PIForeachC _PIForeachNewC(const T & t, bool i = false) {return _PIForeachC(t, i);} +template inline _PIForeachC * _PIForeachCastC(_PIForeachBase & c, const T & ) {return static_cast<_PIForeachC * >(&c);} + +#define piForeach(i,c) for(_PIForeachBase & _for = _PIForeachNew(c); !_PIForeachCast(_for, c)->isEnd(); ++(*_PIForeachCast(_for, c))) \ + for(i = *(_PIForeachCast(_for, c)->_it); !_for._break; _for._break = true) +#define piForeachR(i,c) for(_PIForeachBase & _for = _PIForeachNew(c, true); !_PIForeachCast(_for, c)->isEnd(); ++(*_PIForeachCast(_for, c))) \ + for(i = *(_PIForeachCast(_for, c)->_rit); !_for._break; _for._break = true) +#define piForeachC(i,c) for(_PIForeachBase & _for = _PIForeachNewC(c); !_PIForeachCastC(_for, c)->isEnd(); ++(*_PIForeachCastC(_for, c))) \ + for(const i = *(_PIForeachCastC(_for, c)->_it); !_for._break; _for._break = true) +#define piForeachCR(i,c) for(_PIForeachBase & _for = _PIForeachNewC(c, false); !_PIForeachCastC(_for, c)->isEnd(); ++(*_PIForeachCastC(_for, c))) \ + for(const i = *(_PIForeachCastC(_for, c)->_rit); !_for._break; _for._break = true) + +#endif + +#define piForeachRC piForeachCR + +#endif // DOXYGEN + +template > +class PIP_EXPORT PIList: public list { + typedef PIList _CList; + typedef list _stlc; +public: + PIList() {piMonitor.containers++;} + PIList(const Type & value) {piMonitor.containers++; _stlc::resize(1, value);} + PIList(const Type & v0, const Type & v1) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1);} + PIList(const Type & v0, const Type & v1, const Type & v2) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2);} + PIList(const Type & v0, const Type & v1, const Type & v2, const Type & v3) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2); _stlc::push_back(v3);} + PIList(uint size, const Type & value = Type()) {piMonitor.containers++; _stlc::resize(size, value);} + ~PIList() {piMonitor.containers--;} + Type & operator [](uint index) {return (*this)[index];} + Type & operator [](uint index) const {return (*this)[index];} + const Type * data(uint index = 0) const {return &(*this)[index];} + Type * data(uint index = 0) {return &(*this)[index];} + int size_s() const {return static_cast(_stlc::size());} + bool isEmpty() const {return _stlc::empty();} + bool has(const Type & t) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) return true; return false;} + int etries(const Type & t) const {int ec = 0; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) ++ec; return ec;} + _CList & fill(const Type & t) {_stlc::assign(_stlc::size(), t); return *this;} + _CList & remove(uint index) {_stlc::erase(_stlc::begin() + index); return *this;} + _CList & remove(uint index, uint count) {_stlc::erase(_stlc::begin() + index, _stlc::begin() + index + count); return *this;} + _CList & insert(uint pos, const Type & t) {_stlc::insert(_stlc::begin() + pos, t); return *this;} + _CList & operator <<(const Type & t) {_stlc::push_back(t); return *this;} + PIVector toVector() const {PIVector v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;} +}; + + +#ifndef PIP_CONTAINERS_STL + +# define __PICONTAINERS_SIMPLE_TYPE__(T) \ +__PIDEQUE_SIMPLE_TYPE__(T)\ +__PIVECTOR_SIMPLE_TYPE__(T) + +__PICONTAINERS_SIMPLE_TYPE__(bool) +__PICONTAINERS_SIMPLE_TYPE__(char) +__PICONTAINERS_SIMPLE_TYPE__(uchar) +__PICONTAINERS_SIMPLE_TYPE__(short) +__PICONTAINERS_SIMPLE_TYPE__(ushort) +__PICONTAINERS_SIMPLE_TYPE__(int) +__PICONTAINERS_SIMPLE_TYPE__(uint) +__PICONTAINERS_SIMPLE_TYPE__(long) +__PICONTAINERS_SIMPLE_TYPE__(ulong) +__PICONTAINERS_SIMPLE_TYPE__(llong) +__PICONTAINERS_SIMPLE_TYPE__(ullong) +__PICONTAINERS_SIMPLE_TYPE__(float) +__PICONTAINERS_SIMPLE_TYPE__(double) +__PICONTAINERS_SIMPLE_TYPE__(ldouble) +__PICONTAINERS_SIMPLE_TYPE__(complexi) +__PICONTAINERS_SIMPLE_TYPE__(complexf) +__PICONTAINERS_SIMPLE_TYPE__(complexd) +__PICONTAINERS_SIMPLE_TYPE__(complexld) + +#endif + + +#endif // PICONTAINERS_H diff --git a/src/containers/pideque.h b/src/containers/pideque.h new file mode 100755 index 00000000..c92e112c --- /dev/null +++ b/src/containers/pideque.h @@ -0,0 +1,480 @@ +/*! \file pideque.h + * \brief Dynamic array of any type + * + * This file declares PIDeque +*/ +/* + PIP - Platform Independent Primitives + Dynamic array of any type + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIDEQUE_H +#define PIDEQUE_H + +#include "piincludes.h" + + +#if !defined(PIP_CONTAINERS_STL) || defined(DOXYGEN) + + +template +class PIDeque { +public: + PIDeque(): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { + //printf("new vector 1 %p (%s) ... !{\n", this, typeid(T).name()); + //printf("(s=%d, d=%p) }!\n", int(pid_size), pid_data); + } + PIDeque(const PIDeque & other): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { + //printf("new vector 2 %p (%s) ... !{\n", this, typeid(T).name()); + alloc(other.pid_size, true); + newT(pid_data + pid_start, other.pid_data + other.pid_start, pid_size); + //printf("(s=%d, d=%p) }!\n", int(pid_size), pid_data); + } + PIDeque(const T * data, size_t size): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { + //printf("new vector 2 %p (%s) ... !{\n", this, typeid(T).name()); + alloc(size, true); + newT(pid_data + pid_start, data, pid_size); + //printf("(s=%d, d=%p) }!\n", int(pid_size), pid_data); + } + PIDeque(size_t pid_size, const T & f = T()): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { + //printf("new vector 3 %p (%s) ... !{\n", this, typeid(T).name()); + resize(pid_size, f); + //printf("(s=%d, d=%p) }!\n", int(pid_size), pid_data); + } + ~PIDeque() { + //printf("delete deque %p (%s) (s=%d, rs=%d, st=%d, d=%p) ... ~{\n", this, typeid(T).name(), int(pid_size), int(pid_rsize), int(pid_start), pid_data); + deleteT(pid_data + pid_start, pid_size); + dealloc(); + //deleteRaw(pid_tdata); + _reset(); + //printf("}~\n"); + } + + PIDeque & operator =(const PIDeque & other) { + if (this == &other) return *this; + deleteT(pid_data + pid_start, pid_size); + alloc(other.pid_size, true); + newT(pid_data + pid_start, other.pid_data + other.pid_start, pid_size); + return *this; + } + + typedef T value_type; + + class iterator { + friend class PIDeque; + private: + iterator(PIDeque * v, size_t p): parent(v), pos(p) {} + PIDeque * parent; + size_t pos; + public: + iterator(): parent(0) {} + T & operator *() {return (*parent)[pos];} + const T & operator *() const {return (*parent)[pos];} + void operator ++() {++pos;} + void operator ++(int) {++pos;} + void operator --() {--pos;} + void operator --(int) {--pos;} + bool operator ==(const iterator & it) const {return (pos == it.pos);} + bool operator !=(const iterator & it) const {return (pos != it.pos);} + }; + + class const_iterator { + friend class PIDeque; + private: + const_iterator(const PIDeque * v, size_t p): parent(v), pos(p) {} + const PIDeque * parent; + size_t pos; + public: + const_iterator(): parent(0) {} + //T & operator *() {return (*parent)[pos];} + const T & operator *() const {return (*parent)[pos];} + void operator ++() {++pos;} + void operator ++(int) {++pos;} + void operator --() {--pos;} + void operator --(int) {--pos;} + bool operator ==(const const_iterator & it) const {return (pos == it.pos);} + bool operator !=(const const_iterator & it) const {return (pos != it.pos);} + }; + + class reverse_iterator { + friend class PIDeque; + private: + reverse_iterator(PIDeque * v, size_t p): parent(v), pos(p) {} + PIDeque * parent; + size_t pos; + public: + reverse_iterator(): parent(0) {} + T & operator *() {return (*parent)[pos];} + const T & operator *() const {return (*parent)[pos];} + void operator ++() {--pos;} + void operator ++(int) {--pos;} + void operator --() {++pos;} + void operator --(int) {++pos;} + bool operator ==(const reverse_iterator & it) const {return (pos == it.pos);} + bool operator !=(const reverse_iterator & it) const {return (pos != it.pos);} + }; + + class const_reverse_iterator { + friend class PIDeque; + private: + const_reverse_iterator(const PIDeque * v, size_t p): parent(v), pos(p) {} + const PIDeque * parent; + size_t pos; + public: + const_reverse_iterator(): parent(0) {} + //T & operator *() {return (*parent)[pos];} + const T & operator *() const {return (*parent)[pos];} + void operator ++() {--pos;} + void operator ++(int) {--pos;} + void operator --() {++pos;} + void operator --(int) {++pos;} + bool operator ==(const const_reverse_iterator & it) const {return (pos == it.pos);} + bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);} + }; + + iterator begin() {return iterator(this, 0);} + iterator end() {return iterator(this, pid_size);} + const_iterator begin() const {return const_iterator(this, 0);} + const_iterator end() const {return const_iterator(this, pid_size);} + reverse_iterator rbegin() {return reverse_iterator(this, pid_size - 1);} + reverse_iterator rend() {return reverse_iterator(this, -1);} + const_reverse_iterator rbegin() const {return const_reverse_iterator(this, pid_size - 1);} + const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);} + + size_t size() const {return pid_size;} + ssize_t size_s() const {return pid_size;} + size_t length() const {return pid_size;} + size_t capacity() const {return pid_rsize;} + bool isEmpty() const {return (pid_size == 0);} + + T & operator [](size_t index) {return pid_data[pid_start + index];} + T & at(size_t index) {return pid_data[pid_start + index];} + const T & operator [](size_t index) const {return pid_data[pid_start + index];} + const T & at(size_t index) const {return pid_data[pid_start + index];} + T & back() {return pid_data[pid_start + pid_size - 1];} + const T & back() const {return pid_data[pid_start + pid_size - 1];} + T & front() {return pid_data[pid_start];} + const T & front() const {return pid_data[pid_start];} + bool operator ==(const PIDeque & t) const {if (pid_size != t.pid_size) return false; for (size_t i = 0; i < pid_size; ++i) if (t[i] != (*this)[i]) return false; return true;} + bool operator !=(const PIDeque & t) const {if (pid_size != t.pid_size) return true; for (size_t i = 0; i < pid_size; ++i) if (t[i] != (*this)[i]) return true; return false;} + bool contains(const T & v) const {for (size_t i = pid_start; i < pid_start + pid_size; ++i) if (v == pid_data[i]) return true; return false;} + int etries(const T & v) const {int ec = 0; for (size_t i = pid_start; i < pid_start + pid_size; ++i) if (v == pid_data[i]) ++ec; return ec;} + + T * data(size_t index = 0) {return &(pid_data[pid_start + index]);} + const T * data(size_t index = 0) const {return &(pid_data[pid_start + index]);} + PIDeque & clear() {resize(0); return *this;} + PIDeque & fill(const T & f = T()) { + //if (sizeof(T) == 1) memset(pid_data, f, pid_size); + deleteT(pid_data + pid_start, pid_size); + //zeroRaw(pid_data, pid_size); + for (size_t i = pid_start; i < pid_start + pid_size; ++i) + elementNew(pid_data + i, f); + return *this; + } + PIDeque & assign(const T & f = T()) {return fill(f);} + PIDeque & assign(size_t new_size, const T & f) {resize(new_size); return fill(f);} + PIDeque & resize(size_t new_size, const T & f = T()) { + if (new_size < pid_size) { + deleteT(&(pid_data[new_size + pid_start]), pid_size - new_size); + pid_size = new_size; + } + if (new_size > pid_size) { + size_t os = pid_size; + alloc(new_size, true); + //if (sizeof(T) == 1) memset(&(pid_data[os]), f, ds); + //zeroRaw(&(pid_data[os]), new_size - os); + for (size_t i = os + pid_start; i < new_size + pid_start; ++i) elementNew(pid_data + i, f); + } + return *this; + } + PIDeque & reserve(size_t new_size) {if (new_size <= pid_rsize) return *this; size_t os = pid_size; alloc(new_size, true); pid_size = os; return *this;} + + PIDeque & insert(size_t index, const T & v = T()) { + bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false); + //piCout << "insert" << dir << index << pid_size << pid_rsize << pid_start << "!<"; + if (dir) { + alloc(pid_size + 1, true); + if (index < pid_size - 1) { + size_t os = pid_size - index - 1; + memmove(&(pid_data[index + pid_start + 1]), &(pid_data[index + pid_start]), os * sizeof(T)); + } + } else { + pid_start--; + alloc(pid_size + 1, false); + //piCout << "insert front" << pid_size << pid_rsize << pid_start << "!<"; + if (index > 0) + memmove(&(pid_data[pid_start]), &(pid_data[pid_start + 1]), index * sizeof(T)); + } + //piCout << "insert" << pid_start << index << (pid_start + ssize_t(index)) << pid_size << ">!"; + elementNew(pid_data + pid_start + index, v); + return *this; + } + PIDeque & insert(size_t index, const PIDeque & other) { + if (other.isEmpty()) return *this; + bool dir = pid_rsize <= 2 ? true : (index >= pid_rsize / 2 ? true : false); + //piCout << "insert" << dir << index << pid_size << pid_rsize << pid_start << "!<"; + if (dir) { + ssize_t os = pid_size - index; + alloc(pid_size + other.pid_size, true); + if (os > 0) + memmove(&(pid_data[index + pid_start + other.pid_size]), &(pid_data[index + pid_start]), os * sizeof(T)); + } else { + pid_start -= other.pid_size; + alloc(pid_size + other.pid_size, false); + //piCout << "insert front" << pid_size << pid_rsize << pid_start << "!<"; + if (index > 0) + memmove(&(pid_data[pid_start]), &(pid_data[pid_start + other.pid_size]), index * sizeof(T)); + } + //piCout << "insert" << pid_start << index << (pid_start + ssize_t(index)) << pid_size << ">!"; + newT(pid_data + pid_start + index, other.pid_data + other.pid_start, other.pid_size); + return *this; + } + + PIDeque & remove(size_t index, size_t count = 1) { + if (count == 0) return *this; + if (index + count >= pid_size) { + resize(index); + return *this; + } + size_t os = pid_size - index - count; + deleteT(&(pid_data[index + pid_start]), count); + if (os <= index) { + //if (true) { + if (os > 0) memmove(&(pid_data[index + pid_start]), &(pid_data[index + pid_start + count]), os * sizeof(T)); + } else { + if (index > 0) memmove(&(pid_data[pid_start + count]), &(pid_data[pid_start]), index * sizeof(T)); + pid_start += count; + } + pid_size -= count; + return *this; + } + + void swap(PIDeque & other) { + piSwap(pid_data, other.pid_data); + piSwap(pid_size, other.pid_size); + piSwap(pid_rsize, other.pid_rsize); + piSwap(pid_start, other.pid_start); + } + + typedef int (*CompareFunc)(const T * , const T * ); + static int compare_func(const T * t0, const T * t1) {return (*t0) < (*t1) ? -1 : ((*t0) == (*t1) ? 0 : 1);} + PIDeque & sort(CompareFunc compare = compare_func) {qsort(pid_data + pid_start, pid_size, sizeof(T), (int(*)(const void * , const void * ))compare); return *this;} + + PIDeque & enlarge(llong pid_size) {llong ns = size_s() + pid_size; if (ns <= 0) clear(); else resize(size_t(ns)); return *this;} + + PIDeque & removeOne(const T & v) {for (size_t i = 0; i < pid_size; ++i) if (pid_data[i + pid_start] == v) {remove(i); return *this;} return *this;} + PIDeque & removeAll(const T & v) {for (llong i = 0; i < pid_size; ++i) if (pid_data[i + pid_start] == v) {remove(i); --i;} return *this;} + + PIDeque & push_back(const T & v) {alloc(pid_size + 1, true); elementNew(pid_data + pid_start + pid_size - 1, v); return *this;} + PIDeque & append(const T & v) {return push_back(v);} + PIDeque & operator <<(const T & v) {return push_back(v);} + PIDeque & operator <<(const PIDeque & t) { + size_t ps = pid_size; + alloc(pid_size + t.pid_size, true); + newT(pid_data + ps + pid_start, t.pid_data + t.pid_start, t.pid_size); + return *this; + } + + PIDeque & push_front(const T & v) {insert(0, v); return *this;} + PIDeque & prepend(const T & v) {return push_front(v);} + + PIDeque & pop_back() {if (pid_size == 0) return *this; resize(pid_size - 1); return *this;} + PIDeque & pop_front() {if (pid_size == 0) return *this; remove(0); return *this;} + + T take_back() {T t(back()); pop_back(); return t;} + T take_front() {T t(front()); pop_front(); return t;} + + template + PIDeque toType() const {PIDeque ret(pid_size); for (uint i = 0; i < pid_size; ++i) ret[i] = ST(pid_data[i + pid_start]); return ret;} + +private: + void _reset() {pid_size = pid_rsize = pid_start = 0; pid_data = 0;} + /*void * qmemmove(void * dst, void * src, size_t size) { + if (piAbs(ssize_t(dst) - ssize_t(src)) >= size) + memcpy(dst, src, size); + else { + char * tb = new char[size]; + memcpy(tb, src, size); + memcpy(dst, tb, size); + delete tb; + } + return dst; + }*/ + inline size_t asize(ssize_t s) { + if (s <= 0) return 0; + if (pid_rsize + pid_rsize >= size_t(s) && pid_rsize < size_t(s)) + return pid_rsize + pid_rsize; + size_t t = 0, s_ = size_t(s) - 1; + while (s_ >> t) ++t; + return (1 << t); + } + inline void newT(T * dst, const T * src, size_t s) { + for (size_t i = 0; i < s; ++i) + elementNew(dst + i, src[i]); + } + inline T * newRaw(size_t s) { + //cout << std::dec << " ![("< (new 0x" << (llong)ret << ") ok]!" << endl; + return (T*)ret; + } + /*void reallocRawTemp(size_t s) { + if (pid_tdata == 0) pid_tdata = (T*)(malloc(s * sizeof(T))); + else pid_tdata = (T*)(realloc(pid_tdata, s * sizeof(T))); + }*/ + inline void deleteT(T * d, size_t sz) { + //cout << " ~[("< ok]~" << endl; + } + inline void deleteRaw(T *& d) { + //cout << " ~[("< ok]~" << endl; + } + void zeroRaw(T * d, size_t s) { + //cout << " ~[("< ok]~" << endl; + } + inline void elementNew(T * to, const T & from) {new(to)T(from);} + inline void elementDelete(T & from) {from.~T();} + void dealloc() {deleteRaw(pid_data);} + inline void checkMove(bool direction) { + if (pid_size >= 4 && pid_size < pid_rsize / 4) { + /*if (direction) { + if (pid_start >= 4 && pid_start > pid_size + pid_size && pid_start > pid_rsize / 2) { + piCout << (int)this << "checkMove" << direction << pid_start << (int)pid_data << pid_rsize << pid_size; + piCout << (int)this << "move from" << pid_start << "to" << pid_size << "," << (int)pid_data << pid_rsize << pid_size; + memmove(pid_data + pid_size, pid_data + pid_start, pid_size * sizeof(T)); + pid_start = pid_size; + } + } else { + if (ssize_t(pid_start) < ssize_t(pid_rsize) - pid_size - pid_size && ssize_t(pid_start) < ssize_t(pid_rsize / 2) - pid_size) { + piCout << (int)this << "checkMove" << direction << pid_start << (int)pid_data << pid_rsize << pid_size; + piCout << (int)this << "move from" << pid_start << "to" << (ssize_t(pid_rsize) - pid_size) << "," << (int)pid_data << pid_rsize << pid_size; + memmove(pid_data + ssize_t(pid_rsize) - pid_size - pid_size, pid_data + pid_start, pid_size * sizeof(T)); + pid_start = ssize_t(pid_rsize) - pid_size - pid_size; + } + }*/ + if (pid_start < pid_size + pid_size || pid_start > pid_rsize - pid_size - pid_size) { + size_t ns = (pid_rsize - pid_size) / 2; + if (pid_start != ns) { + memmove(pid_data + ns, pid_data + pid_start, pid_size * sizeof(T)); + pid_start = ns; + } + } + } + } + inline void alloc(size_t new_size, bool direction) { // direction == true -> alloc forward + if (direction) { + if (pid_start + new_size <= pid_rsize) { + pid_size = new_size; + checkMove(direction); + return; + } + pid_size = new_size; + size_t as = asize(pid_start + new_size); + if (as != pid_rsize) { + pid_data = (T*)(realloc(pid_data, as*sizeof(T))); + pid_rsize = as; + } + } else { + size_t as = asize(piMax(new_size, pid_rsize) - pid_start); + //piCout << "alloc" << new_size << pid_size << pid_rsize << as << pid_start; + if (pid_start >= 0 && as <= pid_rsize) { + pid_size = new_size; + checkMove(direction); + return; + } + size_t os = pid_size; + pid_size = new_size; + if (as > pid_rsize) { + //piCout << "alloc new size" << as; + //cout << std::hex << " ![("< 0 && pid_data != 0) { + memcpy(td + pid_start + ns, pid_data + ost, os * sizeof(T)); + deleteRaw(pid_data); + } + pid_data = td; + pid_rsize = as; + } + } + //checkMove(direction); + //piCout << "alloc new start" << pid_start; + } + + T * pid_data; + volatile size_t pid_size, pid_rsize; + volatile size_t pid_start; +}; + +#define __PIDEQUE_SIMPLE_TYPE__(T) \ + template<> inline void PIDeque::newT(T * dst, const T * src, size_t s) {memcpy(dst, src, s * sizeof(T));} \ + template<> inline void PIDeque::deleteT(T * d, size_t sz) {;} \ + template<> inline void PIDeque::elementNew(T * to, const T & from) {(*to) = from;} \ + template<> inline void PIDeque::elementDelete(T & from) {;} + +#else + + +template > +class PIP_EXPORT PIDeque: public deque { + typedef PIDeque _CDeque; + typedef deque _stlc; +public: + PIDeque() {piMonitor.containers++;} + PIDeque(const Type & value) {piMonitor.containers++; _stlc::resize(1, value);} + PIDeque(const Type & v0, const Type & v1) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1);} + PIDeque(const Type & v0, const Type & v1, const Type & v2) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2);} + PIDeque(const Type & v0, const Type & v1, const Type & v2, const Type & v3) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2); _stlc::push_back(v3);} + ~PIDeque() {piMonitor.containers--;} + int size_s() const {return static_cast(_stlc::size());} + bool isEmpty() const {return _stlc::empty();} + bool has(const Type & t) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) return true; return false;} + int etries(const Type & t) const {int ec = 0; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) ++ec; return ec;} + _CDeque & operator <<(const Type & t) {_CDeque::push_back(t); return *this;} + PIDeque toVector() {PIDeque v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;} +}; + + +#define __PIDEQUE_SIMPLE_FUNCTIONS__(T) + + +#endif + + +template +inline std::ostream & operator <<(std::ostream & s, const PIDeque & v) {s << "{"; for (size_t i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << "}"; return s;} + +template +inline PICout operator <<(PICout s, const PIDeque & v) {s.space(); s.setControl(0, true); s << "{"; for (size_t i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << "}"; s.restoreControl(); return s;} + + +#endif // PIDEQUE_H diff --git a/src/containers/pimap.h b/src/containers/pimap.h new file mode 100644 index 00000000..c3c0a739 --- /dev/null +++ b/src/containers/pimap.h @@ -0,0 +1,453 @@ +/*! \file pimap.h + * \brief Associative array with custom types of key and value + * + * This file declares PIMap +*/ +/* + PIP - Platform Independent Primitives + Dynamic array of any type + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIMAP_H +#define PIMAP_H + +#include "pivector.h" +#include "pideque.h" + + +#if !defined(PIP_CONTAINERS_STL) || defined(DOXYGEN) + +template +void piQuickSort(T * a, ssize_t N) { + if (N < 1) return; + ssize_t i = 0, j = N; + T & p(a[N >> 1]); + do { + while (a[i] < p) i++; + while (a[j] > p) j--; + if (i <= j) { + if (i != j) { + //piCout << "swap" << i << j << a[i] << a[j]; + piSwapBinary(a[i], a[j]); + } + i++; j--; + } + } while (i <= j); + if (j > 0) piQuickSort(a, j); + if (N > i) piQuickSort(a + i, N - i); +} + +template +class PIMap { +public: + PIMap() {;} + PIMap(const PIMap & other) {*this = other;} + ~PIMap() {;} + + PIMap & operator =(const PIMap & other) { + if (this == &other) return *this; + clear(); + pim_content = other.pim_content; + pim_index = other.pim_index; + return *this; + } + + typedef T mapped_type; + typedef Key key_type; + typedef PIPair value_type; + + class iterator { + friend class PIMap; + private: + iterator(const PIMap * v, ssize_t p): parent(v), pos(p) {} + const PIMap * parent; + ssize_t pos; + public: + iterator(): parent(0) {} + const Key & key() const {return const_cast * >(parent)->_key(pos);} + T & value() const {return const_cast * >(parent)->_value(pos);} + void operator ++() {++pos;} + void operator ++(int) {++pos;} + void operator --() {--pos;} + void operator --(int) {--pos;} + bool operator ==(const iterator & it) const {return (pos == it.pos);} + bool operator !=(const iterator & it) const {return (pos != it.pos);} + }; + + class reverse_iterator { + friend class PIMap; + private: + reverse_iterator(const PIMap * v, ssize_t p): parent(v), pos(p) {} + const PIMap * parent; + ssize_t pos; + public: + reverse_iterator(): parent(0) {} + const Key & key() const {return const_cast * >(parent)->_key(pos);} + T & value() const {return const_cast * >(parent)->_value(pos);} + void operator ++() {--pos;} + void operator ++(int) {--pos;} + void operator --() {++pos;} + void operator --(int) {++pos;} + bool operator ==(const reverse_iterator & it) const {return (pos == it.pos);} + bool operator !=(const reverse_iterator & it) const {return (pos != it.pos);} + }; + + class const_iterator { + friend class PIMap; + private: + const_iterator(const PIMap * v, ssize_t p): parent(v), pos(p) {} + const PIMap * parent; + ssize_t pos; + public: + const_iterator(): parent(0) {} + const PIMap::value_type operator *() const {return parent->_pair(pos);} + const PIMap::value_type* operator ->() const {cval = parent->_pair(pos); return &cval;} + void operator ++() {++pos;} + void operator ++(int) {++pos;} + void operator --() {--pos;} + void operator --(int) {--pos;} + bool operator ==(const const_iterator & it) const {return (pos == it.pos);} + bool operator !=(const const_iterator & it) const {return (pos != it.pos);} + mutable value_type cval; + }; + + class const_reverse_iterator { + friend class PIMap; + private: + const_reverse_iterator(const PIMap * v, ssize_t p): parent(v), pos(p) {} + const PIMap * parent; + ssize_t pos; + public: + const_reverse_iterator(): parent(0) {} + const PIMap::value_type operator *() const {return parent->_pair(pos);} + const PIMap::value_type* operator ->() const {cval = parent->_pair(pos); return &cval;} + void operator ++() {--pos;} + void operator ++(int) {--pos;} + void operator --() {++pos;} + void operator --(int) {++pos;} + bool operator ==(const const_reverse_iterator & it) const {return (pos == it.pos);} + bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);} + mutable value_type cval; + }; + + iterator begin() {return iterator(this, 0);} + iterator end() {return iterator(this, size());} + const_iterator begin() const {return const_iterator(this, 0);} + const_iterator end() const {return const_iterator(this, size());} + reverse_iterator rbegin() {return reverse_iterator(this, size() - 1);} + reverse_iterator rend() {return reverse_iterator(this, -1);} + const_reverse_iterator rbegin() const {return const_reverse_iterator(this, size() - 1);} + const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);} + + size_t size() const {return pim_content.size();} + int size_s() const {return pim_content.size_s();} + size_t length() const {return pim_content.size();} + bool isEmpty() const {return (pim_content.size() == 0);} + + T & operator [](const Key & key) { + bool f(false); + ssize_t i = _find(key, f); + if (f) return pim_content[pim_index[i].index]; + pim_content.push_back(T()); + pim_index.insert(i, MapIndex(key, pim_content.size() - 1)); + return pim_content.back(); + } + const T operator [](const Key & key) const {bool f(false); ssize_t i = _find(key, f); if (f) return pim_content[pim_index[i].index]; return T();} + T & at(const Key & key) {return (*this)[key];} + const T at(const Key & key) const {return (*this)[key];} + + PIMap & operator <<(const PIMap & other) { + if (other.isEmpty()) return *this; + if (other.size() == 1) {insert(other.pim_index[0].key, other.pim_content[0]); return *this;} + if (other.size() == 2) {insert(other.pim_index[0].key, other.pim_content[0]); insert(other.pim_index[1].key, other.pim_content[1]); return *this;} + pim_content << other.pim_content; + size_t si = pim_index.size(); + for (int i = 0; i < other.pim_index.size_s(); ++i) + pim_index << MapIndex(other.pim_index[i].key, other.pim_index[i].index + si); + _sort(); + return *this; + } + + bool operator ==(const PIMap & t) const {return (pim_content == t.pim_content && pim_index == t.pim_index);} + bool operator !=(const PIMap & t) const {return (pim_content != t.pim_content || pim_index != t.pim_index);} + bool contains(const Key & key) const {bool f(false); _find(key, f); return f;} + //int etries(const T & v) const {int ec = 0; for (size_t i = 0; i < pim_size; ++i) if (v == pim_data[i]) ++ec; return ec;} + + PIMap & reserve(size_t new_size) {pim_content.reserve(new_size); pim_index.reserve(new_size); return *this;} + + //PIMap & removeAll(const T & v) {for (llong i = 0; i < pim_size; ++i) if (pim_data[i] == v) {remove(i); --i;} return *this;} + PIMap & removeOne(const Key & key) {bool f(false); ssize_t i = _find(key, f); if (f) _remove(i); return *this;} + PIMap & remove(const Key & key) {return removeOne(key);} + PIMap & erase(const Key & key) {return removeOne(key);} + PIMap & clear() {pim_content.clear(); pim_index.clear(); return *this;} + + void swap(PIMap & other) { + piSwapBinary >(pim_content, other.pim_content); + piSwapBinary >(pim_index, other.pim_index); + } + + PIMap & insert(const Key & key, const T & value) { + //MapIndex * i = _find(key); + bool f(false); + ssize_t i = _find(key, f); + //piCout << "insert key=" << key << "found=" << f << "index=" << i << "value=" << value; + if (f) { + pim_content[pim_index[i].index] = value; + } else { + pim_content.push_back(value); + pim_index.insert(i, MapIndex(key, pim_content.size() - 1)); + //_sort(); + } + return *this; + } + //const T value(const Key & key, const T & default_ = T()) const {MapIndex * i = _find(key); if (i == 0) return default_; return pim_content[i->index];} + const T value(const Key & key, const T & default_ = T()) const {bool f(false); ssize_t i = _find(key, f); if (!f) return default_; return pim_content[pim_index[i].index];} + PIVector values() const {return pim_content;} + Key key(const T & value_, const Key & default_ = Key()) const {for (int i = 0; i < pim_index.size_s(); ++i) if (pim_content[pim_index[i].index] == value_) return pim_index[i].key; return default_;} + PIVector keys() const { + PIVector ret; + for (int i = 0; i < pim_index.size_s(); ++i) + ret << pim_index[i].key; + return ret; + } + + void dump() { + piCout << "PIMap" << size() << "entries" << NewLine << "content:"; + for (size_t i = 0; i < pim_content.size(); ++i) + piCout << Tab << i << ":" << pim_content[i]; + piCout << "index:"; + for (size_t i = 0; i < pim_index.size(); ++i) + piCout << Tab << i << ":" << pim_index[i].key << "->" << pim_index[i].index; + } + +protected: + struct MapIndex { + MapIndex(Key k = Key(), size_t i = 0): key(k), index(i) {;} + Key key; + size_t index; + bool operator ==(const MapIndex & s) const {return key == s.key;} + bool operator !=(const MapIndex & s) const {return key != s.key;} + bool operator <(const MapIndex & s) const {return key < s.key;} + bool operator >(const MapIndex & s) const {return key > s.key;} + }; + + ssize_t binarySearch(ssize_t first, ssize_t last, const Key & key, bool & found) const { + ssize_t mid; + while (first <= last) { + mid = (first + last) / 2; + if (key > pim_index[mid].key) first = mid + 1; + else if (key < pim_index[mid].key) last = mid - 1; + else {found = true; return mid;} + } + found = false; + return first; + } + void _sort() {piQuickSort(pim_index.data(), pim_index.size_s() - 1);} + ssize_t _find(const Key & k, bool & found) const { + /*for (size_t i = 0; i < pim_index.size(); ++i) + if (pim_index[i].key == k) { + return (MapIndex * )&(pim_index[i]); + } + return 0;*/ + //piCout << "find for" << k << pim_index.size_s(); + if (pim_index.isEmpty()) { + found = false; + return 0; + } + //piCout << k << ret << found; + return binarySearch(0, pim_index.size_s() - 1, k, found); + } + void _remove(ssize_t index) { + //if (index >= pim_index.size()) return; + size_t ci = pim_index[index].index, bi = pim_index.size() - 1; + pim_index.remove(index); + for (size_t i = 0; i < pim_index.size(); ++i) + if (pim_index[i].index == bi) { + pim_index[i].index = ci; + break; + } + piSwapBinary(pim_content[ci], pim_content.back()); + pim_content.resize(pim_index.size()); + } + const value_type _pair(ssize_t index) const { + if (index < 0 || index >= pim_index.size_s()) + return value_type(); + //piCout << "_pair" << index << pim_index[index].index; + return value_type(pim_index[index].key, pim_content[pim_index[index].index]); + } + Key & _key(ssize_t index) {return pim_index[index].key;} + T & _value(ssize_t index) {return pim_content[pim_index[index].index];} + + PIVector pim_content; + PIDeque pim_index; +}; +//template bool operator <(const typename PIMap::MapIndex & f, const typename PIMap::MapIndex & s) {return f.key < s.key;} +//template bool operator >(const typename PIMap::MapIndex & f, const typename PIMap::MapIndex & s) {return f.key > s.key;} + + +/*#define __PIMAP_SIMPLE_FUNCTIONS__(T) + template<> inline PIMap::~PIMap() {dealloc(); _reset();} \ + template<> inline PIMap & PIMap::push_back(const T & v) {alloc(pim_size + 1); pim_data[pim_size - 1] = v; return *this;} \ + template<> inline PIMap & PIMap::fill(const T & f) { \ + for (size_t i = 0; i < pim_size; ++i) \ + pim_data[i] = f; \ + return *this; \ + } \ + template<> inline PIMap & PIMap::resize(size_t new_size, const T & f) { \ + if (new_size < pim_size) \ + pim_size = new_size; \ + if (new_size > pim_size) { \ + size_t os = pim_size; \ + alloc(new_size); \ + for (size_t i = os; i < new_size; ++i) pim_data[i] = f; \ + } \ + return *this; \ + } \ + template<> inline PIMap & PIMap::insert(size_t index, const T & v) { \ + alloc(pim_size + 1); \ + if (index < pim_size - 1) { \ + size_t os = pim_size - index - 1; \ + memmove(&(pim_data[index + 1]), &(pim_data[index]), os * sizeof(T)); \ + } \ + pim_data[index] = v; \ + return *this; \ + } \ + template<> inline PIMap & PIMap::remove(size_t index, size_t count) { \ + if (index + count >= pim_size) { \ + resize(index); \ + return *this; \ + } \ + size_t os = pim_size - index - count; \ + memmove(&(pim_data[index]), &(pim_data[index + count]), os * sizeof(T)); \ + pim_size -= count; \ + return *this; \ + } + +__PIMAP_SIMPLE_FUNCTIONS__(char) +__PIMAP_SIMPLE_FUNCTIONS__(uchar) +__PIMAP_SIMPLE_FUNCTIONS__(short) +__PIMAP_SIMPLE_FUNCTIONS__(ushort) +__PIMAP_SIMPLE_FUNCTIONS__(int) +__PIMAP_SIMPLE_FUNCTIONS__(uint) +__PIMAP_SIMPLE_FUNCTIONS__(long) +__PIMAP_SIMPLE_FUNCTIONS__(ulong) +__PIMAP_SIMPLE_FUNCTIONS__(llong) +__PIMAP_SIMPLE_FUNCTIONS__(ullong) +__PIMAP_SIMPLE_FUNCTIONS__(float) +__PIMAP_SIMPLE_FUNCTIONS__(double) +__PIMAP_SIMPLE_FUNCTIONS__(ldouble)*/ + +#else + + +template +class PIP_EXPORT PIMap: public map { + typedef PIMap _CMap; + typedef map _stlc; + typedef std::pair _stlpair; +public: + PIMap() {;} + PIMap(const Key & key_, const Type & value_) {insert(key_, value_);} + bool isEmpty() const {return _stlc::empty();} + bool contains(const Key & key_) const {return _stlc::count(key_) > 0;} + int size_s() const {return static_cast(_stlc::size());} + _CMap & insert(const Key & key_, const Type & value_) {_stlc::insert(_stlpair(key_, value_)); return *this;} + _CMap & insert(PIPair entry_) {_stlc::insert(_stlpair(entry_.first, entry_.second)); return *this;} + Key key(Type value_, const Key & default_ = Key()) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++) if (i->second == value_) return i->first; return default_;} + PIVector keys() const { + PIVector ret; + for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++) + ret << i->first; + return ret; + } + Type & at(const Key & key_) {return _stlc::find(key_)->second;} + Type value(const Key & key_) const {typename _stlc::const_iterator it = _stlc::find(key_); if (it != _stlc::end()) return it->second; return Type();} +}; + + +template +class PIP_EXPORT PIMultiMap: public multimap { + typedef PIMultiMap _CMultiMap; + typedef multimap _stlc; + typedef std::pair _stlpair; +public: + PIMultiMap() {;} + PIMultiMap(const Key & key_, const Type & value_) {insert(key_, value_);} + _CMultiMap & insert(const Key & key_, const Type & value_) {_stlc::insert(_stlpair(key_, value_)); return *this;} + _CMultiMap & insert(PIPair entry_) {_stlc::insert(_stlpair(entry_.first, entry_.second)); return *this;} + bool isEmpty() const {return _stlc::empty();} + bool contains(const Key & key_) const {return _stlc::count(key_) > 0;} + Key key(Type value_, const Key & default_ = Key()) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++) if (i->second == value_) return i->first; return default_;} + PIVector keys(Type value_) const { + PIVector ret; + for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++) + if (i->second == value_) + ret << i->first; + return ret; + } + Type & value(const Key & key_) {typename _stlc::iterator i = _stlc::find(key_); if (i == _stlc::end()) return Type(); return i->second;} + Type value(const Key & key_) const {typename _stlc::const_iterator i = _stlc::find(key_); if (i == _stlc::end()) return Type(); return i->second;} + PIVector values(const Key & key_) const { + std::pair range = _stlc::equal_range(key_); + PIVector ret; + for (typename _stlc::const_iterator i = range.first; i != range.second; ++i) + ret << i->second; + return ret; + } + Type & operator [](const Key & key_) {if (!contains(key_)) return _stlc::insert(_stlpair(key_, Type()))->second; return _stlc::find(key_)->second;} + Type operator [](const Key & key_) const {return _stlc::find(key_)->second;} +}; + +#define __PIMAP_SIMPLE_FUNCTIONS__(T) + + +#endif + + +template +inline std::ostream & operator <<(std::ostream & s, const PIMap & v) { + s << "{"; + bool first = true; + for (typename PIMap::const_iterator i = v.begin(); i != v.end(); i++) { + if (!first) + s << ", "; + first = false; + s << i->first << ": " << i->second; + } + s << "}"; + return s; +} + +template +inline PICout operator <<(PICout s, const PIMap & v) { + s.space(); + s.setControl(0, true); + s << "{"; + bool first = true; + for (typename PIMap::const_iterator i = v.begin(); i != v.end(); i++) { + if (!first) + s << ", "; + first = false; + s << i->first << ": " << i->second; + } + s << "}"; + s.restoreControl(); + return s; +} + + +#endif // PIMAP_H diff --git a/src/containers/piqueue.h b/src/containers/piqueue.h new file mode 100755 index 00000000..23f808ea --- /dev/null +++ b/src/containers/piqueue.h @@ -0,0 +1,41 @@ +/*! \file picontainers.h + * \brief Queue container + * + * This file declare PIQueue +*/ +/* + PIP - Platform Independent Primitives + Queue container + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIQUEUE_H +#define PIQUEUE_H + +#include "pivector.h" + +template +class PIP_EXPORT PIQueue: public PIVector { +public: + PIQueue() {;} + PIVector & enqueue(const T & v) {PIVector::push_front(v); return *this;} + T dequeue() {return PIVector::take_back();} + T & head() {return PIVector::back();} + const T & head() const {return PIVector::back();} + PIVector toVector() {PIVector v(PIVector::size()); for (uint i = 0; i < PIVector::size(); ++i) v[i] = PIVector::at(i); return v;} +}; + +#endif // PIQUEUE_H diff --git a/src/containers/piset.h b/src/containers/piset.h new file mode 100644 index 00000000..80e4231b --- /dev/null +++ b/src/containers/piset.h @@ -0,0 +1,72 @@ +/*! \file piset.h + * \brief Set container + * + * This file declare PISet +*/ +/* + PIP - Platform Independent Primitives + Set container + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PISET_H +#define PISET_H + +#include "pimap.h" + +/*! \brief Set of any type + * \details This class used to store collection of unique elements + * of any type. You can only add values to set with \a operator<< or + * with function \a insert(). You can discover if value already in + * set with \a operator[] or with function \a find(). These function + * has logarithmic complexity. + */ +template +class PIP_EXPORT PISet: public PIMap { + typedef PIMap _CSet; +public: + + //! Contructs an empty set + PISet() {} + + //! Contructs set with one element "value" + PISet(const T & value) {_CSet::insert(value, 0);} + + //! Contructs set with elements "v0" and "v1" + PISet(const T & v0, const T & v1) {_CSet::insert(v0, 0); _CSet::insert(v1, 0);} + + //! Contructs set with elements "v0", "v1" and "v2" + PISet(const T & v0, const T & v1, const T & v2) {_CSet::insert(v0, 0); _CSet::insert(v1, 0); _CSet::insert(v2, 0);} + + //! Contructs set with elements "v0", "v1", "v2" and "v3" + PISet(const T & v0, const T & v1, const T & v2, const T & v3) {_CSet::insert(v0, 0); _CSet::insert(v1, 0); _CSet::insert(v2, 0); _CSet::insert(v3, 0);} + + typedef T key_type; + + PISet & operator <<(const T & t) {_CSet::insert(t, 0); return *this;} + PISet & operator <<(const PISet & other) {(*(_CSet*)this) << *((_CSet*)&other); return *this;} + + //! Returns if element "t" exists in this set + bool operator [](const T & t) const {return _CSet::contains(t);} + + //! Returns if element "t" exists in this set + PISet & remove(const T & t) {_CSet::remove(t); return *this;} + + //! Returns content of set as PIVector + PIVector toVector() const {PIVector ret; for (typename _CSet::const_iterator i = _CSet::begin(); i != _CSet::end(); ++i) ret << (*i).first; return ret;} +}; + +#endif // PISET_H diff --git a/src/containers/pistack.h b/src/containers/pistack.h new file mode 100755 index 00000000..154ac377 --- /dev/null +++ b/src/containers/pistack.h @@ -0,0 +1,41 @@ +/*! \file pistack.h + * \brief Stack container + * + * This file declare PIStack +*/ +/* + PIP - Platform Independent Primitives + Stack container + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PISTACK_H +#define PISTACK_H + +#include "pivector.h" + +template +class PIP_EXPORT PIStack: public PIVector { +public: + PIStack() {;} + PIVector & push(const T & v) {PIVector::push_back(v); return *this;} + T pop() {return PIVector::take_back();} + T & top() {return PIVector::back();} + const T & top() const {return PIVector::back();} + PIVector toVector() {PIVector v(PIVector::size()); for (uint i = 0; i < PIVector::size(); ++i) v[i] = PIVector::at(i); return v;} +}; + +#endif // PISTACK_H diff --git a/src/containers/pivector.h b/src/containers/pivector.h new file mode 100755 index 00000000..b1fc7c2c --- /dev/null +++ b/src/containers/pivector.h @@ -0,0 +1,530 @@ +/*! \file pivector.h + * \brief Dynamic array of any type + * + * This file declares PIVector +*/ +/* + PIP - Platform Independent Primitives + Dynamic array of any type + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIVECTOR_H +#define PIVECTOR_H + +#include "piincludes.h" + + +#if !defined(PIP_CONTAINERS_STL) || defined(DOXYGEN) + + +template +class PIVector { +public: + PIVector(): piv_data(0), piv_size(0), piv_rsize(0) { + //printf("new vector 1 %p (%s) ... !{\n", this, typeid(T).name()); + //printf("(s=%d, d=%p) }!\n", int(piv_size), piv_data); + } + PIVector(const T * data, size_t size): piv_data(0), piv_size(0), piv_rsize(0) { + //printf("new vector 2 %p (%s) ... !{\n", this, typeid(T).name()); + alloc(size); + newT(piv_data, data, piv_size); + //printf("(s=%d, d=%p) }!\n", int(pid_size), pid_data); + } + PIVector(const PIVector & other): piv_data(0), piv_size(0), piv_rsize(0) { + //printf("new vector 2 %p (%s) ... !{\n", this, typeid(T).name()); + alloc(other.piv_size); + newT(piv_data, other.piv_data, piv_size); + //printf("(s=%d, d=%p) }!\n", int(piv_size), piv_data); + } + PIVector(size_t piv_size, const T & f = T()): piv_data(0), piv_size(0), piv_rsize(0) { + //printf("new vector 3 %p (%s) ... !{\n", this, typeid(T).name()); + resize(piv_size, f); + //printf("(s=%d, d=%p) }!\n", int(piv_size), piv_data); + } + ~PIVector() { + //printf("delete vector %p (%s) (s=%d, d=%p) ... ~{\n", this, typeid(T).name(), int(piv_size), piv_data); + deleteT(piv_data, piv_size); + dealloc(); + //deleteRaw(piv_tdata); + _reset(); + //printf("}~\n"); + } + + PIVector & operator =(const PIVector & other) { + if (this == &other) return *this; + bool tj, oj; + tj = (piv_size != 0 && piv_data == 0);// || (piv_size == 0 && piv_data != 0); + oj = (other.piv_size != 0 && other.piv_data == 0);// || (other.piv_size == 0 && other.piv_data != 0); + //printf("operator= (%p = %p) (s=%d, d=%p, o.s=%d, o.d=%p) (%d, %d) ... o[\n", this, &other, int(piv_size), piv_data, int(other.piv_size), other.piv_data, int(tj), int(oj)); + if (tj) { + printf("JUNK this\n"); + _reset(); + } else { + clear(); + } + /*if (piv_size == other.piv_size) { + for (size_t i = 0; i < piv_size; ++i) + piv_data[i] = other.piv_data[i]; + return *this; + }*/ + if (!oj) { + deleteT(piv_data, piv_size); + alloc(other.piv_size); + //zeroRaw(piv_data, piv_size); + for (size_t i = 0; i < piv_size; ++i) + elementNew(piv_data + i, other.piv_data[i]); //piv_data[i] = other.piv_data[i]; + } else { + printf("JUNK other\n"); + } + //printf("o]\n"); + return *this; + } + + typedef T value_type; + + class iterator { + friend class PIVector; + private: + iterator(PIVector * v, size_t p): parent(v), pos(p) {} + PIVector * parent; + size_t pos; + public: + iterator(): parent(0) {} + T & operator *() {return (*parent)[pos];} + const T & operator *() const {return (*parent)[pos];} + void operator ++() {++pos;} + void operator ++(int) {++pos;} + void operator --() {--pos;} + void operator --(int) {--pos;} + bool operator ==(const iterator & it) const {return (pos == it.pos);} + bool operator !=(const iterator & it) const {return (pos != it.pos);} + }; + + class const_iterator { + friend class PIVector; + private: + const_iterator(const PIVector * v, size_t p): parent(v), pos(p) {} + const PIVector * parent; + size_t pos; + public: + const_iterator(): parent(0) {} + //T & operator *() {return (*parent)[pos];} + const T & operator *() const {return (*parent)[pos];} + void operator ++() {++pos;} + void operator ++(int) {++pos;} + void operator --() {--pos;} + void operator --(int) {--pos;} + bool operator ==(const const_iterator & it) const {return (pos == it.pos);} + bool operator !=(const const_iterator & it) const {return (pos != it.pos);} + }; + + class reverse_iterator { + friend class PIVector; + private: + reverse_iterator(PIVector * v, size_t p): parent(v), pos(p) {} + PIVector * parent; + size_t pos; + public: + reverse_iterator(): parent(0) {} + T & operator *() {return (*parent)[pos];} + const T & operator *() const {return (*parent)[pos];} + void operator ++() {--pos;} + void operator ++(int) {--pos;} + void operator --() {++pos;} + void operator --(int) {++pos;} + bool operator ==(const reverse_iterator & it) const {return (pos == it.pos);} + bool operator !=(const reverse_iterator & it) const {return (pos != it.pos);} + }; + + class const_reverse_iterator { + friend class PIVector; + private: + const_reverse_iterator(const PIVector * v, size_t p): parent(v), pos(p) {} + const PIVector * parent; + size_t pos; + public: + const_reverse_iterator(): parent(0) {} + //T & operator *() {return (*parent)[pos];} + const T & operator *() const {return (*parent)[pos];} + void operator ++() {--pos;} + void operator ++(int) {--pos;} + void operator --() {++pos;} + void operator --(int) {++pos;} + bool operator ==(const const_reverse_iterator & it) const {return (pos == it.pos);} + bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);} + }; + + iterator begin() {return iterator(this, 0);} + iterator end() {return iterator(this, piv_size);} + const_iterator begin() const {return const_iterator(this, 0);} + const_iterator end() const {return const_iterator(this, piv_size);} + reverse_iterator rbegin() {return reverse_iterator(this, piv_size - 1);} + reverse_iterator rend() {return reverse_iterator(this, -1);} + const_reverse_iterator rbegin() const {return const_reverse_iterator(this, piv_size - 1);} + const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);} + + size_t size() const {return piv_size;} + ssize_t size_s() const {return piv_size;} + size_t length() const {return piv_size;} + size_t capacity() const {return piv_rsize;} + bool isEmpty() const {return (piv_size == 0);} + + T & operator [](size_t index) {return piv_data[index];} + T & at(size_t index) {return piv_data[index];} + const T & operator [](size_t index) const {return piv_data[index];} + const T & at(size_t index) const {return piv_data[index];} + T & back() {return piv_data[piv_size - 1];} + const T & back() const {return piv_data[piv_size - 1];} + T & front() {return piv_data[0];} + const T & front() const {return piv_data[0];} + bool operator ==(const PIVector & t) const {if (piv_size != t.piv_size) return false; for (size_t i = 0; i < piv_size; ++i) if (t[i] != piv_data[i]) return false; return true;} + bool operator !=(const PIVector & t) const {if (piv_size != t.piv_size) return true; for (size_t i = 0; i < piv_size; ++i) if (t[i] != piv_data[i]) return true; return false;} + bool contains(const T & v) const {for (size_t i = 0; i < piv_size; ++i) if (v == piv_data[i]) return true; return false;} + int etries(const T & v) const {int ec = 0; for (size_t i = 0; i < piv_size; ++i) if (v == piv_data[i]) ++ec; return ec;} + + T * data(size_t index = 0) {return &(piv_data[index]);} + const T * data(size_t index = 0) const {return &(piv_data[index]);} + PIVector & clear() {resize(0); return *this;} + PIVector & fill(const T & f = T()) { + //if (sizeof(T) == 1) memset(piv_data, f, piv_size); + deleteT(piv_data, piv_size); + //zeroRaw(piv_data, piv_size); + for (size_t i = 0; i < piv_size; ++i) + elementNew(piv_data + i, f); + return *this; + } + PIVector & assign(const T & f = T()) {return fill(f);} + PIVector & assign(size_t new_size, const T & f) {resize(new_size); return fill(f);} + PIVector & resize(size_t new_size, const T & f = T()) { + if (new_size < piv_size) { + T * de = &(piv_data[new_size]); + deleteT(de, piv_size - new_size); + piv_size = new_size; + } + if (new_size > piv_size) { + size_t os = piv_size; + alloc(new_size); + //if (sizeof(T) == 1) memset(&(piv_data[os]), f, ds); + //zeroRaw(&(piv_data[os]), new_size - os); + for (size_t i = os; i < new_size; ++i) elementNew(piv_data + i, f); + } + return *this; + } + PIVector & reserve(size_t new_size) {if (new_size <= piv_rsize) return *this; size_t os = piv_size; alloc(new_size); piv_size = os; return *this;} + + PIVector & insert(size_t index, const T & v = T()) { + alloc(piv_size + 1); + if (index < piv_size - 1) { + size_t os = piv_size - index - 1; + memmove(&(piv_data[index + 1]), &(piv_data[index]), os * sizeof(T)); + } + //zeroRaw(&(piv_data[index]), 1); + elementNew(piv_data + index, v); + return *this; + } + PIVector & insert(size_t index, const PIVector & other) { + if (other.isEmpty()) return *this; + ssize_t os = piv_size - index; + alloc(piv_size + other.piv_size); + if (os > 0) + memmove(&(piv_data[index + other.piv_size]), &(piv_data[index]), os * sizeof(T)); + newT(piv_data + index, other.piv_data, other.piv_size); + return *this; + } + + PIVector & remove(size_t index, size_t count = 1) { + if (count == 0) return *this; + if (index + count >= piv_size) { + resize(index); + return *this; + } + size_t os = piv_size - index - count; + deleteT(&(piv_data[index]), count); + memmove(&(piv_data[index]), &(piv_data[index + count]), os * sizeof(T)); + piv_size -= count; + return *this; + } + + void swap(PIVector & other) { + piSwap(piv_data, other.piv_data); + piSwap(piv_size, other.piv_size); + piSwap(piv_rsize, other.piv_rsize); + } + + typedef int (*CompareFunc)(const T * , const T * ); + static int compare_func(const T * t0, const T * t1) {return (*t0) < (*t1) ? -1 : ((*t0) == (*t1) ? 0 : 1);} + PIVector & sort(CompareFunc compare = compare_func) {qsort(piv_data, piv_size, sizeof(T), (int(*)(const void * , const void * ))compare); return *this;} + + PIVector & enlarge(llong piv_size) {llong ns = size_s() + piv_size; if (ns <= 0) clear(); else resize(size_t(ns)); return *this;} + + PIVector & removeOne(const T & v) {for (size_t i = 0; i < piv_size; ++i) if (piv_data[i] == v) {remove(i); return *this;} return *this;} + PIVector & removeAll(const T & v) {for (llong i = 0; i < piv_size; ++i) if (piv_data[i] == v) {remove(i); --i;} return *this;} + + PIVector & push_back(const T & v) {alloc(piv_size + 1); elementNew(piv_data + piv_size - 1, v); return *this;} + PIVector & append(const T & v) {return push_back(v);} + PIVector & operator <<(const T & v) {return push_back(v);} + PIVector & operator <<(const PIVector & other) { + size_t ps = piv_size; + alloc(piv_size + other.piv_size); + newT(piv_data + ps, other.piv_data, other.piv_size); + return *this; + } + + PIVector & push_front(const T & v) {insert(0, v); return *this;} + PIVector & prepend(const T & v) {return push_front(v);} + + PIVector & pop_back() {if (piv_size == 0) return *this; resize(piv_size - 1); return *this;} + PIVector & pop_front() {if (piv_size == 0) return *this; remove(0); return *this;} + + T take_back() {T t(back()); pop_back(); return t;} + T take_front() {T t(front()); pop_front(); return t;} + + template + PIVector toType() const {PIVector ret(piv_size); for (uint i = 0; i < piv_size; ++i) ret[i] = ST(piv_data[i]); return ret;} + +private: + void _reset() {piv_size = piv_rsize = 0; piv_data = 0;} + size_t asize(size_t s) { + if (s == 0) return 0; + if (piv_rsize + piv_rsize >= s && piv_rsize < s) + return piv_rsize + piv_rsize; + size_t t = 0, s_ = s - 1; + while (s_ >> t) ++t; + return (1 << t); + } + inline void newT(T * dst, const T * src, size_t s) { + for (size_t i = 0; i < s; ++i) + elementNew(dst + i, src[i]); + } + T * newRaw(size_t s) { + //cout << std::dec << " ![("< (new 0x" << (llong)ret << ") ok]!" << endl; + return (T*)ret; + } + /*void reallocRawTemp(size_t s) { + if (piv_tdata == 0) piv_tdata = (T*)(malloc(s * sizeof(T))); + else piv_tdata = (T*)(realloc(piv_tdata, s * sizeof(T))); + }*/ + inline void deleteT(T * d, size_t sz) { + //cout << " ~[("< ok]~" << endl; + } + void deleteRaw(T *& d) { + //cout << " ~[("< ok]~" << endl; + } + void zeroRaw(T * d, size_t s) { + //cout << " ~[("< ok]~" << endl; + } + inline void elementNew(T * to, const T & from) {new(to)T(from);} + inline void elementDelete(T & from) {from.~T();} + void dealloc() {deleteRaw(piv_data);} + inline void alloc(size_t new_size) { + if (new_size <= piv_rsize) { + piv_size = new_size; + return; + } + //int os = piv_size; + piv_size = new_size; + size_t as = asize(new_size); + if (as == piv_rsize) return; + + //cout << std::hex << " ![("< (new 0x" << (llong)piv_data << ") ok]!" << endl; + /*piv_rsize = as; + T * pd = newRaw(piv_rsize); + if (os > 0 && piv_data != 0) { + memcpy(pd, piv_data, os * sizeof(T)); + deleteRaw(piv_data); + } + piv_data = pd;*/ + } + + T * piv_data; + volatile size_t piv_size, piv_rsize; +}; +/* +#define __PIVECTOR_SIMPLE_FUNCTIONS__(T) \ + template<> inline PIVector::~PIVector() {dealloc(); _reset();} \ + template<> inline PIVector & PIVector::push_back(const T & v) {alloc(piv_size + 1); piv_data[piv_size - 1] = v; return *this;} \ + template<> inline PIVector & PIVector::fill(const T & f) { \ + for (size_t i = 0; i < piv_size; ++i) \ + piv_data[i] = f; \ + return *this; \ + } \ + template<> inline PIVector & PIVector::resize(size_t new_size, const T & f) { \ + if (new_size < piv_size) \ + piv_size = new_size; \ + if (new_size > piv_size) { \ + size_t os = piv_size; \ + alloc(new_size); \ + for (size_t i = os; i < new_size; ++i) piv_data[i] = f; \ + } \ + return *this; \ + } \ + template<> inline PIVector & PIVector::insert(size_t index, const T & v) { \ + alloc(piv_size + 1); \ + if (index < piv_size - 1) { \ + size_t os = piv_size - index - 1; \ + memmove(&(piv_data[index + 1]), &(piv_data[index]), os * sizeof(T)); \ + } \ + piv_data[index] = v; \ + return *this; \ + } \ + template<> inline PIVector & PIVector::remove(size_t index, size_t count) { \ + if (count == 0) return *this; \ + if (index + count >= piv_size) { \ + resize(index); \ + return *this; \ + } \ + size_t os = piv_size - index - count; \ + memmove(&(piv_data[index]), &(piv_data[index + count]), os * sizeof(T)); \ + piv_size -= count; \ + return *this; \ + } + +__PIVECTOR_SIMPLE_FUNCTIONS__(char) +__PIVECTOR_SIMPLE_FUNCTIONS__(uchar) +__PIVECTOR_SIMPLE_FUNCTIONS__(short) +__PIVECTOR_SIMPLE_FUNCTIONS__(ushort) +__PIVECTOR_SIMPLE_FUNCTIONS__(int) +__PIVECTOR_SIMPLE_FUNCTIONS__(uint) +__PIVECTOR_SIMPLE_FUNCTIONS__(long) +__PIVECTOR_SIMPLE_FUNCTIONS__(ulong) +__PIVECTOR_SIMPLE_FUNCTIONS__(llong) +__PIVECTOR_SIMPLE_FUNCTIONS__(ullong) +__PIVECTOR_SIMPLE_FUNCTIONS__(float) +__PIVECTOR_SIMPLE_FUNCTIONS__(double) +__PIVECTOR_SIMPLE_FUNCTIONS__(ldouble)*/ +#define __PIVECTOR_SIMPLE_TYPE__(T) \ + template<> inline void PIVector::newT(T * dst, const T * src, size_t s) {memcpy(dst, src, s * sizeof(T));} \ + template<> inline void PIVector::deleteT(T * d, size_t sz) {;} \ + template<> inline void PIVector::elementNew(T * to, const T & from) {(*to) = from;} \ + template<> inline void PIVector::elementDelete(T & from) {;} + +#else + + +template > +class PIP_EXPORT PIVector: public vector { + typedef PIVector _CVector; + typedef vector _stlc; +public: + + PIVector() {piMonitor.containers++;} + PIVector(uint size, const T & value = T()) {piMonitor.containers++; _stlc::resize(size, value);} + ~PIVector() {piMonitor.containers--;} + + const T & at(uint index) const {return (*this)[index];} + T & at(uint index) {return (*this)[index];} + const T * data(uint index = 0) const {return &(*this)[index];} + T * data(uint index = 0) {return &(*this)[index];} + +#ifdef DOXYGEN + uint size() const; +#endif + + int size_s() const {return static_cast(_stlc::size());} + bool isEmpty() const {return _stlc::empty();} + bool has(const T & t) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) return true; return false;} + int etries(const T & t) const {int ec = 0; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) ++ec; return ec;} + + typedef int (*CompareFunc)(const T * , const T * ); + + static int compare_func(const T * t0, const T * t1) {return (*t0) == (*t1) ? 0 : ((*t0) < (*t1) ? -1 : 1);} +#ifdef DOXYGEN + + void resize(uint size, const T & new_type = T()); + PIVector & enlarge(uint size); + void clear(); + PIVector & sort(CompareFunc compare = compare_func) {qsort(&at(0), _stlc::size(), sizeof(T), (int(*)(const void * , const void * ))compare); return *this;} + PIVector & fill(const T & t) {_stlc::assign(_stlc::size(), t); return *this;} + T & back(); + const T & back() const; + T & front(); + const T & front() const; + PIVector & push_back(const T & t); + PIVector & push_front(const T & t) {_stlc::insert(_stlc::begin(), t); return *this;} + PIVector & pop_back(); + PIVector & pop_front() {_stlc::erase(_stlc::begin()); return *this;} + T take_back() {T t(_stlc::back()); _stlc::pop_back(); return t;} + T take_front() {T t(_stlc::front()); pop_front(); return t;} + PIVector & remove(uint index) {_stlc::erase(_stlc::begin() + index); return *this;} + PIVector & remove(uint index, uint count) {_stlc::erase(_stlc::begin() + index, _stlc::begin() + index + count); return *this;} + PIVector & removeOne(const T & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); return *this;} return *this;} + PIVector & removeAll(const T & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); --i;} return *this;} + PIVector & insert(uint pos, const T & t) {_stlc::insert(_stlc::begin() + pos, t); return *this;} + PIVector & insert(uint pos, const PIVector & t) {_stlc::insert(_stlc::begin() + pos, t.begin(), t.end()); return *this;} + T & operator [](uint index); + const T & operator [](uint index) const; + PIVector & operator <<(const T & t) {_stlc::push_back(t); return *this;} + PIVector & operator <<(const PIVector & t) {for (typename _stlc::const_iterator i = t.begin(); i != t.end(); i++) _stlc::push_back(*i); return *this;} + bool operator ==(const PIVector & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return false; return true;} + bool operator !=(const PIVector & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return true; return false;} + bool contains(const T & v) const {for (uint i = 0; i < _stlc::size(); ++i) if (v == at(i)) return true; return false;} + +#else + _CVector & enlarge(int size_) {int ns = size_s() + size_; if (ns <= 0) _stlc::clear(); else _stlc::resize(ns); return *this;} + _CVector & sort(CompareFunc compare = compare_func) {qsort(&at(0), _stlc::size(), sizeof(T), (int(*)(const void * , const void * ))compare); return *this;} + _CVector & fill(const T & t) {_stlc::assign(_stlc::size(), t); return *this;} + _CVector & pop_front() {_stlc::erase(_stlc::begin()); return *this;} + _CVector & push_front(const T & t) {_stlc::insert(_stlc::begin(), t); return *this;} + T take_front() {T t(_stlc::front()); pop_front(); return t;} + T take_back() {T t(_stlc::back()); _stlc::pop_back(); return t;} + _CVector & remove(uint index) {_stlc::erase(_stlc::begin() + index); return *this;} + _CVector & remove(uint index, uint count) {_stlc::erase(_stlc::begin() + index, _stlc::begin() + index + count); return *this;} + _CVector & removeOne(const T & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); return *this;} return *this;} + _CVector & removeAll(const T & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); --i;} return *this;} + _CVector & insert(uint pos, const T & t) {_stlc::insert(_stlc::begin() + pos, t); return *this;} + _CVector & insert(uint pos, const _CVector & t) {_stlc::insert(_stlc::begin() + pos, t.begin(), t.end()); return *this;} + _CVector & operator <<(const T & t) {_stlc::push_back(t); return *this;} + _CVector & operator <<(const _CVector & t) {for (typename _stlc::const_iterator i = t.begin(); i != t.end(); i++) _stlc::push_back(*i); return *this;} + bool operator ==(const _CVector & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return false; return true;} + bool operator !=(const _CVector & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return true; return false;} + bool contains(const T & v) const {for (uint i = 0; i < _stlc::size(); ++i) if (v == at(i)) return true; return false;} +#endif +}; + +#define __PIVECTOR_SIMPLE_TYPE__(T) + + +#endif + + +template +inline std::ostream & operator <<(std::ostream & s, const PIVector & v) {s << "{"; for (size_t i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << "}"; return s;} + +template +inline PICout operator <<(PICout s, const PIVector & v) {s.space(); s.setControl(0, true); s << "{"; for (size_t i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << "}"; s.restoreControl(); return s;} + + +#endif // PIVECTOR_H diff --git a/src/core/pibitarray.h b/src/core/pibitarray.h new file mode 100755 index 00000000..2c874f0e --- /dev/null +++ b/src/core/pibitarray.h @@ -0,0 +1,104 @@ +/* + PIP - Platform Independent Primitives + Bit array + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIBITARRAY_H +#define PIBITARRAY_H + +#include "picontainers.h" + +class PIP_EXPORT PIBitArray { +public: + PIBitArray(const int & size = 0) {resize(size);} + PIBitArray(uchar val) {resize(sizeof(val) * 8); data_[0] = val;} + PIBitArray(ushort val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));} + PIBitArray(uint val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));} + PIBitArray(ulong val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));} + PIBitArray(ullong val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));} + PIBitArray(uchar * bytes, uint size) {resize(size * 8); memcpy(data(), bytes, size);} + + uint bitSize() const {return size_;} + uint byteSize() const {return bytesInBits(size_);} + PIBitArray & resize(const uint & size) {size_ = size; data_.resize(bytesInBits(size_)); return *this;} + + PIBitArray & clearBit(const uint & index) {data_[index / 8] &= ~(1 << (index % 8)); return *this;} + PIBitArray & setBit(const uint & index) {data_[index / 8] |= (1 << (index % 8)); return *this;} + PIBitArray & writeBit(const uint & index, const bool & value) {if (value) setBit(index); else clearBit(index); return *this;} + PIBitArray & writeBit(const uint & index, const uchar & value) {return writeBit(index, value > 0);} + + PIBitArray & push_back(const bool & value) {resize(size_ + 1); writeBit(size_ - 1, value); return *this;} + PIBitArray & push_back(const uchar & value) {return push_back(value > 0);} + PIBitArray & insert(const uint & index, const bool & value) { + resize(size_ + 1); + uint fi = byteSize() - 1, si = index / 8, ti = index % 8; + uchar c = data_[si]; + for (uint i = fi; i > si; --i) { + data_[i] <<= 1; + if ((0x80 & data_[i - 1]) == 0x80) data_[i] |= 1; + else data_[i] &= 0xFE;} + data_[si] &= (0xFF >> (7 - ti)); + data_[si] |= ((c << 1) & (0xFF << (ti))); + if (value) data_[si] |= (1 << ti); + else data_[si] &= ~(1 << ti); + return *this;} + PIBitArray & insert(const uint & index, const uchar & value) {return insert(index, value > 0);} + PIBitArray & push_front(const bool & value) {return insert(0, value);} + PIBitArray & push_front(const uchar & value) {return push_front(value > 0);} + PIBitArray & pop_back() {return resize(size_ - 1);} + PIBitArray & pop_front() { + if (size_ == 0) return *this; + uint fi = byteSize() - 1; + for (uint i = 0; i < fi; ++i) { + data_[i] >>= 1; + if ((1 & data_[i + 1]) == 1) data_[i] |= 0x80; + else data_[i] &= 0x7F;} + data_[fi] >>= 1; + resize(size_ - 1); + return *this;} + PIBitArray & append(const PIBitArray & ba) {for (uint i = 0; i < ba.bitSize(); ++i) push_back(ba[i]); return *this;} + + uchar * data() {return data_.data();} + uchar toUChar() {if (size_ == 0) return 0; return data_[0];} + ushort toUShort() {ushort t = 0; memcpy(&t, data(), piMin(byteSize(), sizeof(t))); return t;} + uint toUInt() {uint t = 0; memcpy(&t, data(), piMin(byteSize(), sizeof(t))); return t;} + ulong toULong() {ulong t = 0; memcpy(&t, data(), piMin(byteSize(), sizeof(t))); return t;} + ullong toULLong() {ullong t = 0; memcpy(&t, data(), piMin(byteSize(), sizeof(t))); return t;} + + bool at(const uint & index) const {return (1 & (data_[index / 8] >> (index % 8))) == 1 ? true : false;} + bool operator [](const uint & index) const {return at(index);} + void operator +=(const PIBitArray & ba) {append(ba);} + bool operator ==(const PIBitArray & ba) const {if (bitSize() != ba.bitSize()) return false; for (uint i = 0; i < bitSize(); ++i) if (at(i) != ba[i]) return false; return true;} + bool operator !=(const PIBitArray & ba) const {return !(*this == ba);} + void operator =(const uchar & val) {resize(sizeof(val) * 8); data_[0] = val;} + void operator =(const ushort & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));} + void operator =(const uint & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));} + void operator =(const ulong & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));} + void operator =(const ullong & val) {resize(sizeof(val) * 8); memcpy(data(), &val, sizeof(val));} + +private: + uint bytesInBits(const uint & bits) const {return (bits + 7) / 8;} + + PIVector data_; + uint size_; + +}; + +inline std::ostream & operator <<(std::ostream & s, const PIBitArray & ba) {for (uint i = 0; i < ba.bitSize(); ++i) {s << ba[i]; if (i % 8 == 7) s << ' ';} return s;} +inline PICout operator <<(PICout s, const PIBitArray & ba) {s.space(); s.setControl(0, true); for (uint i = 0; i < ba.bitSize(); ++i) {s << ba[i]; if (i % 8 == 7) s << ' ';} s.restoreControl(); return s;} + +#endif // PIBITARRAY_H diff --git a/src/core/pibytearray.cpp b/src/core/pibytearray.cpp new file mode 100755 index 00000000..679afde4 --- /dev/null +++ b/src/core/pibytearray.cpp @@ -0,0 +1,293 @@ +/* + PIP - Platform Independent Primitives + Byte array + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pibytearray.h" +#include "pistring.h" + +/*! \class PIByteArray + * \brief Byte array + * \details This class based on PIDeque and provide some handle function + * to manipulate it. + * + * \section PIByteArray_sec0 Usage + * %PIByteArray can be used to store custom data and manipulate it. There are many + * stream operators to store/restore common types to byte array. Store operators + * places data at the end of array, restore operators takes data from the beginning + * of array. + * In addition there are Base 64 convertions and checksums: + * * plain 8-bit + * * plain 32-bit + * + * One of the major usage of %PIByteArray is stream functions. You can form binary + * packet from many types (also dynamic types, e.g. PIVector) with one line: + * \snippet pibytearray.cpp 0 + * + * Or you can descibe stream operator of your own type and store/restore vectors of + * your type: + * \snippet pibytearray.cpp 1 + * + * For store/restore custom data blocks there is PIByteArray::RawData class. Stream + * operators of this class simply store/restore data block to/from byte array. + * \snippet pibytearray.cpp 2 + * + * \section PIByteArray_sec1 Attention + * Stream operator of %PIByteArray store byte array as vector, not simply append + * content of byte array. This operators useful to transmit custom data as %PIByteArray + * packed into parent byte array, e.g. to form packet from %PIByteArray. + * To append one byte array to another use funtion \a append(). + * \snippet pibytearray.cpp 3 + * + * + */ + + +#pragma pack(push, 1) + +const char PIByteArray::base64Table[64] = { +0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, +0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, +0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, +0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, +0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, +0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, +0x77, 0x78, 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, +0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x2f}; + +const char PIByteArray::base64InvTable[256] = { +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x3E, 0x0, 0x0, 0x0, 0x3F, +0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, +0x3C, 0x3D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, +0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, +0xF, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, +0x17, 0x18, 0x19, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, +0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, +0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, +0x31, 0x32, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + +#pragma pack(pop) + + +int PIHuffman::nodeCompare(const void * f, const void * s) { + return (reinterpret_cast(const_cast(s))->freq - + reinterpret_cast(const_cast(f))->freq); +} + + +PIDeque PIHuffman::compress(const PIDeque & src) { + calcFrequencies(src); + return src; +} + + +void PIHuffman::calcFrequencies(const PIDeque & src) { + nodes.resize(256); + for (int i = 0; i < 256; ++i) { + nodes[i].parent = nodes[i].right = nodes[i].left = 0; + nodes[i].freq = 0; + nodes[i].word.resize(1); + nodes[i].word[0] = static_cast(i); + } + for (int i = 0; i < src.size_s(); ++i) + nodes[src[i]].freq++; + std::qsort(nodes.data(), 256, sizeof(node), nodeCompare); + for (int i = 255; i >= 0; --i) + if (nodes[i].freq > 0 && i < 255) + {nodes.remove(i + 1, 255 - i); break;} + for (int i = 0; i < nodes.size_s(); ++i) + cout << string((char*)nodes[i].word.data(), 1) << ": " << nodes[i].freq << endl; +} + + +PIHuffman PIByteArray::huffman; + +PIByteArray & PIByteArray::convertToBase64() { + base64HelpStruct hs; + PIByteArray t; + if (size() == 0) return *this; + int sz = (size_s() / 3) * 3; + for (int i = 0; i < sz; ++i) { + hs.byte.byte0 = hs.byte.byte1 = hs.byte.byte2 = 0; + hs.byte.byte0 = at(i); + hs.byte.byte1 = at(++i); + hs.byte.byte2 = at(++i); + t.push_back(base64Table[hs.ascii.ascii0]); + t.push_back(base64Table[hs.ascii.ascii1]); + t.push_back(base64Table[hs.ascii.ascii2]); + t.push_back(base64Table[hs.ascii.ascii3]); + } + hs.byte.byte0 = hs.byte.byte1 = hs.byte.byte2 = 0; sz = size() % 3; + switch (sz) { + case 1: + hs.byte.byte0 = back(); + t.push_back(base64Table[hs.ascii.ascii0]); + t.push_back(base64Table[hs.ascii.ascii1]); + t.push_back('='); + t.push_back('='); + break; + case 2: + hs.byte.byte0 = at(size() - 2); hs.byte.byte1 = back(); + t.push_back(base64Table[hs.ascii.ascii0]); + t.push_back(base64Table[hs.ascii.ascii1]); + t.push_back(base64Table[hs.ascii.ascii2]); + t.push_back('='); + break; + default: break; + } + *this = t; + return *this; +} + + +PIByteArray & PIByteArray::convertFromBase64() { + base64HelpStruct hs; + PIByteArray t; + uint sz = size(); + if (sz == 0) return *this; + for (uint i = 0; i < sz; ++i) { + hs.byte.byte0 = hs.byte.byte1 = hs.byte.byte2 = 0; + hs.ascii.ascii0 = base64InvTable[at(i)]; + hs.ascii.ascii1 = base64InvTable[at(++i)]; + hs.ascii.ascii2 = base64InvTable[at(++i)]; + hs.ascii.ascii3 = base64InvTable[at(++i)]; + t.push_back(hs.byte.byte0); + t.push_back(hs.byte.byte1); + t.push_back(hs.byte.byte2); + } + if (back() == '=') t.pop_back(); + if (sz > 1) if (at(sz - 2) == '=') t.pop_back(); + *this = t; + return *this; +} + + +PIByteArray & PIByteArray::compressRLE(uchar threshold) { + PIByteArray t; + uchar fb, clen, mlen = 255 - threshold; + for (uint i = 0; i < size();) { + fb = at(i); + clen = 1; + while (at(++i) == fb) { + ++clen; + if (clen == mlen) + break; + } + if (clen > 1) { + t.push_back(threshold + clen); + t.push_back(fb); + continue; + } + if (fb >= threshold) { + t.push_back(threshold + 1); + t.push_back(fb); + } else + t.push_back(fb); + } + *this = t; + return *this; +} + + +PIByteArray & PIByteArray::decompressRLE(uchar threshold) { + PIByteArray t; + uchar fb, clen; + for (uint i = 0; i < size(); ++i) { + fb = at(i); + if (fb >= threshold) { + clen = fb - threshold; + fb = at(++i); + for (uint j = 0; j < clen; ++j) + t.push_back(fb); + continue; + } else + t.push_back(fb); + } + *this = t; + return *this; +} + + +uchar PIByteArray::checksumPlain8() const { + uchar c = 0; + int sz = size_s(); + for (int i = 0; i < sz; ++i) + c += at(i); + c = ~(c + 1); + return c; +} + + +uint PIByteArray::checksumPlain32() const { + uint c = 0; + int sz = size_s(); + for (int i = 0; i < sz; ++i) + c += at(i) * (i + 1); + c = ~(c + 1); + return c; +} + + +PIString PIByteArray::toString(int base) const { + PIString ret; + int sz = size_s(); + for (int i = 0; i < sz; ++i) { + if (i > 0) ret += " "; + if (base == 2) ret += "b"; + if (base == 8) ret += "0"; + if (base == 16) ret += "0x"; + ret += PIString::fromNumber(at(i), base); + } + return ret; +} + + +PIByteArray PIByteArray::fromString(PIString str) { + PIByteArray ret; + if (str.trim().isEmpty()) return ret; + str.replaceAll("\n", " ").replaceAll("\t", " ").replaceAll(" ", " "); + PIStringList bl(str.split(" ")); + bool ok(false); + piForeachC (PIString & b, bl) { + int bv = b.toInt(-1, &ok); + if (ok) ret << uchar(bv); + } + return ret; +} diff --git a/src/core/pibytearray.h b/src/core/pibytearray.h new file mode 100755 index 00000000..92e1acf7 --- /dev/null +++ b/src/core/pibytearray.h @@ -0,0 +1,261 @@ +/*! \file pibytearray.h + * \brief Byte array +*/ +/* + PIP - Platform Independent Primitives + Byte array + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIBYTEARRAY_H +#define PIBYTEARRAY_H + +#ifdef DOXYGEN +//! This macro allow stream template operators for write and read any type from byte array. Use it with attention! +# define PIP_BYTEARRAY_STREAM_ANY_TYPE +#endif + +#include "pibitarray.h" + +class PIString; +class PIByteArray; + +class PIHuffman { +public: + PIDeque compress(const PIDeque & src); + +private: + struct node { + int freq; + PIDeque word; + PIBitArray path; + node * parent; + node * right; + node * left; + }; + static int nodeCompare(const void * f, const void * s); + void calcFrequencies(const PIDeque & src); + PIVector nodes; +}; + +class PIP_EXPORT PIByteArray: public PIDeque +{ +public: + + //! Constructs an empty byte array + PIByteArray() {;} + + //! Constructs 0-filled byte array with size "size" + PIByteArray(const uint size) {resize(size);} + + //! Constructs byte array from data "data" and size "size" + PIByteArray(const void * data, const uint size): PIDeque((const uchar*)data, size_t(size)) {/*for (uint i = 0; i < size; ++i) push_back(((uchar * )data)[i]);*/} + + + //! Help struct to store/restore custom blocks of data to/from PIByteArray + struct RawData { + friend PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v); + friend PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v); + public: + //! Constructs data block + RawData(void * data = 0, int size = 0) {d = data; s = size;} + //! Constructs data block + RawData(const void * data, const int size) {d = const_cast(data); s = size;} + RawData & operator =(const RawData & o) {d = o.d; s = o.s; return *this;} + private: + void * d; + int s; + }; + + //! Return resized byte array + PIByteArray resized(int new_size) const {PIByteArray tv(*this); tv.resize(new_size); return tv;} + + //! Convert data to Base 64 and return this byte array + PIByteArray & convertToBase64(); + + //! Convert data from Base 64 and return this byte array + PIByteArray & convertFromBase64(); + + //! Return converted to Base 64 data + PIByteArray toBase64() const {PIByteArray ba(*this); ba.convertToBase64(); return ba;} + + //! Return converted from Base 64 data + PIByteArray fromBase64() const {PIByteArray ba(*this); ba.convertFromBase64(); return ba;} + + PIByteArray & compressRLE(uchar threshold = 192); + PIByteArray & decompressRLE(uchar threshold = 192); + PIByteArray compressedRLE(uchar threshold = 192) {PIByteArray ba(*this); ba.compressRLE(threshold); return ba;} + PIByteArray decompressedRLE(uchar threshold = 192) {PIByteArray ba(*this); ba.decompressRLE(threshold); return ba;} + + PIByteArray & compressHuffman() {*this = huffman.compress(*this); return *this;} + + PIString toString(int base = 16) const; + + //! Add to the end data "data" with size "size" + PIByteArray & append(const void * data_, int size_) {uint ps = size(); enlarge(size_); memcpy(data(ps), data_, size_); return *this;} + + //! Add to the end byte array "data" + PIByteArray & append(const PIByteArray & data_) {uint ps = size(); enlarge(data_.size_s()); memcpy(data(ps), data_.data(), data_.size()); return *this;} + /*PIByteArray & operator <<(short v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;} + PIByteArray & operator <<(ushort v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;} + PIByteArray & operator <<(int v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;} + PIByteArray & operator <<(uint v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;} + PIByteArray & operator <<(llong v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;} + PIByteArray & operator <<(ullong v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;}*/ + //PIByteArray & operator <<(const PIByteArray & v) {for (uint i = 0; i < v.size(); ++i) push_back(v[i]); return *this;} + + //! Returns plain 8-bit checksum + uchar checksumPlain8() const; + + //! Returns plain 32-bit checksum + uint checksumPlain32() const; + + void operator =(const PIDeque & d) {resize(d.size()); memcpy(data(), d.data(), d.size());} + + static PIByteArray fromString(PIString str); + +private: + union base64HelpStruct { + base64HelpStruct() {memset(this, 0, sizeof(base64HelpStruct));} + struct { + uchar ascii0: 6; + uchar ascii1: 6; + uchar ascii2: 6; + uchar ascii3: 6; + } ascii; + struct { + uchar byte0; + uchar byte1; + uchar byte2; + } byte; + }; + + static const char base64Table[64]; + static const char base64InvTable[256]; + static PIHuffman huffman; + +}; + +inline bool operator <(const PIByteArray & v0, const PIByteArray & v1) {if (v0.size() == v1.size()) {for (uint i = 0; i < v0.size(); ++i) if (v0[i] != v1[i]) return v0[i] < v1[i]; return false;} return v0.size() < v1.size();} +//! \relatesalso PIByteArray \brief Output to std::ostream operator +inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba) {s << "{"; for (uint i = 0; i < ba.size(); ++i) {s << ba[i]; if (i < ba.size() - 1) s << ", ";} s << "}"; return s;} + +//! \relatesalso PIByteArray \brief Output to PICout operator +inline PICout operator <<(PICout s, const PIByteArray & ba) {s.space(); s.setControl(0, true); s << "{"; for (uint i = 0; i < ba.size(); ++i) {s << ba[i]; if (i < ba.size() - 1) s << ", ";} s << "}"; s.restoreControl(); return s;} + +#define PBA_OPERATOR_TO int os = s.size_s(); s.enlarge(sizeof(v)); memcpy(s.data(os), &v, sizeof(v)); + +//! \relatesalso PIByteArray \brief Store operator +inline PIByteArray & operator <<(PIByteArray & s, uchar v) {s.push_back(v); return s;} +//! \relatesalso PIByteArray \brief Store operator +inline PIByteArray & operator <<(PIByteArray & s, const short v) {PBA_OPERATOR_TO return s;} +//! \relatesalso PIByteArray \brief Store operator +inline PIByteArray & operator <<(PIByteArray & s, const int v) {PBA_OPERATOR_TO return s;} +//! \relatesalso PIByteArray \brief Store operator +inline PIByteArray & operator <<(PIByteArray & s, const long & v) {PBA_OPERATOR_TO return s;} +//! \relatesalso PIByteArray \brief Store operator +inline PIByteArray & operator <<(PIByteArray & s, const llong & v) {PBA_OPERATOR_TO return s;} +//! \relatesalso PIByteArray \brief Store operator +inline PIByteArray & operator <<(PIByteArray & s, const ushort v) {PBA_OPERATOR_TO return s;} +//! \relatesalso PIByteArray \brief Store operator +inline PIByteArray & operator <<(PIByteArray & s, const uint v) {PBA_OPERATOR_TO return s;} +//! \relatesalso PIByteArray \brief Store operator +inline PIByteArray & operator <<(PIByteArray & s, const ulong & v) {PBA_OPERATOR_TO return s;} +//! \relatesalso PIByteArray \brief Store operator +inline PIByteArray & operator <<(PIByteArray & s, const ullong & v) {PBA_OPERATOR_TO return s;} +//! \relatesalso PIByteArray \brief Store operator +inline PIByteArray & operator <<(PIByteArray & s, const float v) {PBA_OPERATOR_TO return s;} +//! \relatesalso PIByteArray \brief Store operator +inline PIByteArray & operator <<(PIByteArray & s, const double & v) {PBA_OPERATOR_TO return s;} +//! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details +inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray & v) {s << v.size_s(); int os = s.size_s(); s.enlarge(v.size_s()); if (v.size_s() > 0) memcpy(s.data(os), v.data(), v.size()); return s;} +//! \relatesalso PIByteArray \brief Store operator, see \ref PIByteArray_sec1 for details +inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) {int os = s.size_s(); s.enlarge(v.s); if (v.s > 0) memcpy(s.data(os), v.d, v.s); return s;} +//! \relatesalso PIByteArray \brief Store operator +template +inline PIByteArray & operator <<(PIByteArray & s, const PIPair & v) {s << v.first << v.second; return s;} +//! \relatesalso PIByteArray \brief Store operator +template +inline PIByteArray & operator <<(PIByteArray & s, const PIVector & v) {s << v.size_s(); for (uint i = 0; i < v.size(); ++i) s << v[i]; return s;} +//! \relatesalso PIByteArray \brief Store operator +template +inline PIByteArray & operator <<(PIByteArray & s, const PIList & v) {s << v.size_s(); for (uint i = 0; i < v.size(); ++i) s << v[i]; return s;} +//! \relatesalso PIByteArray \brief Store operator +template +inline PIByteArray & operator <<(PIByteArray & s, const PIDeque & v) {s << v.size_s(); for (uint i = 0; i < v.size(); ++i) s << v[i]; return s;} +#ifdef PIP_BYTEARRAY_STREAM_ANY_TYPE +template +inline PIByteArray & operator <<(PIByteArray & s, const T & v) {PBA_OPERATOR_TO return s;} +#endif + +#undef PBA_OPERATOR_TO +#define PBA_OPERATOR_FROM memcpy(&v, s.data(), sizeof(v)); s.remove(0, sizeof(v)); + +//! \relatesalso PIByteArray \brief Restore operator +inline PIByteArray & operator >>(PIByteArray & s, uchar & v) {assert(s.size() >= 1u); v = s.take_front(); return s;} +//! \relatesalso PIByteArray \brief Restore operator +inline PIByteArray & operator >>(PIByteArray & s, short & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} +//! \relatesalso PIByteArray \brief Restore operator +inline PIByteArray & operator >>(PIByteArray & s, int & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} +//! \relatesalso PIByteArray \brief Restore operator +inline PIByteArray & operator >>(PIByteArray & s, long & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} +//! \relatesalso PIByteArray \brief Restore operator +inline PIByteArray & operator >>(PIByteArray & s, llong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} +//! \relatesalso PIByteArray \brief Restore operator +inline PIByteArray & operator >>(PIByteArray & s, ushort & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} +//! \relatesalso PIByteArray \brief Restore operator +inline PIByteArray & operator >>(PIByteArray & s, uint & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} +//! \relatesalso PIByteArray \brief Restore operator +inline PIByteArray & operator >>(PIByteArray & s, ulong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} +//! \relatesalso PIByteArray \brief Restore operator +inline PIByteArray & operator >>(PIByteArray & s, ullong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} +//! \relatesalso PIByteArray \brief Restore operator +inline PIByteArray & operator >>(PIByteArray & s, float & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} +//! \relatesalso PIByteArray \brief Restore operator +inline PIByteArray & operator >>(PIByteArray & s, double & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} +//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details +inline PIByteArray & operator >>(PIByteArray & s, PIByteArray & v) {assert(s.size_s() >= 4); int sz; s >> sz; v.resize(sz); if (sz > 0) memcpy(v.data(), s.data(), v.size()); s.remove(0, v.size()); return s;} +//! \relatesalso PIByteArray \brief Restore operator, see \ref PIByteArray_sec1 for details +inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) {assert(s.size_s() >= v.s); if (v.s > 0) memcpy(v.d, s.data(), v.s); s.remove(0, v.s); return s;} +//! \relatesalso PIByteArray \brief Restore operator +template +inline PIByteArray & operator >>(PIByteArray & s, PIPair & v) {s >> v.first >> v.second; return s;} +//! \relatesalso PIByteArray \brief Restore operator +template +inline PIByteArray & operator >>(PIByteArray & s, PIVector & v) {assert(s.size_s() >= 4); int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;} +//! \relatesalso PIByteArray \brief Restore operator +template +inline PIByteArray & operator >>(PIByteArray & s, PIList & v) {assert(s.size_s() >= 4); int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;} +//! \relatesalso PIByteArray \brief Restore operator +template +inline PIByteArray & operator >>(PIByteArray & s, PIDeque & v) {assert(s.size_s() >= 4); int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;} +// //! \relatesalso PIByteArray \brief Restore operator +//template +//inline PIByteArray & operator >>(PIByteArray & s, PIMap & v) {assert(s.size_s() >= 4); int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;} +#ifdef PIP_BYTEARRAY_STREAM_ANY_TYPE +template +inline PIByteArray & operator >>(PIByteArray & s, T & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;} +#endif + + +#undef PBA_OPERATOR_FROM + +//! \relatesalso PIByteArray \brief Byte arrays compare operator +inline bool operator ==(PIByteArray & f, PIByteArray & s) {if (f.size_s() != s.size_s()) return false; for (int i = 0; i < f.size_s(); ++i) if (f[i] != s[i]) return false; return true;} +//! \relatesalso PIByteArray \brief Byte arrays compare operator +inline bool operator !=(PIByteArray & f, PIByteArray & s) {if (f.size_s() != s.size_s()) return true; for (int i = 0; i < f.size_s(); ++i) if (f[i] != s[i]) return true; return false;} + +#endif // PIBYTEARRAY_H diff --git a/src/core/pichar.h b/src/core/pichar.h new file mode 100755 index 00000000..c0cd81ea --- /dev/null +++ b/src/core/pichar.h @@ -0,0 +1,221 @@ +/*! \file pichar.h + * \brief Unicode char +*/ +/* + PIP - Platform Independent Primitives + Unicode char + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PICHAR_H +#define PICHAR_H + +#include "pibytearray.h" +/*! \brief Unicode char + * \details This class is wrapper around \c "uint". + * There are many contructors and information functions + */ +class PIP_EXPORT PIChar +{ + friend class PIString; + friend PIByteArray & operator <<(PIByteArray & s, const PIChar & v); + friend PIByteArray & operator >>(PIByteArray & s, PIChar & v); +public: + //! Contructs ascii symbol + PIChar(const char c) {ch = c; ch &= 0xFF;} + + //! Contructs 2-bytes symbol + PIChar(const short c) {ch = c; ch &= 0xFFFF;} + + //! Contructs 4-bytes symbol + PIChar(const int c) {ch = c;} + + //! Contructs ascii symbol + PIChar(const uchar c) {ch = c; ch &= 0xFF;} + + //! Contructs 2-bytes symbol + PIChar(const ushort c) {ch = c; ch &= 0xFFFF;} + + //! Default constructor. Contructs 4-bytes symbol + PIChar(const uint c = 0) {ch = c;} + + //! Contructs symbol from no more than 4 bytes of string + PIChar(const char * c) {ch = *reinterpret_cast(c);} + + //inline operator const int() {return static_cast(ch);} + //inline operator const char() {return toAscii();} + + //! Copy operator + PIChar & operator =(const char v) {ch = v; return *this;} + /*inline PIChar & operator =(const short v) {ch = v; return *this;} + inline PIChar & operator =(const int v) {ch = v; return *this;} + inline PIChar & operator =(const uchar v) {ch = v; return *this;} + inline PIChar & operator =(const ushort v) {ch = v; return *this;} + inline PIChar & operator =(const uint v) {ch = v; return *this;}*/ + + //! Compare operator + bool operator ==(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) == 0;} + /*inline bool operator ==(const PIChar & o) const {if (o.isAscii() ^ isAscii()) return false; + if (isAscii()) return (o.toAscii() == toAscii()); + return (o.toInt() == toInt());} + inline bool operator ==(const char o) const {return (PIChar(o) == *this);} + inline bool operator ==(const short o) const {return (PIChar(o) == *this);} + inline bool operator ==(const int o) const {return (PIChar(o) == *this);} + inline bool operator ==(const uchar o) const {return (PIChar(o) == *this);} + inline bool operator ==(const ushort o) const {return (PIChar(o) == *this);} + inline bool operator ==(const uint o) const {return (PIChar(o) == *this);}*/ + + //! Compare operator + bool operator !=(const PIChar & o) const {return !(o == *this);} + /*inline bool operator !=(const char o) const {return (PIChar(o) != *this);} + inline bool operator !=(const short o) const {return (PIChar(o) != *this);} + inline bool operator !=(const int o) const {return (PIChar(o) != *this);} + inline bool operator !=(const uchar o) const {return (PIChar(o) != *this);} + inline bool operator !=(const ushort o) const {return (PIChar(o) != *this);} + inline bool operator !=(const uint o) const {return (PIChar(o) != *this);}*/ + + //! Compare operator + bool operator >(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) < 0;} + + //! Compare operator + bool operator <(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) > 0;} + + //! Compare operator + bool operator >=(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) <= 0;} + + //! Compare operator + bool operator <=(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) >= 0;} + + //! Return \b true if symbol is digit ('0' to '9') + bool isDigit() const {return isdigit(ch) != 0;} + + //! Return \b true if symbol is HEX digit ('0' to '9', 'a' to 'f', 'A' to 'F') + bool isHex() const {return isxdigit(ch) != 0;} + + //! Return \b true if symbol is drawable (without space) + bool isGraphical() const {return isgraph(ch) != 0;} + + //! Return \b true if symbol is control byte (< 32 or 127) + bool isControl() const {return iscntrl(ch) != 0;} + + //! Return \b true if symbol is in lower case + bool isLower() const {return islower(ch) != 0;} + + //! Return \b true if symbol is in upper case + bool isUpper() const {return isupper(ch) != 0;} + + //! Return \b true if symbol is printable (with space) + bool isPrint() const {return isprint(ch) != 0;} + + //! Return \b true if symbol is space or tab + bool isSpace() const {return isspace(ch) != 0;} + + //! Return \b true if symbol is alphabetical letter + bool isAlpha() const {return isalpha(ch) != 0;} + + //! Return \b true if symbol is ascii (< 128) + bool isAscii() const {return isascii(ch) != 0;} + + int toInt() const {return int(ch);} + const wchar_t * toWCharPtr() const {return reinterpret_cast(&ch);} + + //! Return as "char * " string + const char * toCharPtr() const {return reinterpret_cast(&ch);} + + wchar_t toWChar() const {return wchar_t(ch);} + char toAscii() const {return ch % 256;} + int unicode16Code() const {wchar_t wc; if (mbtowc(&wc, toCharPtr(), 4) > 0) return wc; return 0;} +//#ifdef WINDOWS +// inline PIChar toUpper() const __attribute__ ((optimize(0))) {return PIChar(toupper(ch));} +// inline PIChar toLower() const __attribute__ ((optimize(0))) {return PIChar(tolower(ch));} +//#else + + //! Return symbol in upper case + PIChar toUpper() const {return PIChar(toupper(ch));} + + //! Return symbol in lower case + PIChar toLower() const {return PIChar(tolower(ch));} +//#endif + +private: + uint ch; + +}; + +__PICONTAINERS_SIMPLE_TYPE__(PIChar) + +//! Output operator to \c std::ostream +inline std::ostream & operator <<(std::ostream & s, const PIChar & v) {s << v.toCharPtr(); return s;} + +//! Output operator to \a PICout +inline PICout operator <<(PICout s, const PIChar & v) {s.space(); s.setControl(0, true); s << v.toCharPtr(); s.restoreControl(); return s;} + + +//! Write operator to \c PIByteArray +inline PIByteArray & operator <<(PIByteArray & s, const PIChar & v) {s << uint(v.ch); return s;} + +//! Read operator from \c PIByteArray +inline PIByteArray & operator >>(PIByteArray & s, PIChar & v) {uint i; s >> i; v.ch = wchar_t(i); return s;} + + +//! Compare operator +inline bool operator ==(const char v, const PIChar & c) {return (PIChar(v) == c);} + +//! Compare operator +inline bool operator >(const char v, const PIChar & c) {return (PIChar(v) > c);} + +//! Compare operator +inline bool operator <(const char v, const PIChar & c) {return (PIChar(v) < c);} + +//! Compare operator +inline bool operator >=(const char v, const PIChar & c) {return (PIChar(v) >= c);} + +//! Compare operator +inline bool operator <=(const char v, const PIChar & c) {return (PIChar(v) <= c);} + + +//! Compare operator +inline bool operator ==(const char * v, const PIChar & c) {return (PIChar(v) == c);} + +//! Compare operator +inline bool operator >(const char * v, const PIChar & c) {return (PIChar(v) > c);} + +//! Compare operator +inline bool operator <(const char * v, const PIChar & c) {return (PIChar(v) < c);} + +//! Compare operator +inline bool operator >=(const char * v, const PIChar & c) {return (PIChar(v) >= c);} + +//! Compare operator +inline bool operator <=(const char * v, const PIChar & c) {return (PIChar(v) <= c);} + + +//! Compare operator +inline bool operator ==(const int v, const PIChar & c) {return (PIChar(v) == c);} + +//! Compare operator +inline bool operator >(const int v, const PIChar & c) {return (PIChar(v) > c);} + +//! Compare operator +inline bool operator <(const int v, const PIChar & c) {return (PIChar(v) < c);} + +//! Compare operator +inline bool operator >=(const int v, const PIChar & c) {return (PIChar(v) >= c);} + +//! Compare operator +inline bool operator <=(const int v, const PIChar & c) {return (PIChar(v) <= c);} + +#endif // PICHAR_H diff --git a/src/core/picli.cpp b/src/core/picli.cpp new file mode 100755 index 00000000..5567f2c1 --- /dev/null +++ b/src/core/picli.cpp @@ -0,0 +1,101 @@ +/* + PIP - Platform Independent Primitives + Command-Line Parser + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "picli.h" +#include "pisysteminfo.h" + + +/*! \class PICLI + * \brief Command-line arguments parser + * + * \section PICLI_sec0 Synopsis + * This class provide handy parsing of command-line arguments. First you should add + * arguments to PICLI with function \a addArgument(). Then you can check if there + * is some argument in application command-line with function \a hasArgument(); + * \section PICLI_sec1 Example + * \snippet picli.cpp main + */ + + +PICLI::PICLI(int argc, char * argv[]) { + setName("CLI"); + needParse = true; + _prefix_short = "-"; + _prefix_full = "--"; + _count_opt = 0; + _count_mand = 0; + for (int i = 0; i < argc; ++i) + _args_raw << argv[i]; + if (argc > 0) + PISystemInfo::instance()->execCommand = argv[0]; +} + + +void PICLI::parse() { + if (!needParse) return; + PIString cra, full; + Argument * last = 0; + for (int i = 1; i < _args_raw.size_s(); ++i) { + cra = _args_raw[i]; + if (cra.left(2) == _prefix_full) { + last = 0; + full = cra.right(cra.length() - 2); + piForeach (Argument & a, _args) { + if (a.full_key == full) { + a.found = true; + last = &a; + break; + } + } + } else { + if (cra.left(1) == _prefix_short) { + last = 0; + for (int j = 1; j < cra.length(); ++j) { + bool found = false; + piForeach (Argument & a, _args) { + if (a.short_key == cra[j]) { + a.found = true; + last = &a; + found = true; + break; + } + } + if (!found) break; + } + } else { + if (last == 0 ? true : !last->has_value) { + if (_args_mand.size_s() < _count_mand) { + _args_mand << cra; + continue; + } + if (_args_opt.size_s() < _count_opt || _count_opt < 0) { + _args_opt << cra; + continue; + } + piCoutObj << "[PICli] Arguments overflow, \"" << cra << "\" ignored"; + } + if (last == 0 ? false : last->has_value) { + last->value = cra; + last = 0; + } + } + } + } + needParse = false; +} diff --git a/src/core/picli.h b/src/core/picli.h new file mode 100755 index 00000000..ce58d5f8 --- /dev/null +++ b/src/core/picli.h @@ -0,0 +1,101 @@ +/*! \file picli.h + * \brief Command-Line parser +*/ +/* + PIP - Platform Independent Primitives + Command-Line Parser + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PICLI_H +#define PICLI_H + +#include "piobject.h" + +class PIP_EXPORT PICLI: public PIObject +{ + PIOBJECT(PICLI) +public: + + //! Constructor + PICLI(int argc, char * argv[]); + + + //! Add argument with name "name", short key = name first letter, full key = name + void addArgument(const PIString & name, bool value = false) {_args << Argument(name, name[0], name, value); needParse = true;} + + //! Add argument with name "name", short key = "shortKey", full key = name + void addArgument(const PIString & name, const PIChar & shortKey, bool value = false) {_args << Argument(name, shortKey, name, value); needParse = true;} + + //! Add argument with name "name", short key = "shortKey", full key = name + void addArgument(const PIString & name, const char * shortKey, bool value = false) {_args << Argument(name, PIChar(shortKey), name, value); needParse = true;} + + //! Add argument with name "name", short key = "shortKey", full key = "fullKey" + void addArgument(const PIString & name, const PIChar & shortKey, const PIString & fullKey, bool value = false) {_args << Argument(name, shortKey, fullKey, value); needParse = true;} + + //! Add argument with name "name", short key = "shortKey", full key = "fullKey" + void addArgument(const PIString & name, const char * shortKey, const PIString & fullKey, bool value = false) {_args << Argument(name, PIChar(shortKey), fullKey, value); needParse = true;} + + + //! Returns unparsed command-line argument by index "index". Index 0 is program execute command. + PIString rawArgument(int index) {parse(); return _args_raw[index];} + PIString mandatoryArgument(int index) {parse(); return _args_mand[index];} + PIString optionalArgument(int index) {parse(); return _args_opt[index];} + + //! Returns unparsed command-line arguments + const PIStringList & rawArguments() {parse(); return _args_raw;} + const PIStringList & mandatoryArguments() {parse(); return _args_mand;} + const PIStringList & optionalArguments() {parse(); return _args_opt;} + + //! Returns program execute command without arguments + PIString programCommand() {parse(); return _args_raw.size() > 0 ? _args_raw.front() : PIString();} + bool hasArgument(const PIString & name) {parse(); piForeach (Argument & i, _args) if (i.name == name && i.found) return true; return false;} + PIString argumentValue(const PIString & name) {parse(); piForeach (Argument &i, _args) if (i.name == name && i.found) return i.value; return PIString();} + PIString argumentShortKey(const PIString & name) {piForeach (Argument &i, _args) if (i.name == name) return i.short_key; return PIString();} + PIString argumentFullKey(const PIString & name) {piForeach (Argument &i, _args) if (i.name == name) return i.full_key; return PIString();} + + const PIString & shortKeyPrefix() const {return _prefix_short;} + const PIString & fullKeyPrefix() const {return _prefix_full;} + int mandatoryArgumentsCount() const {return _count_mand;} + int optionalArgumentsCount() const {return _count_opt;} + void setShortKeyPrefix(const PIString & prefix) {_prefix_short = prefix; needParse = true;} + void setFullKeyPrefix(const PIString & prefix) {_prefix_full = prefix; needParse = true;} + void setMandatoryArgumentsCount(const int count) {_count_mand = count; needParse = true;} + void setOptionalArgumentsCount(const int count) {_count_opt = count; needParse = true;} + +private: + struct Argument { + Argument() {has_value = found = false;} + Argument(const PIString & n, const PIChar & s, const PIString & f, bool v) {name = n; short_key = s; full_key = f; has_value = v; found = false;} + PIString name; + PIChar short_key; + PIString full_key; + PIString value; + bool has_value, found; + }; + + void parse(); + + PIString _prefix_short, _prefix_full; + PIStringList _args_raw, _args_mand, _args_opt; + PISet keys_full, keys_short; + PIVector _args; + int _count_mand, _count_opt; + bool needParse; + +}; + +#endif // PICLI_H diff --git a/src/core/picollection.cpp b/src/core/picollection.cpp new file mode 100755 index 00000000..d9fd72cd --- /dev/null +++ b/src/core/picollection.cpp @@ -0,0 +1,57 @@ +#include "picollection.h" + + +/** \class PICollection + * \brief Interface to discover element groups + * \details + * \section PICollection_sec0 Synopsis + * This class has only static functions so no need to create instance of the + * %PICollection. This class provide macros to add some classes or existing + * objects to global collection and access to them from any place of the code. + * \snippet picollection.cpp main + * */ + + +PIStringList PICollection::groups() { + PIStringList sl; + piForeachC (Group & g, *_groups) + sl << g.name; + return sl; +} + + +PIVector PICollection::groupElements(const PIString & group) { + piForeachC (Group & g, *_groups) + if (g.name == group) + return g.elements; + return PIVector(); +} + + +void PICollection::addToGroup(const PIString & group, const PIObject * element) { + //piCout << "add to" << group << element; + PIString n = element->className(); + piForeach (Group & g, *_groups) + if (g.name == group) { + for (int i = 0; i < g.elements.size_s(); ++i) + if (PIString(g.elements[i]->className()) == n) + return; + g.elements << element; + //piCout << "new group" << group << ", ok"; + return; + } + *_groups << Group(group); + _groups->back().elements << element; + //piCout << "new group" << group << ", ok"; +} + + +PICollection::CollectionAdder::CollectionAdder(const PIString & group, const PIObject * element, const PIString & name) { + if (element == 0) return; + const_cast(element)->setName(name); + PICollection::addToGroup(group, element); +} + + +bool __PICollectionInitializer::_inited_(false); +PIVector * PICollection::_groups; diff --git a/src/core/picollection.h b/src/core/picollection.h new file mode 100755 index 00000000..dc4b0cbb --- /dev/null +++ b/src/core/picollection.h @@ -0,0 +1,96 @@ +/*! \file picollection.h + * \brief Custom elements collection +*/ +/* + PIP - Platform Independent Primitives + Peer - named I/O ethernet node, forming self-organized peering network + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PICOLLECTION_H +#define PICOLLECTION_H + +#include "piobject.h" + +#ifdef DOXYGEN + +/** \brief Add existing element "object" in group with name "group" + * \relatesalso PICollection + * \details If there is no group with name "group" it will be created. + * Only one element of the class "object" can be in group "group". If + * this is already exists nothing be happens. \n "object" should to + * be pointer to object based on PIObject. */ +# define ADD_TO_COLLECTION(group, object) + +/** \brief Add new element of class "class" in group with name "group" + * \relatesalso PICollection + * \details If there is no group with name "group" it will be created. + * Only one element of the class "class" can be in group "group". If + * this is already exists nothing be happens. \n "class" should to + * be name of the any class based on PIObject. */ +# define ADD_NEW_TO_COLLECTION(group, class) + +#else +# define ADD_TO_COLLECTION(group, object) static PICollection::CollectionAdder __##group##_##__LINE__##_##adder##__(#group, object); +# define ADD_TO_COLLECTION_WITH_NAME(group, object, name) static PICollection::CollectionAdder __##group##_##__LINE__##_##adder##__(#group, object, #name); +# define ADD_NEW_TO_COLLECTION(group, class) static PICollection::CollectionAdder __##group##_##class##_##adder##__(#group, new class()); +# define ADD_NEW_TO_COLLECTION_WITH_NAME(group, class, name) static PICollection::CollectionAdder __##group##_##class##_##adder##__(#group, new class(), #name); +#endif + +class PIP_EXPORT PICollection +{ + friend class __PICollectionInitializer; +public: + PICollection() {;} + + //! \brief Returns all existing groups by their names + static PIStringList groups(); + + //! \brief Returns all elements of group "group" + static PIVector groupElements(const PIString & group); + + static void addToGroup(const PIString & group, const PIObject * element); + + class CollectionAdder { + public: + CollectionAdder(const PIString & group, const PIObject * element, const PIString & name = PIString()); + }; + +protected: + struct Group { + Group(const PIString & name_ = PIString()) {name = name_;} + //~Group() {piCout << "delete group" << name << this; piForeach (const PIObject * o, elements) delete o; elements.clear();} + PIString name; + PIVector elements; + }; + + static PIVector * _groups; + +}; + +class PIP_EXPORT __PICollectionInitializer { +public: + __PICollectionInitializer() { + if (_inited_) return; + _inited_ = true; + PICollection::_groups = new PIVector(); + } + static bool _inited_; +}; + +static __PICollectionInitializer __picollectioninitializer; + +#endif // PICOLLECTION_H diff --git a/src/core/picout.cpp b/src/core/picout.cpp new file mode 100644 index 00000000..e90f1a9f --- /dev/null +++ b/src/core/picout.cpp @@ -0,0 +1,348 @@ +/* + PIP - Platform Independent Primitives + Universal output to console class + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "picout.h" +#include "piconsole.h" + +/*! \class PICout + * \brief Class for formatted output similar std::cout + * + * \section PICout_sec0 Synopsis + * This class provide many stream operators for output with some features. + * Output to PICout is thread-sequential, i.e. doesn`t mixed from parallel + * threads. + * + * \section PICout_sec1 Features + * - insertion spaces between entries + * - insertion new line at the end of output + * - strings are quoted + * - custom output operator can be easily written + * + * \section PICout_ex0 Usage + * \snippet picout.cpp 0 + * + * \section PICout_ex1 Writing your own output operator + * \snippet picout.cpp own + */ + +PIMutex __PICout_mutex__; +PIString __PICout_string__; + +#ifdef WINDOWS +void * PICout::hOut = 0; +WORD PICout::dattr = 0; +DWORD PICout::smode = 0; +#endif + +bool PICout::buffer_ = false; + + +PICout::PICout(PIFlags controls): fo_(true), cc_(false), fc_(false), cnb_(10), co_(controls) { +#ifdef WINDOWS + if (hOut == 0) { + hOut = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_SCREEN_BUFFER_INFO sbi; + GetConsoleScreenBufferInfo(hOut, &sbi); + dattr = sbi.wAttributes; + } + attr_ = dattr; +#endif + __PICout_mutex__.lock(); +} + + +PICout::~PICout() { + if (fc_) applyFormat(PICoutManipulators::Default); + if (cc_) return; + newLine(); + __PICout_mutex__.unlock(); +} + + +PICout PICout::operator <<(const PICoutAction v) { +#ifdef WINDOWS + CONSOLE_SCREEN_BUFFER_INFO sbi; + COORD coord; + CONSOLE_CURSOR_INFO curinfo; +#endif + switch (v) { + case PICoutManipulators::Flush: + if (!PICout::buffer_) + std::cout << std::flush; + break; + case PICoutManipulators::Backspace: + if (!PICout::buffer_) { +#ifdef WINDOWS + GetConsoleScreenBufferInfo(hOut, &sbi); + coord = sbi.dwCursorPosition; + coord.X = piMax(0, int(coord.X) - 1); + SetConsoleCursorPosition(hOut, coord); + printf(" "); + SetConsoleCursorPosition(hOut, coord); +#else + printf("\e[1D \e[1D"); +#endif + } + break; + case PICoutManipulators::ShowCursor: + if (!PICout::buffer_) { +#ifdef WINDOWS + GetConsoleCursorInfo(hOut, &curinfo); + curinfo.bVisible = true; + SetConsoleCursorInfo(hOut, &curinfo); +#else + printf("\e[?25h"); +#endif + } + break; + case PICoutManipulators::HideCursor: + if (!PICout::buffer_) { +#ifdef WINDOWS + GetConsoleCursorInfo(hOut, &curinfo); + curinfo.bVisible = false; + SetConsoleCursorInfo(hOut, &curinfo); +#else + printf("\e[?25l"); +#endif + } + break; + case PICoutManipulators::ClearScreen: + if (!PICout::buffer_) { +#ifdef WINDOWS + /// TODO !!! + /*GetConsoleCursorInfo(hOut, &curinfo); + curinfo.bVisible = false; + SetConsoleCursorInfo(hOut, &curinfo); + + SetConsoleCursorPosition(hOut, ulcoord); + FillConsoleOutputAttribute(hOut, dattr, width * (height + 1), ulcoord, &written); + FillConsoleOutputCharacter(hOut, ' ', width * (height + 1), ulcoord, &written);*/ +#else + printf("\e[H\e[J"); +#endif + } + break; + case PICoutManipulators::SaveContol: saveControl(); break; + case PICoutManipulators::RestoreControl: restoreControl(); break; + default: break; + }; + return *this; +} + + +#define PICOUTTOTARGET(v) {if (PICout::buffer_) __PICout_string__ << (v); else std::cout << (v);} +#define PINUMERICCOUT if (cnb_ == 10) PICOUTTOTARGET(v) else PICOUTTOTARGET(PIString::fromNumber(v, cnb_)) + + +PICout PICout::operator <<(const char * v) {if (v == '\0') return *this; space(); quote(); PICOUTTOTARGET(v) quote(); return *this;} + +PICout PICout::operator <<(const string & v) {space(); quote(); PICOUTTOTARGET(v) quote(); return *this;} + +PICout PICout::operator <<(const bool v) {space(); if (v) PICOUTTOTARGET("true") else PICOUTTOTARGET("false") return *this;} + +PICout PICout::operator <<(const char v) {space(); PICOUTTOTARGET(v) return *this;} + +PICout PICout::operator <<(const uchar v) {space(); if (cnb_ == 10) PICOUTTOTARGET(ushort(v)) else PICOUTTOTARGET(PIString::fromNumber(v, cnb_)) return *this;} + +PICout PICout::operator <<(const short int v) {space(); PINUMERICCOUT return *this;} + +PICout PICout::operator <<(const ushort v) {space(); PINUMERICCOUT return *this;} + +PICout PICout::operator <<(const int v) {space(); PINUMERICCOUT return *this;} + +PICout PICout::operator <<(const uint v) {space(); PINUMERICCOUT return *this;} + +PICout PICout::operator <<(const long v) {space(); PINUMERICCOUT return *this;} + +PICout PICout::operator <<(const ulong v) {space(); PINUMERICCOUT return *this;} + +PICout PICout::operator <<(const llong v) {space(); PINUMERICCOUT return *this;} + +PICout PICout::operator <<(const ullong v) {space(); PINUMERICCOUT return *this;} + +PICout PICout::operator <<(const float v) {space(); PICOUTTOTARGET(v) return *this;} + +PICout PICout::operator <<(const double v) {space(); PICOUTTOTARGET(v) return *this;} + +PICout PICout::operator <<(const void * v) {space(); PICOUTTOTARGET("0x") PICOUTTOTARGET(PIString::fromNumber(ullong(v), 16)) return *this;} + +PICout PICout::operator <<(const PIObject * v) { + space(); + if (v == 0) PICOUTTOTARGET("PIObject*(0x0)") + else { + PICOUTTOTARGET(v->className()) + PICOUTTOTARGET("*(0x") + PICOUTTOTARGET(PIString::fromNumber(ullong(v), 16)) + PICOUTTOTARGET(", \"") + PICOUTTOTARGET(v->name()) + PICOUTTOTARGET("\")") + } + return *this; +} + +PICout PICout::operator <<(const PICoutSpecialChar v) { + switch (v) { + case Null: + if (PICout::buffer_) __PICout_string__ << PIChar(0); + else std::cout << char(0); + break; + case NewLine: + if (PICout::buffer_) __PICout_string__ << "\n"; + else std::cout << '\n'; + fo_ = true; + break; + case Tab: + if (PICout::buffer_) __PICout_string__ << "\t"; + else std::cout << '\t'; + break; + case Esc: +#ifdef CC_VC + if (PICout::buffer_) __PICout_string__ << PIChar(27); + else std::cout << char(27); +#else + if (PICout::buffer_) __PICout_string__ << "\e"; + else std::cout << '\e'; +#endif + break; + case Quote: + if (PICout::buffer_) __PICout_string__ << "\""; + else std::cout << '"'; + break; + }; + return *this; +} + +#undef PICOUTTOTARGET +#undef PINUMERICCOUT + +PICout & PICout::space() { + if (!fo_ && co_[AddSpaces]) { + if (PICout::buffer_) __PICout_string__ << " "; + else std::cout << ' '; + } + fo_ = false; + return *this; +} + +PICout & PICout::quote() { + if (co_[AddQuotes]) { + if (PICout::buffer_) __PICout_string__ << "\""; + else std::cout << '"'; + } + fo_ = false; + return *this; +} + +PICout & PICout::newLine() { + if (co_[AddNewLine]) { + if (PICout::buffer_) __PICout_string__ << "\n"; + else std::cout << std::endl; + } + fo_ = false; + return *this; +} + + +void PICout::applyFormat(PICoutFormat f) { + if (PICout::buffer_) return; + fc_ = true; +#ifdef WINDOWS + static int mask_fore = ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + static int mask_back = ~(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); + switch (f) { + case Bin: case Oct: case Dec: case Hex: break; + case PICoutManipulators::Bold: attr_ |= FOREGROUND_INTENSITY; break; + case PICoutManipulators::Underline: attr_ |= COMMON_LVB_UNDERSCORE; break; + case PICoutManipulators::Black: attr_ = (attr_ & mask_fore); break; + case PICoutManipulators::Red: attr_ = (attr_ & mask_fore) | FOREGROUND_RED; break; + case PICoutManipulators::Green: attr_ = (attr_ & mask_fore) | FOREGROUND_GREEN; break; + case PICoutManipulators::Blue: attr_ = (attr_ & mask_fore) | FOREGROUND_BLUE; break; + case PICoutManipulators::Yellow: attr_ = (attr_ & mask_fore) | FOREGROUND_RED | FOREGROUND_GREEN; break; + case PICoutManipulators::Magenta: attr_ = (attr_ & mask_fore) | FOREGROUND_RED | FOREGROUND_BLUE; break; + case PICoutManipulators::Cyan: attr_ = (attr_ & mask_fore) | FOREGROUND_GREEN | FOREGROUND_BLUE; break; + case PICoutManipulators::White: attr_ = (attr_ & mask_fore) | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; break; + case PICoutManipulators::BackBlack: attr_ = (attr_ & mask_back); break; + case PICoutManipulators::BackRed: attr_ = (attr_ & mask_back) | BACKGROUND_RED; break; + case PICoutManipulators::BackGreen: attr_ = (attr_ & mask_back) | BACKGROUND_GREEN; break; + case PICoutManipulators::BackBlue: attr_ = (attr_ & mask_back) | BACKGROUND_BLUE; break; + case PICoutManipulators::BackYellow: attr_ = (attr_ & mask_back) | BACKGROUND_RED | BACKGROUND_GREEN; break; + case PICoutManipulators::BackMagenta: attr_ = (attr_ & mask_back) | BACKGROUND_RED | BACKGROUND_BLUE; break; + case PICoutManipulators::BackCyan: attr_ = (attr_ & mask_back) | BACKGROUND_GREEN | BACKGROUND_BLUE; break; + case PICoutManipulators::BackWhite: attr_ = (attr_ & mask_back) | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE; break; + case PICoutManipulators::Default: attr_ = dattr; break; + default: break; + } + SetConsoleTextAttribute(hOut, attr_); +#else + switch (f) { + case Bin: case Oct: case Dec: case Hex: break; + case PICoutManipulators::Bold: printf("\e[1m"); break; + case PICoutManipulators::Faint: printf("\e[2m"); break; + case PICoutManipulators::Italic: printf("\e[3m"); break; + case PICoutManipulators::Underline: printf("\e[4m"); break; + case PICoutManipulators::Blink: printf("\e[5m"); break; + case PICoutManipulators::Black: printf("\e[30m"); break; + case PICoutManipulators::Red: printf("\e[31m"); break; + case PICoutManipulators::Green: printf("\e[32m"); break; + case PICoutManipulators::Blue: printf("\e[34m"); break; + case PICoutManipulators::Yellow: printf("\e[33m"); break; + case PICoutManipulators::Magenta: printf("\e[35m"); break; + case PICoutManipulators::Cyan: printf("\e[36m"); break; + case PICoutManipulators::White: printf("\e[37m"); break; + case PICoutManipulators::BackBlack: printf("\e[40m"); break; + case PICoutManipulators::BackRed: printf("\e[41m"); break; + case PICoutManipulators::BackGreen: printf("\e[42m"); break; + case PICoutManipulators::BackBlue: printf("\e[44m"); break; + case PICoutManipulators::BackYellow: printf("\e[43m"); break; + case PICoutManipulators::BackMagenta: printf("\e[45m"); break; + case PICoutManipulators::BackCyan: printf("\e[46m"); break; + case PICoutManipulators::BackWhite: printf("\e[47m"); break; + case PICoutManipulators::Default: printf("\e[0m"); break; + default: break; + } +#endif +} + + +bool PICout::setBufferActive(bool on, bool clear) { + PIMutexLocker ml(__PICout_mutex__); + bool ret = PICout::buffer_; + if (clear) __PICout_string__.clear(); + PICout::buffer_ = on; + return ret; +} + + +bool PICout::isBufferActive() { + return PICout::buffer_; +} + + +PIString PICout::buffer(bool clear) { + PIMutexLocker ml(__PICout_mutex__); + PIString ret = __PICout_string__; + if (clear) __PICout_string__.clear(); + return ret; +} + + +void PICout::clearBuffer() { + PIMutexLocker ml(__PICout_mutex__); + __PICout_string__.clear(); +} diff --git a/src/core/picout.h b/src/core/picout.h new file mode 100644 index 00000000..0da3f595 --- /dev/null +++ b/src/core/picout.h @@ -0,0 +1,266 @@ +/*! \file picout.h + * \brief Universal output to console class +*/ +/* + PIP - Platform Independent Primitives + Universal output to console class + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PICOUT_H +#define PICOUT_H + +#include "piincludes.h" + +#ifdef DOXYGEN + +//! \brief Macro used for conditional (piDebug) output to PICout +# define piCout + +//! \relatesalso PIObject \brief Macro used for conditional (piDebug and PIObject::debug()) output to PICout for subclasses of PIObject +# define piCoutObj + +#else +# define piCout if (piDebug) PICout() +# define piCoutObj if (piDebug && debug()) PICout() << "" << (PIString("[") + className() + " \"" + name() + "\"]") +#endif + +extern PIMutex __PICout_mutex__; +extern PIString __PICout_string__; + +//! \brief Namespace contains enums controlled PICout +namespace PICoutManipulators { + + //! \brief Enum contains special characters + enum PIP_EXPORT PICoutSpecialChar { + Null /*! Null-character, '\\0' */, + NewLine /*! New line character, '\\n' */, + Tab /*! Tab character, '\\t' */, + Esc /*! Escape character, '\\e' */, + Quote /*! Quote character, '"' */ + }; + + //! \brief Enum contains immediate action + enum PIP_EXPORT PICoutAction { + Flush /*! Flush the output */, + Backspace /*! Remove last symbol */, + ShowCursor /*! Show cursor */, + HideCursor /*! Hide cursor */, + ClearScreen /*! Clear the screen */, + SaveContol /*! Save control flags, equivalent to \a saveControl() */, + RestoreControl /*! Restore control flags, equivalent to \a restoreControl() */ + }; + + //! \brief Enum contains control of PICout + enum PIP_EXPORT PICoutControl { + AddNone /*! No controls */ = 0x0, + AddSpaces /*! Spaces will be appear after each output */ = 0x1, + AddNewLine /*! New line will be appear after all output */ = 0x2, + AddQuotes /*! Each string will be quoted */ = 0x4, + AddAll /*! All controls */ = 0xFFFFFFFF + }; + + //! \brief Enum contains output format + enum PIP_EXPORT PICoutFormat { + Bin /*! Binary representation of integers */ = 0x01, + Oct /*! Octal representation of integers */ = 0x02, + Dec /*! Decimal representation of integers */ = 0x04, + Hex /*! Hexadecimal representation of integers */ = 0x08, + Bold /*! Bold */ = 0x10, + Faint /*! */ = 0x20, + Italic /*! */ = 0x40, + Underline /*! Underline */ = 0x80, + Blink /*! Blink */ = 0x100, + Black /*! Black font */ = 0x400, + Red /*! Red font */ = 0x800, + Green /*! Green font */ = 0x1000, + Blue /*! Blue font */ = 0x2000, + Yellow /*! Yellow font */ = 0x4000, + Magenta /*! Magenta font */ = 0x8000, + Cyan /*! Cyan font */ = 0x10000, + White /*! White font */ = 0x20000, + BackBlack /*! Black background */ = 0x40000, + BackRed /*! Red background */ = 0x80000, + BackGreen /*! Green background */ = 0x100000, + BackBlue /*! Blue background */ = 0x200000, + BackYellow /*! Yellow background */ = 0x400000, + BackMagenta /*! Magenta background */ = 0x800000, + BackCyan /*! Cyan background */ = 0x1000000, + BackWhite /*! White background */ = 0x2000000, + Default /*! Default format */ = 0x4000000 + }; +}; + +using namespace PICoutManipulators; + +typedef PIFlags PICoutControls; + +class PIP_EXPORT PICout { +public: + //! Default constructor with default features (AddSpaces and AddNewLine) + PICout(PIFlags controls = AddSpaces | AddNewLine); + + PICout(const PICout & other): fo_(other.fo_), cc_(true), fc_(false), cnb_(other.cnb_), attr_(other.attr_), co_(other.co_) {;} + ~PICout(); + + //! Output operator for strings with "const char * " type + PICout operator <<(const char * v); + + //! Output operator for strings with "std::string" type + PICout operator <<(const string & v); + + //! Output operator for boolean values + PICout operator <<(const bool v); + + //! Output operator for "char" values + PICout operator <<(const char v); + + //! Output operator for "unsigned char" values + PICout operator <<(const uchar v); + + //! Output operator for "short" values + PICout operator <<(const short v); + + //! Output operator for "unsigned short" values + PICout operator <<(const ushort v); + + //! Output operator for "int" values + PICout operator <<(const int v); + + //! Output operator for "unsigned int" values + PICout operator <<(const uint v); + + //! Output operator for "long" values + PICout operator <<(const long v); + + //! Output operator for "unsigned long" values + PICout operator <<(const ulong v); + + //! Output operator for "long long" values + PICout operator <<(const llong v); + + //! Output operator for "unsigned long long" values + PICout operator <<(const ullong v); + + //! Output operator for "float" values + PICout operator <<(const float v); + + //! Output operator for "double" values + PICout operator <<(const double v); + + //! Output operator for pointers + PICout operator <<(const void * v); + + //! Output operator for PIObject and ancestors + PICout operator <<(const PIObject * v); + + //! Output operator for \a PICoutSpecialChar values + PICout operator <<(const PICoutSpecialChar v); + + //! Output operator for \a PIFlags values + PICout operator <<(const PIFlags v) { + if (v[Bin]) cnb_ = 2; + if (v[Oct]) cnb_ = 8; + if (v[Dec]) cnb_ = 10; + if (v[Hex]) cnb_ = 16; + if (v[Bold]) applyFormat(Bold); + if (v[Faint]) applyFormat(Faint); + if (v[Italic]) applyFormat(Italic); + if (v[Underline]) applyFormat(Underline); + if (v[Blink]) applyFormat(Blink); + if (v[Black]) applyFormat(Black); + if (v[Red]) applyFormat(Red); + if (v[Green]) applyFormat(Green); + if (v[Blue]) applyFormat(Blue); + if (v[Yellow]) applyFormat(Yellow); + if (v[Magenta]) applyFormat(Magenta); + if (v[Cyan]) applyFormat(Cyan); + if (v[White]) applyFormat(White); + if (v[BackBlack]) applyFormat(BackBlack); + if (v[BackRed]) applyFormat(BackRed); + if (v[BackGreen]) applyFormat(BackGreen); + if (v[BackBlue]) applyFormat(BackBlue); + if (v[BackYellow]) applyFormat(BackYellow); + if (v[BackMagenta]) applyFormat(BackMagenta); + if (v[BackCyan]) applyFormat(BackCyan); + if (v[BackWhite]) applyFormat(BackWhite); + if (v[Default]) applyFormat(Default); + return *this; + } + + //! Output operator for \a PICoutFormat values + PICout operator <<(const PICoutFormat v) { + switch (v) { + case Bin: cnb_ = 2; break; + case Oct: cnb_ = 8; break; + case Dec: cnb_ = 10; break; + case Hex: cnb_ = 16; break; + default: applyFormat(v); + }; + return *this; + } + + //! Do some action + PICout operator <<(const PICoutAction v); + + //! Set control flag "c" is "on" state + PICout & setControl(PICoutControl c, bool on = true) {co_.setFlag(c, on); return *this;} + + //! Set control flags "c" and if "save" exec \a saveControl() + PICout & setControl(PICoutControls c, bool save = false) {if (save) saveControl(); co_ = c; return *this;} + + //! Save control flags to internal stack \sa \a restoreControl() + PICout & saveControl() {cos_.push(co_); return *this;} + + //! Restore control flags from internal stack \sa \a saveControl() + PICout & restoreControl() {if (!cos_.empty()) {co_ = cos_.top(); cos_.pop();} return *this;} + + /*! \brief Conditional put space character to output + * \details If it is not a first output and control \a AddSpaces is set + * space character is put \sa \a quote(), \a newLine() */ + PICout & space(); + + /*! \brief Conditional put quote character to output + * \details If control \a AddQuotes is set + * quote character is put \sa \a space(), \a newLine() */ + PICout & quote(); + + /*! \brief Conditional put new line character to output + * \details If control \a AddNewLine is set + * new line character is put \sa \a space(), \a quote() */ + PICout & newLine(); + + static bool setBufferActive(bool on, bool clear = false); + static bool isBufferActive(); + static PIString buffer(bool clear = false); + static void clearBuffer(); + +private: + void applyFormat(PICoutFormat f); + + static bool buffer_; + bool fo_, cc_, fc_; + int cnb_, attr_; + PICoutControls co_; + std::stack cos_; +#ifdef WINDOWS + static void * hOut; + static WORD dattr; + static DWORD smode; +#endif +}; + +#endif // PICOUT_H diff --git a/src/core/piflags.h b/src/core/piflags.h new file mode 100644 index 00000000..676fd9b4 --- /dev/null +++ b/src/core/piflags.h @@ -0,0 +1,137 @@ +/*! \file piflags.h + * \brief General flags class +*/ +/* + PIP - Platform Independent Primitives + General flags class + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIFLAGS_H +#define PIFLAGS_H + +#include "pimonitor.h" + +/*! \brief This class used as container for bit flags + * \details PIFlags is wrapper around \c "int". There are many + * bit-wise operators, native conversion to int and function + * to test flag. \n Example: + * \snippet piincludes.cpp flags + */ +template +class PIP_EXPORT PIFlags { +public: + //! Constructor with flags = 0 + PIFlags(): flags(0) {;} + //! Constructor with flags = Enum "e" + PIFlags(Enum e): flags(e) {;} + //! Constructor with flags = PIFlags "f" + PIFlags(const PIFlags & f): flags(f.flags) {;} + //! Constructor with flags = int "i" + PIFlags(const int i): flags(i) {;} + //! Set flags "f" to value "on" + PIFlags & setFlag(const PIFlags & f, bool on = true) {if (on) flags |= f.flags; else flags &= ~f.flags; return *this;} + //! Set flag "e" to value "on" + PIFlags & setFlag(const Enum & e, bool on = true) {if (on) flags |= e; else flags &= ~e; return *this;} + //! Set flag "i" to value "on" + PIFlags & setFlag(const int & i, bool on = true) {if (on) flags |= i; else flags &= ~i; return *this;} + //! copy operator + void operator =(const PIFlags & f) {flags = f.flags;} + //! copy operator + void operator =(const Enum & e) {flags = e;} + //! copy operator + void operator =(const int & i) {flags = i;} + //! compare operator + bool operator ==(const PIFlags & f) {return flags == f.flags;} + //! compare operator + bool operator ==(const Enum & e) {return flags == e;} + //! compare operator + bool operator ==(const int i) {return flags == i;} + //! compare operator + bool operator !=(const PIFlags & f) {return flags != f.flags;} + //! compare operator + bool operator !=(const Enum & e) {return flags != e;} + //! compare operator + bool operator !=(const int i) {return flags != i;} + //! compare operator + bool operator >(const PIFlags & f) {return flags > f.flags;} + //! compare operator + bool operator >(const Enum & e) {return flags > e;} + //! compare operator + bool operator >(const int i) {return flags > i;} + //! compare operator + bool operator <(const PIFlags & f) {return flags < f.flags;} + //! compare operator + bool operator <(const Enum & e) {return flags < e;} + //! compare operator + bool operator <(const int i) {return flags < i;} + //! compare operator + bool operator >=(const PIFlags & f) {return flags >= f.flags;} + //! compare operator + bool operator >=(const Enum & e) {return flags >= e;} + //! compare operator + bool operator >=(const int i) {return flags >= i;} + //! compare operator + bool operator <=(const PIFlags & f) {return flags <= f.flags;} + //! compare operator + bool operator <=(const Enum & e) {return flags <= e;} + //! compare operator + bool operator <=(const int i) {return flags <= i;} + //! Bit-wise AND operator + void operator &=(const PIFlags & f) {flags &= f.flags;} + //! Bit-wise AND operator + void operator &=(const Enum & e) {flags &= e;} + //! Bit-wise AND operator + void operator &=(const int i) {flags &= i;} + //! Bit-wise OR operator + void operator |=(const PIFlags & f) {flags |= f.flags;} + //! Bit-wise OR operator + void operator |=(const Enum & e) {flags |= e;} + //! Bit-wise OR operator + void operator |=(const int i) {flags |= i;} + //! Bit-wise XOR operator + void operator ^=(const PIFlags & f) {flags ^= f.flags;} + //! Bit-wise XOR operator + void operator ^=(const Enum & e) {flags ^= e;} + //! Bit-wise XOR operator + void operator ^=(const int i) {flags ^= i;} + //! Bit-wise AND operator + PIFlags operator &(PIFlags f) const {PIFlags tf(flags & f.flags); return tf;} + //! Bit-wise AND operator + PIFlags operator &(Enum e) const {PIFlags tf(flags & e); return tf;} + //! Bit-wise AND operator + PIFlags operator &(int i) const {PIFlags tf(flags & i); return tf;} + //! Bit-wise OR operator + PIFlags operator |(PIFlags f) const {PIFlags tf(flags | f.flags); return tf;} + //! Bit-wise OR operator + PIFlags operator |(Enum e) const {PIFlags tf(flags | e); return tf;} + //! Bit-wise OR operator + PIFlags operator |(int i) const {PIFlags tf(flags | i); return tf;} + //! Bit-wise XOR operator + PIFlags operator ^(PIFlags f) const {PIFlags tf(flags ^ f.flags); return tf;} + //! Bit-wise XOR operator + PIFlags operator ^(Enum e) const {PIFlags tf(flags ^ e); return tf;} + //! Bit-wise XOR operator + PIFlags operator ^(int i) const {PIFlags tf(flags ^ i); return tf;} + //! Test flag operator + bool operator [](Enum e) const {return (flags & e) == e;} + //! Implicity conversion to \c int + operator int() const {return flags;} +private: + int flags; +}; + +#endif // PIFLAGS_H diff --git a/src/core/piincludes.cpp b/src/core/piincludes.cpp new file mode 100755 index 00000000..ce8f04c0 --- /dev/null +++ b/src/core/piincludes.cpp @@ -0,0 +1,235 @@ +/* + PIP - Platform Independent Primitives + Global includes + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "piincludes.h" +#include "piconsole.h" + +bool piDebug = true; +double piMountInfoRefreshIntervalMs = 10000.; + +lconv * currentLocale = +#ifdef ANDROID + 0; +#else + std::localeconv(); +#endif + +#ifdef MAC_OS +clock_serv_t __pi_mac_clock; +#endif + +#ifdef WINDOWS +FILETIME __pi_ftjan1970; +long long __pi_perf_freq = -1; +PINtSetTimerResolution setTimerResolutionAddr = 0; +#endif + +void errorClear() { +#ifdef WINDOWS + SetLastError(0); +#else + errno = 0; +#endif +} + +PIString errorString() { +#ifdef WINDOWS + char * msg; + int err = GetLastError(); + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msg, 0, NULL); + return "code " + itos(err) + " - " + string(msg); +#else + int e = errno; + return PIString("code ") + PIString::fromNumber(e) + " - " + PIString(strerror(e)); +#endif +} + +PIString PIPVersion() { + static PIString ret(PIString::fromNumber(PIP_VERSION_MAJOR) + "." + + PIString::fromNumber(PIP_VERSION_MINOR) + "." + + PIString::fromNumber(PIP_VERSION_REVISION) + + PIP_VERSION_SUFFIX); + return ret; +} + +/*! \class PICout + * \brief Class for formatted output similar std::cout + * + * \section PICout_sec0 Synopsis + * This class provide many stream operators for output with some features. + * Output to PICout is thread-sequential, i.e. doesn`t mixed from parallel + * threads. + * + * \section PICout_sec1 Features + * - insertion spaces between entries + * - insertion new line at the end of output + * - strings are quoted + * - custom output operator can be easily written + * + * \section PICout_ex0 Usage + * \snippet picout.cpp 0 + * + * \section PICout_ex1 Writing your own output operator + * \snippet picout.cpp own + */ + + +/*! \mainpage What is PIP + * PIP - Platform-Independent Primitives - is crossplatform library for C++ developers. + * It is wrap around STL and pure C++. This library can help developers write non-GUI + * projects much more quickly, efficiently and customizable than on pure C++. + * Library contains many classes, some of them are pure abstract, some classes + * can be used as they are, some classes should be inherited to new classes. + * PIP provide classes: + * * direct output to console (\a PICout) + * * containers (\a PIVector, \a PIList, \a PIMap, \a PIStack) + * * byte array (\a PIByteArray) + * * string (\a PIString, \a PIStringList) + * * base object (events and handlers) (\a PIObject) + * * thread (\a PIThread) + * * timer (\a PITimer) + * * console (information output) (\a PIConsole) + * * stand-alone + * * server + * * client + * * I/O devices + * * base class (\a PIIODevice) + * * file (\a PIFile) + * * serial port (\a PISerial) + * * ethernet (\a PIEthernet) + * * USB (\a PIUSB) + * * packets extractor (\a PIPacketExtractor) + * * binary log (\a PIBinaryLog) + * * complex I/O point (\a PIConnection) + * * connection quality diagnotic (\a PIDiagnostics) + * * command-line arguments parser (\a PICLI) + * * math evaluator (\a PIEvaluator) + * * peering net node (\a PIPeer) + * * process (\a PIProcess) + * * state machine (\a PIStateMachine) + * \n \n Basic using of PIP described at page \ref using_basic */ + + +/*! \page using_basic Getting started + * Many novice programmers are solved many common task with system integrity: output to console, + * keyboard buttons press detecting, working with serial ports, ethernet or files, and many other. + * These tasks can solve this library, and code, based only on PIP will be compile and work + * similar on many systems: Windows, any Linux, Red Hat, FreeBSD, MacOS X and QNX. + * Typical application on PIP looks like this: \n +\code{.cpp} +#include + + +// declare key press handler +void key_event(char key, void * ); + + +PIConsole console(false, key_event); // don`t start now, key handler is "key_event" + + +// some vars +int i = 2, j = 3; + + +// implicit key press handler +void key_event(char key, void * ) { + switch (key) { + case '-': + i--; + break; + case '+': + i++; + break; + case '(': + j--; + break; + case ')': + j++; + break; + }; +}; + + +class MainClass: public PITimer { + PIOBJECT(MainClass) +public: + MainClass() {} +protected: + void tick(void * data, int delimiter) { + piCout << "timer tick"; + // timer tick + } +}; + + +MainClass main_class; + + +int main(int argc, char * argv[]) { + // enabling auto-detection of exit button press, by default 'Q' (shift+q) + console.enableExitCapture(); + + // if we want to parse command-line arguments + PICLI cli(argc, argv); + cli.addArgument("console"); // "-c" or "--console" + cli.addArgument("debug"); // "-d" or "--debug" + + // enabling or disabling global debug flag + piDebug = cli.hasArgument("debug"); + + // configure console + console.addTab("first tab", '1'); + console.addString("PIP console", 1, PIConsole::Bold); + console.addVariable("int var (i)", &i, 1); + console.addVariable("int green var (j)", &j, 1, PIConsole::Green); + console.addString("'-' - i--", 2); + console.addString("'+' - i++", 2); + console.addString("'(' - j--", 2); + console.addString("')' - j++", 2); + console.addTab("second tab", '2'); + console.addString("col 1", 1); + console.addString("col 2", 2); + console.addString("col 3", 3); + console.setTab("first tab"); + + // start output to console if "console" argument exists + if (cli.hasArgument("console")) + console.start(); + + // start main class, e.g. 40 Hz + main_class.start(25.); + + // wait for 'Q' press, independently if console is started or not + console.waitForFinish(); + + return 0; +}; +\endcode + * This code demonstrates simple interactive configurable program, which can be started with console + * display or not, and with debug or not. \b MainClass is central class that also can be inherited from + * \a PIThread and reimplement \a run() function. + * \n Many PIP classes has events and event handlers, which can be connected one to another. + * Details you can see at \a PIObject reference page (\ref PIObject_sec0). + * \n To configure your program from file use \a PIConfig. + * \n If you want more information see \ref using_advanced */ + + +/*! \page using_advanced Advanced using + * Sorry, creativity crysis xD + */ diff --git a/src/core/piincludes.h b/src/core/piincludes.h new file mode 100755 index 00000000..2704f86c --- /dev/null +++ b/src/core/piincludes.h @@ -0,0 +1,538 @@ +/*! \file piincludes.h + * \brief Global includes of PIP + * + * This file include all needed system headers, STL + * and declare many useful macros and functions +*/ +/* + PIP - Platform Independent Primitives + Global includes + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIINCLUDES_H +#define PIINCLUDES_H + +#include "piversion.h" + +//! Version of PIP in hex - 0x##(Major)##(Minor)##(Revision) +#define PIP_VERSION ((PIP_VERSION_MAJOR << 16) | (PIP_VERSION_MINOR < 8) | PIP_VERSION_REVISION) + +#ifdef DOXYGEN + +//! Major value of PIP version +# define PIP_VERSION_MAJOR + +//! Minor value of PIP version +# define PIP_VERSION_MINOR + +//! Revision value of PIP version +# define PIP_VERSION_REVISION + +//! Suffix of PIP version +# define PIP_VERSION_SUFFIX + +//! Macro is defined when compile-time debug is enabled +# define PIP_DEBUG + +//! Macro is defined when host is any Windows +# define WINDOWS + +//! Macro is defined when host is QNX +# define QNX + +//! Macro is defined when host is FreeBSD +# define FREE_BSD + +//! Macro is defined when host is Mac OS +# define MAC_OS + +//! Macro is defined when host is Android +# define ANDROID + +//! Macro is defined when host is any Linux +# define LINUX + +//! Macro is defined when compiler is GCC or MinGW +# define CC_GCC + +//! Macro is defined when PIP is decided that host is support language +# define HAS_LOCALE + +//! Macro is defined when compiler is Visual Studio +# define CC_VC + +//! Macro is defined when compiler is unknown +# define CC_OTHER + +//! Macro is defined when PIP use "rt" library for timers implementation +# define PIP_TIMER_RT + +//! Define this macro to use STL implementation of containers, else PIP implementation will be used +# define PIP_CONTAINERS_STL + +#endif + +#include "piplatform.h" + +#include "pip_export.h" +#if defined(DOXYGEN) || defined(CC_GCC) || defined(PICODE) +# undef PIP_EXPORT +# define PIP_EXPORT +#endif +#include +#ifdef CC_GCC +# include +#endif +#include +#include +#ifndef QNX +# include +# include +# include +# include +# include +#else +# include +# include +# include +# include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef WINDOWS +# include +# include +# include +# ifdef CC_VC +# define SHUT_RDWR 2 +# pragma comment(lib, "Ws2_32.lib") +# pragma comment(lib, "Iphlpapi.lib") +# pragma comment(lib, "Psapi.lib") +# else +# define SHUT_RDWR SD_BOTH +# endif +# include +# include +# include +# include + typedef int socklen_t; + typedef void(*PINtSetTimerResolution)(ULONG, BOOLEAN, PULONG); + extern FILETIME __pi_ftjan1970; + extern long long __pi_perf_freq; + extern PINtSetTimerResolution setTimerResolutionAddr; + inline long long __PIQueryPerformanceCounter() {LARGE_INTEGER li; QueryPerformanceCounter(&li); return li.QuadPart;} + inline void __PISetTimerResolution() {if (setTimerResolutionAddr == NULL) return; ULONG ret; setTimerResolutionAddr(1, TRUE, &ret);} +#else +# include +# include +# include +# include +# include +# include +# include +# include +# ifndef ANDROID +# include +# endif +#endif +#ifdef ANDROID +# define tcdrain(fd) ioctl(fd, TCSBRK, 1) + inline int wctomb(char * c, wchar_t w) {*c = ((char * )&w)[0]; return 1;} + inline int mbtowc(wchar_t * w, const char * c, size_t) {*w = ((wchar_t * )&c)[0]; return 1;} +#endif +#ifdef MAC_OS +# include +# include +# include +# include +# define environ (*_NSGetEnviron()) + typedef long time_t; + extern clock_serv_t __pi_mac_clock; +#endif +#ifdef LINUX +# define environ __environ +#endif +#if !defined(WINDOWS) && !defined(MAC_OS) +//# define PIP_TIMER_RT +#endif +#ifdef FREE_BSD + extern char ** environ; +#endif +#if defined(DOXYGEN) || defined(PICODE) +# undef PIP_EXPORT +# define PIP_EXPORT +# undef DEPRECATED +# define DEPRECATED +#endif + +#include "pimonitor.h" +#include "piflags.h" + +extern PIMonitor piMonitor; + +//! Macro used for infinite loop +#define FOREVER for (;;) + +//! Macro used for infinite wait +#define FOREVER_WAIT FOREVER msleep(1); + +//! Macro used for infinite wait +#define WAIT_FOREVER FOREVER msleep(1); + +using std::cout; +using std::cin; +using std::endl; +using std::flush; +using std::vector; +using std::list; +using std::queue; +using std::deque; +using std::stack; +using std::set; +using std::map; +using std::multimap; +using std::string; +using std::complex; +#ifndef QNX + using std::wstring; +#else + typedef std::basic_string wstring; +#endif + +typedef long long llong; +typedef unsigned char uchar; +typedef unsigned short int ushort; +typedef unsigned int uint; +typedef unsigned long ulong; +typedef unsigned long long ullong; +typedef long double ldouble; +typedef complex complexi; +typedef complex complexf; +typedef complex complexd; +typedef complex complexld; + +const complexld complexld_i(0., 1.); +const complexld complexld_0(0.); +const complexld complexld_1(1.); +const complexd complexd_i(0., 1.); +const complexd complexd_0(0.); +const complexd complexd_1(1.); + +/*! \brief Templated function for swap two values + * \details Example:\n \snippet piincludes.cpp swap */ +template inline void piSwap(T & f, T & s) {T t = f; f = s; s = t;} + +/*! \brief Templated function for swap two values without "=" + * \details Example:\n \snippet piincludes.cpp swapBinary */ +template inline void piSwapBinary(T & f, T & s) { + static size_t j = (sizeof(T) / sizeof(size_t)), bs = j * sizeof(size_t), bf = sizeof(T); + size_t i = 0; + for (i = 0; i < j; ++i) { + ((size_t*)(&f))[i] ^= ((size_t*)(&s))[i]; + ((size_t*)(&s))[i] ^= ((size_t*)(&f))[i]; + ((size_t*)(&f))[i] ^= ((size_t*)(&s))[i]; + } + for (i = bs; i < bf; ++i) { + ((uchar*)(&f))[i] ^= ((uchar*)(&s))[i]; + ((uchar*)(&s))[i] ^= ((uchar*)(&f))[i]; + ((uchar*)(&f))[i] ^= ((uchar*)(&s))[i]; + } +} + +/*! \brief Templated function return round of float falue + * \details Round is the nearest integer value \n + * There are some macros: + * - \c piRoundf for "float" + * - \c piRoundd for "double" + * + * Example: + * \snippet piincludes.cpp round */ +template inline int piRound(const T & v) {return int(v >= T(0.) ? v + T(0.5) : v - T(0.5));} + +/*! \brief Templated function return floor of float falue + * \details Floor is the largest integer that is not greater than value \n + * There are some macros: + * - \c piFloorf for "float" + * - \c piFloord for "double" + * + * Example: + * \snippet piincludes.cpp floor */ +template inline int piFloor(const T & v) {return v < T(0) ? int(v) - 1 : int(v);} + +/*! \brief Templated function return ceil of float falue + * \details Ceil is the smallest integer that is not less than value \n + * There are some macros: + * - \c piCeilf for "float" + * - \c piCeild for "double" + * + * Example: + * \snippet piincludes.cpp ceil */ +template inline int piCeil(const T & v) {return v < T(0) ? int(v) : int(v) + 1;} + +/*! \brief Templated function return absolute of numeric falue + * \details Absolute is the positive or equal 0 value \n + * There are some macros: + * - \c piAbss for "short" + * - \c piAbsi for "int" + * - \c piAbsl for "long" + * - \c piAbsll for "llong" + * - \c piAbsf for "float" + * - \c piAbsd for "double" + * + * Example: + * \snippet piincludes.cpp abs */ +template inline T piAbs(const T & v) {return (v >= T(0) ? v : -v);} + +/*! \brief Templated function return minimum of two values + * \details There are some macros: + * - \c piMins for "short" + * - \c piMini for "int" + * - \c piMinl for "long" + * - \c piMinll for "llong" + * - \c piMinf for "float" + * - \c piMind for "double" + * + * Example: + * \snippet piincludes.cpp min2 */ +template inline T piMin(const T & f, const T & s) {return ((f > s) ? s : f);} + +/*! \brief Templated function return minimum of tree values + * \details There are some macros: + * - \c piMins for "short" + * - \c piMini for "int" + * - \c piMinl for "long" + * - \c piMinll for "llong" + * - \c piMinf for "float" + * - \c piMind for "double" + * + * Example: + * \snippet piincludes.cpp min3 */ +template inline T piMin(const T & f, const T & s, const T & t) {return ((f < s && f < t) ? f : ((s < t) ? s : t));} + +/*! \brief Templated function return maximum of two values + * \details There are some macros: + * - \c piMaxs for "short" + * - \c piMaxi for "int" + * - \c piMaxl for "long" + * - \c piMaxll for "llong" + * - \c piMaxf for "float" + * - \c piMaxd for "double" + * + * Example: + * \snippet piincludes.cpp max2 */ +template inline T piMax(const T & f, const T & s) {return ((f < s) ? s : f);} + +/*! \brief Templated function return maximum of tree values + * \details There are some macros: + * - \c piMaxs for "short" + * - \c piMaxi for "int" + * - \c piMaxl for "long" + * - \c piMaxll for "llong" + * - \c piMaxf for "float" + * - \c piMaxd for "double" + * + * Example: + * \snippet piincludes.cpp max3 */ +template inline T piMax(const T & f, const T & s, const T & t) {return ((f > s && f > t) ? f : ((s > t) ? s : t));} + +/*! \brief Templated function return clamped value + * \details Clamped is the not greater than "max" and not lesser than "min" value \n + * There are some macros: + * - \c piClamps for "short" + * - \c piClampi for "int" + * - \c piClampl for "long" + * - \c piClampll for "llong" + * - \c piClampf for "float" + * - \c piClampd for "double" + * + * Example: + * \snippet piincludes.cpp clamp */ +template inline T piClamp(const T & v, const T & min, const T & max) {return (v > max ? max : (v < min ? min : v));} + +/// Function inverse byte order in memory block +inline void piLetobe(void * data, int size) { + for (int i = 0; i < size / 2; i++) + piSwap(((uchar*)data)[size - i - 1], ((uchar*)data)[i]); +} + +/// \brief Templated function that inverse byte order of value "v" +template inline void piLetobe(T * v) {piLetobe(v, sizeof(T));} + +/*! \brief Templated function that returns "v" with inversed byte order + * \details This function used to convert values between little and big endian \n + * There are some macros: + * - \c piLetobes for "ushort" + * - \c piLetobei for "uint" + * - \c piLetobel for "ulong" + * - \c piLetobell for "ullong" + * + * Example: + * \snippet piincludes.cpp letobe */ +template inline T piLetobe(const T & v) {T tv(v); piLetobe(&tv, sizeof(T)); return tv;} + +// specialization +template<> inline ushort piLetobe(const ushort & v) {return (v << 8) | (v >> 8);} +template<> inline uint piLetobe(const uint & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);} + +DEPRECATED inline ushort letobe_s(const ushort & v) {return (v << 8) | (v >> 8);} +DEPRECATED inline uint letobe_i(const uint & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);} + +#ifdef DOXYGEN + +/// \deprecated \brief Use \a piLetobe() instead of this function +ushort letobe_s(ushort v) {return (v << 8) | (v >> 8);} + +/// \deprecated \brief Use \a piLetobe() instead of this function +uint letobe_i(uint v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);} + +#endif + +#define piRoundf piRound +#define piRoundd piRound +#define piFloorf piFloor +#define piFloord piFloor +#define piCeilf piCeil +#define piCeild piCeil +#define piAbss piAbs +#define piAbsi piAbs +#define piAbsl piAbs +#define piAbsll piAbs +#define piAbsf piAbs +#define piAbsd piAbs +#define piMins piMin +#define piMini piMin +#define piMinl piMin +#define piMinll piMin +#define piMinf piMin +#define piMind piMin +#define piMaxs piMax +#define piMaxi piMax +#define piMaxl piMax +#define piMaxll piMax +#define piMaxf piMax +#define piMaxd piMax +#define piClamps piClamp +#define piClampi piClamp +#define piClampl piClamp +#define piClampll piClamp +#define piClampf piClamp +#define piClampd piClamp +#define piLetobes piLetobe +#define piLetobei piLetobe +#define piLetobel piLetobe +#define piLetobell piLetobe + +class PIObject; +class PIMutex; +class PIString; +class PIInit; + +//! global variable enabling output to piCout, default is true +extern PIP_EXPORT bool piDebug; + +//! global variable that set minimum real update interval +//! for function PIInit::mountInfo(), default is 10000 ms +extern PIP_EXPORT double piMountInfoRefreshIntervalMs; + +extern lconv * currentLocale; + +#ifdef WINDOWS +inline int random() {return rand();} +# ifdef CC_VC +inline double round(const double & v) {return floor(v + 0.5);} +# endif +#endif +inline bool atob(const string & str) {return str == "1" ? true : false;} +inline string btos(const bool num) {return num ? "0" : "1";} +inline string itos(const int num) { + char ch[256]; +#ifndef CC_VC + sprintf(ch, "%d", num); +#else + sprintf_s(ch, 256, "%d", num); +#endif + return string(ch);} +inline string ltos(const long num) { + char ch[256]; +#ifndef CC_VC + sprintf(ch, "%ld", num); +#else + sprintf_s(ch, 256, "%ld", num); +#endif + return string(ch);} +inline string uitos(const uint num) { + char ch[256]; +#ifndef CC_VC + sprintf(ch, "%u", num); +#else + sprintf_s(ch, 256, "%u", num); +#endif + return string(ch);} +inline string ultos(const ulong num) { + char ch[256]; +#ifndef CC_VC + sprintf(ch, "%lu", num); +#else + sprintf_s(ch, 256, "%lu", num); +#endif + return string(ch);} +inline string ftos(const float num) { + char ch[256]; +#ifndef CC_VC + sprintf(ch, "%.8f", num); +#else + sprintf_s(ch, 256, "%.8f", num); +#endif + return string(ch);} +inline string dtos(const double num) { + char ch[256]; +#ifndef CC_VC + sprintf(ch, "%.8f", num); +#else + sprintf_s(ch, 256, "%.8f", num); +#endif + return string(ch);} + +/*! \fn errorString() + * \brief Return readable error description in format "code - " */ +PIString errorString(); + +void errorClear(); + +/// Return readable version of PIP +PIString PIPVersion(); + +#endif // PIINCLUDES_H diff --git a/src/core/piinit.cpp b/src/core/piinit.cpp new file mode 100644 index 00000000..3c8879d6 --- /dev/null +++ b/src/core/piinit.cpp @@ -0,0 +1,212 @@ +/* + PIP - Platform Independent Primitives + Initialization + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "piplatform.h" +#include "piinit.h" +#include "pisignals.h" +#include "piobject.h" +#include "pisysteminfo.h" +#include "pidir.h" +#include "piprocess.h" +#ifdef WINDOWS +#else +# include +#endif + + +#ifdef HAS_LOCALE +static locale_t currentLocale_t = 0; +#endif + + +void __sighandler__(PISignals::Signal s) { + //piCout << Hex << int(s); + if (s == PISignals::StopTTYInput || s == PISignals::StopTTYOutput) + piMSleep(10); + if (s == PISignals::UserDefined1) + dumpApplicationToFile(PIDir::home().path() + PIDir::separator + "_PIP_DUMP_" + PIString::fromNumber(PIProcess::currentPID())); +} + + +PIInit::PIInit() { + PISystemInfo * sinfo = PISystemInfo::instance(); + sinfo->execDateTime = PIDateTime::current(); + PISignals::setSlot(__sighandler__); + PISignals::grabSignals(PISignals::UserDefined1); +#ifndef WINDOWS + PISignals::grabSignals(PISignals::StopTTYInput | PISignals::StopTTYOutput); + sigset_t ss; + sigemptyset(&ss); + sigaddset(&ss, SIGALRM); + sigprocmask(SIG_BLOCK, &ss, 0); + pthread_sigmask(SIG_BLOCK, &ss, 0); + signal(SIGPIPE, SIG_IGN); + PIStringList ifpathes; + ifpathes << "/bin/ifconfig" << "/sbin/ifconfig" << "/usr/bin/ifconfig" << "/usr/sbin/ifconfig"; + piForeachC (PIString & i, ifpathes) + if (fileExists(i)) { + sinfo->ifconfigPath = i; + piBreak; + } +#else + // OS version + DWORD dwVersion = GetVersion(); + DWORD dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); + DWORD dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); + sinfo->OS_version = PIString(dwMajorVersion) + "." + PIString(dwMinorVersion); + + // WinSock inint + WSADATA wsaData; + WSAStartup(MAKEWORD(2, 2), &wsaData); + + // Timers init + SYSTEMTIME jan1970 = {1970, 1, 4, 1, 0, 14, 15, 0}; + SystemTimeToFileTime(&jan1970, &__pi_ftjan1970); + LARGE_INTEGER pf; + pf.QuadPart = -1; + if (QueryPerformanceFrequency(&pf) != 0) __pi_perf_freq = pf.QuadPart; + if (__pi_perf_freq == 0) __pi_perf_freq = -1; + + // Sleep precision init + ntlib = LoadLibrary("ntdll.dll"); + if (ntlib) setTimerResolutionAddr = (PINtSetTimerResolution)GetProcAddress(ntlib, "NtSetTimerResolution"); + /*if (setTimerResolution) setTimerResolutionAddr(1, TRUE, &prev_res);*/ +#endif + //piDebug = true; +#ifdef HAS_LOCALE + //cout << "has locale" << endl; + if (currentLocale_t != 0) { + freelocale(currentLocale_t); + currentLocale_t = 0; + } + currentLocale_t = newlocale(LC_ALL, setlocale(LC_ALL, ""), 0); +#else + setlocale(LC_ALL, ""); + setlocale(LC_NUMERIC, "C"); +#endif +#ifdef MAC_OS + host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &__pi_mac_clock); +#endif + char cbuff[1024]; + memset(cbuff, 0, 1024); + if (gethostname(cbuff, 1023) == 0) + sinfo->hostname = cbuff; +#ifdef WINDOWS + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + sinfo->processorsCount = sysinfo.dwNumberOfProcessors; + switch (sysinfo.wProcessorArchitecture) { + case PROCESSOR_ARCHITECTURE_AMD64: sinfo->architecture = "x64"; break; + case PROCESSOR_ARCHITECTURE_ARM: sinfo->architecture = "ARM"; break; + case PROCESSOR_ARCHITECTURE_IA64: sinfo->architecture = "Intel Itanium-based"; break; + case PROCESSOR_ARCHITECTURE_INTEL: sinfo->architecture = "x86"; break; + case PROCESSOR_ARCHITECTURE_UNKNOWN: + default: sinfo->architecture = "unknown"; break; + } + int argc_(0); + wchar_t ** argv_ = CommandLineToArgvW(GetCommandLineW(), &argc_); + if (argc_ > 0 && argv_ != 0) + sinfo->execCommand = argv_[0]; + LocalFree(argv_); + memset(cbuff, 0, 1024); + ulong unlen = 1023; + if (GetUserName(cbuff, &unlen) != 0) + sinfo->user = cbuff; +#else + sinfo->processorsCount = piMaxi(1, int(sysconf(_SC_NPROCESSORS_ONLN))); + passwd * ps = getpwuid(getuid()); + if (ps) + sinfo->user = ps->pw_name; + else { + memset(cbuff, 0, 1024); + if (getlogin_r(cbuff, 1023) == 0) + sinfo->user = cbuff; + } + struct utsname uns; + if (uname(&uns) == 0) { + sinfo->OS_version = uns.release; + sinfo->architecture = uns.machine; + } +#endif + sinfo->OS_name = +#ifdef WINDOWS + "Windows"; +#else +# ifdef QNX + "QNX"; +# else +# ifdef MAC_OS + "MacOS"; +# else +# ifdef ANDROID + "Android"; +# else + uns.sysname; +# endif +# endif +# endif +#endif +} + + +PIInit::~PIInit() { +#ifdef WINDOWS + WSACleanup(); + //if (setTimerResolution) setTimerResolutionAddr(prev_res, TRUE, &prev_res); + if (ntlib) FreeLibrary(ntlib); + ntlib = 0; +#endif +#ifdef MAC_OS + mach_port_deallocate(mach_task_self(), __pi_mac_clock); +#endif + //if (currentLocale_t != 0) freelocale(currentLocale_t); +} + + +bool PIInit::fileExists(const PIString & p) { + FILE * f = fopen(p.data(), "r"); + if (f == 0) + return false; + fclose(f); + return true; +} + + + +int __PIInit_Initializer__::count_(0); +PIInit * __PIInit_Initializer__::__instance__(0); + + +__PIInit_Initializer__::__PIInit_Initializer__() { + count_++; + if (count_ > 1) return; + //piCout << "create PIInit"; + __instance__ = new PIInit(); +} + + +__PIInit_Initializer__::~__PIInit_Initializer__() { + count_--; + if (count_ > 1) return; + //piCout << "delete PIInit"; + if (__instance__ != 0) { + delete __instance__; + __instance__ = 0; + } +} diff --git a/src/core/piinit.h b/src/core/piinit.h new file mode 100644 index 00000000..07bccba1 --- /dev/null +++ b/src/core/piinit.h @@ -0,0 +1,56 @@ +/*! \file piinit.h + * \brief Initialization + * + * +*/ +/* + PIP - Platform Independent Primitives + Initialization + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIINIT_H +#define PIINIT_H + +#include "piincludes.h" + + +class __PIInit_Initializer__ { +public: + __PIInit_Initializer__(); + ~__PIInit_Initializer__(); + static int count_; + static PIInit * __instance__; +}; + + +class PIInit { +public: + PIInit(); + ~PIInit(); + static PIInit * instance() {return __PIInit_Initializer__::__instance__;} +private: + bool fileExists(const PIString & p); +#ifdef WINDOWS + HMODULE ntlib; + ULONG prev_res; +#endif +}; + +static __PIInit_Initializer__ __piinit_initializer__; + + +#endif // PIINIT_H diff --git a/src/core/piobject.cpp b/src/core/piobject.cpp new file mode 100755 index 00000000..a94341a6 --- /dev/null +++ b/src/core/piobject.cpp @@ -0,0 +1,417 @@ +/* + PIP - Platform Independent Primitives + Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "piobject.h" +#include "pifile.h" +#include "pisysteminfo.h" + + +/** \class PIObject + * \brief This is base class for any classes which use events -> handlers mechanism. + * \details + * \section PIObject_sec0 Events and Event handlers + * %PIObject provide notification mechanism similar Qt but implemented + * on language capabilities without any special preprocessors or compilers. + * Any class inherits PIObject should use macro \a PIOBJECT() immediate + * after declaration to proper compile. + * + * Event is a some abstract event that can be raised at any time. + * Event is a function but declared with special macro \a EVENT(). + * To raise event simply execute event function. + * + * Event handler is a function but declared with special macro + * \a EVENT_HANDLER(). You can use event handlers as ordinary functions. + * + * Main goal of this mechanism is perform abstract connections between + * various objects. This functionality provide macro \a CONNECT() which + * connect some event of first object to some event handler or event of + * second object. Each event can be connected any times to any event handlers. + * + * \image html events_handlers.png + * + * Example: \snippet piobject.cpp main + * Result: +\code{.cpp} +handler B: 2 , 0.5 +handler A: event to handler +handler A: event to event +\endcode + */ + + +PIVector PIObject::objects; +PIMutex PIObject::__eh_mutex; +PIMap PIObject::__eh_data; + + +PIString PIObject::__EHFunc::fullFormat() const { + PIString ret = type_ret + " " + scope + "::" + func_name +"("; + for (int i = 0; i < types.size_s(); ++i) { + if (i > 0) ret += ", "; + ret += types[i] + " " + names[i]; + } + ret += ")"; + return ret; +} + + +PIObject::PIObject(const PIString & name): _signature_(__PIOBJECT_SIGNATURE__), emitter_(0), thread_safe_(false) { + piMonitor.objects++; + setName(name); + setDebug(true); + objects << this; + //piCout << "new" << this; +} + + +PIObject::~PIObject() { + //piCout << "delete" << this; + piMonitor.objects--; + objects.removeAll(this); + piDisconnect(this); +} + + +void PIObject::piConnect(const PIString & src, const PIString & sig, void * dest, void * ev_h) { + PIObject * o = findByName(src); + if (o == 0) { + piCout << "[PIObject] Can`t find object with name \"" << src << "\"!"; + return; + } + PIMutexLocker _ml(o->mutex_connect); + o->connections << Connection(ev_h, 0, sig, (PIObject*)dest, dest); + ((PIObject*)dest)->connectors << o; +} + + +void PIObject::piConnect(PIObject * src, const PIString & sig, const PIString & dest, void * ev_h) { + PIObject * o = findByName(dest); + if (o == 0) { + piCout << "[PIObject] Can`t find object with name \"" << dest << "\"!"; + return; + } + PIMutexLocker _ml(o->mutex_connect); + src->connections << Connection(ev_h, 0, sig, o, o); + ((PIObject*)o)->connectors << src; +} + + +void PIObject::piConnect(const PIString & src, const PIString & sig, const PIString & dest, void * ev_h) { + PIObject * s = findByName(src); + if (s == 0) { + piCout << "[PIObject] Can`t find object with name \"" << src << "\"!"; + return; + } + PIObject * d = findByName(dest); + if (d == 0) { + piCout << "[PIObject] Can`t find object with name \"" << dest << "\"!"; + return; + } + PIMutexLocker _ml(s->mutex_connect); + s->connections << Connection(ev_h, 0, sig, d, d); + d->connectors << s; +} + +/* +PIStringList PIObject::events() { + PIStringList l; + for (PIMap::const_iterator i = signals_.begin(); i != signals_.end(); i++) + l << (*i).first; + return l; +} +*/ + +PIStringList PIObject::methodsEH() { + PIMutexLocker ml(__eh_mutex); + PIStringList ret; + __EHData & ehd(__eh_data[className()]); + piForeachC (__EHPair & eh, ehd.eh_func) + ret << eh.second.fullFormat(); + return ret; +} + + +bool PIObject::isMethodEHContains(const PIString & name) const { + PIMutexLocker ml(__eh_mutex); + __EHData & ehd(__eh_data[className()]); + piForeachC (__EHPair & eh, ehd.eh_func) + if (eh.second.func_name == name) + return true; + return false; +} + + +PIString PIObject::methodEHArguments(const PIString & name) const { + PIMutexLocker ml(__eh_mutex); + __EHData & ehd(__eh_data[className()]); + piForeachC (__EHPair & eh, ehd.eh_func) + if (eh.second.func_name == name) + return eh.second.arguments(); + return PIString(); +} + + +PIString PIObject::methodEHFullFormat(const PIString & name) const { + PIMutexLocker ml(__eh_mutex); + __EHData & ehd(__eh_data[className()]); + piForeachC (__EHPair & eh, ehd.eh_func) + if (eh.second.func_name == name) + return eh.second.fullFormat(); + return PIString(); +} + + +PIString PIObject::methodEHFromAddr(const void * addr) const { + return methodEH(addr).func_name; +} + + +PIVector PIObject::findEH(const PIString & name) const { + PIVector<__EHFunc> ret; + __EHData & ehd(__eh_data[className()]); + piForeachC (__EHPair & eh, ehd.eh_func) + if (eh.second.func_name == name) + ret << eh.second; + return ret; +} + + +PIObject::__EHFunc PIObject::methodEH(const void * addr) const { + PIMutexLocker ml(__eh_mutex); + return __eh_data[className()].eh_func.value(addr); +} + + +void PIObject::piConnect(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, void * ev_h, void * e_h, int args) { + //piCout << "piConnect ..."; + //piCout << "piConnect" << src << (void*)(dest) << sig; + //piCout << "piConnect" << src->className() << "->" << ((PIObject*)dest)->className(); + PIMutexLocker _ml(src->mutex_connect); + src->connections << Connection(ev_h, e_h, sig, dest_o, dest, args); + //piCout << "piConnect" << ((PIObject*)dest) << sig << ((PIObject*)dest)->connectors.size_s() << "..."; + //piCout << "addConnector" << dest_o << src; + dest_o->connectors << src; + //piCout << "piConnect" << ((PIObject*)dest) << sig << ((PIObject*)dest)->connectors.size_s(); + //piCout << "piConnect ok"; +} + + +bool PIObject::piConnectU(PIObject * src, const PIString & ename, PIObject * dest_o, void * dest, const PIString & hname) { + if (src == 0 || dest_o == 0 || dest == 0) return false; + PIMutexLocker ml(__eh_mutex); + PIVector<__EHFunc> m_src = src->findEH(ename), m_dest = dest_o->findEH(hname); + if (m_src.isEmpty()) { + piCout << "[piConnectU] Error: can`t find event \"" << ename << "\" in class \"" << src->className() << "\"!"; + return false; + } + if (m_dest.isEmpty()) { + piCout << "[piConnectU] Error: can`t find handler \"" << hname << "\" in class \"" << dest_o->className() << "\"!"; + return false; + } + void * addr_src(0), * addr_dest(0); + int args(0); + piForeachC (__EHFunc & fs, m_src) { + if (addr_src != 0) break; + piForeachC (__EHFunc & fd, m_dest) { + if (addr_src != 0) break; + if (fs.arguments().startsWith(fd.arguments()) || fd.arguments().isEmpty()) { + addr_src = fs.addr; + addr_dest = fd.addr; + args = fd.names.size_s(); + } + } + } + if (addr_src == 0) { + piCout << "[piConnectU] Error: can`t find suitable pair of event \"" << ename << "\" in class \"" << src->className() + << "\" and handler \"" << hname << "\" in class \"" << dest_o->className() << "\"!"; + return false; + } + //piCout << "connect" << ename << "->" << hname << "with" << args << "args"; + src->connections << PIObject::Connection(addr_dest, addr_src, ename, dest_o, dest, args); + dest_o->connectors << src; + return true; +} + + +void PIObject::piDisconnect(PIObject * src, const PIString & sig, PIObject * dest, void * ev_h) { + PIMutexLocker _ml(src->mutex_connect); + for (int i = 0; i < src->connections.size_s(); ++i) { + Connection & cc(src->connections[i]); + if (cc.event == sig && cc.dest_o == dest && cc.slot == ev_h) { + src->connections.remove(i); + i--; + } + } + ((PIObject*)dest)->updateConnectors(); +} + + +void PIObject::piDisconnect(PIObject * src, const PIString & sig, PIObject * dest) { + PIMutexLocker _ml(src->mutex_connect); + for (int i = 0; i < src->connections.size_s(); ++i) { + Connection & cc(src->connections[i]); + if (cc.event == sig && cc.dest_o == dest) { + src->connections.remove(i); + i--; + } + } + ((PIObject*)dest)->updateConnectors(); +} + + +void PIObject::piDisconnect(PIObject * src, const PIString & sig) { + PIMutexLocker _ml(src->mutex_connect); + for (int i = 0; i < src->connections.size_s(); ++i) { + Connection & cc(src->connections[i]); + if (cc.event == sig) { + PIObject * dest = cc.dest_o; + src->connections.remove(i); + i--; + dest->updateConnectors(); + } + } +} + + +void PIObject::piDisconnect(PIObject * src) { + PIMutexLocker _ml(src->mutex_connect); + PIVector cv = src->connectors.toVector(); + piForeach (PIObject * o, cv) { + if (o == src) continue; + PIVector & oc(o->connections); + for (int i = 0; i < oc.size_s(); ++i) { + //piCout << " check" << (void*)(oc[i].dest_o) << "==" << (void*)(src); + if (oc[i].dest_o == src) { + oc.remove(i); + --i; + } + } + } + piForeachC (PIObject::Connection & c, src->connections) + c.dest_o->connectors.remove(src); + src->connections.clear(); +} + + +void PIObject::updateConnectors() { + //piCout << "*** updateConnectors" << this; + connectors.clear(); + piForeach (PIObject * o, objects) { + if (o == this) continue; + PIVector & oc(o->connections); + piForeach (Connection & c, oc) + if (c.dest == this) + connectors << o; + } +} + + +bool PIObject::execute(const PIString & method) { + if (method.isEmpty()) return false; + PIVector<__EHFunc> ml = findEH(method); + piForeachC (__EHFunc & m, ml) { + if (!m.names.isEmpty()) continue; + ((void(*)(void*))m.addr)(this); + return true; + } + piCoutObj << "Error: can`t find event or handler \"" << (method + "()") << "\" to execute!"; + return false; +} + + + + +void PIObject::dump(const PIString & line_prefix) const { + //printf("dump %s \"%s\"\n", className(), name().data()); + PICout(AddNewLine) << line_prefix << "class " << className() << " (" << (const void*)this << ", \"" << name() << "\") {"; + PICout(AddNewLine) << line_prefix << " properties {"; + PICout(AddNewLine) << line_prefix << " count: " << properties_.size_s(); + //printf("dump %d properties\n", properties_.size()); + piForeachC (Property p, properties_) + if (p.first != "name") + PICout(AddNewLine) << line_prefix << " " << p.first << ": " << p.second; + //printf("dump %d properties ok\n", properties_.size()); + PICout(AddNewLine) << line_prefix << " }"; + PICout(AddNewLine) << line_prefix << " methodsEH {"; + __EHData & ehd(__eh_data[className()]); + PICout(AddNewLine) << line_prefix << " count: " << ehd.eh_func.size_s(); + //printf("dump %d methods\n", ehd.eh_func.size()); + piForeachC (__EHPair & eh, ehd.eh_func) { + PICout(AddNewLine) << line_prefix << " " << eh.second.fullFormat(); + } + //printf("dump %d methods ok\n", ehd.eh_func.size()); + PICout(AddNewLine) << line_prefix << " }"; + PICout(AddNewLine) << line_prefix << " connections {"; + PICout(AddNewLine) << line_prefix << " count: " << connections.size_s(); + //printf("dump %d connections\n",connections.size()); + piForeachC (Connection & c, connections) { + PIObject * dst = c.dest_o; + __EHFunc hf = dst->methodEH(c.slot); + __EHFunc ef = methodEH(c.signal); + if (hf.func_name.isEmpty()) hf.func_name = "[BROKEN]"; + else hf.func_name += "(" + hf.arguments() + ")"; + PIString src(c.event); + if (!ef.func_name.isEmpty()) + src = ef.func_name + "(" + ef.arguments() + ")"; + PICout(AddNewLine) << line_prefix << " " << src << " -> " << dst->className() << " (" << c.dest << ", \"" << dst->name() << "\")::" << hf.func_name; + } + //printf("dump %d connections ok\n",connections.size()); + PICout(AddNewLine) << line_prefix << " }"; + PICout(AddNewLine) << line_prefix << "}"; +} + + + + +void dumpApplication() { + //printf("dump application ...\n"); + PIDateTime cd = PIDateTime::current(); + PISystemInfo * pi = PISystemInfo::instance(); + PICout(AddNewLine) << "application {"; + PICout(AddNewLine) << " PIP version: " << PIPVersion(); + PICout(AddNewLine) << " processors: " << pi->processorsCount; + PICout(AddNewLine) << " hostname: \"" << pi->hostname << "\""; + PICout(AddNewLine) << " user: \"" << pi->user << "\""; + PICout(AddNewLine) << " exec command: \"" << pi->execCommand << "\""; + PICout(AddNewLine) << " started: " << pi->execDateTime.toString(); + PICout(AddNewLine) << " uptime, s: " << (cd.toSystemTime() - pi->execDateTime.toSystemTime()).toSeconds(); + PICout(AddNewLine) << " PIObjects {"; + PICout(AddNewLine) << " count: " << PIObject::objects.size_s(); + piForeachC (PIObject * o, PIObject::objects) + o->dump(" "); + PICout(AddNewLine) << " }"; + PICout(AddNewLine) << "}"; + //printf("dump application done\n"); +} + + +bool dumpApplicationToFile(const PIString & path) { + PIFile f(path + "_tmp"); + f.setName("__S__DumpFile"); + f.clear(); + if (!f.open(PIIODevice::WriteOnly)) return false; + bool ba = PICout::isBufferActive(); + PICout::setBufferActive(true, true); + dumpApplication(); + f << PICout::buffer(); + f.close(); + PICout::setBufferActive(ba, true); + PIFile::rename(path + "_tmp", path); + return true; +} diff --git a/src/core/piobject.h b/src/core/piobject.h new file mode 100755 index 00000000..51cb4bf8 --- /dev/null +++ b/src/core/piobject.h @@ -0,0 +1,733 @@ +/*! \file piobject.h + * \brief Base object + * + * This file declare PIObject class and associated macros +*/ +/* + PIP - Platform Independent Primitives + Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIOBJECT_H +#define PIOBJECT_H + +#include "piinit.h" +#include "pivariant.h" +#include "pimutex.h" + + +#ifdef DOXYGEN + + +/// \relatesalso PIObject \brief you should use this macro after class declaration to use EVENT and EVENT_HANDLER and correct piCoutObj output +#define PIOBJECT(name) + +/// \relatesalso PIObject \brief you should use this macro after class declaration to use EVENT and EVENT_HANDLER of parent class +#define PIOBJECT_SUBCLASS(name, parent) + + +/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name() +#define EVENT_HANDLER0(ret, name) ret name() + +/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name(type0 var0) +#define EVENT_HANDLER1(ret, name, type0, var0) ret name(type0 var0) + +/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name(type0 var0, type1 var1) +#define EVENT_HANDLER2(ret, name, type0, var0, type1, var1) ret name(type0 var0, type1 var1) + +/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name(type0 var0, type1 var1, type2 var2) +#define EVENT_HANDLER3(ret, name, type0, var0, type1, var1, type2, var2) ret name(type0 var0, type1 var1, type2 var2) + +/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name(type0 var0, type1 var1, type2 var2, type3 var3) +#define EVENT_HANDLER4(ret, name, type0, var0, type1, var1, type2, var2, type3, var3) ret name(type0 var0, type1 var1, type2 var2, type3 var3) + +/// \relatesalso PIObject \brief EVENT_HANDLER is synonym of EVENT_HANDLER0 +#define EVENT_HANDLER EVENT_HANDLER0 + + +/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name() +#define EVENT_VHANDLER0(ret, name) virtual ret name() + +/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name(type0 var0) +#define EVENT_VHANDLER1(ret, name, type0, var0) virtual ret name(type0 var0) + +/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1) +#define EVENT_VHANDLER2(ret, name, type0, var0, type1, var1) virtual ret name(type0 var0, type1 var1) + +/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1, type2 var2) +#define EVENT_VHANDLER3(ret, name, type0, var0, type1, var1, type2, var2) virtual ret name(type0 var0, type1 var1, type2 var2) + +/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1, type2 var2, type3 var3) +#define EVENT_VHANDLER4(ret, name, type0, var0, type1, var1, type2, var2, type3, var3) virtual ret name(type0 var0, type1 var1, type2 var2, type3 var3) + +/// \relatesalso PIObject \brief EVENT_VHANDLER is synonym of EVENT_VHANDLER0 +#define EVENT_VHANDLER EVENT_VHANDLER0 + + +/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name(); +#define EVENT0(name) void name(); + +/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name(type0 var0); +#define EVENT1(name, type0, var0) void name(type0 var0); + +/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name(type0 var0, type1 var1); +#define EVENT2(name, type0, var0, type1, var1) void name(type0 var0, type1 var1); + +/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name(type0 var0, type1 var1, type2 var2); +#define EVENT3(name, type0, var0, type1, var1, type2, var2) void name(type0 var0, type1 var1, type2 var2); + +/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name(type0 var0, type1 var1, type2 var2, type3 var3); +#define EVENT4(name, type0, var0, type1, var1, type2, var2, type3, var3) void name(type0 var0, type1 var1, type2 var2, type3 var3); + +/// \relatesalso PIObject \brief EVENT is synonym of EVENT0 +#define EVENT EVENT0 + + +#define RAISE_EVENT0(src, event) +#define RAISE_EVENT1(src, event, v0) +#define RAISE_EVENT2(src, event, v0, v1) +#define RAISE_EVENT3(src, event, v0, v1, v2) +#define RAISE_EVENT4(src, event, v0, v1, v2, v3) +#define RAISE_EVENT RAISE_EVENT0 + + +/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\". \"Event\" and \"handler\" must has equal argument lists. +#define CONNECTU(src, event, dest, handler) + +/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists +#define CONNECT0(ret, src, event, dest, handler) + +/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists +#define CONNECT1(ret, type0, src, event, dest, handler) + +/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists +#define CONNECT2(ret, type0, type1, src, event, dest, handler) + +/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists +#define CONNECT3(ret, type0, type1, type2, src, event, dest, handler) + +/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists +#define CONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler) + +/// \relatesalso PIObject \brief CONNECT is synonym of CONNECT0 +#define CONNECT CONNECT0 + + +/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists +#define WEAK_CONNECT0(ret, src, event, dest, handler) + +/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists +#define WEAK_CONNECT1(ret, type0, src, event, dest, handler) + +/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists +#define WEAK_CONNECT2(ret, type0, type1, src, event, dest, handler) + +/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists +#define WEAK_CONNECT3(ret, type0, type1, type2, src, event, dest, handler) + +/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists +#define WEAK_CONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler) + +/// \relatesalso PIObject \brief WEAK_CONNECT is synonym of WEAK_CONNECT0 +#define WEAK_CONNECT WEAK_CONNECT0 + + +/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\" +#define DISCONNECT0(ret, src, event, dest, handler) + +/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\" +#define DISCONNECT1(ret, type0, src, event, dest, handler) + +/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\" +#define DISCONNECT2(ret, type0, type1, src, event, dest, handler) + +/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\" +#define DISCONNECT3(ret, type0, type1, type2, src, event, dest, handler) + +/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\" +#define DISCONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler) + +/// \relatesalso PIObject \brief DISCONNECT is synonym of DISCONNECT0 +#define DISCONNECT DISCONNECT0 + + +/// \relatesalso PIObject \brief Returns pointer to events handler \"handler\" +#define HANDLER(handler) + + +#define PIOBJECT(name) +#define PIOBJECT_SUBCLASS(name) + + +#else + + +#define PIOBJECT(name) \ + protected: \ + typedef name __PIObject__; \ + static const PIString __classNameS() {return PIString(#name);} \ + public: \ + virtual const char * className() const {return #name;} \ + private: + +#define PIOBJECT_PARENT(name) \ + class __##name##_ParentInitializer__ { \ + public: \ + __##name##_ParentInitializer__() { \ + PIString pn(name::__classNameS()); \ + if (pn.isEmpty()) return; \ + PIMutexLocker ml(__eh_mutex); \ + if (__eh_data.contains(__classNameS())) return; \ + __eh_data[pn]; \ + __eh_data[__classNameS()]; \ + __EHData & ehp(__eh_data[pn]); \ + __EHData & eh(__eh_data[__classNameS()]); \ + eh.eh_set << ehp.eh_set; \ + eh.eh_func << ehp.eh_func; \ + } \ + }; \ + __##name##_ParentInitializer__ __##name##_parent_init__; \ + public: \ + virtual const char * superClassName() const {return #name;} \ + private: + +#define PIOBJECT_SUBCLASS(name, parent) PIOBJECT(name) PIOBJECT_PARENT(parent) + + +#define EH_INIT0(ret, name) \ + class __##name##0_Initializer__ { \ + public: \ + __##name##0_Initializer__() { \ + PIMutexLocker ml(__eh_mutex); \ + __EHData & eh(__eh_data[__classNameS()]); \ + void * fp = (void*)(ret(*)(void*))__stat_eh_##name##__; \ + if (eh.eh_set[fp]) return; \ + eh.eh_set << fp; \ + __EHFunc & f(eh.eh_func[fp]); \ + f.scope = __classNameS(); \ + f.func_name = #name; \ + f.addr = fp; \ + f.type_ret = #ret; \ + } \ + }; \ + __##name##0_Initializer__ __##name##0_init__; \ + +#define EH_INIT1(ret, name, a0, n0) \ + class __##name##1##n0##_Initializer__ { \ + public: \ + __##name##1##n0##_Initializer__() { \ + PIMutexLocker ml(__eh_mutex); \ + __EHData & eh(__eh_data[__classNameS()]); \ + void * fp = (void*)(ret(*)(void*, a0))__stat_eh_##name##__; \ + if (eh.eh_set[fp]) return; \ + eh.eh_set << fp; \ + __EHFunc & f(eh.eh_func[fp]); \ + f.scope = __classNameS(); \ + f.func_name = #name; \ + f.addr = fp; \ + f.type_ret = #ret; \ + f.types << #a0; \ + f.names << #n0; \ + } \ + }; \ + __##name##1##n0##_Initializer__ __##name##1##n0##_init__; \ + +#define EH_INIT2(ret, name, a0, n0, a1, n1) \ + class __##name##2##n0##n1##_Initializer__ { \ + public: \ + __##name##2##n0##n1##_Initializer__() { \ + PIMutexLocker ml(__eh_mutex); \ + __EHData & eh(__eh_data[__classNameS()]); \ + void * fp = (void*)(ret(*)(void*, a0, a1))__stat_eh_##name##__; \ + if (eh.eh_set[fp]) return; \ + eh.eh_set << fp; \ + __EHFunc & f(eh.eh_func[fp]); \ + f.scope = __classNameS(); \ + f.func_name = #name; \ + f.addr = fp; \ + f.type_ret = #ret; \ + f.types << #a0 << #a1; \ + f.names << #n0 << #n1; \ + } \ + }; \ + __##name##2##n0##n1##_Initializer__ __##name##2##n0##n1##_init__; \ + +#define EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \ + class __##name##3##n0##n1##n2##_Initializer__ { \ + public: \ + __##name##3##n0##n1##n2##_Initializer__() { \ + PIMutexLocker ml(__eh_mutex); \ + __EHData & eh(__eh_data[__classNameS()]); \ + void * fp = (void*)(ret(*)(void*, a0, a1, a2))__stat_eh_##name##__; \ + if (eh.eh_set[fp]) return; \ + eh.eh_set << fp; \ + __EHFunc & f(eh.eh_func[fp]); \ + f.scope = __classNameS(); \ + f.func_name = #name; \ + f.addr = fp; \ + f.type_ret = #ret; \ + f.types << #a0 << #a1 << #a2; \ + f.names << #n0 << #n1 << #n2; \ + } \ + }; \ + __##name##3##n0##n1##n2##_Initializer__ __##name##3##n0##n1##n2##_init__; \ + +#define EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \ + class __##name##4##n0##n1##n2##n3##_Initializer__ { \ + public: \ + __##name##4##n0##n1##n2##n3##_Initializer__() { \ + PIMutexLocker ml(__eh_mutex); \ + __EHData & eh(__eh_data[__classNameS()]); \ + void * fp = (void*)(ret(*)(void*, a0, a1, a2, a3))__stat_eh_##name##__; \ + if (eh.eh_set[fp]) return; \ + eh.eh_set << fp; \ + __EHFunc & f(eh.eh_func[fp]); \ + f.scope = __classNameS(); \ + f.func_name = #name; \ + f.addr = fp; \ + f.type_ret = #ret; \ + f.types << #a0 << #a1 << #a2 << #a3; \ + f.names << #n0 << #n1 << #n2 << #n3; \ + } \ + }; \ + __##name##4##n0##n1##n2##n3##_Initializer__ __##name##4##n0##n1##n2##n3##_init__; \ + + +#define EVENT_HANDLER0(ret, name) \ + EH_INIT0(ret, name) \ + static ret __stat_eh_##name##__(void * __o__) {return ((__PIObject__*)__o__)->name();} \ + ret name() + +#define EVENT_HANDLER1(ret, name, a0, n0) \ + EH_INIT1(ret, name, a0, n0) \ + static ret __stat_eh_##name##__(void * __o__, a0 n0) {return ((__PIObject__*)__o__)->name(n0);} \ + ret name(a0 n0) + +#define EVENT_HANDLER2(ret, name, a0, n0, a1, n1) \ + EH_INIT2(ret, name, a0, n0, a1, n1) \ + static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1) {return ((__PIObject__*)__o__)->name(n0, n1);} \ + ret name(a0 n0, a1 n1) + +#define EVENT_HANDLER3(ret, name, a0, n0, a1, n1, a2, n2) \ + EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \ + static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2) {return ((__PIObject__*)__o__)->name(n0, n1, n2);} \ + ret name(a0 n0, a1 n1, a2 n2) + +#define EVENT_HANDLER4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \ + EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \ + static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2, a3 n3) {return ((__PIObject__*)__o__)->name(n0, n1, n2, n3);} \ + ret name(a0 n0, a1 n1, a2 n2, a3 n3) + +#define EVENT_HANDLER EVENT_HANDLER0 + + +#define EVENT_VHANDLER0(ret, name) \ + EH_INIT0(ret, name) \ + static ret __stat_eh_##name##__(void * __o__) {return ((__PIObject__*)__o__)->name();} \ + virtual ret name() + +#define EVENT_VHANDLER1(ret, name, a0, n0) \ + EH_INIT1(ret, name, a0, n0) \ + static ret __stat_eh_##name##__(void * __o__, a0 n0) {return ((__PIObject__*)__o__)->name(n0);} \ + virtual ret name(a0 n0) + +#define EVENT_VHANDLER2(ret, name, a0, n0, a1, n1) \ + EH_INIT2(ret, name, a0, n0, a1, n1) \ + static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1) {return ((__PIObject__*)__o__)->name(n0, n1);} \ + virtual ret name(a0 n0, a1 n1) + +#define EVENT_VHANDLER3(ret, name, a0, n0, a1, n1, a2, n2) \ + EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \ + static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2) {return ((__PIObject__*)__o__)->name(n0, n1, n2);} \ + virtual ret name(a0 n0, a1 n1, a2 n2) + +#define EVENT_VHANDLER4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \ + EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \ + static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2, a3 n3) {return ((__PIObject__*)__o__)->name(n0, n1, n2, n3);} \ + virtual ret name(a0 n0, a1 n1, a2 n2, a3 n3) + +#define EVENT_VHANDLER EVENT_VHANDLER0 + + +#define EVENT0(name) EVENT_HANDLER0(void, name) {PIObject::raiseEvent(this, #name);} +#define EVENT1(name, a0, n0) EVENT_HANDLER1(void, name, a0, n0) {PIObject::raiseEvent(this, #name, n0);} +#define EVENT2(name, a0, n0, a1, n1) EVENT_HANDLER2(void, name, a0, n0, a1, n1) {PIObject::raiseEvent(this, #name, n0, n1);} +#define EVENT3(name, a0, n0, a1, n1, a2, n2) EVENT_HANDLER3(void, name, a0, n0, a1, n1, a2, n2) {PIObject::raiseEvent(this, #name, n0, n1, n2);} +#define EVENT4(name, a0, n0, a1, n1, a2, n2, a3, n3) EVENT_HANDLER4(void, name, a0, n0, a1, n1, a2, n2, a3, n3) {PIObject::raiseEvent(this, #name, n0, n1, n2, n3);} +#define EVENT EVENT0 + +#define RAISE_EVENT0(src, event) (src)->event(); +#define RAISE_EVENT1(src, event, v0) (src)->event(v0); +#define RAISE_EVENT2(src, event, v0, v1) (src)->event(v0, v1); +#define RAISE_EVENT3(src, event, v0, v1, v2) (src)->event(v0, v1, v2); +#define RAISE_EVENT4(src, event, v0, v1, v2, v3) (src)->event(v0, v1, v2, v3); +#define RAISE_EVENT RAISE_EVENT0 + +#define CONNECTU(src, event, dest, handler) PIObject::piConnectU(src, #event, dest, dest, #handler); + +#define CONNECT0(ret, src, event, dest, handler) PIObject::piConnect(src, #event, dest, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*))(&(src)->__stat_eh_##event##__), 0); +#define CONNECT1(ret, a0, src, event, dest, handler) PIObject::piConnect(src, #event, dest, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0))(&(src)->__stat_eh_##event##__), 1); +#define CONNECT2(ret, a0, a1, src, event, dest, handler) PIObject::piConnect(src, #event, dest, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1))(&(src)->__stat_eh_##event##__), 2); +#define CONNECT3(ret, a0, a1, a2, src, event, dest, handler) PIObject::piConnect(src, #event, dest, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1, a2))(&(src)->__stat_eh_##event##__), 3); +#define CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) PIObject::piConnect(src, #event, dest, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1, a2, a3))(&(src)->__stat_eh_##event##__), 4); +#define CONNECT CONNECT0 + +#define WEAK_CONNECT0(ret, src, event, dest, handler) PIObject::piConnect(src, #event, dest, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__), 0, 0); +#define WEAK_CONNECT1(ret, a0, src, event, dest, handler) PIObject::piConnect(src, #event, dest, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__), 0, 1); +#define WEAK_CONNECT2(ret, a0, a1, src, event, dest, handler) PIObject::piConnect(src, #event, dest, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__), 0, 2); +#define WEAK_CONNECT3(ret, a0, a1, a2, src, event, dest, handler) PIObject::piConnect(src, #event, dest, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__), 0, 3); +#define WEAK_CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) PIObject::piConnect(src, #event, dest, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__), 0, 4); +#define WEAK_CONNECT WEAK_CONNECT0 + +#define DISCONNECT0(ret, src, event, dest, handler) PIObject::piDisconnect(src, #event, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__)); +#define DISCONNECT1(ret, a0, src, event, dest, handler) PIObject::piDisconnect(src, #event, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__)); +#define DISCONNECT2(ret, a0, a1, src, event, dest, handler) PIObject::piDisconnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__)); +#define DISCONNECT3(ret, a0, a1, a2, src, event, dest, handler) PIObject::piDisconnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__)); +#define DISCONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) PIObject::piDisconnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__)); +#define DISCONNECT DISCONNECT0 + +#define HANDLER(handler) __stat_eh_##handler##__ + +#define __PIOBJECT_SIGNATURE__ 0xabcdbadc + +#endif + +typedef void (*Handler)(void * ); + +class PIP_EXPORT PIObject +{ + friend class PIObjectManager; + friend void dumpApplication(); +public: + + //! Contructs PIObject with name "name" + PIObject(const PIString & name = PIString()); + + virtual ~PIObject(); + +private: + uint _signature_; + +public: + + + //! Returns object name + PIString name() const {return property("name").toString();} + + //! Returns object class name + virtual const char * className() const {return "PIObject";} + + //! Returns object superclass name + virtual const char * superClassName() const {return "";} + + //! Return if debug of this object is active + bool debug() const {return property("debug").toBool();} + + + //! Set object name + void setName(const PIString & name) {setProperty("name", name);} + + //! Set object debug active + void setDebug(bool debug) {setProperty("debug", debug);} + + //! Returns properties of the object + const PIMap & properties() const {return properties_;} + + //! Returns properties count of the object + int propertiesCount() const {return properties_.size_s();} + + //! Returns property with name "name" + PIVariant property(const PIString & name) const {if (!properties_.contains(name)) return PIVariant(); return properties_.value(name);} + + //! Set property with name "name" to "value". If there is no such property in object it will be added + void setProperty(const PIString & name, const PIVariant & value) {properties_[name] = value; propertyChanged(name);} + + //! Returns if property with name "name" exists + bool isPropertyExists(const PIString & name) const {return properties_.contains(name);} + + void setThreadSafe(bool yes) {thread_safe_ = yes;} + bool isThreadSafe() const {return thread_safe_;} + + void dump(const PIString & line_prefix = PIString()) const; + + + PIStringList methodsEH(); + bool isMethodEHContains(const PIString & name) const; + PIString methodEHArguments(const PIString & name) const; + PIString methodEHFullFormat(const PIString & name) const; + PIString methodEHFromAddr(const void * addr) const; + + /* + template + static void piConnectU(PIObject * src, RS(*sig)(void*), PIObject * dest, RD(*slt)(void*), PIString signame) { + src->connections << PIObject::Connection((void*)slt, (void*)sig, signame, dest); + } + template + static void piConnectU(PIObject * src, RS(*sig)(void*,A0), PIObject * dest, RD(*slt)(void*,A0), PIString signame) { + src->connections << PIObject::Connection((void*)slt, (void*)sig, signame, dest); + } + template + static void piConnectU(PIObject * src, RS(*sig)(void*,A0,A1), PIObject * dest, RD(*slt)(void*,A0,A1), PIString signame) { + src->connections << PIObject::Connection((void*)slt, (void*)sig, signame, dest); + } + template + static void piConnectU(PIObject * src, RS(*sig)(void*,A0,A1,A2), PIObject * dest, RD(*slt)(void*,A0,A1,A2), PIString signame) { + src->connections << PIObject::Connection((void*)slt, (void*)sig, signame, dest); + } + template + static void piConnectU(PIObject * src, RS(*sig)(void*,A0,A1,A2,A3), PIObject * dest, RD(*slt)(void*,A0,A1,A2,A3), PIString signame) { + src->connections << PIObject::Connection((void*)slt, (void*)sig, signame, dest); + } + template + static void piConnectU(PIObject * src, RS(*sig)(void*,A0,A1,A2,A3,A4), PIObject * dest, RD(*slt)(void*,A0,A1,A2,A3,A4), PIString signame) { + src->connections << PIObject::Connection((void*)slt, (void*)sig, signame, dest); + } + */ + + // / Direct connect + static void piConnect(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, void * ev_h, void * e_h, int args); + static bool piConnectU(PIObject * src, const PIString & ename, PIObject * dest_o, void * dest, const PIString & hname); + + // / Through names and mixed + static void piConnect(const PIString & src, const PIString & sig, void * dest, void * ev_h); + static void piConnect(PIObject * src, const PIString & sig, const PIString & dest, void * ev_h); + static void piConnect(const PIString & src, const PIString & sig, const PIString & dest, void * ev_h); + + + static void piDisconnect(PIObject * src, const PIString & sig, PIObject * dest, void * ev_h); + static void piDisconnect(PIObject * src, const PIString & sig, PIObject * dest); + + //! Disconnect object "src" from all connections with event name "sig" + static void piDisconnect(PIObject * src, const PIString & sig); + + //! Disconnect object "src" from all connections, i.e. all connections where object "src" is emitter + static void piDisconnect(PIObject * src); + + // / Raise events + static void raiseEvent(PIObject * sender, const PIString & event) { + for (int j = 0; j < sender->connections.size_s(); ++j) { + Connection & i(sender->connections[j]); + if (i.event != event) continue; + //piCout << uint(i.dest) << uint(i.dest_o); + if (sender->thread_safe_) i.dest_o->mutex_.lock(); + i.dest_o->emitter_ = sender; + ((void( *)(void * ))i.slot)(i.dest); + i.dest_o->emitter_ = 0; + if (sender->thread_safe_) i.dest_o->mutex_.unlock(); + } + } + + template + static void raiseEvent(PIObject * sender, const PIString & event, const T0 & v0 = T0()) { + for (int j = 0; j < sender->connections.size_s(); ++j) { + Connection & i(sender->connections[j]); + if (i.event != event) continue; + if (sender->thread_safe_) i.dest_o->mutex_.lock(); + i.dest_o->emitter_ = sender; + if (i.args_count == 0) ((void(*)(void *))i.slot)(i.dest); + else ((void(*)(void * , T0))i.slot)(i.dest, v0); + i.dest_o->emitter_ = 0; + if (sender->thread_safe_) i.dest_o->mutex_.unlock(); + } + } + template + static void raiseEvent(PIObject * sender, const PIString & event, const T0 & v0 = T0(), const T1 & v1 = T1()) { + for (int j = 0; j < sender->connections.size_s(); ++j) { + Connection & i(sender->connections[j]); + if (i.event != event) continue; + if (sender->thread_safe_) i.dest_o->mutex_.lock(); + i.dest_o->emitter_ = sender; + switch (i.args_count) { + case 0: ((void(*)(void *))i.slot)(i.dest); break; + case 1: ((void(*)(void * , T0))i.slot)(i.dest, v0); break; + default: ((void(*)(void * , T0, T1))i.slot)(i.dest, v0, v1); break; + } + i.dest_o->emitter_ = 0; + if (sender->thread_safe_) i.dest_o->mutex_.unlock(); + } + } + template + static void raiseEvent(PIObject * sender, const PIString & event, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2()) { + for (int j = 0; j < sender->connections.size_s(); ++j) { + Connection & i(sender->connections[j]); + if (i.event != event) continue; + if (sender->thread_safe_) i.dest_o->mutex_.lock(); + i.dest_o->emitter_ = sender; + switch (i.args_count) { + case 0: ((void(*)(void *))i.slot)(i.dest); break; + case 1: ((void(*)(void * , T0))i.slot)(i.dest, v0); break; + case 2: ((void(*)(void * , T0, T1))i.slot)(i.dest, v0, v1); break; + default: ((void(*)(void * , T0, T1, T2))i.slot)(i.dest, v0, v1, v2); break; + } + i.dest_o->emitter_ = 0; + if (sender->thread_safe_) i.dest_o->mutex_.unlock(); + } + } + template + static void raiseEvent(PIObject * sender, const PIString & event, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2(), const T3 & v3 = T3()) { + for (int j = 0; j < sender->connections.size_s(); ++j) { + Connection & i(sender->connections[j]); + if (i.event != event) continue; + if (sender->thread_safe_) i.dest_o->mutex_.lock(); + i.dest_o->emitter_ = sender; + switch (i.args_count) { + case 0: ((void(*)(void *))i.slot)(i.dest); break; + case 1: ((void(*)(void * , T0))i.slot)(i.dest, v0); break; + case 2: ((void(*)(void * , T0, T1))i.slot)(i.dest, v0, v1); break; + case 3: ((void(*)(void * , T0, T1, T2))i.slot)(i.dest, v0, v1, v2); break; + default: ((void(*)(void * , T0, T1, T2, T3))i.slot)(i.dest, v0, v1, v2, v3); break; + } + i.dest_o->emitter_ = 0; + if (sender->thread_safe_) i.dest_o->mutex_.unlock(); + } + } + + /* + // / Raise events through manager + static void raiseEvent(const PIString & destObject, const PIString & name) { + PIObject * dest = findByName(destObject); + if (dest == 0) { + cout << "PIObject::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl; + return; + } + raiseEvent(dest, name); + } + template + static void raiseEvent(const PIString & destObject, const PIString & name, const T0 & v0 = T0()) { + PIObject * dest = findByName(destObject); + if (dest == 0) { + cout << "PIObject::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl; + return; + } + raiseEvent(dest, name, v0); + } + template + static void raiseEvent(const PIString & destObject, const PIString & name, const T0 & v0 = T0(), const T1 & v1 = T1()) { + PIObject * dest = findByName(destObject); + if (dest == 0) { + cout << "PIObject::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl; + return; + } + raiseEvent(dest, name, v0, v1); + } + template + static void raiseEvent(const PIString & destObject, const PIString & name, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2()) { + PIObject * dest = findByName(destObject); + if (dest == 0) { + cout << "PIObject::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl; + return; + } + raiseEvent(name, dest, v0, v1, v2); + } + template + static void raiseEvent(const PIString & destObject, const PIString & name, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2(), const T3 & v3 = T3()) { + PIObject * dest = findByName(destObject); + if (dest == 0) { + cout << "PIObject::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl; + return; + } + raiseEvent(name,dest , v0, v1, v2, v3); + } + */ + + //! Returns PIObject* with name "name" or 0, if there is no object found + static PIObject * findByName(const PIString & name) { + piForeach (PIObject * i, PIObject::objects) { + if (i->name() != name) continue; + return i; + } + return 0; + }; + + bool isPIObject() const {return isPIObject(this);} + bool execute(const PIString & method); + static bool isPIObject(const PIObject * o) {return o->_signature_ == __PIOBJECT_SIGNATURE__;} + static bool isPIObject(const void * o) {return isPIObject((PIObject*)o);} + static bool execute(PIObject * o, const PIString & method) {return o->execute(method);} + static bool execute(void * o, const PIString & method) {return ((PIObject*)o)->execute(method);} + + struct __EHFunc { + __EHFunc(): addr(0) {;} + bool isNull() const {return addr == 0;} + PIString arguments() const {return types.join(",").removeAll(" ").removeAll("\t");} + PIString fullFormat() const; + void * addr; + PIString func_name; + PIString type_ret; + PIString scope; + PIStringList types; + PIStringList names; + }; + struct __EHData { + PISet eh_set; + PIMap eh_func; + }; + typedef PIPair __EHPair; + static PIMap __eh_data; + static PIMutex __eh_mutex; + +protected: + + //! Returns PIObject* which has raised an event. This value is correct only in definition of some event handler + PIObject * emitter() const {return emitter_;} + + //! Virtual function executes after property with name "name" has been changed + virtual void propertyChanged(const PIString & name) {} + + + static const PIString __classNameS() {return PIString();} \ + +private: + struct Connection { + Connection(void * sl = 0, void * si = 0, const PIString & e = PIString(), PIObject * d_o = 0, void * d = 0, int ac = 0) { + slot = sl; + signal = si; + event = e; + dest_o = d_o; + dest = d; + args_count = ac; + } + void * slot; + void * signal; + PIString event; + PIObject * dest_o; + void * dest; + int args_count; + }; + + PIVector<__EHFunc> findEH(const PIString & name) const; + __EHFunc methodEH(const void * addr) const; + void updateConnectors(); + + PIVector connections; + typedef PIPair Property; + PIMap properties_; + + static PIVector objects; + + PISet connectors; + PIMutex mutex_, mutex_connect; + PIObject * emitter_; + bool thread_safe_; + +}; + + +void dumpApplication(); +bool dumpApplicationToFile(const PIString & path); + +#endif // PIOBJECT_H diff --git a/src/core/pistatemachine.h b/src/core/pistatemachine.h new file mode 100755 index 00000000..2df7214a --- /dev/null +++ b/src/core/pistatemachine.h @@ -0,0 +1,334 @@ +/*! \file pistatemachine.h + * \brief Base class for custom state machine +*/ +/* + PIP - Platform Independent Primitives + State machine + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PISTATEMACHINE_H +#define PISTATEMACHINE_H + +#include "piobject.h" + +/*! \brief Base class for custom state machine + * + * \section PIStateMachine_synopsis Synopsis + * This class provide functionality of state machine. + * You should inherit from this class, implement \a execution() + * and \a transition() functions, set rules and periodically + * call \a tick() function to proper work of machine. + * + * \section PIStateMachine_prepare Prepare for work + * %State machine operates with "state", "rule" and "condition". + * * "State" is some class (by default \c int), associated name and + * optional "handler" - pointer to function executed on every \a tick(); + * * "Rule" define rule of transition from one machine state to other. + * It is also has optional "handler"; + * * "Condition" is a part of rule and define possibility of transition. + * + * First of all you should define states of your machine by function + * \a addState(). Then you should define transition rules for machine + * by function \a addRule(). Finally you can set initial state by function + * \a setInitialState() and provide periodically execution of function + * \a tick(). + * + * \section PIStateMachine_principle Principle of work + * At any time the state machine is in some state. You can ask machine + * to enter in new state by function \a switchToState(). If all conditions + * done machine switch it state immediately, else machine remember request + * and will be try switch to the new state every tick. Successfull state + * switching execute function \a transition(), every tick execute + * function \a execution() with current state. On successfull transition + * if rule "handler" is not null it execute. Every \a tick() if current + * state "handler" is not null it execute. + * + * \section PIStateMachine_conditions Conditions + * Each rule has transition condition. Condition is array of pairs + * (string, number). It means that every condition by name "string" + * should be performed as least "number" times. Empty condition always + * permits transition. + * + * %State machine have current performed conditions. You can read this + * conditions by function \a currentConditions() and perform new + * conditions by functions \a performCondition() and \a performConditions(). + * Currend conditions can de erased by function \a resetConditions(). + * + * \section PIStateMachine_example Example + * This is simple example demonstrates all features: + * \snippet pistatemachine.cpp main +*/ +template +class PIP_EXPORT PIStateMachine: public PIObject +{ + PIOBJECT(PIStateMachine) +public: + //! Constructs an empty state machine + PIStateMachine(void * _parent = 0) {if (_parent == 0) parent_ = this; else parent_ = _parent; resetConditions();} + ~PIStateMachine() {;} + + //! %Condition is a pair (string, number) + typedef PIPair Condition; + + //! %Rule of transition between states of machine + struct Rule { + //! Constuctor + Rule() {handler = 0;} + //! Constuctor + Rule(Type f, Type t, const PIStringList & c = PIStringList(), Handler h = 0, bool at = false, bool rac = false) { + from = f; + to = t; + for (int i = 0; i < c.size_s(); ++i) + conditions << Condition(c[i], 1); + autoTransition = at; + resetAllConditions = rac; + handler = h; + } + //! Source state + Type from; + //! Destination state + Type to; + //! %Conditions of transition + PIVector conditions; + //! Automatic transition + bool autoTransition; + //! Reset or not all performed conditions of machine on transition + bool resetAllConditions; + //! Pointer to function executed on transition + Handler handler; + //! Add condition of transition + void addCondition(const PIString & name, int times = 1) {if (times > 0) conditions << Condition(name, times);} + bool operator ==(const Rule & other) const {return (from == other.from) && (to == other.to);} + bool operator !=(const Rule & other) const {return (from != other.from) || (to != other.to);} + }; + + //! %State of machine + struct State { + //! Constuctor + State() {handler = 0;} + //! Constuctor + State(Type v, const PIString & n = "", Handler h = 0) {value = v; name = n; handler = h;} + //! %State value + Type value; + //! %State name + PIString name; + //! Pointer to function executed on tick + Handler handler; + bool operator ==(const State & other) const {return value == other.value;} + bool operator !=(const State & other) const {return value != other.value;} + }; + + void * parent() const {return parent_;} + void setParent(void * parent) {parent_ = parent;} + + //! Add state of machine + void addState(Type value, const PIString & name = "", Handler handler = 0) {if (states_.contains(State(value, name))) return; states_ << State(value, name, handler);} + + //! States count + int statesCount() const {return states_.size_s();} + + //! Remove all states + void clearStates() {states_.clear();} + + + //! Add rule of transition + void addRule(Type from, Type to, const PIString & condition, Handler handler = 0, bool autoTransition = false, bool resetAllConditions = false) {if (rules_.contains(Rule(from, to))) return; rules_ << Rule(from, to, PIStringList(condition), handler, autoTransition, resetAllConditions);} + + //! Add rule of transition + void addRule(Type from, Type to, Handler handler, bool autoTransition = false, bool resetAllConditions = false) {if (rules_.contains(Rule(from, to))) return; rules_ << Rule(from, to, PIStringList(), handler, autoTransition, resetAllConditions);} + + //! Add rule of transition + void addRule(Type from, Type to, const PIStringList & conditions = PIStringList(), Handler handler = 0, bool autoTransition = false, bool resetAllConditions = false) {if (rules_.contains(Rule(from, to))) return; rules_ << Rule(from, to, conditions, handler, autoTransition, resetAllConditions);} + + //! Add rule of transition + void addRule(const Rule & rule) {if (rules_.contains(rule)) return; rules_ << rule;} + + //! Rules count + int rulesCount() const {return rules_.size_s();} + + //! Remove all rules + void clearRules() {rules_.clear();} + + + //! Setup initial state. \a reset() will set machine state to "value" + void setInitialState(Type value) { + for (int i = 0; i < states_.size_s(); ++i) + if (states_[i].value == value) { + init_ = state_ = states_[i]; + return; + } + } + + /** \brief Try to switch machine state to state "to" + * \details If there is rule of transition exists and this rule conditions + * is performed then machine switched to new state immediately. Otherwise machine + * will be try to enter to new state every \a tick(). + * \return \c true if state switched immediately, otherwise \c false */ + bool switchToState(Type to) { + switch_to = to; + for (int i = 0; i < rules_.size_s(); ++i) { + Rule & r(rules_[i]); + if ((r.from != state_.value) || (r.to != to)) continue; + if (!checkConditions(r)) continue; + State ts = findState(to); + if (r.handler != 0 && parent_ != 0) r.handler(parent_); + transition(state_, ts); + state_ = ts; + resetConditions(r); + return true; + } + return false; + } + + //! Reset machine state to initial and clear all conditions + void reset() {state_ = init_; resetConditions();} + + //! Returns current state of machine + const State & currentState() const {return state_;} + + + //! Reset all performed conditions + void resetConditions() {cond.clear(); cond_count = 0;} + + //! Reset performed condition with name "name" + void resetCondition(const PIString & name) { + for (int i = 0; i < cond.size_s(); ++i) + if (cond[i].first == name) { + cond.remove(i); + i--; + } + } + + //! Perform condition with name "name" "times" times. + void performCondition(const PIString & name, int times = 1) { + if (times <= 0) return; + for (int i = 0; i < cond.size_s(); ++i) + if (cond[i].first == name) { + cond[i].second += times; + return; + } + cond << Condition(name, times); + } + + //! Perform every condition with name from "names" one time. + void performConditions(const PIStringList & names) { + bool ok; + for (int n = 0; n < names.size_s(); ++n) { + ok = false; + for (int i = 0; i < cond.size_s(); ++i) { + if (cond[i].first == names[n]) { + cond[i].second++; + ok = true; + break; + } + } + if (ok) continue; + cond << Condition(names[n], 1); + } + } + + //! Returns all current performed conditions + const PIVector & currentConditions() const {return cond;} + + Type * currentState_ptr() {return &state_.value;} + int * conditionsCount_ptr() {cond_count = cond.size_s(); return &cond_count;} + +//! \handlers +//! \{ + + //! \fn void tick() + //! \brief Main function of machine. Execute \a execution() and check if need to switch state + + //! \fn void tick(void * data, int delim) + //! \brief Main function of machine. Execute \a execution() and check if need to switch state + +//! \} + + EVENT_HANDLER(void, tick) {tick(0, 0);} + EVENT_HANDLER2(void, tick, void * , data, int, delim) { + execution(state_); + if (state_.handler != 0 && parent_ != 0) state_.handler(parent_); + if (switch_to != state_.value) switchToState(switch_to); + else { + piForeachC (Rule & r, rules_) { + if (!r.autoTransition || r.from != state_.value) continue; + if (checkConditions(r)) { + switchToState(r.to); + break; + } + } + } + } + +protected: + + //! Reimplement this function to process current state of machine + virtual void execution(const State & state) {;} + + //! Reimplement this function to process switching current state of machine + virtual void transition(const State & from, const State & to) {;} + +private: + State findState(Type value) { + for (int i = 0; i < states_.size_s(); ++i) + if (states_[i].value == value) + return states_[i]; + return State(); + } + bool checkConditions(const Rule & rule) { + //if (cond.size_s() < rule.conditions.size_s()) return false; + int oc = 0; + for (int i = 0; i < cond.size_s(); ++i) { + PIString & rn(cond[i].first); + for (int j = 0; j < rule.conditions.size_s(); ++j) { + if (rn != rule.conditions[j].first) continue; + if (cond[i].second < rule.conditions[j].second) return false; + oc++; + } + } + return (rule.conditions.size_s() == oc); + } + void resetConditions(const Rule & rule) { + if (rule.resetAllConditions) { + cond.clear(); + return; + } + for (int i = 0; i < cond.size_s(); ++i) { + PIString & rn(cond[i].first); + for (int j = 0; j < rule.conditions.size_s(); ++j) { + if (rn != rule.conditions[j].first) continue; + cond[i].second -= rule.conditions[j].second; + if (cond[i].second <= 0) { + cond.remove(i); + i--; + } + } + } + } + + PIVector states_; + PIVector rules_; + State init_, state_; + Type switch_to; + void * parent_; + int cond_count; + PIVector cond; + +}; + + +#endif // PISTATEMACHINE_H diff --git a/src/core/pistring.cpp b/src/core/pistring.cpp new file mode 100755 index 00000000..9adb9a15 --- /dev/null +++ b/src/core/pistring.cpp @@ -0,0 +1,775 @@ +/* + PIP - Platform Independent Primitives + String + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pistring.h" + + +/*! \class PIString + * \brief String class + * \details PIP use this class for use string information. + * + * \section PIString_sec0 Synopsis + * This class based on \a PIVector to store information. + * String is a sequence of \a PIChar and can contain multibyte + * symbols. Therefore real memory size of string is symbols count * 4. + * String can be constucted from many types of data and can be converted + * to many types. There are man operators and handly functions to use + * string as you wish. + * + * \section PIString_sec1 To/from data convertions + * Most common constructor is \a PIString(const char * str), where "str" + * is null-terminated string, e.g. \c "string". This is 7 chars with last char = 0. + * Also you can constructs \a PIString from single \a PIChar, \a PIByteArray, + * other \a PIString or sequency of the same characters with custom length.\n \n + * This class has implicit conversions to const char * and + * \c std::string. Also there are functions to make same convertions: + * * \a data() - to const char * , + * * \a stdString() - to \c std::string, + * * \a toByteArray() - to \a PIByteArray. + * + * \section PIString_sec2 Numeric operations + * You can get symbolic representation of any numeric value with function + * \a setNumber(any integer value, int base = 10, bool * ok = 0). Default + * arguments are set for decimal base system, but you can choose any system + * from 2 to 40. There are the same static functions \a fromNumber(), that + * returns \a PIString. \n + * Also there is function \a setReadableSize() which is set human-readable + * size in bytes, Kb, Mb, Gb or Pb. Static analog is \a readableSize(). + * + */ + + +const char PIString::toBaseN[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^'}; +const int PIString::fromBaseN[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; + + +void PIString::appendFromChars(const char * c, int s) { + int sz; + wchar_t wc; + for (int i = 0; i < s; ++i) { + if (/*isascii(c[i])*/c[i] >= 0) { + push_back(PIChar(c[i])); + continue; + } + sz = mbtowc(&wc, &(c[i]), 4); + //cout << sz << endl; + switch (sz) { + case 4: + push_back(PIChar(*(int*)&(c[i]))); + i += 3; + continue; + case 3: + push_back(PIChar(*(int*)&(c[i]))); + back().ch &= 0xFFFFFF; + i += 2; + continue; + case 2: + push_back(PIChar(*(short * )&(c[i]))); + ++i; + continue; + default: + push_back(PIChar(c[i])); + break; + } + } +} + + +PIString & PIString::operator +=(const char * str) { + int l = 0; + while (str[l] != '\0') ++l; + appendFromChars(str, l); + return *this; +} + + +PIString & PIString::operator +=(const wchar_t * str) { + //cout << "wc" << endl; + int l = 0, sz; + char * c = new char[MB_CUR_MAX]; + while (str[l] != 0) ++l; + for (int i = 0; i < l; ++i) { + sz = wctomb(c, str[i]); + switch (sz) { + case 4: + push_back(PIChar(*(int*)c)); + continue; + case 3: + push_back(PIChar(*(int*)c)); + back().ch &= 0xFFFFFF; + continue; + case 2: + push_back(PIChar(*(short * )c)); + continue; + default: + push_back(PIChar(c[0])); + break; + } + } + delete[] c; + return *this; +} + + +#ifdef HAS_LOCALE +PIString & PIString::operator +=(const wstring & str) { + uint l = str.size(); + for (uint i = 0; i < l; ++i) push_back(str[i]); + return *this; +} +#endif + + +PIString & PIString::operator +=(const PIString & str) { + //uint l = str.size(); + *((PIDeque*)this) << *((PIDeque*)&str); + return *this; +} + +/* +#ifdef WINDOWS +PIString & PIString::operator +=(const WCHAR * str) { + int l = 0; + while (str[l] != 0) ++l; + for (int i = 0; i < l; ++i) + push_back(str[i]); + return *this; +} +#endif +*/ + +bool PIString::operator ==(const PIString & str) const { + uint l = str.size(); + if (size() != l) return false; + for (uint i = 0; i < l; ++i) + if (str[i] != at(i)) + return false; + return true; +} + + +bool PIString::operator !=(const PIString & str) const { + uint l = str.size(); + if (size() != l) return true; + for (uint i = 0; i < l; ++i) + if (str[i] != at(i)) + return true; + return false; +} + + +bool PIString::operator <(const PIString & str) const { + uint l = str.size(); + if (size() < l) return true; + if (size() > l) return false; + for (uint i = 0; i < l; ++i) { + if (str[i] == at(i)) continue; + if (str[i] < at(i)) return true; + else return false; + } + return false; +} + + +bool PIString::operator >(const PIString & str) const { + uint l = str.size(); + if (size() < l) return false; + if (size() > l) return true; + for (uint i = 0; i < l; ++i) { + if (str[i] == at(i)) continue; + if (str[i] < at(i)) return false; + else return true; + } + return false; +} + + +PIString PIString::mid(const int start, const int len) const { + //PIString str; + int s = start, l = len; + if (l == 0) return PIString(); + if (s < 0) { + l += s; + s = 0; + } + if (l < 0) { + //for (uint i = s; i < size(); ++i) + // str += at(i); + return PIString(&(at(s)), size() - s); + } else { + if (l > length() - s) + l = length() - s; + //for (int i = s; i < s + l; ++i) + // str += at(i); + return PIString(&(at(s)), l); + } + return PIString(); +} + + +PIString & PIString::cutMid(const int start, const int len) { + int s = start, l = len; + if (l == 0) return *this; + if (s < 0) { + l += s; + s = 0; + } + if (l < 0) + remove(s, size() - s); + else { + if (l > length() - s) + l = length() - s; + remove(s, l); + } + return *this; +} + + +PIString & PIString::trim() { + int st = 0, fn = 0; + for (int i = 0; i < length(); ++i) + if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12)) + {st = i; break;} + for (int i = length() - 1; i >= 0; --i) + if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12)) + {fn = i; break;} + //*this = mid(st, fn - st + 1); + if (fn < size_s() - 1) cutRight(size_s() - fn - 1); + if (st > 0) cutLeft(st); + return *this; +} + + +PIString PIString::trimmed() const { + int st = 0, fn = 0; + for (int i = 0; i < length(); ++i) + if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12)) + {st = i; break;} + for (int i = length() - 1; i >= 0; --i) + if (at(i) != ' ' && at(i) != '\t' && at(i) != '\n' && at(i) != '\r' && at(i) != char(12)) + {fn = i; break;} + return mid(st, fn - st + 1); +} + + +PIString & PIString::replace(int from, int count, const PIString & with) { + if (count < length() - from) remove(from, count); + else remove(from, length() - from); + uint c = with.length(); + for (uint i = 0; i < c; ++i) insert(from + i, with[i]); + return *this; +} + + +PIString & PIString::replace(const PIString & what, const PIString & with, bool * ok) { + //piCout << "replace" << what << with; + if (what.isEmpty()) { + if (ok != 0) *ok = false; + return *this; + } + int s = find(what); + if (s >= 0) replace(s, what.length(), with); + if (ok != 0) *ok = (s >= 0); + return *this; +} + + +PIString & PIString::replaceAll(const PIString & what, const PIString & with) { + if (what.isEmpty() || what == with) return *this; + bool ok = true; + while (ok) replace(what, with, &ok); + return *this; +} + + +PIString & PIString::insert(int index, const PIString & str) { + //uint c = str.length(); + //for (uint i = 0; i < c; ++i) insert(index + i, str[i]); + PIDeque::insert(index, *((const PIDeque*)&str)); + return *this; +} + + +PIStringList PIString::split(const PIString & delim) const { + PIStringList sl; + if (isEmpty() || delim.isEmpty()) return sl; + PIString ts(*this); + int ci = ts.find(delim); + while (ci >= 0) { + sl << ts.left(ci); + ts.cutLeft(ci + delim.length()); + ci = ts.find(delim); + } + if (ts.length() > 0) sl << ts; + return sl; +} + + +int PIString::find(const char str, const int start) const { + for (int i = start; i < length(); ++i) + if (at(i) == str) + return i; + return -1; +} + + +int PIString::find(const PIString str, const int start) const { + int l = str.length(); + for (int i = start; i < length() - l + 1; ++i) + if (mid(i, l) == str) + return i; + return -1; +} + + +int PIString::findLast(const char str, const int start) const { + for (int i = length() - 1; i >= start; --i) + if (at(i) == str) + return i; + return -1; +} + + +int PIString::findLast(const PIString str, const int start) const { + int l = str.length(); + for (int i = length() - l; i >= start; --i) + if (mid(i, l) == str) + return i; + return -1; +} + + +int PIString::findWord(const PIString & word, const int start) const { + int f = start - 1, tl = length(), wl = word.length(); + while ((f = find(word, f + 1)) >= 0) { + bool ok = true; + PIChar c; + if (f > 0) {c = (*this)[f - 1]; if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) {ok = false; continue;}} + if (f + wl < tl) {c = (*this)[f + wl]; if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) {ok = false; continue;}} + if (ok) return f; + } + return -1; +} + + +int PIString::findCWord(const PIString & word, const int start) const { + int f = start - 1, tl = length(), wl = word.length(); + while ((f = find(word, f + 1)) >= 0) { + bool ok = true; + PIChar c; + if (f > 0) {c = (*this)[f - 1]; if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r' || (c != '_' && !c.isAlpha() && !c.isDigit()))) {ok = false; continue;}} + if (f + wl < tl) {c = (*this)[f + wl]; if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r' || (c != '_' && !c.isAlpha() && !c.isDigit()))) {ok = false; continue;}} + if (ok) return f; + } + return -1; +} + + +bool PIString::startsWith(const PIString & str) const { + if (size() < str.size()) return false; + return str == left(str.size()); +} + + +bool PIString::endsWith(const PIString & str) const { + if (size() < str.size()) return false; + return str == right(str.size()); +} + + +PIString PIString::takeSymbol() { + PIString ret; + int sz = size_s(), ss = -1; + for (int i = 0; i < sz; ++i) { + PIChar c = at(i); + if (c == ' ' || c == '\t' || c == '\n' || c == '\r') + continue; + ss = i; + break; + } + if (ss < 0) return ret; + ret = mid(ss, 1); + cutLeft(ss + 1); + return ret; +} + + +PIString PIString::takeWord() { + int sz = size_s(), ws = -1, we = -1; + for (int i = 0; i < sz; ++i) { + PIChar c = at(i); + if (c == ' ' || c == '\t' || c == '\n' || c == '\r') { + if (we < 0 && ws >= 0) { + we = i; + break; + } + } else { + if (ws < 0) ws = i; + if (we >= 0) break; + } + } + PIString ret = mid(ws, we - ws); + cutLeft(we < 0 ? sz : we); + return ret; +} + + +PIString PIString::takeCWord() { + PIString ret; + int sz = size_s(), ws = -1, we = -1; + for (int i = 0; i < sz; ++i) { + PIChar c = at(i); + if (c == ' ' || c == '\t' || c == '\n' || c == '\r') { + if (we < 0 && ws >= 0) { + we = i; + break; + } + } else { + if (ws < 0) { + if (c.isAlpha() || c == '_') + ws = i; + else + return ret; + } else { + if (!c.isAlpha() && !c.isDigit() && c != '_') { + we = i; + break; + } + } + if (we >= 0) break; + } + } + ret = mid(ws, we - ws); + cutLeft(we < 0 ? sz : we); + return ret; +} + + +PIString PIString::takeLine() { + int sz = size_s(), le = -1; + for (int i = 0; i < sz; ++i) { + PIChar c = at(i); + if (c == '\n') { + le = i; + break; + } + } + PIString ret = left(le); + if (!ret.isEmpty()) + if (ret.back() == '\r') + ret.cutRight(1); + cutLeft(le < 0 ? sz : le + 1); + return ret; +} + + +PIString PIString::takeNumber() { + PIString ret; + int sz = size_s(), ls = -1, le = -1, phase = 0; + for (int i = 0; i < sz; ++i) { + if (phase > 7) break; + PIChar c = at(i); + //piCout << "char " << c << "phase" << phase; + switch (phase) { + case 0: // trim + if (c == ' ' || c == '\t' || c == '\n' || c == '\r') + continue; + phase = 7; + case 7: // sign + if (c == '-' || c == '+') {ls = i; phase = 1; break;} + case 1: // search start + if (c >= '0' && c <= '9') {le = i; if (ls < 0) ls = i; phase = 2; break;} + if (c == '.') {le = i; if (ls < 0) ls = i; phase = 3; break;} + phase = 9; + break; + case 2: // integer + if (c == '.') {le = i; phase = 3; break;} + if (c == 'e' || c == 'E') {le = i; phase = 4; break;} + if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || c == 'x') {le = i; break;} + phase = 6; + break; + case 3: // point + if (c == 'e' || c == 'E') {le = i; phase = 4; break;} + if (c >= '0' && c <= '9') {le = i; break;} + phase = 6; + break; + case 4: // exp + if ((c >= '0' && c <= '9') || c == '-' || c == '+') {le = i; phase = 5; break;} + phase = 6; + break; + case 5: // power + if (c >= '0' && c <= '9') {le = i; break;} + phase = 6; + break; + case 6: // suffix + if (c == 'f' || c == 's' || c == 'u' || c == 'l' || c == 'L') {le = i; break;} + phase = 9; + break; + } + if (phase == 6) { + if (c == 'f' || c == 's' || c == 'u' || c == 'l' || c == 'L') le = i; + else phase = 9; + } + } + //piCout << ls << le; + if (le < ls) return ret; + ret = mid(ls, le - ls + 1); + cutLeft(le + 1); + return ret; +} + + +PIString PIString::takeRange(const PIChar & start, const PIChar & end, const PIChar & shield) { + PIString ret; + bool trim_ = (start != ' ' && start != '\t' && start != '\n' && start != '\r'), eq = (start == end); + int sz = size_s(), ls = -1, le = -1, cnt = 0; + for (int i = 0; i < sz; ++i) { + PIChar c = at(i); + if (c == shield) {++i; continue;} + if (trim_) { + if (c == ' ' || c == '\t' || c == '\n' || c == '\r') + continue; + trim_ = false; + } + if (eq) { + if (c == start) { + if (cnt == 0) ls = i; + else {le = i; cnt = 0; break;} + cnt++; + } + } else { + if (c == start) { + if (cnt == 0) ls = i; + cnt++; + } + if (c == end) { + cnt--; + if (cnt == 0) le = i; + } + } + if (cnt <= 0) break; + } + //piCout << ls << le << cnt; + if (le < ls || ls < 0 || le < 0 || cnt != 0) return ret; + ret = mid(ls + 1, le - ls - 1); + cutLeft(le + 1); + return ret; +} + + +PIString PIString::toUpperCase() const { + PIString str(*this); + int l = str.size(); + for (int i = 0; i < l; ++i) str[i] = str[i].toUpper(); + return str; +} + + +PIString PIString::toLowerCase() const { + PIString str(*this); + int l = str.size(); + for (int i = 0; i < l; ++i) str[i] = str[i].toLower(); + return str; +} + + +int PIString::lengthAscii() const { + int j = 0; + for (int i = 0; i < size_s(); ++i, ++j) + if (!at(i).isAscii()) ++j; + return j; +} + + +const char * PIString::data() const { + data_.clear(); + uint wc; + uchar tc; + //printf("PIString::data %d\n", size_s()); + for (int i = 0, j = 0; i < size_s(); ++i) { + wc = uint(at(i).toInt()); + //printf("__%d_%d\n", i, wc); + while (tc = wc & 0xFF, tc) { + data_.push_back(uchar(tc)); ++j; + wc >>= 8; + //printf("____%d\n", wc); + } + /*if (at(i).isAscii()) + data_.push_back(uchar(at(i).toAscii())); + else { + data_.push_back((at(i).toCharPtr()[0])); ++j; + data_.push_back((at(i).toCharPtr()[1])); + }*/ + } + data_.push_back(uchar('\0')); + return (const char * )data_.data(); +} + + +string PIString::convertToStd() const { + string s; + uint wc; + uchar tc; + if (size() > 0) { + for (int i = 0; i < length(); ++i) { + wc = uint(at(i).toInt()); + while (tc = wc & 0xFF, tc) { + s.push_back(char(tc)); + wc >>= 8; + } + /*if (at(i).isAscii()) + s.push_back(at(i).toAscii()); + else { + s.push_back(at(i).toCharPtr()[0]); + s.push_back(at(i).toCharPtr()[1]); + }*/ + } + } + return s; +} + + +char PIString::toChar() const { + PIString s(toNativeDecimalPoints()); + char v; + sscanf(s.data(), "%c", &v); + return v; +} + +/* +short PIString::toShort() const { + PIString s(trimmed().toLowerCase().toNativeDecimalPoints()); + short v; + if (s.left(2) == "0x") {sscanf(s.data(), "%hx", &v); return v;} + if (s.left(1) == "0") {sscanf(s.data(), "%ho", &v); return v;} + sscanf(s.data(), "%hd", &v); + return v; +} + + +int PIString::toInt() const { + PIString s(trimmed().toLowerCase().toNativeDecimalPoints()); + int v; + if (s.left(2) == "0x") {sscanf(s.data(), "%x", &v); return v;} + if (s.left(1) == "0") {sscanf(s.data(), "%o", &v); return v;} + sscanf(s.data(), "%d", &v); + return v; +} + + +long PIString::toLong() const { + PIString s(trimmed().toLowerCase().toNativeDecimalPoints()); + long v; + if (s.left(2) == "0x") {sscanf(s.data(), "%lx", &v); return v;} + if (s.left(1) == "0") {sscanf(s.data(), "%lo", &v); return v;} + sscanf(s.data(), "%ld", &v); + return v; +} + + +llong PIString::toLLong() const { + PIString s(trimmed().toLowerCase().toNativeDecimalPoints()); + llong v; + if (s.left(2) == "0x") {sscanf(s.data(), "%llx", &v); return v;} + if (s.left(1) == "0") {sscanf(s.data(), "%llo", &v); return v;} + sscanf(s.data(), "%lld", &v); + return v; +} +*/ + +PIString & PIString::setReadableSize(llong bytes) { + clear(); + if (bytes < 1024) {*this += (PIString::fromNumber(bytes) + " B"); return *this;} + double fres = bytes / 1024.; + llong res = bytes / 1024; + fres -= res; + if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " kB"); return *this;} + fres = res / 1024.; + res /= 1024; + fres -= res; + if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " MB"); return *this;} + fres = res / 1024.; + res /= 1024; + fres -= res; + if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " GB"); return *this;} + fres = res / 1024.; + res /= 1024; + fres -= res; + if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " TB"); return *this;} + fres = res / 1024.; + res /= 1024; + fres -= res; + *this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " PB"); + return *this; +} + + +inline char chrUpr(char c) { + if (c >= 'a' && c <= 'z') return c + 'A' - 'a'; + //if (c >= 'а' && c <= 'Ñ') return c + 'Ð' - 'а'; + return c; +} + + +inline char chrLwr(char c) { + if (c >= 'A' && c <= 'Z') return c + 'a' - 'A'; + //if (c >= 'Ð' && c <= 'Я') return c + 'а' - 'Ð'; + return c; +} + + + +PIStringList& PIStringList::removeDuplicates() { + PIStringList l; + PIString s; + bool ae; + for (int i = 0; i < size_s(); ++i) { + ae = false; + s = at(i); + for (int j = 0; j < l.size_s(); ++j) { + if (s != l[j]) continue; + ae = true; break; + } + if (!ae) { + l << s; + continue; + } + remove(i); + --i; + } + return *this; +} diff --git a/src/core/pistring.h b/src/core/pistring.h new file mode 100755 index 00000000..5812cfb6 --- /dev/null +++ b/src/core/pistring.h @@ -0,0 +1,916 @@ +/*! \file pistring.h + * \brief String + * + * This file declare string and string list classes +*/ +/* + PIP - Platform Independent Primitives + String + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PISTRING_H +#define PISTRING_H + +#include "pibytearray.h" +#include "pichar.h" +#include "math.h" + +class PIStringList; + +class PIP_EXPORT PIString: public PIDeque +{ +public: + //! Contructs an empty string + PIString(): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--;} + + //inline PIString & operator +=(const char c) {push_back(c); return *this;} + PIString & operator +=(const PIChar & c) {push_back(c); return *this;} + PIString & operator +=(const char * str); + PIString & operator +=(const wchar_t * str); + PIString & operator +=(const string & str) {appendFromChars(str.c_str(), str.length()); return *this;} + PIString & operator +=(const PIByteArray & ba) {appendFromChars((const char * )ba.data(), ba.size_s()); return *this;} + PIString & operator +=(const PIString & str); +#ifdef HAS_LOCALE + PIString & operator +=(const wstring & str); +#endif + + //PIString(const char c) {*this += c;} + PIString(const PIString & o): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += o;} + + + //! Contructs string with single symbol "c" + PIString(const PIChar & c): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += c;} + PIString(const char c): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += PIChar(c);} + + /*! \brief Contructs string from c-string "str" + * \details "str" should be null-terminated\n + * Example: \snippet pistring.cpp PIString(char * ) */ + PIString(const char * str): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += str;} + + /*! \brief Contructs string from \c wchar_t c-string "str" + * \details "str" should be null-terminated\n + * Example: \snippet pistring.cpp PIString(wchar_t * ) */ + PIString(const wchar_t * str): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += str;} + + //! Contructs string from std::string "str" + PIString(const string & str): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += str;} + +#ifdef HAS_LOCALE + PIString(const wstring & str): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += str;} +#endif + + //! Contructs string from byte array "ba" + PIString(const PIByteArray & ba): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += ba;} + + //! \brief Contructs string from "len" characters of buffer "str" + PIString(const PIChar * str, const int len): PIDeque(str, size_t(len)) {/*reserve(256); */piMonitor.strings++; piMonitor.containers--;} + + /*! \brief Contructs string from "len" characters of buffer "str" + * \details Example: \snippet pistring.cpp PIString(char * , int) */ + PIString(const char * str, const int len): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this += string(str, len);} + + /*! \brief Contructs string as sequence of characters "c" of buffer with length "len" + * \details Example: \snippet pistring.cpp PIString(int, char) */ + PIString(const int len, const char c): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);} + + /*! \brief Contructs string as sequence of symbols "c" of buffer with length "len" + * \details Example: \snippet pistring.cpp PIString(int, PIChar) */ + PIString(const int len, const PIChar & c): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);} +/* +#ifdef WINDOWS + PIString(const WCHAR * str): PIDeque() {piMonitor.strings++; piMonitor.containers--; *this += str;} + PIString & operator +=(const WCHAR * str); + PIString & operator <<(const WCHAR * str) {*this += str; return *this;} +#endif +*/ + + PIString(const short & value): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} + PIString(const ushort & value): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} + PIString(const int & value): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} + PIString(const uint & value): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} + PIString(const long & value): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} + PIString(const ulong & value): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} + PIString(const llong & value): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} + PIString(const ullong & value): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} + PIString(const float & value): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} + PIString(const double & value): PIDeque() {/*reserve(256); */piMonitor.strings++; piMonitor.containers--; *this = fromNumber(value);} + + + //~PIString() {piMonitor.strings--; piMonitor.containers++;} + + + PIString & operator =(const PIString & o) {clear(); *this += o; return *this;} + + /*! \brief Return c-string representation of string + * \details Converts content of string to c-string and return + * pointer to first char. This buffer is valid until new convertion + * or execution \a data() or \a toByteArray().\n + * Example: \snippet pistring.cpp PIString::char* */ + operator const char*() {return data();} + + //! Return std::string representation of string + operator const string() {if (size() == 0) return string(); string s; for (int i = 0; i < length(); ++i) s.push_back(at(i).toAscii()); return s;} + + //! Return symbol at index "pos" + PIChar operator [](const int pos) const {return at(pos);} + + //! Return reference to symbol at index "pos" + PIChar & operator [](const int pos) {return at(pos);} + + //! Compare operator + bool operator ==(const PIString & str) const; + + //! Compare operator + bool operator ==(const PIChar c) const {return *this == PIString(c);} + //inline bool operator ==(const char c) const {return *this == PIString(c);} + + //! Compare operator + bool operator ==(const char * str) const {return *this == PIString(str);} + + //! Compare operator + bool operator ==(const string & str) const {return *this == PIString(str);} + + + //! Compare operator + bool operator !=(const PIString & str) const; + + //! Compare operator + bool operator !=(const PIChar c) const {return *this != PIString(c);} + //inline bool operator !=(const char c) const {return *this != PIString(c);} + + //! Compare operator + bool operator !=(const char * str) const {return *this != PIString(str);} + + //! Compare operator + bool operator !=(const string & str) const {return *this != PIString(str);} + + + //! Compare operator + bool operator <(const PIString & str) const; + + //! Compare operator + bool operator <(const PIChar c) const {return *this < PIString(c);} + //inline bool operator <(const char c) const {return *this < PIString(c);} + + //! Compare operator + bool operator <(const char * str) const {return *this < PIString(str);} + + //! Compare operator + bool operator <(const string & str) const {return *this < PIString(str);} + + + //! Compare operator + bool operator >(const PIString & str) const; + + //! Compare operator + bool operator >(const PIChar c) const {return *this > PIString(c);} + //inline bool operator >(const char c) const {return *this > PIString(c);} + + //! Compare operator + bool operator >(const char * str) const {return *this > PIString(str);} + + //! Compare operator + bool operator >(const string & str) const {return *this > PIString(str);} + + + //! Compare operator + bool operator <=(const PIString & str) const {return !(*this > str);} + + //! Compare operator + bool operator <=(const PIChar c) const {return *this <= PIString(c);} + //inline bool operator <=(const char c) const {return *this <= PIString(c);} + + //! Compare operator + bool operator <=(const char * str) const {return *this <= PIString(str);} + + //! Compare operator + bool operator <=(const string & str) const {return *this <= PIString(str);} + + + //! Compare operator + bool operator >=(const PIString & str) const {return !(*this < str);} + + //! Compare operator + bool operator >=(const PIChar c) const {return *this >= PIString(c);} + //inline bool operator >=(const char c) const {return *this >= PIString(c);} + + //! Compare operator + bool operator >=(const char * str) const {return *this >= PIString(str);} + + //! Compare operator + bool operator >=(const string & str) const {return *this >= PIString(str);} + + + operator bool() const {return toBool();} + operator short() const {return toShort();} + operator ushort() const {return toUShort();} + operator int() const {return toInt();} + operator uint() const {return toUInt();} + operator long() const {return toLong();} + operator ulong() const {return toULong();} + operator llong() const {return toLLong();} + operator ullong() const {return toULLong();} + operator float() const {return toFloat();} + operator double() const {return toDouble();} + + + /*! \brief Append string "str" at the end of string + * \details Example: \snippet pistring.cpp PIString::<<(PIString) */ + PIString & operator <<(const PIString & str) {*this += str; return *this;} + //inline PIString & operator <<(const char c) {*this += c; return *this;} + + /*! \brief Append symbol "c" at the end of string + * \details Example: \snippet pistring.cpp PIString::<<(PIChar) */ + PIString & operator <<(const PIChar & c) {*this += c; return *this;} + + /*! \brief Append c-string "str" at the end of string + * \details Example: \snippet pistring.cpp PIString::<<(char * ) */ + PIString & operator <<(const char * str) {*this += str; return *this;} + + /*! \brief Append \c wchar_t c-string "str" at the end of string + * \details Example: \snippet pistring.cpp PIString::<<(wchar_t * ) */ + PIString & operator <<(const wchar_t * str) {*this += str; return *this;} + + //! Append std::string "str" at the end of string + PIString & operator <<(const string & str) {*this += str; return *this;} + + /*! \brief Append string representation of "num" at the end of string + * \details Example: \snippet pistring.cpp PIString::<<(int) */ + PIString & operator <<(const int & num) {*this += PIString::fromNumber(num); return *this;} + PIString & operator <<(const uint & num) {*this += PIString::fromNumber(num); return *this;} + + /*! \brief Append string representation of "num" at the end of string + * \details Example: \snippet pistring.cpp PIString::<<(int) */ + PIString & operator <<(const short & num) {*this += PIString::fromNumber(num); return *this;} + PIString & operator <<(const ushort & num) {*this += PIString::fromNumber(num); return *this;} + + /*! \brief Append string representation of "num" at the end of string + * \details Example: \snippet pistring.cpp PIString::<<(int) */ + PIString & operator <<(const long & num) {*this += PIString::fromNumber(num); return *this;} + PIString & operator <<(const ulong & num) {*this += PIString::fromNumber(num); return *this;} + + PIString & operator <<(const llong & num) {*this += PIString::fromNumber(num); return *this;} + PIString & operator <<(const ullong & num) {*this += PIString::fromNumber(num); return *this;} + + /*! \brief Append string representation of "num" at the end of string + * \details Example: \snippet pistring.cpp PIString::<<(int) */ + PIString & operator <<(const float & num) {*this += PIString::fromNumber(num); return *this;} + + /*! \brief Append string representation of "num" at the end of string + * \details Example: \snippet pistring.cpp PIString::<<(int) */ + PIString & operator <<(const double & num) {*this += PIString::fromNumber(num); return *this;} + + + //! \brief Insert string "str" at the begin of string + PIString & prepend(const PIString & str) {insert(0, str); return *this;} + + //! \brief Insert string "str" at the end of string + PIString & append(const PIString & str) {*this += str; return *this;} + + + /*! \brief Return part of string from symbol at index "start" and maximum length "len" + * \details All variants demonstrated in example: \snippet pistring.cpp PIString::mid + * \sa \a left(), \a right() */ + PIString mid(const int start, const int len = -1) const; + + /*! \brief Return part of string from left and maximum length "len" + * \details Example: \snippet pistring.cpp PIString::left + * \sa \a mid(), \a right() */ + PIString left(const int len) const {return len <= 0 ? PIString() : mid(0, len);} + + /*! \brief Return part of string from right and maximum length "len" + * \details Example: \snippet pistring.cpp PIString::right + * \sa \a mid(), \a left() */ + PIString right(const int len) const {return len <= 0 ? PIString() : mid(size() - len, len);} + + /*! \brief Remove part of string from symbol as index "start" and maximum length "len" + * and return this string + * \details All variants demonstrated in example: \snippet pistring.cpp PIString::cutMid + * \sa \a cutLeft(), \a cutRight() */ + PIString & cutMid(const int start, const int len); + + /*! \brief Remove part of string from left and maximum length "len" and return this string + * \details Example: \snippet pistring.cpp PIString::cutLeft + * \sa \a cutMid(), \a cutRight() */ + PIString & cutLeft(const int len) {return len <= 0 ? *this : cutMid(0, len);} + + /*! \brief Remove part of string from right and maximum length "len" and return this string + * \details Example: \snippet pistring.cpp PIString::cutRight + * \sa \a cutMid(), \a cutLeft() */ + PIString & cutRight(const int len) {return len <= 0 ? *this : cutMid(size() - len, len);} + + /*! \brief Remove spaces at the start and at the end of string and return this string + * \details Example: \snippet pistring.cpp PIString::trim + * \sa \a trimmed() */ + PIString & trim(); + + /*! \brief Return copy of this string without spaces at the start and at the end + * \details Example: \snippet pistring.cpp PIString::trimmed + * \sa \a trim() */ + PIString trimmed() const; + + /*! \brief Replace part of string from index "from" and maximum length "len" + * with string "with" and return this string + * \details Example: \snippet pistring.cpp PIString::replace_0 + * \sa \a replaced(), \a replaceAll() */ + PIString & replace(const int from, const int count, const PIString & with); + + /*! \brief Replace part copy of this string from index "from" and maximum length "len" + * with string "with" and return copied string + * \details Example: \snippet pistring.cpp PIString::replaced_0 + * \sa \a replace(), \a replaceAll() */ + PIString replaced(const int from, const int count, const PIString & with) const {PIString str(*this); str.replace(from, count, with); return str;} + + /*! \brief Replace first founded substring "what" with string "with" and return this string + * \details If "ok" is not null, it set to "true" if something was replaced\n + * Example: \snippet pistring.cpp PIString::replace_1 + * \sa \a replaced(), \a replaceAll() */ + PIString & replace(const PIString & what, const PIString & with, bool * ok = 0); + + /*! \brief Replace first founded substring "what" with string "with" and return copied string + * \details If "ok" is not null, it set to "true" if something was replaced\n + * Example: \snippet pistring.cpp PIString::replaced_1 + * \sa \a replaced(), \a replaceAll() */ + PIString replaced(const PIString & what, const PIString & with, bool * ok = 0) const {PIString str(*this); str.replace(what, with, ok); return str;} + + /*! \brief Replace all founded substrings "what" with strings "with" and return this string + * \details Example: \snippet pistring.cpp PIString::replaceAll + * \sa \a replace(), \a replaced() */ + PIString & replaceAll(const PIString & what, const PIString & with); + PIString replaceAll(const PIString & what, const PIString & with) const {PIString str(*this); str.replaceAll(what, with); return str;} + + /*! \brief Repeat content of string "times" times and return this string + * \details Example: \snippet pistring.cpp PIString::repeat */ + PIString & repeat(int times) {PIString ss(*this); times--; piForTimes (times) *this += ss; return *this;} + + /*! \brief Returns repeated "times" times string + * \details Example: \snippet pistring.cpp PIString::repeated */ + PIString repeated(int times) const {PIString ss(*this); return ss.repeat(times);} + + /*! \brief Insert symbol "c" after index "index" and return this string + * \details Example: \snippet pistring.cpp PIString::insert_0 */ + PIString & insert(const int index, const PIChar & c) {PIDeque::insert(index, c); return *this;} + + /*! \brief Insert symbol "c" after index "index" and return this string + * \details Example: \snippet pistring.cpp PIString::insert_1 */ + PIString & insert(const int index, const char & c) {return insert(index, PIChar(c));} + + /*! \brief Insert string "str" after index "index" and return this string + * \details Example: \snippet pistring.cpp PIString::insert_2 */ + PIString & insert(const int index, const PIString & str); + + /*! \brief Insert string "str" after index "index" and return this string + * \details Example: \snippet pistring.cpp PIString::insert_2 */ + PIString & insert(const int index, const char * c) {return insert(index, PIString(c));} + + /*! \brief Enlarge string to length "len" by addition sequence of symbols + * "c" at the end of string, and return this string + * \details Example: \snippet pistring.cpp PIString::expandRightTo + * \sa \a expandLeftTo() */ + PIString & expandRightTo(const int len, const PIChar & c) {if (len > length()) resize(len, c); return *this;} + + /*! \brief Enlarge string to length "len" by addition sequence of symbols + * "c" at the beginning of string, and return this string + * \details Example: \snippet pistring.cpp PIString::expandLeftTo + * \sa \a expandRightTo() */ + PIString & expandLeftTo(const int len, const PIChar & c) {if (len > length()) insert(0, PIString(len - length(), c)); return *this;} + + /*! \brief Reverse string and return this string + * \details Example: \snippet pistring.cpp PIString::reverse + * \sa \a reversed() */ + PIString & reverse() {PIString str(*this); clear(); piForeachR (const PIChar & c, str) push_back(c); return *this;} + + /*! \brief Reverse copy of this string and return it + * \details Example: \snippet pistring.cpp PIString::reversed + * \sa \a reverse() */ + PIString reversed() const {PIString str(*this); str.reverse(); return str;} + + + /*! \brief Take a part of string from symbol at index "start" and maximum length "len" and return it + * \details Example: \snippet pistring.cpp PIString::takeMid + * \sa \a takeLeft, \a takeRight() */ + PIString takeMid(const int start, const int len = -1) {PIString ret(mid(start, len)); cutMid(start, len); return ret;} + + /*! \brief Take a part from the begin of string with maximum length "len" and return it + * \details Example: \snippet pistring.cpp PIString::takeLeft + * \sa \a takeMid(), \a takeRight() */ + PIString takeLeft(const int len) {PIString ret(left(len)); cutLeft(len); return ret;} + + /*! \brief Take a part from the end of string with maximum length "len" and return it + * \details Example: \snippet pistring.cpp PIString::takeRight + * \sa \a takeMid(), \a takeLeft() */ + PIString takeRight(const int len) {PIString ret(right(len)); cutRight(len); return ret;} + + /*! \brief Take a symbol from the begin of this string and return it + * \details Example: \snippet pistring.cpp PIString::takeSymbol + * \sa \a takeWord(), \a takeCWord(), \a takeLine(), \a takeNumber(), \a takeRange() */ + PIString takeSymbol(); + + /*! \brief Take a word from the begin of this string and return it + * \details Example: \snippet pistring.cpp PIString::takeWord + * \sa \a takeSymbol(), \a takeCWord(), \a takeLine(), \a takeNumber(), \a takeRange() */ + PIString takeWord(); + + /*! \brief Take a word with letters, numbers and '_' symbols from the + * begin of this string and return it + * \details Example: \snippet pistring.cpp PIString::takeCWord + * \sa \a takeSymbol(), \a takeWord(), \a takeLine(), \a takeNumber(), \a takeRange() */ + PIString takeCWord(); + + /*! \brief Take a line from the begin of this string and return it + * \details Example: \snippet pistring.cpp PIString::takeLine + * \sa \a takeSymbol(), \a takeWord(), \a takeCWord(), \a takeNumber(), \a takeRange() */ + PIString takeLine(); + + /*! \brief Take a number with C-format from the begin of this string and return it + * \details Example: \snippet pistring.cpp PIString::takeNumber + * \sa \a takeSymbol(), \a takeWord(), \a takeCWord(), \a takeLine(), \a takeRange() */ + PIString takeNumber(); + + /*! \brief Take a range between "start" and "end" symbols from the begin of this + * string and return it. + * \details "Shield" symbol prevent analysis of the next symbol. + * Example: \snippet pistring.cpp PIString::takeRange + * \sa \a takeSymbol(), \a takeWord(), \a takeLine(), \a takeNumber() */ + PIString takeRange(const PIChar & start, const PIChar & end, const PIChar & shield = '\\'); + + //const char * data() {return convertToStd().c_str();} + + + /*! \brief Return real bytes count of this string + * \details It`s equivalent length of char sequence + * returned by function \a data() \n + * Example: \snippet pistring.cpp PIString::lengthAscii + * \sa \a data() */ + int lengthAscii() const; + + /*! \brief Return \c char * representation of this string + * \details This function fill buffer by sequence + * of chars. Minimum length of this buffer is count + * of symbols. Returned \c char * is valid until next + * execution of this function.\n + * Example: \snippet pistring.cpp PIString::data + * \sa \a lengthAscii() */ + const char * data() const; + + //! \brief Return \c std::string representation of this string + std::string stdString() const {return convertToStd();} +#ifdef HAS_LOCALE + wstring stdWString() const {return convertToWString();} +#endif + + //! \brief Return \a PIByteArray contains \a data() of this string + PIByteArray toByteArray() const {const char * d = data(); return PIByteArray(d, lengthAscii());} + + /*! \brief Split string with delimiter "delim" to \a PIStringList and return it + * \details Example: \snippet pistring.cpp PIString::split */ + PIStringList split(const PIString & delim) const; + + + //! \brief Convert each symbol in copyed string to upper case and return it + PIString toUpperCase() const; + + //! \brief Convert each symbol in copyed string to lower case and return it + PIString toLowerCase() const; +#ifdef HAS_LOCALE + PIString toNativeDecimalPoints() const {PIString s(*this); if (currentLocale == 0) return s; return s.replaceAll(".", currentLocale->decimal_point).replaceAll(",", currentLocale->decimal_point);} +#else + PIString toNativeDecimalPoints() const {return PIString(*this).replaceAll(",", ".");} +#endif + + + //! \brief Search substring "str" from symbol at index "start" and return first occur position + //! \details Example: \snippet pistring.cpp PIString::find + int find(const char str, const int start = 0) const; + + //! \brief Search substring "str" from symbol at index "start" and return first occur position + //! \details Example: \snippet pistring.cpp PIString::find + int find(const PIString str, const int start = 0) const; + + //! \brief Search substring "str" from symbol at index "start" and return first occur position + //! \details Example: \snippet pistring.cpp PIString::find + int find(const char * str, const int start = 0) const {return find(PIString(str), start);} + + //! \brief Search substring "str" from symbol at index "start" and return first occur position + //! \details Example: \snippet pistring.cpp PIString::find + int find(const string str, const int start = 0) const {return find(PIString(str), start);} + + //! \brief Search substring "str" from symbol at index "start" and return last occur position + //! \details Example: \snippet pistring.cpp PIString::findLast + int findLast(const char str, const int start = 0) const; + + //! \brief Search substring "str" from symbol at index "start" and return last occur position + //! \details Example: \snippet pistring.cpp PIString::findLast + int findLast(const PIString str, const int start = 0) const; + + //! \brief Search substring "str" from symbol at index "start" and return last occur position + //! \details Example: \snippet pistring.cpp PIString::findLast + int findLast(const char * str, const int start = 0) const {return findLast(PIString(str), start);} + + //! \brief Search substring "str" from symbol at index "start" and return last occur position + //! \details Example: \snippet pistring.cpp PIString::findLast + int findLast(const string str, const int start = 0) const {return findLast(PIString(str), start);} + + //! \brief Search word "word" from symbol at index "start" and return first occur position. + //! \details Example: \snippet pistring.cpp PIString::findWord + int findWord(const PIString & word, const int start = 0) const; + + //! \brief Search C-style word "word" from symbol at index "start" and return first occur position. + //! \details Example: \snippet pistring.cpp PIString::findCWord + int findCWord(const PIString & word, const int start = 0) const; + + //! \brief Return if string starts with "str" + bool startsWith(const PIString & str) const; + + //! \brief Return if string ends with "str" + bool endsWith(const PIString & str) const; + + //! \brief Return symbols length of string + int length() const {return size();} + + //! \brief Return \c true if string is empty, i.e. length = 0 + bool isEmpty() const {return (size() == 0 || *this == "");} + + + //! \brief Return \c true if string equal "true", "yes", "on" or positive not null numeric value + bool toBool() const {PIString s(*this); if (atof(s.toNativeDecimalPoints().data()) > 0. || s.trimmed().toLowerCase() == "true" || s.trimmed().toLowerCase() == "yes" || s.trimmed().toLowerCase() == "on") return true; return false;} + + //! \brief Return \c char numeric value of string + char toChar() const; + + //! \brief Return \c short numeric value of string in base "base" + //! \details Example: \snippet pistring.cpp PIString::toNumber + short toShort(int base = -1, bool * ok = 0) const {return short(toNumberBase(*this, base, ok));} + + //! \brief Return \c ushort numeric value of string in base "base" + //! \details Example: \snippet pistring.cpp PIString::toNumber + ushort toUShort(int base = -1, bool * ok = 0) const {return ushort(toNumberBase(*this, base, ok));} + + //! \brief Return \c int numeric value of string in base "base" + //! \details Example: \snippet pistring.cpp PIString::toNumber + int toInt(int base = -1, bool * ok = 0) const {return int(toNumberBase(*this, base, ok));} + + //! \brief Return \c uint numeric value of string in base "base" + //! \details Example: \snippet pistring.cpp PIString::toNumber + uint toUInt(int base = -1, bool * ok = 0) const {return uint(toNumberBase(*this, base, ok));} + + //! \brief Return \c long numeric value of string in base "base" + //! \details Example: \snippet pistring.cpp PIString::toNumber + long toLong(int base = -1, bool * ok = 0) const {return long(toNumberBase(*this, base, ok));} + + //! \brief Return \c ulong numeric value of string in base "base" + //! \details Example: \snippet pistring.cpp PIString::toNumber + ulong toULong(int base = -1, bool * ok = 0) const {return ulong(toNumberBase(*this, base, ok));} + + //! \brief Return \c llong numeric value of string in base "base" + //! \details Example: \snippet pistring.cpp PIString::toNumber + llong toLLong(int base = -1, bool * ok = 0) const {return toNumberBase(*this, base, ok);} + + //! \brief Return \c ullong numeric value of string in base "base" + //! \details Example: \snippet pistring.cpp PIString::toNumber + ullong toULLong(int base = -1, bool * ok = 0) const {return ullong(toNumberBase(*this, base, ok));} + + //! \brief Return \c float numeric value of string + //! \details Example: \snippet pistring.cpp PIString::toFloat + float toFloat() const {return (float)atof(toNativeDecimalPoints().data());} + + //! \brief Return \c double numeric value of string + //! \details Example: \snippet pistring.cpp PIString::toFloat + double toDouble() const {return atof(toNativeDecimalPoints().data());} + + //! \brief Return \c ldouble numeric value of string + //! \details Example: \snippet pistring.cpp PIString::toFloat + ldouble toLDouble() const {return atof(toNativeDecimalPoints().data());} + + //inline PIString & setNumber(const char value) {clear(); *this += itos(value); return *this;} + + //! \brief Set string content to numeric representation of "value" in base "base" + //! \details Example: \snippet pistring.cpp PIString::setNumber + PIString & setNumber(const short value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} + + //! \brief Set string content to numeric representation of "value" in base "base" + //! \details Example: \snippet pistring.cpp PIString::setNumber + PIString & setNumber(const ushort value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} + + //! \brief Set string content to numeric representation of "value" in base "base" + //! \details Example: \snippet pistring.cpp PIString::setNumber + PIString & setNumber(const int value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} + + //! \brief Set string content to numeric representation of "value" in base "base" + //! \details Example: \snippet pistring.cpp PIString::setNumber + PIString & setNumber(const uint value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} + + //! \brief Set string content to numeric representation of "value" in base "base" + //! \details Example: \snippet pistring.cpp PIString::setNumber + PIString & setNumber(const long value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} + + //! \brief Set string content to numeric representation of "value" in base "base" + //! \details Example: \snippet pistring.cpp PIString::setNumber + PIString & setNumber(const ulong value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} + + //! \brief Set string content to numeric representation of "value" in base "base" + //! \details Example: \snippet pistring.cpp PIString::setNumber + PIString & setNumber(const llong & value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} + + //! \brief Set string content to numeric representation of "value" in base "base" + //! \details Example: \snippet pistring.cpp PIString::setNumber + PIString & setNumber(const ullong & value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} + + //! \brief Set string content to numeric representation of "value" + //! \details Example: \snippet pistring.cpp PIString::setFloat + PIString & setNumber(const float value) {clear(); *this += ftos(value); return *this;} + + //! \brief Set string content to numeric representation of "value" + //! \details Example: \snippet pistring.cpp PIString::setFloat + PIString & setNumber(const double & value) {clear(); *this += dtos(value); return *this;} + + //! \brief Set string content to numeric representation of "value" + //! \details Example: \snippet pistring.cpp PIString::setFloat + PIString & setNumber(const ldouble & value) {clear(); *this += dtos(value); return *this;} + + //! \brief Set string content to human readable size in B/kB/MB/GB/TB + //! \details Example: \snippet pistring.cpp PIString::setReadableSize + PIString & setReadableSize(llong bytes); + + //inline static PIString fromNumber(const char value) {return PIString(itos(value));} + + //! \brief Return string contains numeric representation of "value" in base "base" + //! \details Example: \snippet pistring.cpp PIString::fromNumber + static PIString fromNumber(const short value, int base = 10, bool * ok = 0) {return fromNumberBaseS(llong(value), base, ok);} + + //! \brief Return string contains numeric representation of "value" in base "base" + //! \details Example: \snippet pistring.cpp PIString::fromNumber + static PIString fromNumber(const ushort value, int base = 10, bool * ok = 0) {return fromNumberBaseU(ullong(value), base, ok);} + + //! \brief Return string contains numeric representation of "value" in base "base" + //! \details Example: \snippet pistring.cpp PIString::fromNumber + static PIString fromNumber(const int value, int base = 10, bool * ok = 0) {return fromNumberBaseS(llong(value), base, ok);} + + //! \brief Return string contains numeric representation of "value" in base "base" + //! \details Example: \snippet pistring.cpp PIString::fromNumber + static PIString fromNumber(const uint value, int base = 10, bool * ok = 0) {return fromNumberBaseU(ullong(value), base, ok);} + + //! \brief Return string contains numeric representation of "value" in base "base" + //! \details Example: \snippet pistring.cpp PIString::fromNumber + static PIString fromNumber(const long value, int base = 10, bool * ok = 0) {return fromNumberBaseS(llong(value), base, ok);} + + //! \brief Return string contains numeric representation of "value" in base "base" + //! \details Example: \snippet pistring.cpp PIString::fromNumber + static PIString fromNumber(const ulong value, int base = 10, bool * ok = 0) {return fromNumberBaseU(ullong(value), base, ok);} + + //! \brief Return string contains numeric representation of "value" in base "base" + //! \details Example: \snippet pistring.cpp PIString::fromNumber + static PIString fromNumber(const llong & value, int base = 10, bool * ok = 0) {return fromNumberBaseS(value, base, ok);} + + //! \brief Return string contains numeric representation of "value" in base "base" + //! \details Example: \snippet pistring.cpp PIString::fromNumber + static PIString fromNumber(const ullong & value, int base = 10, bool * ok = 0) {return fromNumberBaseU(value, base, ok);} + + //! \brief Return string contains numeric representation of "value" + //! \details Example: \snippet pistring.cpp PIString::fromFloat + static PIString fromNumber(const float value) {return PIString(ftos(value));} + + //! \brief Return string contains numeric representation of "value" + //! \details Example: \snippet pistring.cpp PIString::fromFloat + static PIString fromNumber(const double & value) {return PIString(dtos(value));} + + //! \brief Return string contains numeric representation of "value" + //! \details Example: \snippet pistring.cpp PIString::fromFloat + static PIString fromNumber(const ldouble & value) {return PIString(dtos(value));} + + //! \brief Return "true" or "false" + static PIString fromBool(const bool value) {return PIString(value ? "true" : "false");} + + //! \brief Return string contains human readable size in B/kB/MB/GB/TB + //! \details Example: \snippet pistring.cpp PIString::readableSize + static PIString readableSize(llong bytes) {PIString s; s.setReadableSize(bytes); return s;} + + PIString & removeAll(char v) {replaceAll(v, ""); return *this;} + PIString & removeAll(const PIString & v) {replaceAll(v, ""); return *this;} + +private: + static const char toBaseN[]; + static const int fromBaseN[]; + + static PIString fromNumberBaseS(const llong value, int base = 10, bool * ok = 0) { + if (value == 0) return PIString("0"); + if (base < 2 || base > 40) {if (ok != 0) *ok = false; return PIString();} + if (ok != 0) *ok = true; + if (base == 10) return itos(value); + PIString ret; + llong v = value < 0 ? -value : value, cn; + int b = base; + while (v >= llong(base)) { + cn = v % b; + v /= b; + //cout << int(cn) << ", " << int(v) << endl; + ret.push_front(PIChar(toBaseN[cn])); + } + if (v > 0) ret.push_front(PIChar(toBaseN[v])); + if (value < 0) ret.push_front('-'); + return ret; + } + static PIString fromNumberBaseU(const ullong value, int base = 10, bool * ok = 0) { + if (value == 0) return PIString("0"); + if (base < 2 || base > 40) {if (ok != 0) *ok = false; return PIString();} + if (ok != 0) *ok = true; + if (base == 10) return itos(value); + PIString ret; + ullong v = value, cn; + int b = base; + while (v >= ullong(base)) { + cn = v % b; + v /= b; + //cout << int(cn) << ", " << int(v) << endl; + ret.push_front(PIChar(toBaseN[cn])); + } + if (v > 0) ret.push_front(PIChar(toBaseN[v])); + return ret; + } + static llong toNumberBase(const PIString & value, int base = -1, bool * ok = 0) { + PIString v = value.trimmed(); + if (base < 0) { + int ind = v.find("0x"); + if (ind == 0 || ind == 1) {v.remove(ind, 2); base = 16;} + else base = 10; + } else + if (base < 2 || base > 40) {if (ok != 0) *ok = false; return 0;} + //v.reverse(); + if (ok != 0) *ok = true; + PIVector digits; + llong ret = 0, m = 1; + bool neg = false; + int cs; + for (int i = 0; i < v.size_s(); ++i) { + if (v[i] == PIChar('-')) {neg = !neg; continue;} + cs = fromBaseN[int(v[i].toAscii())]; + if (cs < 0 || cs >= base) break; + digits << cs; + } + for (int i = digits.size_s() - 1; i >= 0; --i) { + ret += digits[i] * m; + m *= base; + } + if (neg) ret = -ret; + /*piForeachC (PIChar & i, v) { + if (i == PIChar('-')) {ret = -ret; continue;} + cs = fromBaseN[int(i.toAscii())]; + cout << i << " = " << cs << endl; + if (cs < 0 || cs >= base) return ret; + ret += cs * m; + m *= base; + }*/ + return ret; + } + void appendFromChars(const char * c, int s); + string convertToStd() const; +#ifdef HAS_LOCALE + wstring convertToWString() const {wstring s; for (int i = 0; i < length(); ++i) s.push_back(at(i).toWChar()); return s;} +#endif + + mutable PIByteArray data_; + //string std_string; + //wstring std_wstring; + +}; + + +//! \relatesalso PIString \brief Output operator to std::ostream (cout) +inline std::ostream & operator <<(std::ostream & s, const PIString & v) {for (int i = 0; i < v.length(); ++i) s << v[i]; return s;} + +//! \relatesalso PIString \brief Input operator from std::istream (cin) +inline std::istream & operator >>(std::istream & s, PIString & v) {string ss; s >> ss; v << PIString(ss); return s;} + +//! \relatesalso PIString \relatesalso PICout \brief Output operator to PICout +inline PICout operator <<(PICout s, const PIString & v) {s.space(); s.quote(); s.setControl(0, true); for (int i = 0; i < v.length(); ++i) s << v[i]; s.restoreControl(); s.quote(); return s;} + + +//! \relatesalso PIString \relatesalso PIByteArray \brief Output operator to PIByteArray +inline PIByteArray & operator <<(PIByteArray & s, const PIString & v) {int l = v.lengthAscii(); s << l; if (l <= 0) return s; int os = s.size_s(); s.enlarge(l); memcpy(s.data(os), v.data(), l); return s;} + +//! \relatesalso PIString \relatesalso PIByteArray \brief Input operator from PIByteArray +inline PIByteArray & operator >>(PIByteArray & s, PIString & v) {if (s.size() < 4) {v.clear(); return s;} int l; s >> l; if (l <= 0) return s; v = PIString((const char * )s.data(), l); s.remove(0, l); return s;} + + +//! \relatesalso PIString \brief Return concatenated string +inline PIString operator +(const PIString & str, const PIString & f) {PIString s(str); s += f; return s;} + +//inline PIString operator +(const PIString & f, const char c) {PIString s(f); s.push_back(c); return s;} + +//! \relatesalso PIString \brief Return concatenated string +inline PIString operator +(const PIString & f, const char * str) {PIString s(f); s += str; return s;} + +//! \relatesalso PIString \brief Return concatenated string +inline PIString operator +(const PIString & f, const string & str) {PIString s(f); s += str; return s;} + +//inline PIString operator +(const char c, const PIString & f) {return PIString(c) + f;} + +//! \relatesalso PIString \brief Return concatenated string +inline PIString operator +(const char * str, const PIString & f) {return PIString(str) + f;} + +//! \relatesalso PIString \brief Return concatenated string +inline PIString operator +(const string & str, const PIString & f) {return PIString(str) + f;} + +inline char chrUpr(char c); +inline char chrLwr(char c); + + +/*!\brief Strings array class + * \details This class is based on \a PIDeque and + * expand it functionality. */ +class PIP_EXPORT PIStringList: public PIDeque +{ +public: + + //! Contructs empty strings list + PIStringList() {;} + + //! Contructs strings list with one string "str" + PIStringList(const PIString & str) {push_back(str);} + + //! Contructs empty strings list with strings "s0" and "s1" + PIStringList(const PIString & s0, const PIString & s1) {push_back(s0); push_back(s1);} + + //! Contructs empty strings list with strings "s0", "s1" and "s2" + PIStringList(const PIString & s0, const PIString & s1, const PIString & s2) {push_back(s0); push_back(s1); push_back(s2);} + + //! Contructs empty strings list with strings "s0", "s1", "s2" and "s3" + PIStringList(const PIString & s0, const PIString & s1, const PIString & s2, const PIString & s3) {push_back(s0); push_back(s1); push_back(s2); push_back(s3);} + + PIStringList(const PIStringList & o): PIDeque() {resize(o.size()); for (uint i = 0; i < size(); ++i) (*this)[i] = o[i];} + PIStringList(const PIVector & o): PIDeque() {resize(o.size()); for (uint i = 0; i < size(); ++i) (*this)[i] = o[i];} + PIStringList(const PIDeque & o): PIDeque() {resize(o.size()); for (uint i = 0; i < size(); ++i) (*this)[i] = o[i];} + + + //! \brief Join all strings in one with delimiter "delim" and return it + //! \details Example: \snippet pistring.cpp PIStringList::join + PIString join(const PIString & delim) const {PIString s; for (uint i = 0; i < size(); ++i) {s += at(i); if (i < size() - 1) s += delim;} return s;} + + //! \brief Remove all strings equal "value" and return this + //! \details Example: \snippet pistring.cpp PIStringList::removeStrings + PIStringList & removeStrings(const PIString & value) {for (uint i = 0; i < size(); ++i) {if (at(i) == value) {remove(i); --i;}} return *this;} + + PIStringList & remove(uint num) {PIDeque::remove(num); return *this;} + PIStringList & remove(uint num, uint count) {PIDeque::remove(num, count); return *this;} + + //! \brief Remove duplicated strings and return this + //! \details Example: \snippet pistring.cpp PIStringList::removeDuplicates + PIStringList & removeDuplicates(); + + //! \brief Trim all strings + //! \details Example: \snippet pistring.cpp PIStringList::trim + PIStringList & trim() {for (uint i = 0; i < size(); ++i) at(i).trim(); return *this;} + + //! Return sum of lengths of all strings + uint contentSize() {uint s = 0; for (uint i = 0; i < size(); ++i) s += at(i).size(); return s;} + + //! Compare operator + bool operator ==(const PIStringList & o) const {if (size() != o.size()) return false; for (size_t i = 0; i < size(); ++i) if (o[i] != (*this)[i]) return false; return true;} + + //! Compare operator + bool operator !=(const PIStringList & o) const {return !(o == (*this));} + + PIStringList & operator =(const PIStringList & o) {clear(); for (uint i = 0; i < o.size(); ++i) *this << o[i]; return *this;} + + PIStringList & operator <<(const PIString & str) {push_back(str); return *this;} + PIStringList & operator <<(const PIStringList & sl) {piForeachC (PIString & i, sl) push_back(i); return *this;} + //inline PIStringList & operator <<(const char c) {push_back(PIString(c)); return *this;} + PIStringList & operator <<(const char * str) {push_back(PIString(str)); return *this;} + PIStringList & operator <<(const string & str) {push_back(str); return *this;} + PIStringList & operator <<(const int & num) {push_back(PIString::fromNumber(num)); return *this;} + PIStringList & operator <<(const short & num) {push_back(PIString::fromNumber(num)); return *this;} + PIStringList & operator <<(const long & num) {push_back(PIString::fromNumber(num)); return *this;} + PIStringList & operator <<(const float & num) {push_back(PIString::fromNumber(num)); return *this;} + PIStringList & operator <<(const double & num) {push_back(PIString::fromNumber(num)); return *this;} + +}; + + +//! \relatesalso PIStringList \relatesalso PIByteArray \brief Output operator to PIByteArray +inline PIByteArray & operator <<(PIByteArray & s, const PIStringList & v) {s << v.size_s(); for (int i = 0; i < v.size_s(); ++i) s << v[i]; return s;} + +//! \relatesalso PIStringList \relatesalso PIByteArray \brief Input operator from PIByteArray +inline PIByteArray & operator >>(PIByteArray & s, PIStringList & v) {int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;} + + +//! \relatesalso PIStringList \brief Output operator to std::ostream (cout) +inline std::ostream & operator <<(std::ostream & s, const PIStringList & v) {s << "{"; for (uint i = 0; i < v.size(); ++i) {s << '\"' << v[i] << '\"'; if (i < v.size() - 1) s << ", ";} s << "}"; return s;} + +//! \relatesalso PIStringList \relatesalso PICout \brief Output operator to PICout +inline PICout operator <<(PICout s, const PIStringList & v) {s.space(); s.setControl(0, true); s << "{"; for (uint i = 0; i < v.size(); ++i) {s << '\"' << v[i] << '\"'; if (i < v.size() - 1) s << ", ";} s << "}"; s.restoreControl(); return s;} + +#endif // PISTRING_H diff --git a/src/core/pitime.cpp b/src/core/pitime.cpp new file mode 100755 index 00000000..4b276c4a --- /dev/null +++ b/src/core/pitime.cpp @@ -0,0 +1,404 @@ +/* + PIP - Platform Independent Primitives + Timer + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pitime.h" +#include "pisystemtests.h" + + +/*! \class PISystemTime + * \brief System time + * + * \section PISystemTime_sec0 Synopsis + * This class provide arithmetic functions for POSIX system time. + * This time represents as seconds and nanosecons in integer formats. + * You can take current system time with function \a PISystemTime::current(), + * compare times, sum or subtract two times, convert time to/from + * seconds, milliseconds, microseconds or nanoseconds. + * \section PISystemTime_sec1 Example + * \snippet pitimer.cpp system_time +*/ + + +/*! \class PITimeMeasurer + * \brief Time measurements + * + * \section PITimeMeasurer_sec0 Synopsis + * Function \a reset() set time mark to current + * system time, then functions double elapsed_*() returns time elapsed from this mark. + * These functions can returns nano-, micro-, milli- and seconds with suffixes "n", "u", "m" + * and "s" +*/ + + +void piUSleep(int usecs) { + if (usecs <= 0) return; +#ifdef WINDOWS + if (usecs > 0) Sleep(usecs / 1000); +#else + usecs -= PISystemTests::usleep_offset_us; + if (usecs > 0) usleep(usecs); +#endif +} + + +bool operator ==(const PITime & t0, const PITime & t1) { + return (t0.hours == t1.hours && t0.minutes == t1.minutes && t0.seconds == t1.seconds); +} + + +bool operator <(const PITime & t0, const PITime & t1) { + if (t0.hours == t1.hours) { + if (t0.minutes == t1.minutes) { + return t0.seconds < t1.seconds; + } else return t0.minutes < t1.minutes; + } else return t0.hours < t1.hours; +} + + +bool operator >(const PITime & t0, const PITime & t1) { + if (t0.hours == t1.hours) { + if (t0.minutes == t1.minutes) { + return t0.seconds > t1.seconds; + } else return t0.minutes > t1.minutes; + } else return t0.hours > t1.hours; +} + +bool operator ==(const PIDate & t0, const PIDate & t1) { + return (t0.year == t1.year && t0.month == t1.month && t0.day == t1.day); +} + + +bool operator <(const PIDate & t0, const PIDate & t1) { + if (t0.year == t1.year) { + if (t0.month == t1.month) { + return t0.day < t1.day; + } else return t0.month < t1.month; + } else return t0.year < t1.year; +} + + +bool operator >(const PIDate & t0, const PIDate & t1) { + if (t0.year == t1.year) { + if (t0.month == t1.month) { + return t0.day > t1.day; + } else return t0.month > t1.month; + } else return t0.year > t1.year; +} + +bool operator ==(const PIDateTime & t0, const PIDateTime & t1) { + return (t0.year == t1.year && t0.month == t1.month && t0.day == t1.day && + t0.hours == t1.hours && t0.minutes == t1.minutes && t0.seconds == t1.seconds); +} + + +bool operator <(const PIDateTime & t0, const PIDateTime & t1) { + if (t0.year == t1.year) { + if (t0.month == t1.month) { + if (t0.day == t1.day) { + if (t0.hours == t1.hours) { + if (t0.minutes == t1.minutes) { + return t0.seconds < t1.seconds; + } else return t0.minutes < t1.minutes; + } else return t0.hours < t1.hours; + } else return t0.day < t1.day; + } else return t0.month < t1.month; + } else return t0.year < t1.year; +} + + +bool operator >(const PIDateTime & t0, const PIDateTime & t1) { + if (t0.year == t1.year) { + if (t0.month == t1.month) { + if (t0.day == t1.day) { + if (t0.hours == t1.hours) { + if (t0.minutes == t1.minutes) { + return t0.seconds > t1.seconds; + } else return t0.minutes > t1.minutes; + } else return t0.hours > t1.hours; + } else return t0.day > t1.day; + } else return t0.month > t1.month; + } else return t0.year > t1.year; +} + + +PITime PITime::current() { + time_t rt = ::time(0); + tm * pt = localtime(&rt); + PITime t; + t.seconds = pt->tm_sec; + t.minutes = pt->tm_min; + t.hours = pt->tm_hour; + return t; +} + + +PIDate PIDate::current() { + time_t rt = ::time(0); + tm * pt = localtime(&rt); + PIDate d; + d.day = pt->tm_mday; + d.month = pt->tm_mon + 1; + d.year = pt->tm_year + 1900; + return d; +} + + +PIDateTime PIDateTime::current() { + time_t rt = ::time(0); + tm * pt = localtime(&rt); + PIDateTime dt; + dt.milliseconds = 0; + dt.seconds = pt->tm_sec; + dt.minutes = pt->tm_min; + dt.hours = pt->tm_hour; + dt.day = pt->tm_mday; + dt.month = pt->tm_mon + 1; + dt.year = pt->tm_year + 1900; + return dt; +} + + +#ifdef WINDOWS +PISystemTime::PISystemTime(const FILETIME & t) { + ullong lt = ullong(t.dwHighDateTime) * 0x100000000U + ullong(t.dwLowDateTime); + seconds = lt / 10000000U; + nanoseconds = (lt % 10000000U) * 100U; +} +#endif + + +PISystemTime PISystemTime::abs() const { + if (seconds < 0) + return PISystemTime(piAbsl(seconds) - 1, 1e+9 - piAbsl(nanoseconds)); + else + return PISystemTime(piAbsl(seconds), piAbsl(nanoseconds)); +} + + +PISystemTime PISystemTime::current(bool precise_but_not_system) { +#ifdef WINDOWS + if (precise_but_not_system) { + llong qpc(0); + if (__pi_perf_freq > 0) { + qpc = __PIQueryPerformanceCounter(); + return PISystemTime::fromSeconds(qpc / double(__pi_perf_freq)); + } + return PISystemTime(); + } else { + FILETIME ft, sft; +# if (_WIN32_WINNT >= 0x0602) + GetSystemTimePreciseAsFileTime(&ft); +# else + GetSystemTimeAsFileTime(&ft); +# endif + sft.dwHighDateTime = ft.dwHighDateTime - __pi_ftjan1970.dwHighDateTime; + if (ft.dwLowDateTime < __pi_ftjan1970.dwLowDateTime) { + sft.dwLowDateTime = ft.dwLowDateTime + (0xFFFFFFFF - __pi_ftjan1970.dwLowDateTime); + sft.dwHighDateTime++; + } else + sft.dwLowDateTime = ft.dwLowDateTime - __pi_ftjan1970.dwLowDateTime; + ullong lt = ullong(sft.dwHighDateTime) * 0x100000000U + ullong(sft.dwLowDateTime); + return PISystemTime(lt / 10000000U, (lt % 10000000U) * 100U); + } + //long t_cur = GetCurrentTime(); + //return PISystemTime(t_cur / 1000, (t_cur % 1000) * 1000000); +#else +# ifdef MAC_OS + mach_timespec_t t_cur; + clock_get_time(__pi_mac_clock, &t_cur); +# else + timespec t_cur; + clock_gettime(0, &t_cur); +# endif + return PISystemTime(t_cur.tv_sec, t_cur.tv_nsec); +#endif +} + + +PIString PITime::toString(const PIString & format) const { + PIString ts = format; + ts.replace("hh", PIString::fromNumber(hours).expandLeftTo(2, '0')); + ts.replace("h", PIString::fromNumber(hours)); + ts.replace("mm", PIString::fromNumber(minutes).expandLeftTo(2, '0')); + ts.replace("m", PIString::fromNumber(minutes)); + ts.replace("ss", PIString::fromNumber(seconds).expandLeftTo(2, '0')); + ts.replace("s", PIString::fromNumber(seconds)); + ts.replace("zzz", PIString::fromNumber(milliseconds).expandLeftTo(3, '0')); + ts.replace("zz", PIString::fromNumber(milliseconds).expandLeftTo(2, '0')); + ts.replace("z", PIString::fromNumber(milliseconds)); + return ts; +} + + +PIString PIDate::toString(const PIString & format) const { + PIString ts = format; + ts.replace("yyyy", PIString::fromNumber(year).expandLeftTo(4, '0')); + ts.replace("yy", PIString::fromNumber(year).right(2)); + ts.replace("y", PIString::fromNumber(year).right(1)); + ts.replace("MM", PIString::fromNumber(month).expandLeftTo(2, '0')); + ts.replace("M", PIString::fromNumber(month)); + ts.replace("dd", PIString::fromNumber(day).expandLeftTo(2, '0')); + ts.replace("d", PIString::fromNumber(day)); + return ts; +} + + +PIString PIDateTime::toString(const PIString & format) const { + PIString ts = format; + ts.replace("yyyy", PIString::fromNumber(year).expandLeftTo(4, '0')); + ts.replace("yy", PIString::fromNumber(year).right(2)); + ts.replace("y", PIString::fromNumber(year).right(1)); + ts.replace("MM", PIString::fromNumber(month).expandLeftTo(2, '0')); + ts.replace("M", PIString::fromNumber(month)); + ts.replace("dd", PIString::fromNumber(day).expandLeftTo(2, '0')); + ts.replace("d", PIString::fromNumber(day)); + ts.replace("hh", PIString::fromNumber(hours).expandLeftTo(2, '0')); + ts.replace("h", PIString::fromNumber(hours)); + ts.replace("mm", PIString::fromNumber(minutes).expandLeftTo(2, '0')); + ts.replace("m", PIString::fromNumber(minutes)); + ts.replace("ss", PIString::fromNumber(seconds).expandLeftTo(2, '0')); + ts.replace("s", PIString::fromNumber(seconds)); + ts.replace("zzz", PIString::fromNumber(milliseconds).expandLeftTo(3, '0')); + ts.replace("zz", PIString::fromNumber(milliseconds).expandLeftTo(2, '0')); + ts.replace("z", PIString::fromNumber(milliseconds)); + return ts; +} + + +#ifdef WINDOWS + PIDateTime::PIDateTime(FILETIME t) { + FILETIME lt; + FileTimeToLocalFileTime(&t, <); + SYSTEMTIME st; + FileTimeToSystemTime(<, &st); + year = st.wYear; + month = st.wMonth; + day = st.wDay; + hours = st.wHour; + minutes = st.wMinute; + seconds = st.wSecond; + milliseconds = st.wMilliseconds; + } +#endif + + +time_t PIDateTime::toSecondSinceEpoch() const { + tm pt; + memset(&pt, 0, sizeof(pt)); + pt.tm_sec = seconds; + pt.tm_min = minutes; + pt.tm_hour = hours; + pt.tm_mday = day; + pt.tm_mon = month - 1; +#ifdef WINDOWS + pt.tm_year = piMaxi(year - 1900, 70); +#else + pt.tm_year = piMaxi(year - 1900, 0); +#endif + return mktime(&pt); +} + + +PIDateTime PIDateTime::fromSecondSinceEpoch(const time_t sec) { + tm * pt = localtime(&sec); + PIDateTime dt; + dt.seconds = pt->tm_sec; + dt.minutes = pt->tm_min; + dt.hours = pt->tm_hour; + dt.day = pt->tm_mday; + dt.month = pt->tm_mon + 1; + dt.year = pt->tm_year + 1900; + return dt; + +} + + +PIString time2string(const PITime & time, const PIString & format) { + PIString ts = format; + ts.replace("hh", PIString::fromNumber(time.hours).expandLeftTo(2, '0')); + ts.replace("h", PIString::fromNumber(time.hours)); + ts.replace("mm", PIString::fromNumber(time.minutes).expandLeftTo(2, '0')); + ts.replace("m", PIString::fromNumber(time.minutes)); + ts.replace("ss", PIString::fromNumber(time.seconds).expandLeftTo(2, '0')); + ts.replace("s", PIString::fromNumber(time.seconds)); + return ts; +} + + +PIString date2string(const PIDate & date, const PIString & format) { + PIString ts = format; + ts.replace("yyyy", PIString::fromNumber(date.year).expandLeftTo(4, '0')); + ts.replace("yy", PIString::fromNumber(date.year).right(2)); + ts.replace("y", PIString::fromNumber(date.year).right(1)); + ts.replace("MM", PIString::fromNumber(date.month).expandLeftTo(2, '0')); + ts.replace("M", PIString::fromNumber(date.month)); + ts.replace("dd", PIString::fromNumber(date.day).expandLeftTo(2, '0')); + ts.replace("d", PIString::fromNumber(date.day)); + return ts; +} + + +PIString datetime2string(const PIDateTime & date, const PIString & format) { + PIString ts = format; + ts.replace("hh", PIString::fromNumber(date.hours).expandLeftTo(2, '0')); + ts.replace("h", PIString::fromNumber(date.hours)); + ts.replace("mm", PIString::fromNumber(date.minutes).expandLeftTo(2, '0')); + ts.replace("m", PIString::fromNumber(date.minutes)); + ts.replace("ss", PIString::fromNumber(date.seconds).expandLeftTo(2, '0')); + ts.replace("s", PIString::fromNumber(date.seconds)); + ts.replace("yyyy", PIString::fromNumber(date.year).expandLeftTo(4, '0')); + ts.replace("yy", PIString::fromNumber(date.year).right(2)); + ts.replace("y", PIString::fromNumber(date.year).right(1)); + ts.replace("MM", PIString::fromNumber(date.month).expandLeftTo(2, '0')); + ts.replace("M", PIString::fromNumber(date.month)); + ts.replace("dd", PIString::fromNumber(date.day).expandLeftTo(2, '0')); + ts.replace("d", PIString::fromNumber(date.day)); + return ts; +} + + + +PITimeMeasurer::PITimeMeasurer() { + reset(); +} + + +double PITimeMeasurer::elapsed_n() { + return (PISystemTime::current(true) - t_st).toNanoseconds() - PISystemTests::time_elapsed_ns; +} + + +double PITimeMeasurer::elapsed_u() { + return (PISystemTime::current(true) - t_st).toMicroseconds() - PISystemTests::time_elapsed_ns / 1.E+3; +} + + +double PITimeMeasurer::elapsed_m() { + return (PISystemTime::current(true) - t_st).toMilliseconds() - PISystemTests::time_elapsed_ns / 1.E+6; +} + + +double PITimeMeasurer::elapsed_s() { + return (PISystemTime::current(true) - t_st).toSeconds() - PISystemTests::time_elapsed_ns / 1.E+9; +} + + +PISystemTime PITimeMeasurer::elapsed() { + return (PISystemTime::current(true) - t_st); +} diff --git a/src/core/pitime.h b/src/core/pitime.h new file mode 100755 index 00000000..cf8b2d90 --- /dev/null +++ b/src/core/pitime.h @@ -0,0 +1,328 @@ +/*! \file pitime.h + * \brief Time structs +*/ +/* + PIP - Platform Independent Primitives + Time structs + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PITIME_H +#define PITIME_H + +#include +#include +#include "pistring.h" + +#ifdef DOXYGEN +//! \brief Sleep for "msecs" milliseconds +void msleep(int msecs); +#else +# ifdef WINDOWS +inline void msleep(int msecs) {Sleep(msecs);} +# else +inline void msleep(int msecs) {usleep(msecs * 1000);} +# endif +#endif + +/*! \brief Precise sleep for "usecs" microseconds + * \details This function consider \c "usleep" offset + * on QNX/Linux/Mac, which is calculated with + * \a pip_sys_test program. If there is correct + * offset value in system config, this function + * wait \b exactly "usecs" microseconds. */ +void piUSleep(int usecs); // on !Windows consider constant "usleep" offset + +/*! \brief Precise sleep for "msecs" milliseconds + * \details This function exec \a piUSleep (msecs * 1000). */ +inline void piMSleep(double msecs) {piUSleep(msecs * 1000);} // on !Windows consider constant "usleep" offset + +/*! \brief Precise sleep for "secs" seconds + * \details This function exec \a piUSleep (msecs * 1000000). */ +inline void piSleep(double secs) {piUSleep(secs * 1000000);} // on !Windows consider constant "usleep" offset + +class PIP_EXPORT PISystemTime { +public: + + //! Contructs system time with s = ns = 0 + PISystemTime() {seconds = nanoseconds = 0;} + + //! Contructs system time with s = "s" and ns = "ns" + PISystemTime(long s, long ns) {seconds = s; nanoseconds = ns; checkOverflows();} + + //! Contructs system time from another + PISystemTime(const PISystemTime & t) {seconds = t.seconds; nanoseconds = t.nanoseconds;} + +#ifdef WINDOWS + PISystemTime(const FILETIME & t); +#endif + + //! Returns stored system time value in seconds + double toSeconds() const {return double(seconds) + nanoseconds / 1.e+9;} + + //! Returns stored system time value in milliseconds + double toMilliseconds() const {return seconds * 1.e+3 + nanoseconds / 1.e+6;} + + //! Returns stored system time value in microseconds + double toMicroseconds() const {return seconds * 1.e+6 + nanoseconds / 1.e+3;} + + //! Returns stored system time value in nanoseconds + double toNanoseconds() const {return seconds * 1.e+9 + double(nanoseconds);} + + + //! Add to stored system time "v" seconds + PISystemTime & addSeconds(double v) {*this += fromSeconds(v); return *this;} + + //! Add to stored system time "v" milliseconds + PISystemTime & addMilliseconds(double v) {*this += fromMilliseconds(v); return *this;} + + //! Add to stored system time "v" microseconds + PISystemTime & addMicroseconds(double v) {*this += fromMicroseconds(v); return *this;} + + //! Add to stored system time "v" nanoseconds + PISystemTime & addNanoseconds(double v) {*this += fromNanoseconds(v); return *this;} + + + //! Sleep for stored value. \warning Use this function to sleep for difference of system times or constructs system time. + //! If you call this function on system time returned with \a PISystemTime::current() thread will be sleep almost forever. + void sleep() {piUSleep(piFloord(toMicroseconds()));} // wait self value, useful to wait some dT = (t1 - t0) + + + //! Returns copy of this system time with absolutely values of s and ns + PISystemTime abs() const; + + //! Returns sum of this system time with "t" + PISystemTime operator +(const PISystemTime & t) const {PISystemTime tt(*this); tt.seconds += t.seconds; tt.nanoseconds += t.nanoseconds; tt.checkOverflows(); return tt;} + + //! Returns difference between this system time and "t" + PISystemTime operator -(const PISystemTime & t) const {PISystemTime tt(*this); tt.seconds -= t.seconds; tt.nanoseconds -= t.nanoseconds; tt.checkOverflows(); return tt;} + + //! Returns multiplication between this system time and "t" + PISystemTime operator *(const double & v) const {return fromMilliseconds(toMilliseconds() * v);} + + //! Returns division between this system time and "t" + PISystemTime operator /(const double & v) const {return fromMilliseconds(toMilliseconds() / v);} + + //! Add to stored value system time "t" + PISystemTime & operator +=(const PISystemTime & t) {seconds += t.seconds; nanoseconds += t.nanoseconds; checkOverflows(); return *this;} + + //! Subtract from stored value system time "t" + PISystemTime & operator -=(const PISystemTime & t) {seconds -= t.seconds; nanoseconds -= t.nanoseconds; checkOverflows(); return *this;} + + //! Multiply stored value system time by "v" + PISystemTime & operator *=(const double & v) {*this = fromMilliseconds(toMilliseconds() * v); return *this;} + + //! Divide stored value system time by "v" + PISystemTime & operator /=(const double & v) {*this = fromMilliseconds(toMilliseconds() / v); return *this;} + + + //! Compare system times + bool operator ==(const PISystemTime & t) const {return ((seconds == t.seconds) && (nanoseconds == t.nanoseconds));} + + //! Compare system times + bool operator !=(const PISystemTime & t) const {return ((seconds != t.seconds) || (nanoseconds != t.nanoseconds));} + + //! Compare system times + bool operator >(const PISystemTime & t) const {if (seconds == t.seconds) return nanoseconds > t.nanoseconds; return seconds > t.seconds;} + + //! Compare system times + bool operator <(const PISystemTime & t) const {if (seconds == t.seconds) return nanoseconds < t.nanoseconds; return seconds < t.seconds;} + + //! Compare system times + bool operator >=(const PISystemTime & t) const {if (seconds == t.seconds) return nanoseconds >= t.nanoseconds; return seconds >= t.seconds;} + + //! Compare system times + bool operator <=(const PISystemTime & t) const {if (seconds == t.seconds) return nanoseconds <= t.nanoseconds; return seconds <= t.seconds;} + + + //! Contructs system time from seconds "v" + static PISystemTime fromSeconds(double v) {long s = piFloord(v); return PISystemTime(s, (v - s) * 1000000000);} + + //! Contructs system time from milliseconds "v" + static PISystemTime fromMilliseconds(double v) {long s = piFloord(v / 1000.); return PISystemTime(s, (v / 1000. - s) * 1000000000);} + + //! Contructs system time from microseconds "v" + static PISystemTime fromMicroseconds(double v) {long s = piFloord(v / 1000000.); return PISystemTime(s, (v / 1000000. - s) * 1000000000);} + + //! Contructs system time from nanoseconds "v" + static PISystemTime fromNanoseconds(double v) {long s = piFloord(v / 1000000000.); return PISystemTime(s, (v / 1000000000. - s) * 1000000000);} + + //! Returns current system time + static PISystemTime current(bool precise_but_not_system = false); + + //! Seconds of stored system time + long seconds; + + //! Nanoseconds of stored system time + long nanoseconds; + +private: + void checkOverflows() {while (nanoseconds >= 1000000000) {nanoseconds -= 1000000000; seconds++;} while (nanoseconds < 0) {nanoseconds += 1000000000; seconds--;}} + +}; + +//! \relatesalso PICout \relatesalso PIByteArray \brief Output operator to PICout +inline PICout operator <<(PICout s, const PISystemTime & v) {s.space(); s.setControl(0, true); s << "(" << v.seconds << " s, " << v.nanoseconds << " ns)"; s.restoreControl(); return s;} + +//! \relatesalso PISystemTime \relatesalso PIByteArray \brief Output operator to PIByteArray +inline PIByteArray & operator <<(PIByteArray & s, const PISystemTime & v) {s << v.seconds << v.nanoseconds; return s;} + +//! \relatesalso PISystemTime \relatesalso PIByteArray \brief Input operator from PIByteArray +inline PIByteArray & operator >>(PIByteArray & s, PISystemTime & v) {s >> v.seconds >> v.nanoseconds; return s;} + +struct PIP_EXPORT PITime { + PITime(int hours_ = 0, int minutes_ = 0, int seconds_ = 0, int milliseconds_ = 0): hours(hours_), minutes(minutes_), seconds(seconds_), milliseconds(milliseconds_) {;} + int hours; + int minutes; + int seconds; + int milliseconds; + PIString toString(const PIString & format = "h:mm:ss") const; + static PITime current(); +}; +PIP_EXPORT bool operator ==(const PITime & t0, const PITime & t1); +PIP_EXPORT bool operator <(const PITime & t0, const PITime & t1); +PIP_EXPORT bool operator >(const PITime & t0, const PITime & t1); +inline bool operator !=(const PITime & t0, const PITime & t1) {return !(t0 == t1);} +inline bool operator <=(const PITime & t0, const PITime & t1) {return !(t0 > t1);} +inline bool operator >=(const PITime & t0, const PITime & t1) {return !(t0 < t1);} +inline PIByteArray & operator <<(PIByteArray & s, const PITime & v) {s << v.hours << v.minutes << v.seconds << v.milliseconds; return s;} +inline PIByteArray & operator >>(PIByteArray & s, PITime & v) {s >> v.hours >> v.minutes >> v.seconds >> v.milliseconds; return s;} + +struct PIP_EXPORT PIDate { + PIDate(int year_ = 0, int month_ = 0, int day_ = 0): year(year_), month(month_), day(day_) {;} + int year; + int month; + int day; + PIString toString(const PIString & format = "d.MM.yyyy") const; + static PIDate current(); +}; +PIP_EXPORT bool operator ==(const PIDate & t0, const PIDate & t1); +PIP_EXPORT bool operator <(const PIDate & t0, const PIDate & t1); +PIP_EXPORT bool operator >(const PIDate & t0, const PIDate & t1); +inline bool operator !=(const PIDate & t0, const PIDate & t1) {return !(t0 == t1);} +inline bool operator <=(const PIDate & t0, const PIDate & t1) {return !(t0 > t1);} +inline bool operator >=(const PIDate & t0, const PIDate & t1) {return !(t0 < t1);} +inline PIByteArray & operator <<(PIByteArray & s, const PIDate & v) {s << v.year << v.month << v.day; return s;} +inline PIByteArray & operator >>(PIByteArray & s, PIDate & v) {s >> v.year >> v.month >> v.day; return s;} + +struct PIP_EXPORT PIDateTime { + PIDateTime() {year = month = day = hours = minutes = seconds = milliseconds = 0;} + PIDateTime(const PITime & time) {year = month = day = 0; hours = time.hours; minutes = time.minutes; seconds = time.seconds; milliseconds = time.milliseconds;} + PIDateTime(const PIDate & date) {year = date.year; month = date.month; day = date.day; hours = minutes = seconds = milliseconds = 0;} + PIDateTime(const PIDate & date, const PITime & time) {year = date.year; month = date.month; day = date.day; hours = time.hours; minutes = time.minutes; seconds = time.seconds; milliseconds = time.milliseconds;} +#ifdef WINDOWS + PIDateTime(FILETIME t); +#endif + int year; + int month; + int day; + int hours; + int minutes; + int seconds; + int milliseconds; + PIDateTime normalized() const {return PIDateTime::fromSecondSinceEpoch(toSecondSinceEpoch());} + void normalize() {*this = normalized();} + PIString toString(const PIString & format = "h:mm:ss d.MM.yyyy") const; + time_t toSecondSinceEpoch() const; + PISystemTime toSystemTime() const {return PISystemTime(int(toSecondSinceEpoch()), milliseconds * 1000000);} + PIDate date() const {return PIDate(year, month, day);} + PITime time() const {return PITime(hours, minutes, seconds, milliseconds);} + void setDate(const PIDate & d) {year = d.year; month = d.month; day = d.day;} + void setTime(const PITime & t) {hours = t.hours; minutes = t.minutes; seconds = t.seconds; milliseconds = t.milliseconds;} + void operator +=(const PIDateTime & d1) {year += d1.year; month += d1.month; day += d1.day; hours += d1.hours; minutes += d1.minutes; seconds += d1.seconds; normalize();} + void operator -=(const PIDateTime & d1) {year -= d1.year; month -= d1.month; day -= d1.day; hours -= d1.hours; minutes -= d1.minutes; seconds -= d1.seconds; normalize();} + static PIDateTime fromSecondSinceEpoch(const time_t sec); + static PIDateTime fromSystemTime(const PISystemTime & st) {PIDateTime dt = fromSecondSinceEpoch(st.seconds); dt.milliseconds = piClampi(st.nanoseconds / 1000000, 0, 999); return dt;} + static PIDateTime current(); +}; +inline PIDateTime operator +(const PIDateTime & d0, const PIDateTime & d1) {PIDateTime td = d0; td += d1; return td.normalized();} +inline PIDateTime operator -(const PIDateTime & d0, const PIDateTime & d1) {PIDateTime td = d0; td -= d1; return td.normalized();} +PIP_EXPORT bool operator ==(const PIDateTime & t0, const PIDateTime & t1); +PIP_EXPORT bool operator <(const PIDateTime & t0, const PIDateTime & t1); +PIP_EXPORT bool operator >(const PIDateTime & t0, const PIDateTime & t1); +inline bool operator !=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 == t1);} +inline bool operator <=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 > t1);} +inline bool operator >=(const PIDateTime & t0, const PIDateTime & t1) {return !(t0 < t1);} +inline PIByteArray & operator <<(PIByteArray & s, const PIDateTime & v) {s << v.year << v.month << v.day << v.hours << v.minutes << v.seconds << v.milliseconds; return s;} +inline PIByteArray & operator >>(PIByteArray & s, PIDateTime & v) {s >> v.year >> v.month >> v.day >> v.hours >> v.minutes >> v.seconds >> v.milliseconds; return s;} + +DEPRECATED inline PITime currentTime() {return PITime::current();} // obsolete, use PITime::current() instead +DEPRECATED inline PIDate currentDate() {return PIDate::current();} // obsolete, use PIDate::current() instead +DEPRECATED inline PIDateTime currentDateTime() {return PIDateTime::current();} // obsolete, use PIDateTime::current() instead + +//! \brief Returns current system time \deprecated Use \a PISystemTime::current() instead +DEPRECATED inline PISystemTime currentSystemTime() {return PISystemTime::current();} // obsolete, use PISystemTime::current() instead +DEPRECATED PIP_EXPORT PIString time2string(const PITime & time, const PIString & format = "h:mm:ss"); // obsolete, use PITime.toString() instead +DEPRECATED PIP_EXPORT PIString date2string(const PIDate & date, const PIString & format = "d.MM.yyyy"); // obsolete, use PITime.toString() instead +DEPRECATED PIP_EXPORT PIString datetime2string(const PIDateTime & datetime, const PIString & format = "h:mm:ss d.MM.yyyy"); // obsolete, use PIDateTime.toString() instead + + +class PITimeMeasurer { +public: + PITimeMeasurer(); + + /** \brief Set internal time mark to current system time + * \details This function used for set start time mark. Later + * you can find out elapsed time from this time mark to any + * moment of time with \a elapsed_s(), \a elapsed_m(), + * \a elapsed_u() or \a elapsed_n() functions. + * \sa \a elapsed_s(), \a elapsed_m(), \a elapsed_u(), \a elapsed_n() */ + void reset() {t_st = PISystemTime::current(true);} + + //! \brief Returns nanoseconds elapsed from last \a reset() execution or from timer measurer creation. + double elapsed_n(); + + //! \brief Returns microseconds elapsed from last \a reset() execution or from timer measurer creation. + double elapsed_u(); + + //! \brief Returns milliseconds elapsed from last \a reset() execution or from timer measurer creation. + double elapsed_m(); + + //! \brief Returns seconds elapsed from last \a reset() execution or from timer measurer creation. + double elapsed_s(); + + //! \brief Returns PISystemTime elapsed from last \a reset() execution or from timer measurer creation. + PISystemTime elapsed(); + + double reset_time_n() {return t_st.toNanoseconds();} + double reset_time_u() {return t_st.toMicroseconds();} + double reset_time_m() {return t_st.toMilliseconds();} + double reset_time_s() {return t_st.toSeconds();} + + //! \brief Returns time mark of last \a reset() execution or timer measurer creation. + PISystemTime reset_time() {return t_st;} + + //! \brief Returns nanoseconds representation of current system time. + static double elapsed_system_n() {return PISystemTime::current(true).toNanoseconds();} + + //! \brief Returns microseconds representation of current system time. + static double elapsed_system_u() {return PISystemTime::current(true).toMicroseconds();} + + //! \brief Returns milliseconds representation of current system time. + static double elapsed_system_m() {return PISystemTime::current(true).toMilliseconds();} + + //! \brief Returns seconds representation of current system time. + static double elapsed_system_s() {return PISystemTime::current(true).toSeconds();} + + //! \brief Returns time mark of current system time. + static PISystemTime elapsed_system() {return PISystemTime::current(true);} + +private: + PISystemTime t_st, t_cur; + +}; + +#endif // PITIME_H diff --git a/src/core/pivariant.cpp b/src/core/pivariant.cpp new file mode 100755 index 00000000..b170e884 --- /dev/null +++ b/src/core/pivariant.cpp @@ -0,0 +1,534 @@ +/* + PIP - Platform Independent Primitives + Variant type + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pivariant.h" + + +/** \class PIVariant + * \brief Variant type + * \details + * \section PIVariant_sec0 Synopsis + * This class provides general type that can contains all standard types, some + * PIP types or custom type. In case of standard types this class also provides + * convertions between them. + * + * \section PIVariant_sec1 Usage + * %PIVariant useful if you want pass many variables with different types in + * single array, e.g.: + * \code{cpp} + * PIVector array; + * array << PIVariant(10) << PIVariant(1.61) << PIVariant(true) << PIVariant("0xFF"); + * piCout << array; + * piForeachC (PIVariant & i, array) + * piCout << i.toInt(); + * \endcode + * Result: + * \code{cpp} + * {PIVariant(Int, 10), PIVariant(Double, 1,61), PIVariant(Bool, true), PIVariant(String, 0xFF)} + * 10 + * 1 + * 1 + * 255 + * \endcode + * */ + + +PIVariant::PIVariant() { + type_ = PIVariant::Invalid; + memset(_vraw, 0, __PIVARIANT_UNION_SIZE__); +} + + +PIVariant & PIVariant::operator =(const PIVariant & v) { + type_ = v.type_; + memcpy(_vraw, v._vraw, __PIVARIANT_UNION_SIZE__); + _vbytearray = v._vbytearray; + _vbitarray = v._vbitarray; + _vstring = v._vstring; + _vstringlist = v._vstringlist; + _vcustom = v._vcustom; + return *this; +} + + +bool PIVariant::operator ==(const PIVariant & v) const { + if (type_ != v.type_) return false; + switch (type_) { + case PIVariant::Bool: + case PIVariant::Char: + case PIVariant::UChar: + case PIVariant::Short: + case PIVariant::UShort: + case PIVariant::Int: + case PIVariant::UInt: + case PIVariant::Long: + case PIVariant::ULong: return _vint == v._vint; + case PIVariant::LLong: + case PIVariant::ULLong: return _vllong == v._vllong; + case PIVariant::Float: return _vfloat == v._vfloat; + case PIVariant::Double: return _vdouble == v._vdouble; + case PIVariant::LDouble: return _vldouble == v._vldouble; + case PIVariant::Complexd: return _vcomplexd == _vvcomplexd(v); + case PIVariant::Complexld: return _vcomplexld == _vvcomplexld(v); + case PIVariant::BitArray: return _vbitarray == v._vbitarray; + case PIVariant::ByteArray: return _vbytearray == v._vbytearray; + case PIVariant::String: return _vstring == v._vstring; + case PIVariant::StringList: return _vstringlist == v._vstringlist; + case PIVariant::Time: return _vtime == _vvtime(v); + case PIVariant::Date: return _vdate == _vvdate(v); + case PIVariant::DateTime: return _vdatetime == _vvdatetime(v); + case PIVariant::SystemTime: return _vsystime == _vvsystime(v); + default: break; + }; + return false; +} + + +PIVariant::Type PIVariant::typeFromName(const PIString & tname) { + PIString s = tname.trimmed().toLowerCase().replaceAll(" ", ""); + if (s == "bool" || s == "boolean") return PIVariant::Bool; + if (s == "char" || s == "sbyte") return PIVariant::Char; + if (s == "short" || s == "shortint" || s == "signedshort" || s == "signedshortint" || s == "sword") return PIVariant::Short; + if (s == "int" || s == "signed" || s == "signedint") return PIVariant::Int; + if (s == "long" || s == "longint" || s == "signedlong" || s == "signedlongint" || s == "sdword") return PIVariant::Long; + if (s == "llong" || s == "longlong" || s == "longlongint" || s == "signedlonglong" || s == "signedlonglongint" || s == "sqword") return PIVariant::LLong; + if (s == "uchar" || s == "byte") return PIVariant::UChar; + if (s == "ushort" || s == "unsignedshort" || s == "unsignedshortint" || s == "word") return PIVariant::UShort; + if (s == "uint" || s == "unsigned" || s == "unsignedint") return PIVariant::UInt; + if (s == "ulong" || s == "unsignedlong" || s == "unsignedlongint" || s == "dword") return PIVariant::ULong; + if (s == "ullong" || s == "unsignedlonglong" || s == "unsignedlonglongint" || s == "qword") return PIVariant::ULLong; + if (s == "float") return PIVariant::Float; + if (s == "double" || s == "real") return PIVariant::Double; + if (s == "ldouble" || s == "longdouble") return PIVariant::LDouble; + if (s == "complexd" || s == "complex") return PIVariant::Complexd; + if (s == "complexld" || s == "complex" || s == "complex") return PIVariant::Complexld; + if (s == "pibitarray" || s == "bitarray") return PIVariant::BitArray; + if (s == "pibytearray" || s == "bytearray" || s == "vector" || s == "pivector" || s == "vector" || s == "pivector" || + s == "vector" || s == "pivector") return PIVariant::ByteArray; + if (s == "pistring" || s == "string") return PIVariant::String; + if (s == "pistringlist" || s == "stringlist" || s == "vector" || s == "vector" || s == "pivector" || s == "pivector") return PIVariant::StringList; + if (s == "pitime" || s == "time") return PIVariant::Time; + if (s == "pidate" || s == "date") return PIVariant::Date; + if (s == "pidatetime" || s == "datetime") return PIVariant::DateTime; + if (s == "pisystemtime" || s == "systemtime") return PIVariant::SystemTime; + return PIVariant::Invalid; +} + + +PIString PIVariant::typeName(PIVariant::Type type) { + switch (type) { + case PIVariant::Bool: return "Bool"; + case PIVariant::Char: return "Char"; + case PIVariant::UChar: return "UChar"; + case PIVariant::Short: return "Short"; + case PIVariant::UShort: return "UShort"; + case PIVariant::Int: return "Int"; + case PIVariant::UInt: return "UInt"; + case PIVariant::Long: return "Long"; + case PIVariant::ULong: return "ULong"; + case PIVariant::LLong: return "LLong"; + case PIVariant::ULLong: return "ULLong"; + case PIVariant::Float: return "Float"; + case PIVariant::Double: return "Double"; + case PIVariant::LDouble: return "LDouble"; + case PIVariant::Complexd: return "Complexd"; + case PIVariant::Complexld: return "Complexld"; + case PIVariant::BitArray: return "BitArray"; + case PIVariant::ByteArray: return "ByteArray"; + case PIVariant::String: return "String"; + case PIVariant::StringList: return "StringList"; + case PIVariant::Time: return "Time"; + case PIVariant::Date: return "Date"; + case PIVariant::DateTime: return "DateTime"; + case PIVariant::SystemTime: return "SystemTime"; + case PIVariant::Custom: return "Custom"; + default: break; + } + return "Invalid"; +} + + +/** \brief Returns variant content as boolean + * \details In case of numeric types returns \b true if value != 0. \n + * In case of String type returns \a PIString::toBool(). \n + * In case of StringList type returns \b false if string list is empty, + * otherwise returns \a PIString::toBool() of first string. \n + * In case of other types returns \b false. */ +bool PIVariant::toBool() const { + switch (type_) { + case PIVariant::Bool: + case PIVariant::Char: + case PIVariant::UChar: + case PIVariant::Short: + case PIVariant::UShort: + case PIVariant::Int: + case PIVariant::UInt: + case PIVariant::Long: + case PIVariant::ULong: return _vint != 0; + case PIVariant::LLong: + case PIVariant::ULLong: return _vllong != 0; + case PIVariant::Float: return _vfloat != 0; + case PIVariant::Double: return _vdouble != 0; + case PIVariant::LDouble: return _vldouble != 0; + case PIVariant::Complexd: return _vcomplexd.real() != 0; + case PIVariant::Complexld: return _vcomplexld.real() != 0; + case PIVariant::String: return _vstring.toBool(); + case PIVariant::StringList: if (_vstringlist.isEmpty()) return false; return _vstringlist.front().toBool(); + default: break; + } + return false; +} + + + +/** \brief Returns variant content as int + * \details In case of numeric types returns integer value. \n + * In case of String type returns \a PIString::toInt(). \n + * In case of StringList type returns \b 0 if string list is empty, + * otherwise returns \a PIString::toInt() of first string. \n + * In case of other types returns \b 0. */ +int PIVariant::toInt() const { + switch (type_) { + case PIVariant::Bool: + case PIVariant::Char: + case PIVariant::UChar: + case PIVariant::Short: + case PIVariant::UShort: + case PIVariant::Int: + case PIVariant::UInt: + case PIVariant::Long: + case PIVariant::ULong: return _vint; + case PIVariant::LLong: + case PIVariant::ULLong: return _vllong; + case PIVariant::Float: return _vfloat; + case PIVariant::Double: return _vdouble; + case PIVariant::LDouble: return _vldouble; + case PIVariant::Complexd: return _vcomplexd.real(); + case PIVariant::Complexld: return _vcomplexld.real(); + case PIVariant::String: return _vstring.toInt(); + case PIVariant::StringList: if (_vstringlist.isEmpty()) return 0; return _vstringlist.front().toInt(); + default: break; + } + return 0; +} + + +/** \brief Returns variant content as long long + * \details In case of numeric types returns integer value. \n + * In case of String type returns \a PIString::toLLong(). \n + * In case of StringList type returns \b 0L if string list is empty, + * otherwise returns \a PIString::toLLong() of first string. \n + * In case of other types returns \b 0L. */ +llong PIVariant::toLLong() const { + switch (type_) { + case PIVariant::Bool: + case PIVariant::Char: + case PIVariant::UChar: + case PIVariant::Short: + case PIVariant::UShort: + case PIVariant::Int: + case PIVariant::UInt: + case PIVariant::Long: + case PIVariant::ULong: return _vint; + case PIVariant::LLong: + case PIVariant::ULLong: return _vllong; + case PIVariant::Float: return _vfloat; + case PIVariant::Double: return _vdouble; + case PIVariant::LDouble: return _vldouble; + case PIVariant::Complexd: return _vcomplexd.real(); + case PIVariant::Complexld: return _vcomplexld.real(); + case PIVariant::String: return _vstring.toLLong(); + case PIVariant::StringList: if (_vstringlist.isEmpty()) return 0L; return _vstringlist.front().toLLong(); + default: break; + } + return 0L; +} + + +/** \brief Returns variant content as float + * \details In case of numeric types returns float value. \n + * In case of String type returns \a PIString::toFloat(). \n + * In case of StringList type returns \b 0.f if string list is empty, + * otherwise returns \a PIString::toFloat() of first string. \n + * In case of other types returns \b 0.f. */ +float PIVariant::toFloat() const { + switch (type_) { + case PIVariant::Bool: + case PIVariant::Char: + case PIVariant::UChar: + case PIVariant::Short: + case PIVariant::UShort: + case PIVariant::Int: + case PIVariant::UInt: + case PIVariant::Long: + case PIVariant::ULong: return _vint; + case PIVariant::LLong: + case PIVariant::ULLong: return _vllong; + case PIVariant::Float: return _vfloat; + case PIVariant::Double: return _vdouble; + case PIVariant::LDouble: return _vldouble; + case PIVariant::Complexd: return _vcomplexd.real(); + case PIVariant::Complexld: return _vcomplexld.real(); + case PIVariant::String: return _vstring.toFloat(); + case PIVariant::StringList: if (_vstringlist.isEmpty()) return 0.f; return _vstringlist.front().toFloat(); + default: break; + } + return 0.f; +} + + +/** \brief Returns variant content as double + * \details In case of numeric types returns double value. \n + * In case of String type returns \a PIString::toDouble(). \n + * In case of StringList type returns \b 0. if string list is empty, + * otherwise returns \a PIString::toDouble() of first string. \n + * In case of other types returns \b 0.. */ +double PIVariant::toDouble() const { + switch (type_) { + case PIVariant::Bool: + case PIVariant::Char: + case PIVariant::UChar: + case PIVariant::Short: + case PIVariant::UShort: + case PIVariant::Int: + case PIVariant::UInt: + case PIVariant::Long: + case PIVariant::ULong: return _vint; + case PIVariant::LLong: + case PIVariant::ULLong: return _vllong; + case PIVariant::Float: return _vfloat; + case PIVariant::Double: return _vdouble; + case PIVariant::LDouble: return _vldouble; + case PIVariant::Complexd: return _vcomplexd.real(); + case PIVariant::Complexld: return _vcomplexld.real(); + case PIVariant::String: return _vstring.toDouble(); + case PIVariant::StringList: if (_vstringlist.isEmpty()) return 0.; return _vstringlist.front().toDouble(); + default: break; + } + return 0.; +} + + +/** \brief Returns variant content as long double + * \details In case of numeric types returns long double value. \n + * In case of String type returns \a PIString::toLDouble(). \n + * In case of StringList type returns \b 0. if string list is empty, + * otherwise returns \a PIString::toLDouble() of first string. \n + * In case of other types returns \b 0.. */ +ldouble PIVariant::toLDouble() const { + switch (type_) { + case PIVariant::Bool: + case PIVariant::Char: + case PIVariant::UChar: + case PIVariant::Short: + case PIVariant::UShort: + case PIVariant::Int: + case PIVariant::UInt: + case PIVariant::Long: + case PIVariant::ULong: return _vint; + case PIVariant::LLong: + case PIVariant::ULLong: return _vllong; + case PIVariant::Float: return _vfloat; + case PIVariant::Double: return _vdouble; + case PIVariant::LDouble: return _vldouble; + case PIVariant::Complexd: return _vcomplexd.real(); + case PIVariant::Complexld: return _vcomplexld.real(); + case PIVariant::String: return _vstring.toLDouble(); + case PIVariant::StringList: if (_vstringlist.isEmpty()) return 0.; return _vstringlist.front().toLDouble(); + default: break; + } + return 0.; +} + + +/** \brief Returns variant content as complex + * \details In case of numeric types returns complex value. \n + * In case of String type returns \a PIString::toDouble(). \n + * In case of StringList type returns \b 0. if string list is empty, + * otherwise returns \a PIString::toDouble() of first string. \n + * In case of other types returns \b 0.. */ +complexd PIVariant::toComplexd() const { + switch (type_) { + case PIVariant::Bool: + case PIVariant::Char: + case PIVariant::UChar: + case PIVariant::Short: + case PIVariant::UShort: + case PIVariant::Int: + case PIVariant::UInt: + case PIVariant::Long: + case PIVariant::ULong: return _vint; + case PIVariant::LLong: + case PIVariant::ULLong: return _vllong; + case PIVariant::Float: return _vfloat; + case PIVariant::Double: return _vdouble; + case PIVariant::LDouble: return _vldouble; + case PIVariant::Complexd: return _vcomplexd.real(); + case PIVariant::Complexld: return _vcomplexld.real(); + case PIVariant::String: return _vstring.toDouble(); + case PIVariant::StringList: if (_vstringlist.isEmpty()) return complexd_0; return _vstringlist.front().toDouble(); + default: break; + } + return complexd_0; +} + + +/** \brief Returns variant content as long complex + * \details In case of numeric types returns long complex value. \n + * In case of String type returns \a PIString::toLDouble(). \n + * In case of StringList type returns \b 0. if string list is empty, + * otherwise returns \a PIString::toLDouble() of first string. \n + * In case of other types returns \b 0.. */ +complexld PIVariant::toComplexld() const { + switch (type_) { + case PIVariant::Bool: + case PIVariant::Char: + case PIVariant::UChar: + case PIVariant::Short: + case PIVariant::UShort: + case PIVariant::Int: + case PIVariant::UInt: + case PIVariant::Long: + case PIVariant::ULong: return _vint; + case PIVariant::LLong: + case PIVariant::ULLong: return _vllong; + case PIVariant::Float: return _vfloat; + case PIVariant::Double: return _vdouble; + case PIVariant::LDouble: return _vldouble; + case PIVariant::Complexd: return _vcomplexd.real(); + case PIVariant::Complexld: return _vcomplexld.real(); + case PIVariant::String: return _vstring.toLDouble(); + case PIVariant::StringList: if (_vstringlist.isEmpty()) return complexld_0; return _vstringlist.front().toLDouble(); + default: break; + } + return complexld_0; +} + + +/** \brief Returns variant content as time + * \details In case of Time type returns time value. \n + * In case of DateTime type returns time part of value. \n + * In case of other types returns \a PITime(). */ +PITime PIVariant::toTime() const { + if (type_ == PIVariant::Time) return _vtime; + if (type_ == PIVariant::DateTime) return _vtime; + return PITime(); +} + + +/** \brief Returns variant content as date + * \details In case of Date type returns date value. \n + * In case of DateTime type returns date part of value. \n + * In case of other types returns \a PIDate(). */ +PIDate PIVariant::toDate() const { + if (type_ == PIVariant::Date) return _vdate; + if (type_ == PIVariant::DateTime) return *((PIDate*)(&(_vdatetime.day))); + return PIDate(); +} + + +/** \brief Returns variant content as date and time + * \details In case of Time type returns time value with null date. \n + * In case of Date type returns date value with null time. \n + * In case of DateTime type returns date and time. \n + * In case of other types returns \a PIDateTime(). */ +PIDateTime PIVariant::toDateTime() const { + if (type_ == PIVariant::DateTime) return _vdatetime; + if (type_ == PIVariant::Time) return PIDateTime(_vtime); + if (type_ == PIVariant::Date) return PIDateTime(_vdate); + return PIDateTime(); +} + + +/** \brief Returns variant content as system time + * \details In case of SystemTime type returns system time. \n + * In case of other types returns \a PISystemTime::fromSeconds() from + * double value of variant content. */ +PISystemTime PIVariant::toSystemTime() const { + if (type_ == PIVariant::SystemTime) return _vsystime; + return PISystemTime::fromSeconds(toDouble()); +} + + +/** \brief Returns variant content as string + * \details In case of numeric types returns \a PIString::fromNumber(). \n + * In case of String type returns string value. \n + * In case of StringList type returns joined string ("(" + PIStringList::join("; ") + ")"). \n + * In case of BitArray or ByteArray types returns number of bits/bytes. \n + * In case of Time, Date or DateTime types returns toString() of this values. \n + * In case of SystemTime types returns second and nanoseconds of time + * ("(PISystemTime::seconds s, PISystemTime::nanoseconds ns)"). \n + * In case of other types returns \b "". */ +PIString PIVariant::toString() const { + switch (type_) { + case PIVariant::Bool: return _vint == 0 ? "false" : "true"; + case PIVariant::Char: + case PIVariant::UChar: + case PIVariant::Short: + case PIVariant::UShort: + case PIVariant::Int: + case PIVariant::UInt: + case PIVariant::Long: + case PIVariant::ULong: return PIString::fromNumber(_vint); + case PIVariant::LLong: + case PIVariant::ULLong: return PIString::fromNumber(_vllong); + case PIVariant::Float: return PIString::fromNumber(_vfloat); + case PIVariant::Double: return PIString::fromNumber(_vdouble); + case PIVariant::LDouble: return PIString::fromNumber(_vldouble); + case PIVariant::Complexd: return "(" + PIString::fromNumber(_vcomplexd.real()) + "; " + PIString::fromNumber(_vcomplexd.imag()) + ")"; + case PIVariant::Complexld: return "(" + PIString::fromNumber(_vcomplexld.real()) + "; " + PIString::fromNumber(_vcomplexld.imag()) + ")"; + case PIVariant::BitArray: return PIString::fromNumber(_vbitarray.bitSize()) + " bits"; + case PIVariant::ByteArray: return _vbytearray.toString(); + case PIVariant::String: return _vstring; + case PIVariant::StringList: return "(" + _vstringlist.join("; ") + ")"; + case PIVariant::Time: return _vtime.toString(); + case PIVariant::Date: return _vdate.toString(); + case PIVariant::DateTime: return _vdatetime.toString(); + case PIVariant::SystemTime: return "(" + PIString::fromNumber(_vsystime.seconds) + " s, " + PIString::fromNumber(_vsystime.nanoseconds) + " ns)"; + default: break; + } + return ""; +} + + +/** \brief Returns variant content as strings list + * \details In case of StringList type returns strings list value. \n + * In case of other types returns \a PIStringList with one string value of variant content. */ +PIStringList PIVariant::toStringList() const { + if (type_ == PIVariant::StringList) return _vstringlist; + return PIStringList(toString()); +} + + +/** \brief Returns variant content as bit array + * \details In case of BitArray type returns bit array value. \n + * In case of other types returns \a PIBitArray from \a toLLong() value. */ +PIBitArray PIVariant::toBitArray() const { + if (type_ == PIVariant::BitArray) return _vbitarray; + return PIBitArray(ullong(toLLong())); +} + + +/** \brief Returns variant content as byte array + * \details In case of ByteArray type returns byte array value. \n + * In case of other types returns empty \a PIByteArray. */ +PIByteArray PIVariant::toByteArray() const { + if (type_ == PIVariant::ByteArray) return _vbytearray; + return PIByteArray(); +} diff --git a/src/core/pivariant.h b/src/core/pivariant.h new file mode 100755 index 00000000..7cba2770 --- /dev/null +++ b/src/core/pivariant.h @@ -0,0 +1,461 @@ +/*! \file pivariant.h + * \brief Variant type + * + * This file declares PIVariant +*/ +/* + PIP - Platform Independent Primitives + Variant type + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIVARIANT_H +#define PIVARIANT_H + +#include "pistring.h" +#include "pibitarray.h" +#include "pitime.h" +#include "pimath.h" + +#define __PIVARIANT_UNION_SIZE__ 32 + +#define _vcomplexd (*((complexd*)_vraw)) +#define _vcomplexld (*((complexld*)_vraw)) +#define _vtime (*((PITime*)_vraw)) +#define _vdate (*((PIDate*)_vraw)) +#define _vdatetime (*((PIDateTime*)_vraw)) +#define _vsystime (*((PISystemTime*)_vraw)) + +#define _vvcomplexd(v) (*((complexd*)v._vraw)) +#define _vvcomplexld(v) (*((complexld*)v._vraw)) +#define _vvtime(v) (*((PITime*)v._vraw)) +#define _vvdate(v) (*((PIDate*)v._vraw)) +#define _vvdatetime(v) (*((PIDateTime*)v._vraw)) +#define _vvsystime(v) (*((PISystemTime*)v._vraw)) + +class PIP_EXPORT PIVariant { + friend PICout operator <<(PICout s, const PIVariant & v); +public: + + //! Type of %PIVariant content + enum Type { + Invalid /** Invalid type , default type of empty contructor */ = 0 , + Bool /** bool */ , + Char /** char */ , + UChar /** uchar */ , + Short /** short */ , + UShort /** ushort */ , + Int /** int */ , + UInt /** uint */ , + Long /** long */ , + ULong /** ulong */ , + LLong /** llong */ , + ULLong /** ullong */ , + Float /** float */ , + Double /** double */ , + LDouble /** ldouble */ , + Complexd /** complexd */ , + Complexld /** complexld */ , + BitArray /** PIBitArray */ , + ByteArray /** PIByteArray */ , + String /** PIString */ , + StringList /** PIStringList */ , + Time /** PITime */ , + Date /** PIDate */ , + DateTime /** PIDateTime */ , + SystemTime /** PISystemTime */ , + Custom /** Custom */ = 0xFF + }; + + //! Empty constructor, \a type() will be set to \a Invalid + PIVariant(); + + //! Constructs variant from string + PIVariant(const char * v) {setValue(PIString(v));} + + //! Constructs variant from boolean + PIVariant(const bool v) {setValue(v);} + + //! Constructs variant from char + PIVariant(const char v) {setValue(v);} + + //! Constructs variant from integer + PIVariant(const uchar v) {setValue(v);} + + //! Constructs variant from integer + PIVariant(const short v) {setValue(v);} + + //! Constructs variant from integer + PIVariant(const ushort v) {setValue(v);} + + //! Constructs variant from integer + PIVariant(const int & v) {setValue(v);} + + //! Constructs variant from integer + PIVariant(const uint & v) {setValue(v);} + + //! Constructs variant from integer + PIVariant(const long & v) {setValue(v);} + + //! Constructs variant from integer + PIVariant(const ulong & v) {setValue(v);} + + //! Constructs variant from integer + PIVariant(const llong & v) {setValue(v);} + + //! Constructs variant from integer + PIVariant(const ullong & v) {setValue(v);} + + //! Constructs variant from float + PIVariant(const float & v) {setValue(v);} + + //! Constructs variant from double + PIVariant(const double & v) {setValue(v);} + + //! Constructs variant from long double + PIVariant(const ldouble & v) {setValue(v);} + + //! Constructs variant from complex + PIVariant(const complexd & v) {setValue(v);} + + //! Constructs variant from complex + PIVariant(const complexld & v) {setValue(v);} + + //! Constructs variant from bit array + PIVariant(const PIBitArray & v) {setValue(v);} + + //! Constructs variant from byte array + PIVariant(const PIByteArray & v) {setValue(v);} + + //! Constructs variant from string + PIVariant(const PIString & v) {setValue(v);} + + //! Constructs variant from strings list + PIVariant(const PIStringList & v) {setValue(v);} + + //! Constructs variant from time + PIVariant(const PITime & v) {setValue(v);} + + //! Constructs variant from date + PIVariant(const PIDate & v) {setValue(v);} + + //! Constructs variant from date and time + PIVariant(const PIDateTime & v) {setValue(v);} + + //! Constructs variant from system time + PIVariant(const PISystemTime & v) {setValue(v);} + + + //! Set variant content and type to string + void setValue(const char * v) {setValue(PIString(v));} + + //! Set variant content and type to boolean + void setValue(const bool v) {type_ = PIVariant::Bool; _vint = (v ? 1 : 0);} + + //! Set variant content and type to char + void setValue(const char v) {type_ = PIVariant::Char; _vint = v;} + + //! Set variant content and type to integer + void setValue(const uchar v) {type_ = PIVariant::UChar; _vint = v;} + + //! Set variant content and type to integer + void setValue(const short v) {type_ = PIVariant::Short; _vint = v;} + + //! Set variant content and type to integer + void setValue(const ushort v) {type_ = PIVariant::UShort; _vint = v;} + + //! Set variant content and type to integer + void setValue(const int & v) {type_ = PIVariant::Int; _vint = v;} + + //! Set variant content and type to integer + void setValue(const uint & v) {type_ = PIVariant::UInt; _vint = v;} + + //! Set variant content and type to integer + void setValue(const long & v) {type_ = PIVariant::Long; _vint = v;} + + //! Set variant content and type to integer + void setValue(const ulong & v) {type_ = PIVariant::ULong; _vint = v;} + + //! Set variant content and type to integer + void setValue(const llong & v) {type_ = PIVariant::LLong; _vllong = v;} + + //! Set variant content and type to integer + void setValue(const ullong & v) {type_ = PIVariant::ULLong; _vllong = v;} + + //! Set variant content and type to float + void setValue(const float & v) {type_ = PIVariant::Float; _vfloat = v;} + + //! Set variant content and type to double + void setValue(const double & v) {type_ = PIVariant::Double; _vdouble = v;} + + //! Set variant content and type to long double + void setValue(const ldouble & v) {type_ = PIVariant::LDouble; _vldouble = v;} + + //! Set variant content and type to complex + void setValue(const complexd & v) {type_ = PIVariant::Complexd; _vcomplexd = v;} + + //! Set variant content and type to complex + void setValue(const complexld & v) {type_ = PIVariant::Complexld; _vcomplexld = v;} + + //! Set variant content and type to bit array + void setValue(const PIBitArray & v) {type_ = PIVariant::BitArray; _vbitarray = v;} + + //! Set variant content and type to byte array + void setValue(const PIByteArray & v) {type_ = PIVariant::ByteArray; _vbytearray = v;} + + //! Set variant content and type to string + void setValue(const PIString & v) {type_ = PIVariant::String; _vstring = v;} + + //! Set variant content and type to strings list + void setValue(const PIStringList & v) {type_ = PIVariant::StringList; _vstringlist = v;} + + //! Set variant content and type to time + void setValue(const PITime & v) {type_ = PIVariant::Time; _vtime = v;} + + //! Set variant content and type to date + void setValue(const PIDate & v) {type_ = PIVariant::Date; _vdate = v;} + + //! Set variant content and type to date and time + void setValue(const PIDateTime & v) {type_ = PIVariant::DateTime; _vdatetime = v;} + + //! Set variant content and type to system time + void setValue(const PISystemTime & v) {type_ = PIVariant::SystemTime; _vsystime = v;} + + + bool toBool() const; + int toInt() const; + llong toLLong() const; + float toFloat() const; + double toDouble() const; + ldouble toLDouble() const; + complexd toComplexd() const; + complexld toComplexld() const; + PITime toTime() const; + PIDate toDate() const; + PIDateTime toDateTime() const; + PISystemTime toSystemTime() const; + PIString toString() const; + PIStringList toStringList() const; + PIBitArray toBitArray() const; + PIByteArray toByteArray() const; + + + /** \brief Returns variant content as custom type + * \details In case of known types this function equivalent \a to function. \n + * Otherwise returns content as type T. */ + template + T toValue() const {if (_vcustom.size() != sizeof(T)) return T(); return *((T*)_vcustom.data());} + /* + operator bool() const {return toBool();} + operator char() const {return toInt();} + operator uchar() const {return toInt();} + operator short() const {return toInt();} + operator ushort() const {return toInt();} + operator int() const {return toInt();} + operator uint() const {return toInt();} + operator long() const {return toInt();} + operator ulong() const {return toInt();} + operator llong() const {return toLLong();} + operator ullong() const {return (ullong)toLLong();} + operator float() const {return toFloat();} + operator double() const {return toDouble();} + operator ldouble() const {return toLDouble();} + operator complexd() const {return toComplexd();} + operator complexld() const {return toComplexld();} + operator PITime() const {return toTime();} + operator PIDate() const {return toDate();} + operator PIDateTime() const {return toDateTime();} + operator PIString() const {return toString();} + operator PIStringList() const {return toStringList();} + operator PIBitArray() const {return toBitArray();} + operator PIByteArray() const {return toByteArray();} + operator const char*() const {return toString().data();} + operator void*() const {return (void*)(toLLong());} + */ + + //! Assign operator + PIVariant & operator =(const PIVariant & v); + //! Assign operator + PIVariant & operator =(const char * v) {setValue(PIString(v)); return *this;} + //! Assign operator + PIVariant & operator =(const bool v) {setValue(v); return *this;} + //! Assign operator + PIVariant & operator =(const char v) {setValue(v); return *this;} + //! Assign operator + PIVariant & operator =(const uchar v) {setValue(v); return *this;} + //! Assign operator + PIVariant & operator =(const short v) {setValue(v); return *this;} + //! Assign operator + PIVariant & operator =(const ushort v) {setValue(v); return *this;} + //! Assign operator + PIVariant & operator =(const int & v) {setValue(v); return *this;} + //! Assign operator + PIVariant & operator =(const uint & v) {setValue(v); return *this;} + //! Assign operator + PIVariant & operator =(const long & v) {setValue(v); return *this;} + //! Assign operator + PIVariant & operator =(const ulong & v) {setValue(v); return *this;} + //! Assign operator + PIVariant & operator =(const llong & v) {setValue(v); return *this;} + //! Assign operator + PIVariant & operator =(const ullong & v) {setValue(v); return *this;} + //! Assign operator + PIVariant & operator =(const float & v) {setValue(v); return *this;} + //! Assign operator + PIVariant & operator =(const double & v) {setValue(v); return *this;} + //! Assign operator + PIVariant & operator =(const ldouble & v) {setValue(v); return *this;} + //! Assign operator + PIVariant & operator =(const complexd & v) {setValue(v); return *this;} + //! Assign operator + PIVariant & operator =(const complexld & v) {setValue(v); return *this;} + //! Assign operator + PIVariant & operator =(const PIBitArray & v) {setValue(v); return *this;} + //! Assign operator + PIVariant & operator =(const PIByteArray & v) {setValue(v); return *this;} + //! Assign operator + PIVariant & operator =(const PIString & v) {setValue(v); return *this;} + //! Assign operator + PIVariant & operator =(const PIStringList & v) {setValue(v); return *this;} + //! Assign operator + PIVariant & operator =(const PITime & v) {setValue(v); return *this;} + //! Assign operator + PIVariant & operator =(const PIDate & v) {setValue(v); return *this;} + //! Assign operator + PIVariant & operator =(const PIDateTime & v) {setValue(v); return *this;} + //! Assign operator + PIVariant & operator =(const PISystemTime & v) {setValue(v); return *this;} + + + //! Compare operator + bool operator ==(const PIVariant & v) const; + //! Compare operator + bool operator !=(const PIVariant & v) const {return !(*this == v);} + + + //! Returns type of variant content + PIVariant::Type type() const {return type_;} + + //! Returns type name of variant content + PIString typeName() const {return typeName(type_);} + + + //! Returns \b true if type is not Invalid + bool isValid() const {return type_ != PIVariant::Invalid;} + + + /** \brief Returns new variant from custom type + * \details In case of known types this function equivalent \a PIVariant(T) constructors. \n + * Otherwise returns variant with content \a v and type Custom. */ + template + static PIVariant fromValue(const T & v) {PIVariant ret; ret._vcustom.resize(sizeof(T)); new((T*)(ret._vcustom.data()))T(v); ret.type_ = PIVariant::Custom; return ret;} + + + //! Returns type from name + static PIVariant::Type typeFromName(const PIString & tname); + + //! Returns type name + static PIString typeName(PIVariant::Type type); + +private: + void destroy() {_vcustom.clear();} + + union { + int _vint; + llong _vllong; + float _vfloat; + double _vdouble; + ldouble _vldouble; + uchar _vraw[__PIVARIANT_UNION_SIZE__]; + /*complexd _vcomplexd; + complexld _vcomplexld; + PITime _vtime; + PIDate _vdate; + PIDateTime _vdatetime; + PISystemTime _vsystime;*/ + }; + PIBitArray _vbitarray; + PIByteArray _vbytearray; + PIString _vstring; + PIStringList _vstringlist; + PIByteArray _vcustom; + PIVariant::Type type_; + +}; + +template<> inline bool PIVariant::toValue() const {return toBool();} +template<> inline char PIVariant::toValue() const {return (char)toInt();} +template<> inline uchar PIVariant::toValue() const {return (uchar)toInt();} +template<> inline short PIVariant::toValue() const {return (short)toInt();} +template<> inline ushort PIVariant::toValue() const {return (ushort)toInt();} +template<> inline int PIVariant::toValue() const {return toInt();} +template<> inline uint PIVariant::toValue() const {return (uint)toInt();} +template<> inline long PIVariant::toValue() const {return (long)toInt();} +template<> inline ulong PIVariant::toValue() const {return (ulong)toInt();} +template<> inline llong PIVariant::toValue() const {return toLLong();} +template<> inline ullong PIVariant::toValue() const {return (ullong)toLLong();} +template<> inline float PIVariant::toValue() const {return toFloat();} +template<> inline double PIVariant::toValue() const {return toDouble();} +template<> inline ldouble PIVariant::toValue() const {return toLDouble();} +template<> inline complexd PIVariant::toValue() const {return toComplexd();} +template<> inline complexld PIVariant::toValue() const {return toComplexld();} +template<> inline void* PIVariant::toValue() const {return (void*)toLLong();} +template<> inline const char* PIVariant::toValue() const {return toString().data();} +template<> inline PITime PIVariant::toValue() const {return toTime();} +template<> inline PIDate PIVariant::toValue() const {return toDate();} +template<> inline PIDateTime PIVariant::toValue() const {return toDateTime();} +template<> inline PIString PIVariant::toValue() const {return toString();} +template<> inline PIStringList PIVariant::toValue() const {return toStringList();} +template<> inline PIBitArray PIVariant::toValue() const {return toBitArray();} +template<> inline PIByteArray PIVariant::toValue() const {return toByteArray();} + +//template<> inline PIVariant PIVariant::fromValue(const char * v) {return PIVariant(PIString(v));} +template<> inline PIVariant PIVariant::fromValue(const bool & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const char & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const uchar & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const short & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const ushort & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const int & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const uint & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const long & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const ulong & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const llong & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const ullong & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const float & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const double & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const ldouble & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const complexd & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const complexld & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const PIBitArray & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const PIByteArray & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const PIString & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const PIStringList & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const PITime & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const PIDate & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const PIDateTime & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const PISystemTime & v) {return PIVariant(v);} + +inline PICout operator <<(PICout s, const PIVariant & v) { + s.space(); s.setControl(0, true); + s << "PIVariant(" << PIVariant::typeName(v.type()) << ", "; + if (v.type() == PIVariant::Custom) s << v._vcustom.size() << " bytes"; + else s << v.toString(); + s << ")"; + s.restoreControl(); return s; +} + + +#endif // PIVARIANT_H diff --git a/src/io/pibinarylog.cpp b/src/io/pibinarylog.cpp new file mode 100644 index 00000000..e2efeb47 --- /dev/null +++ b/src/io/pibinarylog.cpp @@ -0,0 +1,524 @@ +/* + PIP - Platform Independent Primitives + Class for write binary data to logfile, and read or playback this data + Copyright (C) 2014 Andrey Bychkov work.a.b@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pibinarylog.h" +#include "pidir.h" + +/*! \class PIBinaryLog + * \brief Class for read and write binary data to logfile, and playback this data in realtime, or custom speed + * + * \section PIBinaryLog_sec0 Synopsis + * Binary Log is a file with simple header, where you can read and write some binary data. + * Any written data include special header with ID, size and timestamp. + * This header provides separation different messages from the one file by choosing different IDs. + * With \a filterID or special functions, like \a readBinLog() you can choose IDs what you want to read. + * With function \a writeBinLog() or \a setDefaultID() you can choose ID that mark you data. + * By default ID = 1, and \a filterID is empty, that mean you read any ID without filtering. + * ThreadedRead provide you playback data, with delay that you write data. + * You can choose different playbak modes by set \a PlayMode. + * + * \section PIBinaryLog_sec1 Basic usage + * This class provide all functions of \a PIIODevice, such \a open(), \a close(), + * \a read() ,\a write(), and threaded read/write. + * function \a setLogDir() need to set directory for BinLog files + * function \a createNewFile() need to create new binlog file + * function \a restart() need start from the begining of binlog file + * + */ + +REGISTER_DEVICE(PIBinaryLog) + +PIBinaryLog::PIBinaryLog() { + setThreadedReadBufferSize(65536); + is_started = is_indexed = false; + current_index = -1; + setPlaySpeed(1.); + setDefaultID(1); + setPlaySpeed(1.0); + setPlayDelay(PISystemTime::fromSeconds(1.0)); + setPlayRealTime(); + setSplitTime(PISystemTime(600, 0)); + setSplitRecordCount(1000); + setSplitFileSize(0xFFFFFF); + setSplitMode(SplitNone); + setLogDir(PIString()); + setFilePrefix(PIString()); + setRapidStart(false); + file.setName("__S__PIBinaryLog::file"); +} + + +bool PIBinaryLog::openDevice() { + lastrecord.timestamp = PISystemTime(); + lastrecord.id = 0; + write_count = 0; + is_started = false; + is_thread_ok = true; + is_indexed = false; + index.clear(); + index_pos.clear(); + if (mode_ == ReadWrite) { + piCoutObj << "Error: ReadWrite mode not supported, use WriteOnly or ReadOnly"; + return false; + } + if (!file.open(path(), mode_)) { + piCoutObj << "Error: Can't open file" << path(); + return false; + } + setName(path()); + if (mode_ == WriteOnly) { + file.clear(); + if (!writeFileHeader()) { + piCoutObj << "Error: Can't write binlog file header" << path(); + return false; + } + is_started = true; + } + if (mode_ == ReadOnly) { + if (file.isEmpty()) { + piCoutObj << "Error: File is null" << path(); + fileError(); + return false; + } + if (!checkFileHeader()) { + fileError(); + return false; + } + if (isEmpty()) { + piCoutObj << "Warning: Empty BinLog file" << path(); + fileEnd(); + } + play_time = 0; + if (!rapidStart()) is_started = true; + } + startlogtime = PISystemTime::current(); + return true; +} + + +bool PIBinaryLog::closeDevice() { + moveIndex(-1); + is_indexed = false; + index.clear(); + index_pos.clear(); + if (canWrite() && isEmpty()) { + file.remove(); + return true; + } + return file.close(); +} + + +bool PIBinaryLog::threadedRead(uchar *readed, int size) { + is_thread_ok = false; + PISystemTime pt; + double delay; + switch (play_mode) { + case PlayRealTime: + pt = PISystemTime::current() - startlogtime; + if (is_started) { + if (lastrecord.timestamp > pt) + (lastrecord.timestamp - pt).sleep(); + } else { + startlogtime = PISystemTime::current() - lastrecord.timestamp; + is_started = true; + } + break; + case PlayVariableSpeed: + delay = lastrecord.timestamp.toMilliseconds() - play_time; + delay /= play_speed; + if (is_started) { + if (delay > 0) + /// TODO: Sleep by steps (about 100ms) + PISystemTime::fromMilliseconds(delay).sleep(); + } else is_started = true; + play_time = lastrecord.timestamp.toMilliseconds(); + break; + case PlayStaticDelay: + if (is_started) play_delay.sleep(); + else is_started = true; + break; + default: + return false; + } + bool res = PIIODevice::threadedRead(readed, size); + is_thread_ok = true; + return res; +} + + +PIString PIBinaryLog::createNewFile() { + if (!file.close()) return PIString(); + PIDir dir(logDir()); + dir.setDir(dir.absolutePath()); + if (!dir.isExists()) { + piCoutObj << "Creating directory" << dir.path(); + dir.make(true); + } + PIString npath = logDir() + "/" + filePrefix() + PIDateTime::current().toString("yyyy_MM_dd__hh_mm_ss"); + PIString cnpath = npath + ".binlog"; + int i = 1; + while (PIFile::isExists(cnpath)) { + cnpath = npath + "_" + PIString::fromNumber(i) + ".binlog"; + i++; + } + if (open(cnpath, PIIODevice::WriteOnly)) { + newFile(file.path()); + return file.path(); + } + piCoutObj << "Can't create new file, maybe LogDir is invalid."; + return PIString(); +} + + +int PIBinaryLog::writeBinLog(int id, const void *data, int size) { + if (size <= 0 || !canWrite()) return -1; + switch (split_mode) { + case SplitSize: + if (logSize() > split_size) createNewFile(); + break; + case SplitTime: + if ((PISystemTime::current() - startlogtime) > split_time) createNewFile(); + break; + case SplitCount: + if (write_count > split_count) createNewFile(); + break; + default: break; + } + PIByteArray logdata; + logdata << id << size << (PISystemTime::current() - startlogtime) << PIByteArray::RawData(data, size); + int res = file.write(logdata.data(), logdata.size()); + file.flush(); + write_count++; + if (res > 0) return size; + else return res; +} + + +PIByteArray PIBinaryLog::readBinLog(int id) { + if (!canRead()) return PIByteArray(); + BinLogRecord br = readRecord(); + if (br.id == -1) { + piCoutObj << "End of BinLog file"; + fileEnd(); + return PIByteArray(); + } + if (id == 0 && br.id > 0) return br.data; + while (br.id != id && !isEnd()) br = readRecord(); + if (br.id == -1) { + piCoutObj << "End of BinLog file"; + fileEnd(); + return PIByteArray(); + } + if (br.id == id) return br.data; + piCoutObj << "Can't find record with id =" << id; + return PIByteArray(); +} + + +int PIBinaryLog::readBinLog(int id, void *read_to, int max_size) { + if (max_size <= 0 || read_to == 0) return -1; + PIByteArray ba = readBinLog(id); + if (ba.isEmpty()) return -1; + int sz = piMini(max_size, ba.size()); + memcpy(read_to, ba.data(), sz); + return sz; +} + + +int PIBinaryLog::read(void *read_to, int max_size) { + if (lastrecord.id == -1 || isEnd()) return 0; + if(!is_thread_ok && lastrecord.id > 0) return lastrecord.data.size(); + if (!canRead()) return -1; + if (max_size <= 0 || read_to == 0) return -1; + BinLogRecord br; + br.id = 0; + if (filterID.isEmpty()) br = readRecord(); + else { + while (!filterID.contains(br.id) && !isEnd()) br = readRecord(); + } + if (br.id == -1) { + fileEnd(); + piCoutObj << "End of BinLog file"; + return 0; + } + if (br.id <= 0) { + piCoutObj << "Read record error"; + return -1; + } + int sz = piMini(max_size, br.data.size()); + memcpy(read_to, br.data.data(), sz); + return sz; +} + + +void PIBinaryLog::restart() { + bool th = isRunning(); + if (th) stopThreadedRead(); + if (!canRead()) return; + lastrecord.timestamp = PISystemTime(); + lastrecord.id = 0; + is_thread_ok = true; + is_started = !rapidStart(); + play_time = 0; + file.seekToBegin(); + checkFileHeader(); + moveIndex(0); + startlogtime = PISystemTime::current(); + if (th) startThreadedRead(); +} + + +bool PIBinaryLog::writeFileHeader() { + if (file.write(&__S__PIBinaryLog::binlog_sig, PIBINARYLOG_SIGNATURE_SIZE) <= 0) return false; + uchar version = PIBINARYLOG_VERSION; + if (file.write(&version, 1) <= 0) return false; + file.flush(); + return true; +} + + +bool PIBinaryLog::checkFileHeader() { + uchar read_sig[PIBINARYLOG_SIGNATURE_SIZE]; + for (uint i=0; i PIBINARYLOG_VERSION) + piCoutObj << "BinLogFile has too newest version"; + return false; +} + + +PIBinaryLog::BinLogRecord PIBinaryLog::readRecord() { + PIByteArray ba; + BinLogRecord br; + lastrecord.id = 0; + lastrecord.data.clear(); + lastrecord.timestamp = PISystemTime(); + ba.resize(sizeof(BinLogRecord) - sizeof(PIByteArray)); + if(file.read(ba.data(), ba.size_s()) > 0) { + ba >> br.id >> br.size >> br.timestamp; + } else { + br.id = -1; + return br; + } + if (br.id > 0 && br.size > 0) { + ba.resize(br.size); + if(file.read(ba.data(), ba.size_s()) > 0) br.data = ba; + else br.id = 0; + } else br.id = 0; + lastrecord = br; + if (br.id == 0) fileError(); + moveIndex(index_pos.value(file.pos(), -1)); + return br; +} + + + +void PIBinaryLog::parseLog(PIFile * f, PIBinaryLog::BinLogInfo * info, PIVector * index) { + BinLogInfo * bi = info; + bool ginfo = info != 0; + bool gindex = index != 0; + if (!ginfo && !gindex) return; + if (ginfo) { + bi->log_size = -1; + bi->records_count = 0; + bi->records.clear(); + } + if (gindex) index->clear(); + if (f == 0) return; + if (!f->canRead()) return; + if (ginfo) { + bi->path = f->path(); + bi->log_size = f->size(); + } + uchar read_sig[PIBINARYLOG_SIGNATURE_SIZE]; + for (uint i=0; iread(read_sig, PIBINARYLOG_SIGNATURE_SIZE) < 0) {if (ginfo) bi->records_count = -1; ok = false;} + for (uint i=0; irecords_count = -2; ok = false;} + uchar read_version = 0; + if (f->read(&read_version, 1) < 0) {if (ginfo) bi->records_count = -3; ok = false;} + if (read_version == 0) {if (ginfo) bi->records_count = -4; ok = false;} + if (read_version < PIBINARYLOG_VERSION) {if (ginfo) bi->records_count = -5; ok = false;} + if (read_version > PIBINARYLOG_VERSION) {if (ginfo) bi->records_count = -6; ok = false;} + if (!ok) return; + PIByteArray ba; + BinLogRecord br; + bool first = true; + llong hdr_size = sizeof(BinLogRecord) - sizeof(PIByteArray); + ba.resize(hdr_size); + while (1) { + ba.resize(hdr_size); + if(f->read(ba.data(), ba.size_s()) > 0) { + ba >> br.id >> br.size >> br.timestamp; + } else break; + if (f->size() - f->pos() >= br.size) f->seek(f->pos() + br.size); + else break; + if (br.id > 0) { + if (gindex) { + BinLogIndex bl_ind; + bl_ind.id = br.id; + bl_ind.pos = f->pos() - br.size - hdr_size; + bl_ind.timestamp = br.timestamp; + index->append(bl_ind); + } + if (ginfo) { + bi->records_count++; + if (first) { + bi->start_time = br.timestamp; + first = false; + } + BinLogRecordInfo &bri(bi->records[br.id]); + bri.count++; + if (bri.id == 0) { + bri.id = br.id; + bri.minimum_size = bri.maximum_size = br.size; + bri.start_time = br.timestamp; + } else { + bri.end_time = br.timestamp; + if (bri.minimum_size > br.size) bri.minimum_size = br.size; + if (bri.maximum_size < br.size) bri.maximum_size = br.size; + } + } + } + } + if (ginfo) bi->end_time = br.timestamp; +} + + +void PIBinaryLog::moveIndex(int i) { + if (is_indexed) { + current_index = i; + posChanged(current_index); + } +} + + +PIBinaryLog::BinLogInfo PIBinaryLog::getLogInfo(const PIString & path) { + BinLogInfo bi; + bi.path = path; + bi.records_count = 0; + PIFile tfile; + if (!tfile.open(path, PIIODevice::ReadOnly)) return bi; + parseLog(&tfile, &bi, 0); + return bi; +} + + +PIString PIBinaryLog::constructFullPath() const { + PIString ret(fullPathPrefix() + "://"); + ret << logDir() << ":" << filePrefix() << ":" << defaultID(); + return ret; +} + + +bool PIBinaryLog::createIndex() { + llong cp = file.pos(); + file.seekToBegin(); + index.clear(); + index_pos.clear(); + parseLog(&file, &binfo, &index); + file.seek(cp); + is_indexed = !index.isEmpty(); + for (uint i=0; i= 0) { + file.seek(index[rindex].pos); + moveIndex(index_pos.value(file.pos(), -1)); + play_time = index[rindex].timestamp.toMilliseconds(); + } +} + + +bool PIBinaryLog::seek(const PISystemTime & time) { + int ci = -1; + for (uint i=0; i= 0) { + seekTo(ci); + return true; + } + return false; +} + + +bool PIBinaryLog::seek(llong filepos) { + int ci = -1; + for (uint i=0; i= 0) { + seekTo(ci); + return true; + } + return false; +} + + +void PIBinaryLog::configureFromFullPath(const PIString & full_path) { + PIStringList pl = full_path.split(":"); + for (int i = 0; i < pl.size_s(); ++i) { + PIString p(pl[i]); + switch (i) { + case 0: setLogDir(p); break; + case 1: setFilePrefix(p); break; + case 2: setDefaultID(p.toInt()); break; + } + } +} + + +void PIBinaryLog::propertyChanged(const PIString &) { + default_id = property("defaultID").toInt(); + rapid_start = property("rapidStart").toBool(); + play_mode = (PlayMode)property("playMode").toInt(); + play_speed = property("playSpeed").toDouble(); + play_delay = property("playDelay").toSystemTime(); + split_mode = (SplitMode)property("splitMode").toInt(); + split_time = property("splitTime").toSystemTime(); + split_size = property("splitFileSize").toLLong(); + split_count = property("splitRecordCount").toInt(); +} + diff --git a/src/io/pibinarylog.h b/src/io/pibinarylog.h new file mode 100644 index 00000000..c4b775b5 --- /dev/null +++ b/src/io/pibinarylog.h @@ -0,0 +1,333 @@ +/*! \file pibinarylog.h + * \brief Binary log +*/ +/* + PIP - Platform Independent Primitives + Class for write binary data to logfile, and read or playback this data + Copyright (C) 2014 Andrey Bychkov work.a.b@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIBINARYLOG_H +#define PIBINARYLOG_H + +#include "pifile.h" + +#define PIBINARYLOG_VERSION 0x31 +namespace __S__PIBinaryLog { +static const uchar binlog_sig[] = {'B','I','N','L','O','G'}; +}; +#define PIBINARYLOG_SIGNATURE_SIZE sizeof(__S__PIBinaryLog::binlog_sig) + +/// TODO: Create static functions to split and join binlog files +/// TODO: Create functions to insert and delete records +class PIBinaryLog: public PIIODevice +{ + PIIODEVICE(PIBinaryLog) +public: + PIBinaryLog(); + ~PIBinaryLog() {closeDevice();} + + //! \brief Play modes for \a PIBinaryLog + enum PlayMode { + PlayRealTime /*! Play in system realtime, default mode */ , + PlayVariableSpeed /*! Play in software realtime with speed, set by \a setSpeed */ , + PlayStaticDelay /*! Play with custom static delay, ignoring timestamp */ + }; + + //! \brief Different split modes for writing \a PIBinaryLog, which can separate files by size, by time or by records count + enum SplitMode { + SplitNone /*! Without separate, default mode */ , + SplitTime /*! Separate files by record time */ , + SplitSize /*! Separate files by size */ , + SplitCount /*! Separate files by records count */ + }; + + //! \brief Struct contains information about all records with same ID + struct BinLogRecordInfo { + BinLogRecordInfo() { + id = count = 0; + minimum_size = maximum_size = 0; + } + int id; + int count; + int minimum_size; + int maximum_size; + PISystemTime start_time; + PISystemTime end_time; + }; + + //! \brief Struct contains full information about Binary Log file and about all Records using map of \a BinLogRecordInfo + struct BinLogInfo { + PIString path; + int records_count; + llong log_size; + PISystemTime start_time; + PISystemTime end_time; + PIMap records; + }; + + //! \brief Struct contains position, ID and timestamp of record in file + struct BinLogIndex { + int id; + llong pos; + PISystemTime timestamp; + }; + + + //! Current \a PlayMode + PlayMode playMode() const {return play_mode;} + + //! Current \a SplitMode + SplitMode splitMode() const {return split_mode;} + + //! Current directory where billogs wiil be saved + PIString logDir() const {return property("logDir").toString();} + + //! Returns current file prefix + PIString filePrefix() const {return property("filePrefix").toString();} + + //! Current LogDir, returns directory where billogs wiil be saved + int defaultID() const {return default_id;} + + //! Returns current play speed + double playSpeed() const {return play_speed;} + + //! Returns current play delay + PISystemTime playDelay() const {return play_delay;} + + //! Returns current binlog file split time + PISystemTime splitTime() const {return split_time;} + + //! Returns current binlog file split size + llong splitFileSize() const {return split_size;} + + //! Returns current binlog file split records count + int splitRecordCount() const {return split_count;} + + //! Returns if rapid start enabled + bool rapidStart() const {return rapid_start;} + + + //! Set \a PlayMode + void setPlayMode(PlayMode mode) {setProperty("playMode", (int)mode);} + + //! Set \a SplitMode + void setSplitMode(SplitMode mode) {setProperty("splitMode", (int)mode);} + + //! Set path to directory where binlogs will be saved + void setLogDir(const PIString & path) {setProperty("logDir", path);} + + //! Set file prefix, used to + void setFilePrefix(const PIString & prefix) {setProperty("filePrefix", prefix);} + + //! Set defaultID, used in \a write function + void setDefaultID(int id) {setProperty("defaultID", id);} + + //! If enabled BinLog \a ThreadedRead starts without delay for first record, i.e. first record will be readed immediately + void setRapidStart(bool enabled) {setProperty("rapidStart", enabled);} + + //! Set play speed to "speed", default value is 1.0x + //! Also this function set \a playMode to \a PlayVariableSpeed + void setPlaySpeed(double speed) {setPlayMode(PlayVariableSpeed); setProperty("playSpeed", speed);} + + //! Setting static delay between records, default value is 1 sec + //! Also this function set \a playMode to \a PlayStaticDelay + void setPlayDelay(const PISystemTime & delay) {setPlayMode(PlayStaticDelay); setProperty("playDelay", delay);} + + //! Set \a playMode to \a PlayRealTime + void setPlayRealTime() {setPlayMode(PlayRealTime);} + + //! Set binlog file split time + //! Also this function set \a splitMode to \a SplitTime + void setSplitTime(const PISystemTime & time) {setSplitMode(SplitTime); setProperty("splitTime", time);} + + //! Set binlog file split size + //! Also this function set \a splitMode to \a SplitSize + void setSplitFileSize(llong size) {setSplitMode(SplitSize); setProperty("splitFileSize", size);} + + //! Set binlog file split records count + //! Also this function set \a splitMode to \a SplitCount + void setSplitRecordCount(int count) {setSplitMode(SplitCount); setProperty("splitRecordCount", count);} + + + //! Write one record to BinLog file, with ID = id, id must be greather than 0 + int writeBinLog(int id, PIByteArray data) {return writeBinLog(id, data.data(), data.size_s());} + + //! Write one record to BinLog file, with ID = id, id must be greather than 0 + int writeBinLog(int id, const void * data, int size); + + //! Returns count of writed records + int writeCount() const {return write_count;} + + //! Read one record from BinLog file, with ID = id, if id = 0 than any id will be readed + PIByteArray readBinLog(int id = 0); + + //! Read one record from BinLog file, with ID = id, if id = 0 than any id will be readed + int readBinLog(int id, void * read_to, int max_size); + + //! Returns binary log file size + llong logSize() const {return file.size();} + + //! Return true, if position at the end of BinLog file + bool isEnd() const {if (!opened_) return true; return file.isEnd();} + + //! Returns if BinLog file is empty + bool isEmpty() const {return (file.size() <= PIBINARYLOG_SIGNATURE_SIZE + 1);} + + //! Returns if BinLog file is empty + int lastReadedID() const {return lastrecord.id;} + + //! Set position in file to reading/playing + + //! Read one message from binlog file, with ID contains in "filterID" or any ID, if "filterID" is empty + int read(void *read_to, int max_size); + + //! Write one record to BinLog file, with ID = "defaultID" + int write(const void * data, int size) {return writeBinLog(default_id, data, size);} + + //! Array of ID, that BinLog can read from binlog file, when use \a read function, or in \a ThreadedRead + PIVector filterID; + + //! Go to begin of BinLog file + void restart(); + + PIString constructFullPath() const; + + //! Get binlog info \a BinLogInfo + BinLogInfo logInfo() const {if (is_indexed) return binfo; return getLogInfo(path());} + + //! Get binlog index \a BinLogIndex, need \a createIndex before getting index + const PIVector & logIndex() const {return index;} /// TODO: Think about index positions + + //! Create index of current binlog file + bool createIndex(); + + //! Go to record #index + void seekTo(int rindex); + + //! Go to nearest record + bool seek(const PISystemTime & time); + bool seek(llong filepos); + + //! Get current record index (position record in file) + int pos() const {if (is_indexed) return current_index; return -1;} /// TODO: Think about index positions + + //! \handlers + //! \{ + + //! \fn PIString createNewFile() + //! \brief Create new binlog file in \a logDir, if successful returns filename, else returns empty string. + //! Filename is like \a filePrefix + "yyyy_MM_dd__hh_mm_ss.binlog" + + //! \} + //! \events + //! \{ + + //! \fn void fileEnd() + //! \brief Raise on file end while reading + + //! \fn void fileError() + //! \brief Raise on file creation error + + //! \fn void newFile(const PIString & filename) + //! \brief Raise on new file created + + //! \} + + EVENT_HANDLER(PIString, createNewFile); + EVENT(fileEnd) + EVENT(fileError) + EVENT1(newFile, const PIString &, filename) + EVENT1(posChanged, int, pos) /// TODO: Think about index positions + + //! Get binlog info and statistic + static BinLogInfo getLogInfo(const PIString & path); + +protected: + PIString fullPathPrefix() const {return "binlog";} + void configureFromFullPath(const PIString & full_path); + bool openDevice(); + bool closeDevice(); + void propertyChanged(const PIString &); + bool threadedRead(uchar *readed, int size); + +private: + struct BinLogRecord { + int id; + int size; + PISystemTime timestamp; + PIByteArray data; + }; + + bool writeFileHeader(); + bool checkFileHeader(); + BinLogRecord readRecord(); + static void parseLog(PIFile *f, BinLogInfo *info, PIVector * index); + void moveIndex(int i); + + PIVector index; + PIMap index_pos; + BinLogInfo binfo; + + PlayMode play_mode; + SplitMode split_mode; + PIFile file; + BinLogRecord lastrecord; + PISystemTime startlogtime, play_delay, split_time; + double play_time, play_speed; + llong split_size; + int write_count, split_count, default_id, current_index; + bool is_started, is_thread_ok, is_indexed, rapid_start; +}; + +//! \relatesalso PICout \relatesalso PIBinaryLog::BinLogInfo \brief Output operator to PICout +inline PICout operator <<(PICout s, const PIBinaryLog::BinLogInfo & bi) { + s.space(); + s.setControl(0, true); + s << "[PIBinaryLog] " << bi.path << "\n"; + if (bi.log_size < 0) { + s << "invalid file path"; + s.restoreControl(); + return s; + } + if (bi.log_size == 0) { + s << "Invalid empty file"; + s.restoreControl(); + return s; + } if (bi.records_count < 0 && bi.records_count > -4) { + s << "Invalid file or corrupted signature"; + s.restoreControl(); + return s; + } + if (bi.records_count < -3) { + s << "Invalid binlog version"; + s.restoreControl(); + return s; + } + s << "read records " << bi.records_count << " in " << bi.records.size() << " types, log size " << bi.log_size; + s << "\nlog start " << bi.start_time << " , log end " << bi.end_time; + PIVector keys = bi.records.keys(); + piForeachC(int i, keys) { + const PIBinaryLog::BinLogRecordInfo &bri(bi.records[i]); + s << "\n record id " << bri.id << " , count " << bri.count; + s << "\n record start " << bri.start_time << " , end " << bri.end_time; + s << "\n record size " << bri.minimum_size << " - " << bri.maximum_size; + } + s.restoreControl(); + return s; +} + +#endif // PIBINARYLOG_H diff --git a/src/io/piconfig.cpp b/src/io/piconfig.cpp new file mode 100755 index 00000000..f858d9f8 --- /dev/null +++ b/src/io/piconfig.cpp @@ -0,0 +1,710 @@ +/* + PIP - Platform Independent Primitives + Config parser + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "piconfig.h" +#include "pifile.h" +#include "piiostring.h" + +/*! \class PIConfig + * \brief Configuration file + * \details This class provide handle access to configuration file. + * + * \section PIConfig_sec0 Synopsis + * PIConfig reads configuration file and create internal dendritic + * representation of all entries of this file. You can easily read + * some values and write new. + * \image html piconfig.png + * + * %PIConfig supports also INI-style files with sections "[section]". + * In this case line with section name interpret as prefix to the next + * lines. For example, these configs are equal: + * \code + * ser.device = /dev/ttyS0 + * ser.speed = 115200 + * debug = true + * \endcode + * \code + * [ser] + * device = /dev/ttyS0 + * speed = 115200 + * [] + * debug = true + * \endcode + * + * \section PIConfig_sec1 Concepts + * Each node of internal tree has type PIConfig::Entry. %PIConfig + * has one root element \a rootEntry(). Any entry of configuration file is a + * child of this element. + * + */ + +/*! \class PIConfig::Entry + * \brief %Entry of configuration file + * \details This class is node of internal PIConfig tree. + * %Entry provide access to elements of PIConfig. Each entry has + * children or next properties: + * * name + * * value + * * type + * * comment + * + * Each property is a PIString. These properties forms from text line with + * format: \code{.cpp} = # \endcode + * Type and comment are optional fields. Type is a single letter immediately + * after comment symbol "#". \n \n + * %Entry has many implicit convertions to common types: boolean, integers, + * float, double, PIString, PIStringList. \n \n + * Generally there is no need to create instance of %PIConfig::Entry manually, + * it returns by functions \a getValue() of \a PIConfig, \a PIConfig::Entry or + * \a PIConfig::Branch. If there is no suitable entry to return, reference to + * internal instance of %PIConfig::Entry with "default" value will be returned. + * \snippet piconfig.cpp PIConfig::Entry + * +*/ + +/*! \class PIConfig::Branch + * \brief %Branch is a list of entries of configuration file + * \details %Branch provides some features to get entries lists. + * \snippet piconfig.cpp PIConfig::Branch + * +*/ + + +PIConfig::Entry PIConfig::Branch::_empty; +PIConfig::Entry PIConfig::Entry::_empty; + + +PIConfig::Branch PIConfig::Branch::allLeaves() { + Branch b; + b.delim = delim; + piForeach (Entry * i, *this) { + if (i->isLeaf()) b << i; + else allLeaves(b, i); + } + return b; +} + + +PIConfig::Entry & PIConfig::Branch::getValue(const PIString & vname, const PIString & def, bool * exist) { + if (vname.isEmpty()) { + _empty.clear(); + _empty.delim = delim; + if (exist != 0) *exist = false; + return _empty; + } + PIStringList tree = vname.split(delim); + PIString name = tree.front(); + tree.pop_front(); + Entry * ce = 0; + piForeach (Entry * i, *this) + if (i->_name == name) { + ce = i; + break; + } + if (ce == 0) { + _empty._name = vname; + _empty._value = def; + _empty.delim = delim; + if (exist != 0) *exist = false; + return _empty; + } + piForeach (PIString & i, tree) { + ce = ce->findChild(i); + if (ce == 0) { + _empty._name = vname; + _empty._value = def; + _empty.delim = delim; + if (exist != 0) *exist = false; + return _empty; + } + } + if (exist != 0) *exist = true; + return *ce; +} + + +PIConfig::Branch PIConfig::Branch::getValues(const PIString & name) { + Branch b; + b.delim = delim; + piForeach (Entry * i, *this) { + if (i->isLeaf()) { + if (i->_name.find(name) >= 0) + b << i; + } else { + piForeach (Entry * j, i->_children) + if (j->_name.find(name) >= 0) + b << j; + } + } + return b; +} + + +PIConfig::Branch PIConfig::Branch::getLeaves() { + Branch b; + b.delim = delim; + piForeach (Entry * i, *this) + if (i->isLeaf()) + b << i; + return b; +} + + +PIConfig::Branch PIConfig::Branch::getBranches() { + Branch b; + b.delim = delim; + piForeach (Entry * i, *this) + if (!i->isLeaf()) + b << i; + return b; +} + + +PIConfig::Branch & PIConfig::Branch::filter(const PIString & f) { + for (int i = 0; i < size_s(); ++i) { + if (at(i)->_name.find(f) < 0) { + remove(i); + --i; + } + } + return *this; +} + + +bool PIConfig::Branch::entryExists(const Entry * e, const PIString & name) const { + if (e->_children.isEmpty()) { + return (e->_name == name); + } + piForeachC (Entry * i, e->_children) + if (entryExists(i, name)) return true; + return false; +} + + +PIConfig::Entry & PIConfig::Entry::getValue(const PIString & vname, const PIString & def, bool * exist) { + PIStringList tree = vname.split(delim); + Entry * ce = this; + piForeach (PIString & i, tree) { + ce = ce->findChild(i); + if (ce == 0) { + _empty._name = vname; + _empty._value = def; + _empty.delim = delim; + if (exist != 0) *exist = false; + return _empty; + } + } + if (exist != 0) *exist = true; + return *ce; +} + + +PIConfig::Branch PIConfig::Entry::getValues(const PIString & vname) { + Branch b; + b.delim = delim; + piForeach (Entry * i, _children) + if (i->_name.find(vname) >= 0) + b << i; + return b; +}; + + +bool PIConfig::Entry::entryExists(const Entry * e, const PIString & name) const { + if (e->_children.isEmpty()) { + return (e->_name == name); + } + piForeachC (Entry * i, e->_children) + if (entryExists(i, name)) return true; + return false; +} + + +PIConfig::PIConfig(const PIString & path, PIIODevice::DeviceMode mode) { + _init(); + own_dev = true; + dev = new PIFile(path, mode); + if (!dev->isOpened()) + dev->open(path, mode); + parse(); +} + + +PIConfig::PIConfig(PIString * string, PIIODevice::DeviceMode mode) { + _init(); + own_dev = true; + dev = new PIIOString(string, mode); + parse(); +} + + +PIConfig::PIConfig(PIIODevice * device, PIIODevice::DeviceMode mode) { + _init(); + own_dev = false; + dev = device; + if (dev) dev->open(mode); + parse(); +} + + +PIConfig::~PIConfig() { + root.deleteBranch(); + if (own_dev && dev) delete dev; + dev = 0; +} + + +bool PIConfig::open(const PIString & path, PIIODevice::DeviceMode mode) { + if (own_dev && dev) delete dev; + own_dev = true; + dev = new PIFile(path, mode); + if (!dev->isOpened()) + dev->open(path, mode); + parse(); + return dev->isOpened(); +} + + +bool PIConfig::open(PIString * string, PIIODevice::DeviceMode mode) { + if (own_dev && dev) delete dev; + own_dev = true; + dev = new PIIOString(string, mode); + parse(); + return true; +} + + +void PIConfig::_init() { + delim = "."; + root.delim = delim; + empty.delim = delim; + empty._parent = 0; +} + + +void PIConfig::_clearDev() { + if (!dev) return; + if (PIString(dev->className()) == "PIFile") {((PIFile*)dev)->clear(); return;} + if (PIString(dev->className()) == "PIIOString") {((PIIOString*)dev)->clear(); return;} +} + + +void PIConfig::_flushDev() { + if (!dev) return; + if (PIString(dev->className()) == "PIFile") {((PIFile*)dev)->flush();} +} + + +bool PIConfig::_isEndDev() { + if (!dev) return true; + if (PIString(dev->className()) == "PIFile") {return ((PIFile*)dev)->isEnd();} + if (PIString(dev->className()) == "PIIOString") {return ((PIIOString*)dev)->isEnd();} + return true; +} + + +void PIConfig::_seekToBeginDev() { + if (!dev) return; + if (PIString(dev->className()) == "PIFile") {((PIFile*)dev)->seekToBegin(); return;} + if (PIString(dev->className()) == "PIIOString") {((PIIOString*)dev)->seekToBegin(); return;} +} + + +PIString PIConfig::_readLineDev() { + if (!dev) return PIString(); + if (PIString(dev->className()) == "PIFile") {return ((PIFile*)dev)->readLine();} + if (PIString(dev->className()) == "PIIOString") {return ((PIIOString*)dev)->readLine();} + return PIString(); +} + + +void PIConfig::_writeDev(const PIString & l) { + //piCout << "write \"" << l << "\""; + if (!dev) return; + if (PIString(dev->className()) == "PIFile") {*((PIFile*)dev) << (l); return;} + if (PIString(dev->className()) == "PIIOString") {((PIIOString*)dev)->writeString(l); return;} + dev->write(l.toByteArray()); +} + + +bool PIConfig::isOpened() const { + if (dev) return dev->isOpened(); + return false; +} + + +PIConfig::Entry & PIConfig::getValue(const PIString & vname, const PIString & def, bool * exist) { + PIStringList tree = vname.split(delim); + Entry * ce = &root; + piForeach (PIString & i, tree) { + ce = ce->findChild(i); + if (ce == 0) { + if (exist != 0) *exist = false; + empty._name = vname; + empty._value = def; + empty.delim = delim; + return empty; + } + } + if (exist != 0) *exist = true; + return *ce; +} + + +PIConfig::Branch PIConfig::getValues(const PIString & vname) { + Branch b; + b.delim = delim; + piForeach (Entry * i, root._children) + if (i->_name.find(vname) >= 0) + b << i; + return b; +}; + + +void PIConfig::addEntry(const PIString & name, const PIString & value, const PIString & type, bool write) { + if (getValue(name)._parent != 0) + return; + bool toRoot = false; + PIStringList tree = name.split(delim); + PIString ename = tree.back(); + tree.pop_back(); + Entry * te, * ce, * entry = &root; + if (tree.isEmpty()) toRoot = true; + piForeach (PIString & i, tree) { + te = entry->findChild(i); + if (te == 0) { + ce = new Entry(); + ce->delim = delim; + ce->_tab = entry->_tab; + ce->_line = entry->_line; + ce->_name = i; + ce->_parent = entry; + entry->_children << ce; + entry = ce; + } else entry = te; + } + PIConfig::Branch ch = entry->_children; + ch.sort(PIConfig::Entry::compare); + te = (entry->isLeaf() ? 0 : ch.back()); + ce = new Entry(); + ce->delim = delim; + ce->_name = ename; + ce->_value = value; + ce->_type = type; + if (te == 0) { + ce->_tab = entry->_tab; + if (toRoot) ce->_line = other.size_s() - 1; + else ce->_line = entry->_line; + } else { + ce->_tab = te->_tab; + if (toRoot) ce->_line = other.size_s() - 1; + else { + ch = entry->_parent->_children; + ch.sort(PIConfig::Entry::compare); + ce->_line = ch.back()->_line + 1; + } + } + ce->_parent = entry; + entry->_children << ce; + other.insert(ce->_line, ""); + Branch b = allLeaves(); + bool found = false; + for (int i = 0; i < b.size_s(); ++i) { + if (found) { + b[i]->_line++; + continue; + } + if (b[i] == ce) { + found = true; + if (i > 0) + if (b[i - 1]->_line == b[i]->_line) + b[i - 1]->_line++; + } + } + if (write) writeAll(); +} + + +void PIConfig::setValue(const PIString & name, const PIString & value, const PIString & type, bool write) { + Entry & e(getValue(name)); + if (&e == &empty) { + addEntry(name, value, type, write); + return; + } + e._value = value; + e._type = type; + if (write) writeAll(); +} + + +int PIConfig::entryIndex(const PIString & name) { + PIStringList tree = name.split(delim); + Entry * ce = &root; + piForeach (PIString & i, tree) { + ce = ce->findChild(i); + if (ce == 0) + return -1; + } + return allLeaves().indexOf(ce); +} + + +void PIConfig::setValue(uint number, const PIString & value, bool write) { + Entry & e(entryByIndex(number)); + if (&e == &empty) return; + e._value = value; + if (write) writeAll(); +} + + +void PIConfig::setName(uint number, const PIString & name, bool write) { + Entry & e(entryByIndex(number)); + if (&e == &empty) return; + e._name = name; + if (write) writeAll(); +} + + +void PIConfig::setType(uint number, const PIString & type, bool write) { + Entry & e(entryByIndex(number)); + if (&e == &empty) return; + e._type = type; + if (write) writeAll(); +} + + +void PIConfig::setComment(uint number, const PIString & comment, bool write) { + Entry & e(entryByIndex(number)); + if (&e == &empty) return; + e._comment = comment; + if (write) writeAll(); +} + + +void PIConfig::removeEntry(const PIString & name, bool write) { + Entry & e(getValue(name)); + if (&e == &empty) return; + Branch b = allLeaves(); + removeEntry(b, &e); + if (write) writeAll(); +} + + +void PIConfig::removeEntry(uint number, bool write) { + Entry & e(entryByIndex(number)); + if (&e == &empty) return; + Branch b = allLeaves(); + removeEntry(b, &e); + if (write) writeAll(); +} + + +void PIConfig::removeEntry(Branch & b, PIConfig::Entry * e) { + bool leaf = true; + if (e->isLeaf()) other.remove(e->_line); + if (!e->isLeaf() && !e->_value.isEmpty()) { + e->_value.clear(); + leaf = false; + } else { + int cc = e->_children.size_s(); + piForTimes (cc) + removeEntry(b, e->_children.back()); + } + bool found = false; + for (int i = 0; i < b.size_s(); ++i) { + if (found) { + b[i]->_line--; + continue; + } + if (b[i] == e) found = true; + } + if (!leaf) return; + e->_parent->_children.removeOne(e); + b.removeOne(e); + delete e; +} + + +PIString PIConfig::getPrefixFromLine(PIString line, bool * exists) { + line.trim(); + if (line.left(1) == "#") {if (exists) *exists = false; return PIString();} + int ci = line.find("#"); + if (ci >= 0) line.cutRight(line.size() - ci); + if (line.find("=") >= 0) {if (exists) *exists = false; return PIString();} + if (line.find("[") >= 0 && line.find("]") >= 0) { + if (exists) *exists = true; + return line.takeRange('[', ']').trim(); + } + if (exists) *exists = false; + return PIString(); +} + + +void PIConfig::writeAll() { + //cout << this << " write < " << size() << endl; + _clearDev(); + //*this << "1234567894132456798\n"; return; + //writeEntry(&root); + buildFullNames(&root); + Branch b = allLeaves(); + PIString prefix, tprefix; + bool isPrefix; + //for (int i = 0; i < b.size_s(); ++i) + // cout << b[i]->_name << " = " << b[i]->_value << endl; + int j = 0; + for (int i = 0; i < other.size_s(); ++i) { + //cout << j << endl; + if (j >= 0 && j < b.size_s()) { + if (b[j]->_line == i) { + b[j]->buildLine(); + _writeDev((b[j]->_all).cutLeft(prefix.size()) + "\n"); + //cout << this << " " << b[j]->_all << endl; + ++j; + } else { + _writeDev(other[i]); + tprefix = getPrefixFromLine(other[i], &isPrefix); + if (isPrefix) { + prefix = tprefix; + if (!prefix.isEmpty()) + prefix += delim; + } + if (i < other.size_s() - 1) + _writeDev('\n'); + //cout << this << " " << other[i] << endl; + } + } else { + _writeDev(other[i]); + tprefix = getPrefixFromLine(other[i], &isPrefix); + if (isPrefix) { + prefix = tprefix; + if (!prefix.isEmpty()) + prefix += delim; + } + if (i < other.size_s() - 1) + _writeDev('\n'); + //cout << this << " " << other[i] << endl; + } + } + _flushDev(); + readAll(); + //cout << this << " write > " << size() << endl; +} + + +void PIConfig::clear() { + _clearDev(); + parse(); +} + + +void PIConfig::readAll() { + root.deleteBranch(); + root.clear(); + parse(); +} + + +bool PIConfig::entryExists(const Entry * e, const PIString & name) const { + if (e->_children.isEmpty()) { + return (e->_name == name); + } + piForeachC (Entry * i, e->_children) + if (entryExists(i, name)) return true; + return false; +} + + +void PIConfig::parse() { + PIString src, str, tab, comm, all, name, type, prefix, tprefix; + PIStringList tree; + Entry * entry, * te, * ce; + int ind, sind; + bool isNew, isPrefix; + if (!isOpened()) return; + _seekToBeginDev(); + other.clear(); + lines = centry = 0; + while (!_isEndDev()) { + other.push_back(PIString()); + src = str = _readLineDev(); + tprefix = getPrefixFromLine(src, &isPrefix); + if (isPrefix) { + prefix = tprefix; + if (!prefix.isEmpty()) + prefix += delim; + } + //piCout << "line \"" << str << "\""; + tab = str.left(str.find(str.trimmed().left(1))); + str.trim(); + //cout << endl << str << endl << endl; + all = str; + ind = str.find('='); + if ((ind > 0) && (str[0] != '#')) { + sind = str.find('#'); + if (sind > 0) { + comm = str.right(str.length() - sind - 1).trimmed(); + if (comm.length() > 0) type = comm[0]; + else type = "s"; + comm = comm.right(comm.length() - 1).trimmed(); + str = str.left(sind); + } else { + type = "s"; + comm = ""; + } + //name = str.left(ind).trimmed(); + tree = (prefix + str.left(ind).trimmed()).split(delim); + name = tree.back(); + tree.pop_back(); + entry = &root; + piForeachC (PIString & i, tree) { + te = entry->findChild(i); + if (te == 0) { + ce = new Entry(); + ce->delim = delim; + ce->_tab = tab; + ce->_line = lines; + ce->_name = i; + ce->_parent = entry; + entry->_children << ce; + entry = ce; + } else entry = te; + } + isNew = false; + ce = entry->findChild(name); + if (ce == 0) { + ce = new Entry(); + isNew = true; + } + ce->delim = delim; + ce->_tab = tab; + ce->_name = name; + ce->_value = str.right(str.length() - ind - 1).trimmed(); + ce->_type = type; + ce->_comment = comm; + ce->_line = lines; + ce->_all = all; + if (isNew) { + ce->_parent = entry; + entry->_children << ce; + } + } else other.back() = src; + lines++; + } + setEntryDelim(&root, delim); + buildFullNames(&root); +} diff --git a/src/io/piconfig.h b/src/io/piconfig.h new file mode 100755 index 00000000..0b34938f --- /dev/null +++ b/src/io/piconfig.h @@ -0,0 +1,525 @@ +/*! \file piconfig.h + * \brief Configuration parser and writer +*/ +/* + PIP - Platform Independent Primitives + Configuration parser and writer + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PICONFIG_H +#define PICONFIG_H + +#include "piiodevice.h" + +#define PICONFIG_GET_VALUE \ + Entry & getValue(const PIString & vname, const char * def, bool * exists = 0) {return getValue(vname, PIString(def), exists);} \ + Entry & getValue(const PIString & vname, const PIStringList & def, bool * exists = 0) {return getValue(vname, def.join("%|%"), exists);} \ + Entry & getValue(const PIString & vname, const bool def, bool * exists = 0) {return getValue(vname, PIString::fromBool(def), exists);} \ + Entry & getValue(const PIString & vname, const short def, bool * exists = 0) {return getValue(vname, itos(def), exists);} \ + Entry & getValue(const PIString & vname, const int def, bool * exists = 0) {return getValue(vname, itos(def), exists);} \ + Entry & getValue(const PIString & vname, const long def, bool * exists = 0) {return getValue(vname, ltos(def), exists);} \ + Entry & getValue(const PIString & vname, const uchar def, bool * exists = 0) {return getValue(vname, uitos(def), exists);} \ + Entry & getValue(const PIString & vname, const ushort def, bool * exists = 0) {return getValue(vname, uitos(def), exists);} \ + Entry & getValue(const PIString & vname, const uint def, bool * exists = 0) {return getValue(vname, uitos(def), exists);} \ + Entry & getValue(const PIString & vname, const ulong def, bool * exists = 0) {return getValue(vname, ultos(def), exists);} \ + Entry & getValue(const PIString & vname, const float def, bool * exists = 0) {return getValue(vname, ftos(def), exists);} \ + Entry & getValue(const PIString & vname, const double def, bool * exists = 0) {return getValue(vname, dtos(def), exists);} \ + \ + Entry & getValue(const PIString & vname, const char * def, bool * exists = 0) const {return getValue(vname, PIString(def), exists);} \ + Entry & getValue(const PIString & vname, const PIStringList & def, bool * exists = 0) const {return getValue(vname, def.join("%|%"), exists);} \ + Entry & getValue(const PIString & vname, const bool def, bool * exists = 0) const {return getValue(vname, PIString::fromBool(def), exists);} \ + Entry & getValue(const PIString & vname, const short def, bool * exists = 0) const {return getValue(vname, itos(def), exists);} \ + Entry & getValue(const PIString & vname, const int def, bool * exists = 0) const {return getValue(vname, itos(def), exists);} \ + Entry & getValue(const PIString & vname, const long def, bool * exists = 0) const {return getValue(vname, ltos(def), exists);} \ + Entry & getValue(const PIString & vname, const uchar def, bool * exists = 0) const {return getValue(vname, uitos(def), exists);} \ + Entry & getValue(const PIString & vname, const ushort def, bool * exists = 0) const {return getValue(vname, uitos(def), exists);} \ + Entry & getValue(const PIString & vname, const uint def, bool * exists = 0) const {return getValue(vname, uitos(def), exists);} \ + Entry & getValue(const PIString & vname, const ulong def, bool * exists = 0) const {return getValue(vname, ultos(def), exists);} \ + Entry & getValue(const PIString & vname, const float def, bool * exists = 0) const {return getValue(vname, ftos(def), exists);} \ + Entry & getValue(const PIString & vname, const double def, bool * exists = 0) const {return getValue(vname, dtos(def), exists);} + +class PIP_EXPORT PIConfig +{ + friend class Entry; + friend class Branch; +public: + + //! Contructs and read configuration file at path "path" in mode "mode" + PIConfig(const PIString & path, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); + + //! Contructs and read configuration string "string" in mode "mode" + PIConfig(PIString * string, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); + + //! Contructs and read configuration from custom device "device" in mode "mode" + PIConfig(PIIODevice * device = 0, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); + + ~PIConfig(); + + class Entry; + + + class PIP_EXPORT Branch: public PIVector { + friend class PIConfig; + friend class Entry; + friend std::ostream & operator <<(std::ostream & s, const Branch & v); + friend PICout operator <<(PICout s, const Branch & v); + public: + Branch() {;} + + Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0); + Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0) const {return const_cast(this)->getValue(vname, def, exists);} + PICONFIG_GET_VALUE + + Branch allLeaves(); + Branch getValues(const PIString & name); + Branch getLeaves(); + Branch getBranches(); + Branch & filter(const PIString & f); + bool isEntryExists(const PIString & name) const {piForeachC (Entry * i, *this) if (entryExists(i, name)) return true; return false;} + int indexOf(const Entry * e) {for (int i = 0; i < size_s(); ++i) if (at(i) == e) return i; return -1;} + + //void clear() {piForeach (Entry * i, *this) delete i; PIVector::clear();} + + private: + bool entryExists(const Entry * e, const PIString & name) const; + void allLeaves(Branch & b, Entry * e) {piForeach (Entry * i, e->_children) {if (i->isLeaf()) b << i; else allLeaves(b, i);}} + void coutt(std::ostream & s, const PIString & p) const {piForeachC (Entry * i, *this) i->coutt(s, p);} + void piCoutt(PICout s, const PIString & p) const {piForeachC (Entry * i, *this) i->piCoutt(s, p);} + + static Entry _empty; + PIString delim; + + }; + + + class PIP_EXPORT Entry { + friend class PIConfig; + friend class Branch; + public: + Entry() {_parent = 0;} + + //! Returns parent entry, or 0 if there is no parent (root of default value) + Entry * parent() const {return _parent;} + + //! Returns children count + int childCount() const {return _children.size_s();} + + //! Returns children as \a PIConfig::Branch + Branch & children() const {_children.delim = delim; return _children;} + + //! Returns child at index "index" + Entry * child(const int index) const {return _children[index];} + + //! Returns first child with name "name" + Entry * findChild(const PIString & name) {piForeach (Entry * i, _children) if (i->_name == name) return i; return 0;} + + //! Returns first child with name "name" + const Entry * findChild(const PIString & name) const {piForeachC (Entry * i, _children) if (i->_name == name) return i; return 0;} + + //! Returns \b true if there is no children + bool isLeaf() const {return _children.isEmpty();} + + + //! Returns name + const PIString & name() const {return _name;} + + //! Returns value + const PIString & value() const {return _value;} + + //! Returns type + const PIString & type() const {return _type;} + + //! Returns comment + const PIString & comment() const {return _comment;} + + /** \brief Returns full name, i.e. name as it looks in file + * \details In case of default entry full name always is empty + * \snippet piconfig.cpp fullName */ + const PIString & fullName() const {return _full_name;} + + //! Set name to "value" and returns this + Entry & setName(const PIString & value) {_name = value; return *this;} + + //! Set type to "value" and returns this + Entry & setType(const PIString & value) {_type = value; return *this;} + + //! Set comment to "value" and returns this + Entry & setComment(const PIString & value) {_comment = value; return *this;} + + //! Set value to "value" and returns this + Entry & setValue(const PIString & value) {_value = value; return *this;} + + //! Set value to "value" and returns this. Type is set to "l" + Entry & setValue(const PIStringList & value) {setValue(value.join("%|%")); setType("l"); return *this;} + + //! Set value to "value" and returns this. Type is set to "s" + Entry & setValue(const char * value) {setValue(PIString(value)); setType("s"); return *this;} + + //! Set value to "value" and returns this. Type is set to "b" + Entry & setValue(const bool value) {setValue(btos(value)); setType("b"); return *this;} + + //! Set value to "value" and returns this. Type is set to "s" + Entry & setValue(const char value) {setValue(PIString(1, value)); setType("s"); return *this;} + + //! Set value to "value" and returns this. Type is set to "n" + Entry & setValue(const short value) {setValue(itos(value)); setType("n"); return *this;} + + //! Set value to "value" and returns this. Type is set to "n" + Entry & setValue(const int value) {setValue(itos(value)); setType("n"); return *this;} + + //! Set value to "value" and returns this. Type is set to "n" + Entry & setValue(const long value) {setValue(ltos(value)); setType("n"); return *this;} + + //! Set value to "value" and returns this. Type is set to "n" + Entry & setValue(const uchar value) {setValue(uitos(value)); setType("n"); return *this;} + + //! Set value to "value" and returns this. Type is set to "n" + Entry & setValue(const ushort value) {setValue(uitos(value)); setType("n"); return *this;} + + //! Set value to "value" and returns this. Type is set to "n" + Entry & setValue(const uint value) {setValue(uitos(value)); setType("n"); return *this;} + + //! Set value to "value" and returns this. Type is set to "n" + Entry & setValue(const ulong value) {setValue(ultos(value)); setType("n"); return *this;} + + //! Set value to "value" and returns this. Type is set to "f" + Entry & setValue(const float value) {setValue(ftos(value)); setType("f"); return *this;} + + //! Set value to "value" and returns this. Type is set to "f" + Entry & setValue(const double value) {setValue(dtos(value)); setType("f"); return *this;} + + + /** \brief Returns entry with name "vname" and default value "def" + * \details If there is no suitable entry found, reference to default internal entry with + * value = "def" will be returned, and if "exists" not null it will be set to \b false */ + Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0); + Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0) const {return const_cast(this)->getValue(vname, def, exists);} + PICONFIG_GET_VALUE + + //! \fn Entry & getValue(const PIString & vname, const char * def, bool * exists = 0) + //! \brief Returns entry with name "vname" and default value "def" + + //! \fn Entry & getValue(const PIString & vname, const char * def, bool * exists = 0) + //! \brief Returns entry with name "vname" and default value "def" + + //! \fn Entry & getValue(const PIString & vname, const PIStringList & def, bool * exists = 0) + //! \brief Returns entry with name "vname" and default value "def" + + //! \fn Entry & getValue(const PIString & vname, const bool def, bool * exists = 0) + //! \brief Returns entry with name "vname" and default value "def" + + //! \fn Entry & getValue(const PIString & vname, const short def, bool * exists = 0) + //! \brief Returns entry with name "vname" and default value "def" + + //! \fn Entry & getValue(const PIString & vname, const int def, bool * exists = 0) + //! \brief Returns entry with name "vname" and default value "def" + + //! \fn Entry & getValue(const PIString & vname, const long def, bool * exists = 0) + //! \brief Returns entry with name "vname" and default value "def" + + //! \fn Entry & getValue(const PIString & vname, const uchar def, bool * exists = 0) + //! \brief Returns entry with name "vname" and default value "def" + + //! \fn Entry & getValue(const PIString & vname, const ushort def, bool * exists = 0) + //! \brief Returns entry with name "vname" and default value "def" + + //! \fn Entry & getValue(const PIString & vname, const uint def, bool * exists = 0) + //! \brief Returns entry with name "vname" and default value "def" + + //! \fn Entry & getValue(const PIString & vname, const ulong def, bool * exists = 0) + //! \brief Returns entry with name "vname" and default value "def" + + //! \fn Entry & getValue(const PIString & vname, const float def, bool * exists = 0) + //! \brief Returns entry with name "vname" and default value "def" + + //! \fn Entry & getValue(const PIString & vname, const double def, bool * exists = 0) + //! \brief Returns entry with name "vname" and default value "def" + + + //! Find all entries with names with substrings "vname" and returns them as \a PIConfig::Branch + Branch getValues(const PIString & vname); + + + //! If there is no children returns if name == "name". Else returns if any child has name == "name" + bool isEntryExists(const PIString & name) const {return entryExists(this, name);} + + + //! Convertion to boolean + operator bool() {return _value.toBool();} + + //! Convertion to char + operator char() {return (_value.isEmpty() ? 0 : _value[0].toAscii());} + + //! Convertion to short + operator short() {return _value.toShort();} + + //! Convertion to int + operator int() {return _value.toInt();} + + //! Convertion to long + operator long() {return _value.toLong();} + + //! Convertion to uchar + operator uchar() {return _value.toInt();} + + //! Convertion to ushort + operator ushort() {return _value.toShort();} + + //! Convertion to uint + operator uint() {return _value.toInt();} + + //! Convertion to ulong + operator ulong() {return _value.toLong();} + + //! Convertion to float + operator float() {return _value.toFloat();} + + //! Convertion to double + operator double() {return _value.toDouble();} + + //! Convertion to PIString + operator PIString() {return _value;} + + //! Convertion to PIStringList + operator PIStringList() {return _value.split("%|%");} + + private: + typedef PIConfig::Entry * EntryPtr; + static int compare(const EntryPtr * f, const EntryPtr * s) {return (*f)->_line == (*s)->_line ? 0 : (*f)->_line < (*s)->_line ? -1 : 1;} + bool entryExists(const Entry * e, const PIString & name) const; + void buildLine() {_all = _tab + _full_name + " = " + _value + " #" + _type + " " + _comment;} + void clear() {_children.clear(); _name = _value = _type = _comment = _all = PIString(); _line = 0; _parent = 0;} + void coutt(std::ostream & s, const PIString & p) const {PIString nl = p + " "; if (!_value.isEmpty()) s << p << _name << " = " << _value << endl; else cout << p << _name << endl; piForeachC (Entry * i, _children) i->coutt(s, nl);} + void piCoutt(PICout s, const PIString & p) const {PIString nl = p + " "; if (!_value.isEmpty()) s << p << _name << " = " << _value << NewLine; else cout << p << _name << endl; piForeachC (Entry * i, _children) i->piCoutt(s, nl);} + void deleteBranch() {piForeach (Entry * i, _children) {i->deleteBranch(); delete i;}} + + static Entry _empty; + Entry * _parent; + mutable Branch _children; + PIString _tab; + PIString _name; + PIString _value; + PIString _type; + PIString _comment; + PIString _all; + PIString _full_name; + PIString delim; + int _line; + }; + + + //! Read configuration file at path "path" in mode "mode" + bool open(const PIString & path, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); + + //! Read configuration string "string" in mode "mode" + bool open(PIString * string, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);\ + + bool isOpened() const; + + //! Returns top-level entry with name "vname", if doesn`t exists return entry with value "def" and set *exist to false + Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0); + Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0) const {return const_cast(this)->getValue(vname, def, exists);} + + PICONFIG_GET_VALUE + + //! \fn Entry & getValue(const PIString & vname, const char * def, bool * exists = 0) + //! \brief Returns top-level entry with name "vname" and default value "def" + + //! \fn Entry & getValue(const PIString & vname, const char * def, bool * exists = 0) + //! \brief Returns top-level entry with name "vname" and default value "def" + + //! \fn Entry & getValue(const PIString & vname, const PIStringList & def, bool * exists = 0) + //! \brief Returns top-level entry with name "vname" and default value "def" + + //! \fn Entry & getValue(const PIString & vname, const bool def, bool * exists = 0) + //! \brief Returns top-level entry with name "vname" and default value "def" + + //! \fn Entry & getValue(const PIString & vname, const short def, bool * exists = 0) + //! \brief Returns top-level entry with name "vname" and default value "def" + + //! \fn Entry & getValue(const PIString & vname, const int def, bool * exists = 0) + //! \brief Returns top-level entry with name "vname" and default value "def" + + //! \fn Entry & getValue(const PIString & vname, const long def, bool * exists = 0) + //! \brief Returns top-level entry with name "vname" and default value "def" + + //! \fn Entry & getValue(const PIString & vname, const uchar def, bool * exists = 0) + //! \brief Returns top-level entry with name "vname" and default value "def" + + //! \fn Entry & getValue(const PIString & vname, const ushort def, bool * exists = 0) + //! \brief Returns top-level entry with name "vname" and default value "def" + + //! \fn Entry & getValue(const PIString & vname, const uint def, bool * exists = 0) + //! \brief Returns top-level entry with name "vname" and default value "def" + + //! \fn Entry & getValue(const PIString & vname, const ulong def, bool * exists = 0) + //! \brief Returns top-level entry with name "vname" and default value "def" + + //! \fn Entry & getValue(const PIString & vname, const float def, bool * exists = 0) + //! \brief Returns top-level entry with name "vname" and default value "def" + + //! \fn Entry & getValue(const PIString & vname, const double def, bool * exists = 0) + //! \brief Returns top-level entry with name "vname" and default value "def" + + + //! Returns top-level entries with names with substrings "vname" + Branch getValues(const PIString & vname); + + + //! Set top-level entry with name "name" value to "value", type to "type" and if "write" immediate write to file. Add new entry if there is no suitable exists + void setValue(const PIString & name, const PIString & value, const PIString & type = "s", bool write = true); + + //! Set top-level entry with name "name" value to "value", type to "l" and if "write" immediate write to file. Add new entry if there is no suitable exists + void setValue(const PIString & name, const PIStringList & value, bool write = true) {setValue(name, value.join("%|%"), "l", write);} + + //! Set top-level entry with name "name" value to "value", type to "s" and if "write" immediate write to file. Add new entry if there is no suitable exists + void setValue(const PIString & name, const char * value, bool write = true) {setValue(name, PIString(value), "s", write);} + + //! Set top-level entry with name "name" value to "value", type to "b" and if "write" immediate write to file. Add new entry if there is no suitable exists + void setValue(const PIString & name, const bool value, bool write = true) {setValue(name, btos(value), "b", write);} + + //! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists + void setValue(const PIString & name, const short value, bool write = true) {setValue(name, itos(value), "n", write);} + + //! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists + void setValue(const PIString & name, const int value, bool write = true) {setValue(name, itos(value), "n", write);} + + //! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists + void setValue(const PIString & name, const long value, bool write = true) {setValue(name, ltos(value), "n", write);} + + //! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists + void setValue(const PIString & name, const uchar value, bool write = true) {setValue(name, uitos(value), "n", write);} + + //! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists + void setValue(const PIString & name, const ushort value, bool write = true) {setValue(name, uitos(value), "n", write);} + + //! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists + void setValue(const PIString & name, const uint value, bool write = true) {setValue(name, uitos(value), "n", write);} + + //! Set top-level entry with name "name" value to "value", type to "n" and if "write" immediate write to file. Add new entry if there is no suitable exists + void setValue(const PIString & name, const ulong value, bool write = true) {setValue(name, ultos(value), "n", write);} + + //! Set top-level entry with name "name" value to "value", type to "f" and if "write" immediate write to file. Add new entry if there is no suitable exists + void setValue(const PIString & name, const float value, bool write = true) {setValue(name, ftos(value), "f", write);} + + //! Set top-level entry with name "name" value to "value", type to "f" and if "write" immediate write to file. Add new entry if there is no suitable exists + void setValue(const PIString & name, const double value, bool write = true) {setValue(name, dtos(value), "f", write);} + + //! Returns root entry + Entry & rootEntry() {return root;} + + //! Returns top-level entries count + int entriesCount() const {return childCount(&root);} + + //! Returns if top-level entry with name "name" exists + bool isEntryExists(const PIString & name) const {return entryExists(&root, name);} + + //! Returns all top-level entries + Branch allTree() {Branch b; piForeach (Entry * i, root._children) b << i; b.delim = delim; return b;} + + //! Returns all entries without children + Branch allLeaves() {Branch b; allLeaves(b, &root); b.sort(Entry::compare); b.delim = delim; return b;} + + int entryIndex(const PIString & name); + + PIString getName(uint number) {return entryByIndex(number)._name;} + PIString getValue(uint number) {return entryByIndex(number)._value;} + PIChar getType(uint number) {return entryByIndex(number)._type[0];} + PIString getComment(uint number) {return entryByIndex(number)._comment;} + + void addEntry(const PIString & name, const PIString & value, const PIString & type = "s", bool write = true); + void setName(uint number, const PIString & name, bool write = true); + void setValue(uint number, const PIString & value, bool write = true); + void setType(uint number, const PIString & type, bool write = true); + void setComment(uint number, const PIString & comment, bool write = true); + + void removeEntry(const PIString & name, bool write = true); + void removeEntry(uint number, bool write = true); + + //! Remove all tree and device content + void clear(); + + //! Parse device and build internal tree + void readAll(); + + //! Write all internal tree to device + void writeAll(); + + //! Returns current tree delimiter, default "." + const PIString & delimiter() const {return delim;} + + //! Set current tree delimiter + void setDelimiter(const PIString & d) {delim = d; setEntryDelim(&root, d); readAll();} + +private: + void _init(); + void _clearDev(); + void _flushDev(); + bool _isEndDev(); + void _seekToBeginDev(); + PIString _readLineDev(); + void _writeDev(const PIString & l); + int childCount(const Entry * e) const {int c = 0; piForeachC (Entry * i, e->_children) c += childCount(i); c += e->_children.size_s(); return c;} + bool entryExists(const Entry * e, const PIString & name) const; + void buildFullNames(Entry * e) {piForeach (Entry * i, e->_children) {if (e != &root) i->_full_name = e->_full_name + delim + i->_name; else i->_full_name = i->_name; buildFullNames(i);}} + void allLeaves(Branch & b, Entry * e) {piForeach (Entry * i, e->_children) {if ((!i->_value.isEmpty() && !i->isLeaf()) || i->isLeaf()) b << i; allLeaves(b, i);}} + void setEntryDelim(Entry * e, const PIString & d) {piForeach (Entry * i, e->_children) setEntryDelim(i, d); e->delim = d;} + Entry & entryByIndex(const int index) {Branch b = allLeaves(); if (index < 0 || index >= b.size_s()) return empty; return *(b[index]);} + void removeEntry(Branch & b, Entry * e); + void deleteEntry(Entry * e) {piForeach (Entry * i, e->_children) deleteEntry(i); delete e;} + PIString getPrefixFromLine(PIString line, bool * exists); + void parse(); + + int centry; + bool own_dev; + PIIODevice * dev; + PIString delim; + Entry root, empty; + uint lines; + PIStringList other; + +}; + + +inline std::ostream & operator <<(std::ostream & s, const PIConfig::Branch & v) {v.coutt(s, ""); return s;} +inline std::ostream & operator <<(std::ostream & s, const PIConfig::Entry & v) {s << v.value(); return s;} +inline PICout operator <<(PICout s, const PIConfig::Branch & v) {s.setControl(0, true); v.piCoutt(s, ""); s.restoreControl(); return s;} +inline PICout operator <<(PICout s, const PIConfig::Entry & v) {s << v.value(); return s;} + + +/** \relatesalso PIConfig \relatesalso PIIODevice + * \brief Service function. useful for configuring devices + * \details Function takes entry name "name", default value "def" and two + * \a PIConfig::Entry sections: "em" and their parent "ep". If there is no + * parent ep = 0. If "ep" is not null and entry "name" exists in "ep" function + * returns this value. Else returns value of entry "name" in section "em" or + * "def" if entry doesn`t exists. \n This function useful to read settings + * from configuration file in implementation \a PIIODevice::configureDevice() function */ +template +T readDeviceSetting(const PIString & name, const T & def, const PIConfig::Entry * em, const PIConfig::Entry * ep) { + if (ep != 0) { + T ret; + bool ex; + ret = ep->getValue(name, def, &ex); + if (!ex) ret = em->getValue(name, def); + return ret; + } + return em->getValue(name, def); + +} + +#endif // PICONFIG_H diff --git a/src/io/piconnection.cpp b/src/io/piconnection.cpp new file mode 100755 index 00000000..6247b8eb --- /dev/null +++ b/src/io/piconnection.cpp @@ -0,0 +1,1195 @@ +/* + PIP - Platform Independent Primitives + Complex I/O point + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "piconnection.h" +#include "piconfig.h" + +/** \class PIConnection + * \brief Complex Input/Output point + * + * \section PIConnection_synopsis Synopsis + * %PIConnection provides abstract layer over physical devices, + * filtering and connecting data streams. Each %PIConnection + * works through Device Pool, so several %PIConnections can + * read from single physical device. General scheme: + * \image html piconnection.png + * + * \section PIConnection_pool Device pool concept + * Device pool is static object, single for each application, which + * contains unique devices. Each %PIConnection works with real devices + * through Device pool. Each device has assosiated thread for read + * and it can be started or stopped with %PIConnection functions + * \a startThreadedRead() and \a stopThreadedRead(). + * + * \section PIConnection_filters Filters + * %PIConnection filter is a PIPacketExtractor and assosiated + * array of devices or other filters. When read thread is successfully read + * from device this data can be passed to one or more filters. Each filter + * has name and filter names should be unique. You can use this name for + * access to PIPacketExtractor* with function \a filter(), or get array of + * assosiated devices and filters with function \a filterBoundedDevices(). + * One filter can receive data from several sources, and can be bounded to + * several filters. + * \image html piconnection_filters.png + * + * \section PIConnection_diag Diagnostics + * %PIConnection create PIDiagnostics for each device or filter. You can + * access to these objects with functions \a diagnostic(). + * + * \section PIConnection_sender Senders + * %PIConnection can send data to devices with named timers ("senders"). + * You can create sender or add device to sender with function \a addSender(). + * Each sender has internal timer and every tick execute virtual function + * \a senderData(). Returns value of this function sended to bounded devices. + * You can assign fixed send data to sender with function \a setSenderFixedData(). + * In this case sender will NOT execute \a senderData(), but send assigned data. + * \image html piconnection_senders.png + * + * \section PIConnection_config Configuration + * You can create %PIConnection from config file section or configure + * it later with function \a configureFromConfig(). Devices describes + * with its full pathes, for details see \ref PIIODevice_sec7. Example: + * \image html piconnection_conf.png + * Also %PIConnection can create PIString with its configuration with + * function \a makeConfig(). This string can be directly inserted into the + * config file. + * +*/ + + +PIVector PIConnection::_connections; + + +PIConnection::PIConnection(): PIObject() { + _connections << this; +} + + +PIConnection::PIConnection(const PIString & name): PIObject(name) { + _connections << this; +} + + +PIConnection::PIConnection(const PIString & config, const PIString & name_): PIObject(name_) { + _connections << this; + configureFromConfig(config, name_); +} + + +PIConnection::PIConnection(PIString * string, const PIString & name_): PIObject(name_) { + _connections << this; + configureFromString(string, name_); +} + + +PIConnection::~PIConnection() { + __device_pool__->unboundConnection(this); + removeAllFilters(); + _connections.removeAll(this); +} + + +bool PIConnection::configureFromConfig(const PIString & conf_path, const PIString & name_) { + PIConfig conf(conf_path, PIIODevice::ReadOnly); + return configure(conf, name_); +} + + +bool PIConnection::configureFromString(PIString * string, const PIString & name_) { + PIConfig conf(string, PIIODevice::ReadOnly); + return configure(conf, name_); +} + + +bool PIConnection::configure(PIConfig & conf, const PIString & name_) { + if (!conf.isOpened()) return false; + __device_pool__->unboundConnection(this); + removeAllSenders(); + removeAllChannels(); + removeAllFilters(); + removeAllDevices(); + setName(name_); + PIConfig::Entry ce(conf.getValue(name_)); + PIConfig::Branch db(ce.getValue("device").children()), fb(ce.getValue("filter").children()), + cb(ce.getValue("channel").children()), sb(ce.getValue("sender").children()); + PIStringList dev_list(ce.getValue("device").value()); + PIStringList name_list(ce.getValue("device").name()); + piForeachC (PIConfig::Entry * e, db) { + dev_list << e->value(); + name_list << e->name(); + } + PIMap dev_aliases; + for (int i = 0; i < dev_list.size_s(); ++i) { + PIString fn(dev_list[i]); + if (fn.isEmpty()) continue; + PIString & n(name_list[i]); + PIIODevice::DeviceMode dm = PIIODevice::ReadWrite; + splitFullPathWithMode(fn, &fn, &dm); + //piCout << fn; + PIIODevice * dev = addDevice(fn, dm); + if (!dev) continue; + dev_aliases[n] = fn; + device_names[n] = dev; + setDeviceName(dev, n); + dev->setName(name_ + ".device." + dev_list[i]); + PIDiagnostics * diag = diags_.value(dev, 0); + if (diag != 0) + diag->setDisconnectTimeout(ce.getValue("device." + n + ".disconnectTimeout", diag->disconnectTimeout())); + } + int added(0), padded(-1), tries(0); + bool pdebug = debug(); + setDebug(false); + PIStringList filter_fails; + while (added != padded && tries < 100) { + padded = added; + added = 0; + ++tries; + piForeachC (PIConfig::Entry * e, fb) { + PIPacketExtractor::SplitMode sm = PIPacketExtractor::None; + PIString sms(e->getValue("splitMode").value()); + int smi = sms.toInt(); + if (smi >= 1 && smi <= 5) sm = (PIPacketExtractor::SplitMode)smi; + else { + sms = sms.trim().toLowerCase(); + if (sms.find("header") >= 0 && sms.find("footer") >= 0) + sm = PIPacketExtractor::HeaderAndFooter; + else { + if (sms.find("header") >= 0) + sm = PIPacketExtractor::Header; + else { + if (sms.find("footer") >= 0) + sm = PIPacketExtractor::Footer; + else { + if (sms.find("time") >= 0) + sm = PIPacketExtractor::Timeout; + else { + if (sms.find("size") >= 0) + sm = PIPacketExtractor::Size; + } + } + } + } + } + PIStringList devs(e->value()); + PIConfig::Branch db(e->getValue("device").children()); + devs << e->getValue("device", "").value(); + piForeachC (PIConfig::Entry * e2, db) + devs << e2->value(); + devs.removeStrings(""); + if (devs.isEmpty()) continue; + PIString dname = dev_aliases.value(devs.front(), devs.front()); + PIPacketExtractor * pe = addFilter(e->name(), dname, sm); + if (pe == 0) { + if (!filter_fails.contains(dname)) + filter_fails << dname; + continue; + } else { + filter_fails.removeAll(dname); + } + ++added; + for (int i = 1; i < devs.size_s(); ++i) { + dname = dev_aliases.value(devs[i], devs[i]); + if (addFilter(e->name(), dname, sm) != 0) { + filter_fails.removeAll(dname); + ++added; + } else { + if (!filter_fails.contains(dname)) + filter_fails << dname; + } + } + PIDiagnostics * diag = diags_.value(pe, 0); + if (diag != 0) + diag->setDisconnectTimeout(e->getValue("disconnectTimeout", diag->disconnectTimeout())); + pe->setPayloadSize(e->getValue("payloadSize", pe->payloadSize())); + pe->setPacketSize(e->getValue("packetSize", pe->packetSize())); + pe->setTimeout(e->getValue("timeout", pe->timeout())); + pe->setHeader(PIByteArray::fromString(e->getValue("header", "").value())); + pe->setFooter(PIByteArray::fromString(e->getValue("footer", "").value())); + } + } + setDebug(pdebug); + piForeachC (PIString & f, filter_fails) + piCoutObj << "\"addFilter\" error: no such device \"" << f << "\"!"; + piForeachC (PIConfig::Entry * e, cb) { + PIString f(e->getValue("from").value()), t(e->getValue("to").value()); + addChannel(dev_aliases.value(f, f), dev_aliases.value(t, t)); + } + piForeachC (PIConfig::Entry * e, sb) { + PIStringList devs(e->value()); + PIConfig::Branch db(e->getValue("device").children()); + devs << e->getValue("device", "").value(); + piForeachC (PIConfig::Entry * e2, db) + devs << e2->value(); + devs.removeStrings(""); + if (devs.isEmpty()) continue; + float freq = e->getValue("frequency"); + piForeachC (PIString & d, devs) + addSender(e->name(), dev_aliases.value(d, d), freq); + PIByteArray fd(PIByteArray::fromString(e->getValue("fixedData").value())); + setSenderFixedData(e->name(), fd); + } + return true; +} + + +PIString PIConnection::makeConfig() const { + PIString ret; + ret << "[" << name() << "]\n"; + PIVector devs(boundedDevices()); + int dn(-1); + piForeachC (PIIODevice * d, devs) { + PIStringList dnl(deviceNames(d)); + if (dnl.isEmpty()) dnl << PIString::fromNumber(++dn); + piForeachC (PIString & dname, dnl) { + ret << "device." << dname << " = " << d->constructFullPath(); + if (d->mode() == PIIODevice::ReadOnly) ret << " (ro)"; + if (d->mode() == PIIODevice::WriteOnly) ret << " (wo)"; + ret << " #s\n"; + PIDiagnostics * diag = diags_.value(const_cast(d), 0); + if (diag != 0) + ret << "device." << dname << ".disconnectTimeout = " << diag->disconnectTimeout() << " #f\n"; + } + } + piForeachC (PEPair & f, extractors) { + if (f.second == 0) continue; + if (f.second->extractor == 0) continue; + PIString prefix = "filter." + f.first; + for (int i = 0; i < f.second->devices.size_s(); ++i) + ret << prefix << ".device." << i << " = " << devPath(f.second->devices[i]) << " #s\n"; + PIDiagnostics * diag = diags_.value(f.second->extractor, 0); + if (diag != 0) + ret << prefix << ".disconnectTimeout = " << diag->disconnectTimeout() << " #f\n"; + ret << prefix << ".splitMode = "; + switch (f.second->extractor->splitMode()) { + case PIPacketExtractor::None: ret << "none"; break; + case PIPacketExtractor::Header: ret << "header"; break; + case PIPacketExtractor::Footer: ret << "footer"; break; + case PIPacketExtractor::HeaderAndFooter: ret << "header & footer"; break; + case PIPacketExtractor::Size: ret << "size"; break; + case PIPacketExtractor::Timeout: ret << "timeout"; break; + } + ret << " #s\n"; + ret << prefix << ".payloadSize = " << f.second->extractor->payloadSize() << " #n\n"; + ret << prefix << ".packetSize = " << f.second->extractor->packetSize() << " #n\n"; + ret << prefix << ".timeout = " << f.second->extractor->timeout() << " #f\n"; + ret << prefix << ".header = " << f.second->extractor->header().toString() << " #s\n"; + ret << prefix << ".footer = " << f.second->extractor->footer().toString() << " #s\n"; + } + dn = 0; + piForeachC (CPair & c, channels_) { + piForeachC (PIIODevice * d, c.second) { + PIString prefix = "channel." + PIString::fromNumber(dn); ++dn; + ret << prefix << ".from = " << devPath(c.first) << " #s\n"; + ret << prefix << ".to = " << devPath(d) << " #s\n"; + } + } + piForeachC (SPair & s, senders) { + if (s.second == 0) continue; + PIString prefix = "sender." + s.second->name(); + for (int i = 0; i < s.second->devices.size_s(); ++i) + ret << prefix << ".device." << i << " = " << devPath(s.second->devices[i]) << " #s\n"; + double int_ = s.second->int_; + if (int_ > 0.) + ret << prefix << ".frequency = " << (1000. / int_) << " #f\n"; + if (!s.second->sdata.isEmpty()) + ret << prefix << ".fixedData = " << s.second->sdata.toString() << " #s\n"; + } + ret << "[]\n"; + return ret; +} + + +PIIODevice * PIConnection::addDevice(const PIString & full_path, PIIODevice::DeviceMode mode, bool start) { + PIString fp(PIIODevice::normalizeFullPath(full_path)); + PIIODevice * dev = __device_pool__->addDevice(this, fp, mode, start); + if (dev) { + dev->setName(name() + ".device." + fp); + device_modes[dev] = mode; + __device_pool__->lock(); + if (diags_.value(dev, 0) == 0) { + PIDiagnostics * d = new PIDiagnostics(false); + diags_[dev] = d; + CONNECTU(d, qualityChanged, this, diagQualityChanged); + } + __device_pool__->unlock(); + } + return dev; +} + + +PIStringList PIConnection::deviceNames(const PIIODevice *dev) const { + PIStringList ret; + piForeachC (DNPair & s, device_names) + if (s.second == dev) + ret << s.first; + return ret; +} + + +bool PIConnection::removeDevice(const PIString & full_path) { + PIString fp(PIIODevice::normalizeFullPath(full_path)); + PIIODevice * dev = __device_pool__->device(fp); + if (dev == 0) return false; + PIStringList dntd(deviceNames(dev)); + piForeachC (PIString & n, dntd) + device_names.removeOne(n); + piForeachC (SPair & s, senders) { + if (s.second == 0) continue; + s.second->lock(); + s.second->devices.removeAll(dev); + s.second->unlock(); + } + device_modes.remove(dev); + piForeachC (PEPair & i, extractors) { + if (i.second == 0) continue; + i.second->devices.removeAll(dev); + } + bounded_extractors.remove(dev); + channels_.remove(dev); + for (PIMap >::iterator it = channels_.begin(); it != channels_.end(); ++it) + it.value().removeAll(dev); + __device_pool__->lock(); + if (diags_.value(dev, 0) != 0) + delete diags_.value(dev); + diags_.remove(dev); + __device_pool__->unlock(); + return __device_pool__->removeDevice(this, fp); +} + + +void PIConnection::removeAllDevices() { + device_names.clear(); + PIVector bdevs(__device_pool__->boundedDevices(this)); + __device_pool__->lock(); + piForeach (PIIODevice * d, bdevs) { + piForeachC (SPair & s, senders) { + if (s.second == 0) continue; + s.second->lock(); + s.second->devices.removeAll(d); + s.second->unlock(); + } + channels_.remove(d); + for (PIMap >::iterator it = channels_.begin(); it != channels_.end(); ++it) + it.value().removeAll(d); + if (diags_.value(d, 0) != 0) + delete diags_.value(d); + diags_.remove(d); + } + __device_pool__->unboundConnection(this); + __device_pool__->unlock(); + device_modes.clear(); + bounded_extractors.clear(); + piForeachC (PEPair & i, extractors) { + if (i.second == 0) continue; + i.second->devices.clear(); + } +} + + +PIIODevice * PIConnection::deviceByFullPath(const PIString & full_path) const { + PIString fp(PIIODevice::normalizeFullPath(full_path)); + DevicePool::DeviceData * dd = __device_pool__->devices.value(fp); + if (dd == 0) return 0; + if (dd->dev == 0) return 0; + if (!dd->listeners.contains(const_cast(this))) return 0; + return dd->dev; +} + + +PIIODevice * PIConnection::deviceByName(const PIString & name) const { + return device_names.value(name, 0); +} + + +PIVector PIConnection::boundedDevices() const { + return __device_pool__->boundedDevices(this); +} + + +PIPacketExtractor * PIConnection::addFilter(const PIString & name_, const PIString & full_path, PIPacketExtractor::SplitMode mode) { + PIString fp(PIIODevice::normalizeFullPath(full_path)); + PIString fname_ = name_.trimmed(); + Extractor * e = extractors.value(fname_); + if (full_path.isEmpty()) return (e == 0 ? 0 : e->extractor); + PIIODevice * dev = deviceByFullPath(fp); + PIPacketExtractor * pe(0); + if (extractors.value(full_path) != 0) pe = extractors.value(full_path)->extractor; + if (pe != 0) dev = pe; + if (dev == 0) { + piCoutObj << "\"addFilter\" error: no such device \"" << full_path << "\"!"; + return 0; + } + if (e == 0) { + e = new Extractor(); + extractors[fname_] = e; + } + if (e->extractor == 0) { + e->extractor = new PIPacketExtractor(0, mode); + e->extractor->setName(fname_); + e->extractor->setThreadedReadData(new PIPair(this, fname_)); + e->extractor->setHeaderCheckSlot(filterValidateHeaderS); + e->extractor->setFooterCheckSlot(filterValidateFooterS); + e->extractor->setPayloadCheckSlot(filterValidatePayloadS); + __device_pool__->lock(); + if (diags_.value(e->extractor, 0) == 0) { + PIDiagnostics * d = new PIDiagnostics(false); + diags_[e->extractor] = d; + CONNECTU(d, qualityChanged, this, diagQualityChanged); + } + __device_pool__->unlock(); + CONNECT2(void, uchar * , int, e->extractor, packetReceived, this, packetExtractorReceived) + } + if (!e->devices.contains(dev)) { + bounded_extractors[dev] << e->extractor; + //if (PIString(dev->className()) == "PIPacketExtractor") dev->setThreadSafe(false); + e->devices << dev; + } + return e->extractor; +} + + +bool PIConnection::removeFilter(const PIString & name_, const PIString & full_path) { + PIString fp(PIIODevice::normalizeFullPath(full_path)); + Extractor * p = extractors.value(name_.trimmed()); + if (p == 0) return false; + bool ret = false; + for (int i = 0; i < p->devices.size_s(); ++i) { + if (devFPath(p->devices[i]) == fp || devFPath(p->devices[i]) == full_path) { + bounded_extractors[p->devices[i]].removeAll(p->extractor); + p->devices.remove(i); + --i; + ret = true; + } + } + if (p->devices.isEmpty()) { + unboundExtractor(p->extractor); + delete p; + } + return ret; +} + + +bool PIConnection::removeFilter(const PIString & name, const PIIODevice * dev) { + if (dev == 0) return false; + return removeFilter(name, devFPath(dev)); +} + + +bool PIConnection::removeFilter(const PIString & name_) { + Extractor * p = extractors.value(name_.trimmed()); + if (p == 0) return false; + unboundExtractor(p->extractor); + delete p; + return true; +} + + +void PIConnection::removeAllFilters() { + __device_pool__->lock(); + piForeachC (PEPair & i, extractors) { + if (i.second == 0) continue; + channels_.remove(i.second->extractor); + for (PIMap >::iterator it = channels_.begin(); it != channels_.end(); ++it) + it.value().removeAll(i.second->extractor); + if (diags_.value(i.second->extractor, 0) != 0) + delete diags_.value(i.second->extractor); + diags_.remove(i.second->extractor); + delete i.second; + } + extractors.clear(); + bounded_extractors.clear(); + __device_pool__->unlock(); +} + + +PIVector PIConnection::filters() const { + PIVector ret; + piForeachC (PEPair & i, extractors) + if (i.second != 0) + if (i.second->extractor != 0) ret << i.second->extractor; + return ret; +} + + +PIStringList PIConnection::filterNames() const { + PIStringList ret; + piForeachC (PEPair & i, extractors) + if (i.second != 0) + if (i.second->extractor != 0) ret << i.first; + return ret; +} + + +PIPacketExtractor * PIConnection::filter(const PIString & name_) const { + PIString fname_ = name_.trimmed(); + piForeachC (PEPair & i, extractors) + if (i.second != 0) + if (i.second->extractor != 0 && i.first == fname_) + return i.second->extractor; + return 0; +} + + +PIVector PIConnection::filterBoundedDevices(const PIString & name_) const { + PIVector ret; + Extractor * p = extractors.value(name_.trimmed()); + if (p == 0) return ret; + return p->devices; +} + + +bool PIConnection::addChannel(const PIString & name0, const PIString & name1) { + //piCout << "addChannel" << name0 << name1; + if (name0.isEmpty() || name1.isEmpty()) return false; + PIIODevice * dev0 = deviceByFullPath(name0), * dev1 = deviceByFullPath(name1); + PIPacketExtractor * pe0(0), * pe1(0); + if (extractors.value(name0) != 0) pe0 = extractors.value(name0)->extractor; + if (extractors.value(name1) != 0) pe1 = extractors.value(name1)->extractor; + if (pe0 != 0) dev0 = pe0; + if (pe1 != 0) dev1 = pe1; + if (dev0 == 0 || dev1 == 0) { + if (dev0 == 0) piCoutObj << "\"addChannel\" error: no such device \"" << name0 << "\"!"; + if (dev1 == 0) piCoutObj << "\"addChannel\" error: no such device \"" << name1 << "\"!"; + return false; + } + if (!channels_[dev0].contains(dev1)) + channels_[dev0] << dev1; + return true; +} + + +bool PIConnection::removeChannel(const PIString & name0, const PIString & name1) { + PIIODevice * dev0 = deviceByFullPath(name0), * dev1 = deviceByFullPath(name1); + PIPacketExtractor * pe0(0), * pe1(0); + if (extractors.value(name0) != 0) pe0 = extractors.value(name0)->extractor; + if (extractors.value(name1) != 0) pe1 = extractors.value(name1)->extractor; + if (pe0 != 0) dev0 = pe0; + if (pe1 != 0) dev1 = pe1; + if (dev0 == 0 || dev1 == 0) return false; + channels_[dev0].removeAll(dev1); + return true; +} + + +bool PIConnection::removeChannel(const PIString & name0) { + PIIODevice * dev0 = deviceByFullPath(name0); + PIPacketExtractor * pe0(0); + if (extractors.value(name0) != 0) pe0 = extractors.value(name0)->extractor; + if (pe0 != 0) dev0 = pe0; + if (dev0 == 0) return false; + channels_.remove(dev0); + for (PIMap >::iterator it = channels_.begin(); it != channels_.end(); ++it) + it.value().removeAll(dev0); + return true; +} + + +void PIConnection::removeAllChannels() { + channels_.clear(); +} + + +PIString PIConnection::devPath(const PIIODevice * d) const { + if (d == 0) return PIString(); + if (strcmp(d->className(), "PIPacketExtractor") == 0) return d->name(); + return d->constructFullPath(); +} + + +PIString PIConnection::devFPath(const PIIODevice * d) const { + if (d == 0) return PIString(); + if (d->isPropertyExists("__fullPath__")) return d->property("__fullPath__").toString(); + return d->name(); +} + + +PIVector > PIConnection::channels() const { + PIVector > ret; + piForeachC (CPair & i, channels_) { + PIString fp0(devFPath(i.first)); + piForeachC (PIIODevice * d, i.second) + ret << PIPair(fp0, devFPath(d)); + } + return ret; +} + + +void PIConnection::addSender(const PIString & name_, const PIString & full_path, float frequency, bool start_) { + PIString fp(PIIODevice::normalizeFullPath(full_path)); + PIString fname_ = name_.trimmed(); + if (fp.isEmpty() || frequency <= 0.) return; + Sender * s = senders.value(fname_); + PIIODevice * dev = deviceByFullPath(fp); + if (s == 0) { + s = new Sender(this); + s->setName(fname_); + s->int_ = 1000. / frequency; + senders[fname_] = s; + } + if (dev == 0) { + piCoutObj << "\"addSender\" error: no such device \"" << full_path << "\"!"; + return; + } + if (!s->isRunning() && start_) { + //piCoutObj << name_ << "start" << 1000. / frequency; + if (!__device_pool__->fake) s->start(s->int_); + } + s->lock(); + if (!s->devices.contains(dev)) + s->devices << dev; + s->unlock(); +} + + +bool PIConnection::removeSender(const PIString & name, const PIString & full_path) { + PIString fp(PIIODevice::normalizeFullPath(full_path)); + Sender * s = senders.value(name, 0); + PIIODevice * d = deviceByFullPath(fp); + if (s == 0 || d == 0) return false; + s->lock(); + bool ret = s->devices.contains(d); + if (ret) + s->devices.removeAll(d); + s->unlock(); + return ret; +} + + +bool PIConnection::removeSender(const PIString & name) { + Sender * s = senders.value(name, 0); + if (s == 0) return false; + delete s; + senders.remove(name); + return true; +} + + +bool PIConnection::setSenderFixedData(const PIString & name, const PIByteArray & data) { + Sender * s = senders.value(name, 0); + if (s == 0) return false; + s->lock(); + s->sdata = data; + s->unlock(); + return true; +} + + +bool PIConnection::clearSenderFixedData(const PIString & name) { + Sender * s = senders.value(name, 0); + if (s == 0) return false; + s->lock(); + s->sdata.clear(); + s->unlock(); + return true; +} + + +PIByteArray PIConnection::senderFixedData(const PIString & name) const { + Sender * s = senders.value(name, 0); + if (s == 0) return PIByteArray(); + return s->sdata; +} + + +float PIConnection::senderFrequency(const PIString & name) const { + Sender * s = senders.value(name, 0); + if (s == 0) return -1.f; + double i = s->interval(); + if (i == 0.) return 0.f; + return 1000. / s->interval(); +} + + +void PIConnection::removeAllSenders() { + piForeachC (SPair & s, senders) + if (s.second != 0) + delete s.second; + senders.clear(); +} + + +void PIConnection::startThreadedRead(const PIString & full_path) { + PIString fp(PIIODevice::normalizeFullPath(full_path)); + DevicePool::DeviceData * dd = __device_pool__->devices.value(fp, 0); + if (dd == 0) return; + if (dd->dev == 0) return; + if (dd->started || dd->dev->mode() == PIIODevice::WriteOnly) return; + if (!__device_pool__->fake) dd->rthread->start(); + dd->started = true; +} + + +void PIConnection::startAllThreadedReads() { + piForeachC (DevicePool::DDPair & d, __device_pool__->devices) + startThreadedRead(d.first); +} + + +void PIConnection::startSender(const PIString & name) { + Sender * s = senders.value(name, 0); + if (s == 0) return; + if (!s->isRunning() && !__device_pool__->fake) + s->start(s->int_); +} + + +void PIConnection::startAllSenders() { + piForeachC (SPair & s, senders) { + if (s.second == 0) continue; + if (!s.second->isRunning() && !__device_pool__->fake) + s.second->start(s.second->int_); + } +} + + +void PIConnection::stopThreadedRead(const PIString & full_path) { + PIString fp(PIIODevice::normalizeFullPath(full_path)); + DevicePool::DeviceData * dd = __device_pool__->devices.value(fp, 0); + if (dd == 0) return; + if (dd->dev == 0) return; + if (!dd->started || dd->dev->mode() == PIIODevice::WriteOnly) return; + dd->rthread->stop(); + dd->started = false; +} + + +void PIConnection::stopAllThreadedReads() { + piForeachC (DevicePool::DDPair & d, __device_pool__->devices) + stopThreadedRead(d.first); +} + + +void PIConnection::stopSender(const PIString & name) { + Sender * s = senders.value(name, 0); + if (s == 0) return; + if (s->isRunning()) s->stop(); +} + + +void PIConnection::stopAllSenders() { + piForeachC (SPair & s, senders) { + if (s.second == 0) continue; + if (s.second->isRunning()) + s.second->stop(); + } +} + + +PIDiagnostics * PIConnection::diagnostic(const PIString & full_path_name) const { + PIIODevice * dev = deviceByFullPath(full_path_name); + if (dev == 0) dev = device_names.value(full_path_name, 0); + PIPacketExtractor * pe(0); + if (extractors.value(full_path_name) != 0) pe = extractors.value(full_path_name)->extractor; + if (pe != 0) dev = pe; + if (dev == 0) return 0; + return diags_.value(dev, 0); +} + + +int PIConnection::writeByFullPath(const PIString & full_path, const PIByteArray & data) { + PIString fp(full_path); + if (fp.endsWith(")")) + splitFullPathWithMode(fp, &fp, 0); + fp = PIIODevice::normalizeFullPath(fp); + PIIODevice * dev = __device_pool__->device(fp); + //piCout << "SEND" << full_path << fp; + return write(dev, data); +} + + +int PIConnection::writeByName(const PIString & name, const PIByteArray & data) { + PIIODevice * dev = deviceByName(name); + return write(dev, data); +} + + +int PIConnection::write(PIIODevice * dev, const PIByteArray & data) { + if (dev == 0) { + piCoutObj << "Null Device!"; + return -1; + } + if (!dev->canWrite()) { + piCoutObj << "Device \"" << dev->constructFullPath() << "\" can`t write!"; + return -1; + } + int ret = dev->write(data); + PIDiagnostics * diag = diags_.value(dev); + if (diag != 0 && ret > 0) diag->sended(ret); + return ret; +} + + +PIVector< PIConnection * > PIConnection::allConnections() { + return _connections; +} + + +PIVector< PIIODevice * > PIConnection::allDevices() { + return __device_pool__->boundedDevices(); +} + + +bool PIConnection::setFakeMode(bool yes) { + bool ret = isFakeMode(); + __device_pool__->fake = yes; + return ret; +} + + +bool PIConnection::isFakeMode() { + return __device_pool__->fake; +} + + + + +PIIODevice * PIConnection::DevicePool::addDevice(PIConnection * parent, const PIString & fp, PIIODevice::DeviceMode mode, bool start) { + DeviceData * dd = devices[fp]; + int pmode(0); + bool need_start = false; + if (dd == 0) { + dd = new DeviceData(); + devices[fp] = dd; + } + if (dd->dev == 0) { + //piCout << "new device" << fp; + dd->dev = PIIODevice::createFromFullPath(fp); + if (dd->dev == 0) { + piCoutObj << "Error: can`t create device \"" << fp << "\"!"; //:" << errorString(); + return 0; + } + dd->dev->setProperty("__fullPath__", fp); + } else + pmode = dd->dev->mode(); + if (!dd->listeners.contains(parent)) + dd->listeners << parent; + if (pmode == mode || pmode == PIIODevice::ReadWrite) + return dd->dev; + if ((mode & PIIODevice::ReadOnly) > 0) { + if (dd->rthread != 0) { + delete dd->rthread; + dd->rthread = 0; + dd->started = false; + } + dd->rthread = new PIThread(dd, threadReadDP); + dd->rthread->setName("__S__connection_" + fp + "_read_thread"); + need_start = true; + pmode |= PIIODevice::ReadOnly; + } + if ((mode & PIIODevice::WriteOnly) > 0) + pmode |= PIIODevice::WriteOnly; + if (!fake) { + dd->dev->close(); + dd->dev->open((PIIODevice::DeviceMode)pmode); + } + if (need_start && start) { + if (!fake) dd->rthread->start(); + dd->started = true; + } + return dd->dev; +} + + +bool PIConnection::DevicePool::removeDevice(PIConnection * parent, const PIString & fp) { + DeviceData * dd = devices.value(fp); + if (dd == 0) + return false; + if (dd->dev == 0) + return false; + bool ok = dd->listeners.contains(parent); + dd->listeners.removeAll(parent); + if (dd->listeners.isEmpty()) { + delete dd; + devices.remove(fp); + } + return ok; +} + + +void PIConnection::DevicePool::unboundConnection(PIConnection * parent) { + PIStringList rem; + piForeachC (DDPair & i, devices) { + if (i.second == 0) { + rem << i.first; + continue; + } + i.second->listeners.removeAll(parent); + if (i.second->listeners.isEmpty()) + rem << i.first; + } + piForeachC (PIString & i, rem) { + DeviceData * dd = devices.value(i); + if (dd == 0) + continue; + delete dd; + devices.remove(i); + } +} + + +PIIODevice * PIConnection::DevicePool::device(const PIString & fp) const { + DeviceData * dd = devices.value(fp); + if (dd == 0) return 0; + return dd->dev; +} + + +PIVector PIConnection::DevicePool::boundedConnections() const { + PIVector ret; + piForeachC (DDPair & i, devices) { + if (i.second == 0) + continue; + ret << i.second->listeners; + } + for (int i = 0; i < ret.size_s(); ++i) + for (int j = i + 1; j < ret.size_s(); ++j) + if (ret[i] == ret[j]) { + ret.remove(j); + --j; + } + return ret; +} + + +PIVector< PIIODevice * > PIConnection::DevicePool::boundedDevices() const { + PIVector ret; + piForeachC (DDPair & i, devices) { + if (i.second == 0) continue; + if (i.second->dev == 0) continue; + ret << i.second->dev; + } + return ret; +} + + +PIVector PIConnection::DevicePool::boundedDevices(const PIConnection * parent) const { + PIVector ret; + piForeachC (DDPair & i, devices) { + if (i.second == 0) continue; + if (i.second->dev == 0) continue; + if (i.second->listeners.contains(const_cast(parent))) + ret << i.second->dev; + } + return ret; +} + + +PIConnection::DevicePool::DeviceData::~DeviceData() { + if (rthread != 0) { + rthread->stop(); + delete rthread; + rthread = 0; + } + if (dev != 0) { + delete dev; + dev = 0; + } +} + + +void PIConnection::DevicePool::run() { + PIVector conns(PIConnection::allConnections()); + piForeach (PIConnection * c, conns) { + piForeachC (PIConnection::DPair & d, c->diags_) { + if (d.second == 0) continue; + d.second->tick(0, 1); + } + } +} + + +void PIConnection::DevicePool::threadReadDP(void * ddp) { + DeviceData * dd((DeviceData * )ddp); + if (dd->dev == 0) {piMSleep(100); return;} + PIByteArray ba; + ba = dd->dev->read(dd->dev->threadedReadBufferSize()); + if (ba.isEmpty()) {piMSleep(10); return;} + //piCout << "Readed from" << dd->dev->path() << Hex << ba; + __device_pool__->deviceReaded(dd, ba); +} + + +void PIConnection::DevicePool::deviceReaded(PIConnection::DevicePool::DeviceData * dd, const PIByteArray & data) { + PIString from = dd->dev->property("__fullPath__").toString(); + piForeach (PIConnection * ld, dd->listeners) + ld->rawReceived(dd->dev, from, data); +} + + +void PIConnection::splitFullPathWithMode(PIString fpwm, PIString * full_path, PIIODevice::DeviceMode * mode) { + PIIODevice::DeviceMode dm = PIIODevice::ReadWrite; + if (fpwm.find("(") > 0 && fpwm.find(")") > 0) { + PIString dms(fpwm.right(fpwm.length() - fpwm.find("(")).takeRange("(", ")").trim().toLowerCase().removeAll(" ")); + //piCout << dms; + if (dms == "r" || dms == "ro" || dms == "read" || dms == "readonly") + dm = PIIODevice::ReadOnly; + if (dms == "w" || dms == "wo" || dms == "write" || dms == "writeonly") + dm = PIIODevice::WriteOnly; + fpwm.cutRight(fpwm.length() - fpwm.find("(") + 1).trim(); + } + if (full_path) *full_path = fpwm; + if (mode) *mode = dm; +} + + +bool PIConnection::filterValidateHeaderS(void * c, uchar * src, uchar * rec, int size) { + PIPair * p((PIPair * )c); + return p->first->filterValidateHeader(p->second, src, rec, size); +} + + +bool PIConnection::filterValidateFooterS(void * c, uchar * src, uchar * rec, int size) { + PIPair * p((PIPair * )c); + return p->first->filterValidateFooter(p->second, src, rec, size); +} + + +bool PIConnection::filterValidatePayloadS(void * c, uchar * rec, int size) { + PIPair * p((PIPair * )c); + return p->first->filterValidatePayload(p->second, rec, size); +} + + +void PIConnection::rawReceived(PIIODevice * dev, const PIString & from, const PIByteArray & data) { + dataReceived(from, data); + dataReceivedEvent(from, data); + PIVector be(bounded_extractors.value(dev)); + //piCout << be; + piForeach (PIPacketExtractor * i, be) + i->threadedRead(const_cast(data.data()), data.size_s()); + PIVector chd(channels_.value(dev)); + piForeach (PIIODevice * d, chd) { + int ret = d->write(data); + PIDiagnostics * diag = diags_.value(d); + if (diag != 0 && ret > 0) diag->sended(ret); + } + PIDiagnostics * diag = diags_.value(dev); + if (diag != 0) diag->received(data.size_s()); +} + + +bool PIConnection::filterValidateHeader(const PIString & filter_name, uchar * src, uchar * rec, int size) { + for (int i = 0; i < size; ++i) + if (src[i] != rec[i]) + return false; + return true; +} + + +bool PIConnection::filterValidateFooter(const PIString & filter_name, uchar * src, uchar * rec, int size) { + for (int i = 0; i < size; ++i) + if (src[i] != rec[i]) + return false; + return true; +} + + +bool PIConnection::filterValidatePayload(const PIString & filter_name, uchar * rec, int size) { + return true; +} + + +PIByteArray PIConnection::senderData(const PIString & sender_name) { + return PIByteArray(); +} + + +PIConnection::Extractor::~Extractor() { + if (extractor != 0) { + if (extractor->threadedReadData() != 0) + delete (PIPair * )(extractor->threadedReadData()); + delete extractor; + extractor = 0; + } +} + + +void PIConnection::Sender::tick(void * , int) { + if (parent == 0) return; + PIByteArray data; + if (!sdata.isEmpty()) data = sdata; + else data = parent->senderData(name()); + if (data.isEmpty()) return; + //piCoutObj << "write"<write(data); + PIDiagnostics * diag = parent->diags_.value(d); + if (diag != 0 && ret > 0) diag->sended(ret); + } +} + + +void PIConnection::unboundExtractor(PIPacketExtractor * pe) { + if (pe == 0) return; + channels_.remove(pe); + for (PIMap >::iterator it = channels_.begin(); it != channels_.end(); ++it) + it.value().removeAll(pe); + bounded_extractors.remove(pe); + PIVector k = bounded_extractors.keys(); + piForeach (PIIODevice * i, k) { + PIVector & be(bounded_extractors[i]); + be.removeAll(pe); + if (be.isEmpty()) + bounded_extractors.remove(i); + } + __device_pool__->lock(); + if (diags_.value(pe, 0) != 0) + delete diags_.value(pe); + diags_.remove(pe); + extractors.remove(pe->name()); + __device_pool__->unlock(); +} + + +void PIConnection::packetExtractorReceived(uchar * data, int size) { + PIString from(emitter() == 0 ? "" : emitter()->name()); + packetReceived(from, PIByteArray(data, size)); + packetReceivedEvent(from, PIByteArray(data, size)); + PIIODevice * cd = (PIIODevice * )emitter(); + if (cd == 0) return; + PIVector be(bounded_extractors.value(cd)); + //piCout << be << (void*)data << size; + piForeach (PIPacketExtractor * i, be) + i->threadedRead(data, size); + PIVector chd(channels_.value(cd)); + piForeach (PIIODevice * d, chd) { + int ret = d->write(data, size); + PIDiagnostics * diag = diags_.value(d); + if (diag != 0) diag->sended(ret); + } + PIDiagnostics * diag = diags_.value(cd); + if (diag != 0) diag->received(size); +} + + +void PIConnection::diagQualityChanged(PIDiagnostics::Quality new_quality, PIDiagnostics::Quality old_quality) { + qualityChanged(diags_.key((PIDiagnostics*)emitter()), new_quality, old_quality); +} + + + +PIConnection::DevicePool * __device_pool__; + +bool __DevicePoolContainer__::inited_(false); + +__DevicePoolContainer__::__DevicePoolContainer__() { + if (inited_) return; + inited_ = true; + __device_pool__ = new PIConnection::DevicePool(); +} diff --git a/src/io/piconnection.h b/src/io/piconnection.h new file mode 100755 index 00000000..f4d94fc0 --- /dev/null +++ b/src/io/piconnection.h @@ -0,0 +1,417 @@ +/*! \file piconnection.h + * \brief Complex I/O point +*/ +/* + PIP - Platform Independent Primitives + Complex I/O point + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PICONNECTION_H +#define PICONNECTION_H + +#include "pipacketextractor.h" +#include "pidiagnostics.h" + +class PIConfig; + +class PIP_EXPORT PIConnection: public PIObject +{ + PIOBJECT(PIConnection) +public: + + //! Constructs an empty connection + PIConnection(); + + //! Constructs connection with name "name" + PIConnection(const PIString & name); + + //! Constructs connection and configure it from config file "config" from section "name" + PIConnection(const PIString & config, const PIString & name); + + //! Constructs connection and configure it from config content "string" from section "name" + PIConnection(PIString * string, const PIString & name); + + ~PIConnection(); + + + /*! \brief Configure connection from config file "config" from section "name". Returns if configuration was successful + * \details \b Warning: all devices, filters and channels removed before configure! */ + bool configureFromConfig(const PIString & config, const PIString & name); + + /*! \brief Configure connection from config content "string" from section "name". Returns if configuration was successful + * \details \b Warning: all devices, filters and channels removed before configure! */ + bool configureFromString(PIString * string, const PIString & name); + + //! Returns config file section of current connection configuration + PIString makeConfig() const; + + + /*! \brief Add device with full path "full_path", open mode "mode" to Device pool and connection + * \details Returns pointer to device or null if device can not be created. If "start" is true, + * read thread is started immediately. Else, you can start read thread with functions \a startThreadedRead() + * or \a startAllThreadedReads(). By default, read thread doesn`t start */ + PIIODevice * addDevice(const PIString & full_path, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite, bool start = false); + + void setDeviceName(PIIODevice * dev, const PIString & name) {device_names[name] = dev;} + + PIStringList deviceNames(const PIIODevice * dev) const; + + /*! \brief Remove device with full path "full_path" from connection + * \details Returns if device was removed. If there is no connection bounded to this device, + * it will be removed from Device pool */ + bool removeDevice(const PIString & full_path); + + /*! \brief Remove all device from connection + * \details If there is no connection bounded to there devices, they removed from Device pool */ + void removeAllDevices(); + + //! Returns device with full path "full_path" or null if there is no such device + PIIODevice * deviceByFullPath(const PIString & full_path) const; + + //! Returns device with name "name" or null if there is no such device + PIIODevice * deviceByName(const PIString & name) const; + + //! Returns all devices bounded to this connection + PIVector boundedDevices() const; + + + /*! \brief Add filter with name "name" to device with full path "full_path_name" or filter "full_path_name" + * \details If there is no filter with name "name", connection create new with split mode "mode" and bound + * to it device "full_path_name" or filter "full_path_name". If filter with name "name" already exists, + * device "full_path_name" or filter "full_path_name" add to this filter. + * This function returns PIPacketExtractor * assosiated with this filter + * \n \b Attention! "mode" is altual olny if new filter was created! */ + PIPacketExtractor * addFilter(const PIString & name, const PIString & full_path_name, PIPacketExtractor::SplitMode mode = PIPacketExtractor::None); + + //! Add filter with name "name" to device "dev" + PIPacketExtractor * addFilter(const PIString & name, const PIIODevice * dev, PIPacketExtractor::SplitMode mode = PIPacketExtractor::None) {return addFilter(name, devFPath(dev), mode);} + + /*! \brief Remove from filter with name "name" device with full path "full_path_name" or filter "full_path_name" + * \details If there is no devices bounded to this filter, it will be removed. Returns if device was removed */ + bool removeFilter(const PIString & name, const PIString & full_path_name); + + //! Remove from filter with name "name" device or filter "dev" + bool removeFilter(const PIString & name, const PIIODevice * dev); + + //! Remove filter with name "name". Returns if filter was removed + bool removeFilter(const PIString & name); + + //! Remove all filters from connection + void removeAllFilters(); + + + //! Returns all filters of connection + PIVector filters() const; + + //! Returns all filter names of connection + PIStringList filterNames() const; + + //! Returns PIPacketExtractor * assosiated with filter "name" or null if there is no such filter + PIPacketExtractor * filter(const PIString & name) const; + + //! Returns all devices bounded to filter "name" + PIVector filterBoundedDevices(const PIString & name) const; + + + /*! \brief Add to connection channel from "name_from" to "name_to" + * \details "name_from" and "name_to" can be full pathes of devices or filter names. + * Returns \b false if there if no such device or filter, else create channel and returns \b true */ + bool addChannel(const PIString & name_from, const PIString & name_to); + + //! Add to connection channel from "name_from" to "dev_to" + bool addChannel(const PIString & name_from, const PIIODevice * dev_to) {return addChannel(name_from, devFPath(dev_to));} + + //! Add to connection channel from "dev_from" to "name_to" + bool addChannel(const PIIODevice * dev_from, const PIString & name_to) {return addChannel(devFPath(dev_from), name_to);} + + //! Add to connection channel from "dev_from" to "dev_to" + bool addChannel(const PIIODevice * dev_from, const PIIODevice * dev_to) {return addChannel(devFPath(dev_from), devFPath(dev_to));} + + /*! \brief Remove from connection channel from "name_from" to "name_to" + * \details "name_from" and "name_to" can be full pathes of devices or filter names. + * Returns \b false if there if no such device or filter, else remove channel and returns \b true */ + bool removeChannel(const PIString & name_from, const PIString & name_to); + + //! Remove from connection channel from "name_from" to "dev_to" + bool removeChannel(const PIString & name_from, const PIIODevice * dev_to) {return removeChannel(name_from, devFPath(dev_to));} + + //! Remove from connection channel from "dev_from" to "name_to" + bool removeChannel(const PIIODevice * dev_from, const PIString & name_to) {return removeChannel(devFPath(dev_from), name_to);} + + //! Remove from connection channel from "dev_from" to "dev_to" + bool removeChannel(const PIIODevice * dev_from, const PIIODevice * dev_to) {return removeChannel(devFPath(dev_from), devFPath(dev_to));} + + /*! \brief Remove from connection all channels from "name_from" + * \details "name_from" can be full path of device or filter name. + * Returns \b false if there if no such device or filter, else remove channels and returns \b true */ + bool removeChannel(const PIString & name_from); + + //! Remove from connection all channels from "dev_from" + bool removeChannel(const PIIODevice * dev_from) {return removeChannel(devFPath(dev_from));} + + //! Remove from connection all channels + void removeAllChannels(); + + //! Returns all channels of this connection as full pathes or filter names pair array (from, to) + PIVector > channels() const; + + + /*! \brief Add to connection sender with name "name" device with full path "full_path" + * \details If there is no sender with name "name", connection create new, bound + * to it device "full_path_name" and start sender timer with frequency "frequency". + * If sender with name "name" already exists, device "full_path_name" add to this sender + * If "start" is true, sender is started immediately. Else, you can start sender with + * functions \a startSender() + * \n \b Attention! "frequency" is actual olny if new sender was created! */ + void addSender(const PIString & name, const PIString & full_path, float frequency, bool start = false); + + //! Add to connection sender with name "name" device "dev" + void addSender(const PIString & name, const PIIODevice * dev, float frequency, bool start = false) {addSender(name, devFPath(dev), frequency, start);} + + /*! \brief Remove from sender with name "name" device with full path "full_path_name" + * \details If there is no devices bounded to this sender, it will be removed. Returns if sender was removed */ + bool removeSender(const PIString & name, const PIString & full_path); + + //! Remove from sender with name "name" device "dev" + bool removeSender(const PIString & name, const PIIODevice * dev) {return removeSender(name, devFPath(dev));} + + //! Remove sender with name "name", returns if sender was removed + bool removeSender(const PIString & name); + + //! Set sender "name" fixed send data "data", returns if sender exists + bool setSenderFixedData(const PIString & name, const PIByteArray & data); + + //! Remove sender "name" fixed send data, returns if sender exists + bool clearSenderFixedData(const PIString & name); + + //! Returns sender "name" fixed send data + PIByteArray senderFixedData(const PIString & name) const; + + //! Returns sender "name" timer frequency, -1 if there is no such sender, or 0 if sender is not started yet + float senderFrequency(const PIString & name) const; + + //! Remove from connection all senders + void removeAllSenders(); + + + //! Start read thread of device with full path "full_path" + void startThreadedRead(const PIString & full_path); + + //! Start read thread of device "dev" + void startThreadedRead(const PIIODevice * dev) {startThreadedRead(devFPath(dev));} + + //! Start read threads of all Device pool device + void startAllThreadedReads(); + + //! Start sender "name" timer + void startSender(const PIString & name); + + //! Start all senders timers + void startAllSenders(); + + //! Start all read threads and senders + void start() {startAllThreadedReads(); startAllSenders();} + + //! Stop read thread of device with full path "full_path" + void stopThreadedRead(const PIString & full_path); + + //! Stop read thread of device "dev" + void stopThreadedRead(const PIIODevice * dev) {stopThreadedRead(devFPath(dev));} + + //! Stop read threads of all Device pool device + void stopAllThreadedReads(); + + //! Stop sender "name" timer + void stopSender(const PIString & name); + + //! Stop all senders timers + void stopAllSenders(); + + //! Stop all read threads and senders + void stop() {stopAllThreadedReads(); stopAllSenders();} + + + //! Returns if there are no devices in this connection + bool isEmpty() const {return device_modes.isEmpty();} + + + //! Returns PIDiagnostics * assosiated with device with full path "full_path_name", name "full_path_name" or filter "full_path_name" + PIDiagnostics * diagnostic(const PIString & full_path_name) const; + + //! Returns PIDiagnostics * assosiated with device or filter "dev" + PIDiagnostics * diagnostic(const PIIODevice * dev) const {return diags_.value(const_cast(dev), 0);} + + + //! Write data "data" to device with full path "full_path" and returns result of \a write() function of device + int writeByFullPath(const PIString & full_path, const PIByteArray & data); + + //! Write data "data" to device with name "name" and returns result of \a write() function of device + int writeByName(const PIString & name, const PIByteArray & data); + + //! Write data "data" to device "dev" and returns result of \a write() function of device + int write(PIIODevice * dev, const PIByteArray & data); + + + //! Returns all connections in application + static PIVector allConnections(); + + //! Returns all devices in Device pool + static PIVector allDevices(); + + //! Set Device pool fake mode to \"yes\" and returns previous mode + static bool setFakeMode(bool yes); + + //! Returns if Device pool works in fake mode + static bool isFakeMode(); + + class DevicePool: public PIThread { + PIOBJECT_SUBCLASS(DevicePool, PIThread) + friend class PIConnection; + public: + DevicePool(): PIThread(true, 10) {setName("PIConnection::DevicePool"); needLockRun(true); fake = false;} + + PIIODevice * addDevice(PIConnection * parent, const PIString & fp, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite, bool start = true); + bool removeDevice(PIConnection * parent, const PIString & fp); + void unboundConnection(PIConnection * parent); + PIIODevice * device(const PIString & fp) const; + PIVector boundedConnections() const; + PIVector boundedDevices() const; + PIVector boundedDevices(const PIConnection * parent) const; + + protected: + struct DeviceData { + DeviceData(): dev(0), rthread(0), started(false) {} + ~DeviceData(); + PIIODevice * dev; + PIThread * rthread; + bool started; + PIVector listeners; + }; + + void run(); + + static void threadReadDP(void * ddp); + void deviceReaded(DeviceData * dd, const PIByteArray & data); + + typedef PIMap::value_type DDPair; + PIMap devices; + bool fake; + }; + + EVENT2(dataReceivedEvent, const PIString &, from, const PIByteArray &, data) + EVENT2(packetReceivedEvent, const PIString &, from, const PIByteArray &, data) + EVENT3(qualityChanged, const PIIODevice * , dev, PIDiagnostics::Quality, new_quality, PIDiagnostics::Quality, old_quality) + + static void splitFullPathWithMode(PIString fpwm, PIString * full_path, PIIODevice::DeviceMode * mode); + +//! \events +//! \{ + + //! \fn void dataReceivedEvent(const PIString & from, const PIByteArray & data) + //! \brief Raise on data received from device with full path "from" + + //! \fn void packetReceivedEvent(const PIString & from, const PIByteArray & data) + //! \brief Raise on packet received from filter with name "from" + + //! \fn void qualityChanged(const PIIODevice * device, PIDiagnostics::Quality new_quality, PIDiagnostics::Quality old_quality) + //! \brief Raise on diagnostic quality of device "device" changed from "old_quality" to "new_quality" + +//! \} + +protected: + + //! Executes on data received from device with full path "from" + virtual void dataReceived(const PIString & from, const PIByteArray & data) {} + + //! Executes on packet received from filter with name "from" + virtual void packetReceived(const PIString & from, const PIByteArray & data) {} + + //! Validate header "rec" with source header "src" and size "size", executes from filter "filter_name" + virtual bool filterValidateHeader(const PIString & filter_name, uchar * src, uchar * rec, int size); + + //! Validate footer "rec" with source footer "src" and size "size", executes from filter "filter_name" + virtual bool filterValidateFooter(const PIString & filter_name, uchar * src, uchar * rec, int size); + + //! Validate payload "rec" with size "size", executes from filter "filter_name" + virtual bool filterValidatePayload(const PIString & filter_name, uchar * rec, int size); + + //! You should returns data for sender "sender_name" + virtual PIByteArray senderData(const PIString & sender_name); + +private: + static bool filterValidateHeaderS(void * c, uchar * src, uchar * rec, int size); + static bool filterValidateFooterS(void * c, uchar * src, uchar * rec, int size); + static bool filterValidatePayloadS(void * c, uchar * rec, int size); + bool configure(PIConfig & conf, const PIString & name_); + void rawReceived(PIIODevice * dev, const PIString & from, const PIByteArray & data); + void unboundExtractor(PIPacketExtractor * pe); + EVENT_HANDLER2(void, packetExtractorReceived, uchar * , data, int, size); + EVENT_HANDLER2(void, diagQualityChanged, PIDiagnostics::Quality, new_quality, PIDiagnostics::Quality, old_quality); + + PIString devPath(const PIIODevice * d) const; + PIString devFPath(const PIIODevice * d) const; + + struct Extractor { + Extractor(): extractor(0) {} + ~Extractor(); + PIPacketExtractor * extractor; + PIVector devices; + }; + + class Sender: public PITimer { + PIOBJECT(Sender) + public: + Sender(PIConnection * parent_ = 0): parent(parent_), int_(0.f) {needLockRun(true);} + ~Sender() {stop();} + PIConnection * parent; + PIVector devices; + PIByteArray sdata; + float int_; + void tick(void * , int); + }; + + typedef PIMap::value_type PEPair; + typedef PIMap::value_type SPair; + typedef PIMap::value_type DNPair; + typedef PIMap >::value_type BEPair; + typedef PIMap >::value_type CPair; + typedef PIMap::value_type DPair; + PIMap extractors; + PIMap senders; + PIMap device_names; + PIMap device_modes; + PIMap > bounded_extractors; + PIMap > channels_; + PIMap diags_; + + static PIVector _connections; + +}; + + +extern PIConnection::DevicePool * __device_pool__; + +class __DevicePoolContainer__ { +public: + __DevicePoolContainer__(); + static bool inited_; +}; + +static __DevicePoolContainer__ __device_pool_container__; + + +#endif // PICONNECTION_H diff --git a/src/io/pidatatransfer.cpp b/src/io/pidatatransfer.cpp new file mode 100644 index 00000000..2aabb616 --- /dev/null +++ b/src/io/pidatatransfer.cpp @@ -0,0 +1,374 @@ +#include "pidatatransfer.h" + +const uint PIBaseTransfer::signature = 0x54444950; + +PIBaseTransfer::PIBaseTransfer(): crc(standardCRC_16()) { + header.sig = signature; + header.session_id = 0; + packet_header_size = sizeof(PacketHeader); + part_header_size = sizeof(Part) + sizeof(PIByteArray); + is_sending = is_receiving = false; + break_ = true; + bytes_all = bytes_cur = 0; + timeout_ = 1.; + setPacketSize(4096); + srand(PISystemTime::current().toMilliseconds()); +} + + +PIBaseTransfer::~PIBaseTransfer() { + break_ = true; + session.clear(); + replies.clear(); +} + + +void PIBaseTransfer::stopSend() { + if (!is_sending) return; + break_ = true; +} + + +void PIBaseTransfer::stopReceive() { + if (!is_receiving) return; + break_ = true; + finish_receive(false); +} + + +void PIBaseTransfer::received(PIByteArray& data) { + if (data.size() < sizeof(PacketHeader)) return; + PacketHeader h; + memcpy(&h, data.data(), sizeof(PacketHeader)); + PacketType pt = (PacketType)h.type; +// piCoutObj << "receive" << h.session_id << h.type << h.id; + switch (pt) { + case pt_Unknown: + break; + case pt_Data: + if (h.session_id != header.session_id || !is_receiving) { + sendBreak(h.session_id); + return; + } else { + uint rcrc = h.crc; + uint ccrc = crc.calculate(data.data(sizeof(PacketHeader)), data.size_s() - sizeof(PacketHeader)); + if (rcrc != ccrc) { + header.id = h.id; + sendReply(pt_ReplyInvalid); + } else { + data >> h; + processData(h.id, data); + } + } + break; + case pt_ReplySuccess: + case pt_ReplyInvalid: + if (h.session_id != header.session_id) return; + if (is_sending) { + if (h.id >= 0 && h.id < replies.size()) + replies[h.id] = pt; + } + if (is_receiving && h.id == 0) { + if (checkSession() == 0 && pt == pt_ReplySuccess) finish_receive(true); + } + break; + case pt_Break: + break_ = true; + if (is_receiving) { + stopReceive(); + return; + } + if (is_sending) { + stopSend(); + return; + } + break; + case pt_Start: + if (is_sending) { + sendBreak(h.session_id); + return; + } + if (header.session_id != h.session_id && is_receiving) { + sendBreak(h.session_id); + return; + } + if (data.size() == sizeof(StartRequest) + sizeof(PacketHeader)) { + StartRequest sr; + memcpy(&sr, data.data(sizeof(PacketHeader)), sizeof(StartRequest)); + bytes_all = sr.size; + header.session_id = h.session_id; + header.id = 0; + state_string = "start request"; + session.clear(); + replies.clear(); + session.resize(sr.packets); + replies.resize(sr.packets + 1); + replies.fill(pt_Unknown); + is_receiving = true; + break_ = false; + state_string = "receiving"; + replies[0] = pt_ReplySuccess; + sendReply(pt_ReplySuccess); + } + break; + default: + break; + } +} + + +bool PIBaseTransfer::send_process() { + break_ = false; + is_sending = true; + startSend(); + replies.resize(session.size() + 1); + replies.fill(pt_Unknown); + PIByteArray ba; + if (!getStartRequest()) return finish_send(false); + for (int i = 0; i < session.size_s(); i++) { + ba = build_packet(i); + sendRequest(ba); + if (break_) return finish_send(false); + } +// piCoutObj << "correct errors"; + PITimeMeasurer tm; + int prev_chk = 0; + while (tm.elapsed_s() < timeout_) { + int chk = checkSession(); + if (chk != prev_chk) tm.reset(); + if (chk == 0) return finish_send(true); + if (chk > 0) { + ba = buildPacket(chk - 1); + sendRequest(ba); + } +// if (chk == -1) return finish_send(false); + if (break_) return finish_send(false); + prev_chk = chk; + piMSleep(1); + } + return finish_send(false); +} + + +int PIBaseTransfer::checkSession() { + int miss = 0; + for (int i = 1; i < replies.size_s(); i++) { + if (replies[i] != pt_ReplySuccess) miss++; + if (replies[i] == pt_ReplyInvalid) return i; + } + for (int i = 1; i < replies.size_s(); i++) { + if (replies[i] != pt_ReplySuccess) return i; + } + if (miss > 0) { + piCoutObj << "missing" << miss << "packets"; + return -miss; + } else return 0; +} + + +void PIBaseTransfer::buildSession(PIVector parts) { + state_string = "calculating files... "; + session.clear(); + header.session_id = rand(); + bytes_all = 0; + Part fi; + int fi_index, fi_prts; + PIVector lfi; + int min_size = packet_header_size + part_header_size; + int cur_size = min_size; + for (int i = 0; i < parts.size_s(); i++) { + state_string = "calculating files... " + PIString::fromNumber(i) + " of " + PIString::fromNumber(parts.size()); + fi.id = parts[i].id; + bytes_all += fi.size; +// fi.size = fi.entry.size; + fi.start = 0; + int rest = parts[i].size - (packet_size - cur_size); +// piCout << i << fi.entry << rest; + if (rest <= 0) { + fi.size = parts[i].size; + lfi << fi; + cur_size += fi.size + part_header_size; + } else { + fi.size = parts[i].size - rest; + fi_index = 1; + fi_prts = 1 + 1 + piMaxi(1, rest / (packet_size - min_size)); +// piCout << fi_prts; + lfi << fi; + session << lfi; + lfi.clear(); + cur_size = min_size; + llong fs = fi.size; + for (int j = 1; j < fi_prts; j++) { + fi_index++; + fi.start = fs; + fi.size = piMin(parts[i].size - fs, packet_size - min_size); + lfi << fi; + cur_size += fi.size + part_header_size; + if (fi_index != fi_prts) { + session << lfi; + lfi.clear(); + cur_size = min_size; + fs += fi.size; + } + } + } + if (packet_size - cur_size < min_size) { + session << lfi; + lfi.clear(); + cur_size = min_size; + } + } + if (cur_size > min_size) session << lfi; +} + + +void PIBaseTransfer::sendBreak(int session_id) { + uint psid = header.session_id; + header.session_id = session_id; + sendReply(pt_Break); + header.session_id = psid; +} + + +void PIBaseTransfer::sendReply(PacketType reply) { + header.type = reply; + PIByteArray ba; + ba << header; + sendRequest(ba); +} + + +bool PIBaseTransfer::getStartRequest() { + PITimeMeasurer tm; + header.type = pt_Start; + header.id = 0; + PIByteArray ba; + ba << header; + ba << (uint)session.size() << bytes_all; + state_string = "send request"; + for (int i = 0; i < 3; i++) { + tm.reset(); + sendRequest(ba); + while (tm.elapsed_s() < timeout_) { + if (break_) return false; + //piCoutObj << send_replyes[0]; + if (replies[0] == pt_ReplySuccess) { + state_string = "send permited!"; + return true; + } + piMSleep(10); + } + } + return false; +} + + +void PIBaseTransfer::processData(int id, PIByteArray & data) { +// piCoutObj << "received packet" << id << ", size" << data.size(); + if (id < 1 || id > replies.size_s()) return; + if (!session[id - 1].isEmpty()) { + header.id = id; + replies[id] = pt_ReplySuccess; + sendReply(pt_ReplySuccess); + if (checkSession() == 0) state_string = "receive ok"; + return; + } + Part fi; + PIByteArray ba, pheader; + pheader.resize(packet_header_size - sizeof(PacketHeader)); + if (!pheader.isEmpty()) { + memcpy(pheader.data(), data.data(), pheader.size()); + data.remove(0, pheader.size_s()); + } + while (!data.isEmpty()) { + ba.clear(); + data >> fi; + if (fi.size > 0) data >> ba; +// fi.fsize = ba.size(); + bytes_cur += fi.size; +// piCoutObj << "recv" << fi; + session[id - 1] << fi; + state_string = "receiving..."; + receivePart(fi, ba, pheader); + } + header.id = id; + replies[id] = pt_ReplySuccess; + if (checkSession() == 0) state_string = "receive ok"; + sendReply(pt_ReplySuccess); +} + + +PIByteArray PIBaseTransfer::build_packet(int id) { + PIByteArray ret; + PIByteArray ba; + header.id = id + 1; + header.type = pt_Data; + //piCoutObj << "Packet" << header.id; + //piCoutObj << "session id" << header.session_id; + ret << header; + ret << buildPacket(id); + /*for (int i = 0; i < session[id].size_s(); i++) { + EntryInfo fi = session[id][i]; +// piCoutObj << "send" << fi; + bytes_total_cur += fi.fsize; + ret << fi; + if (fi.entry.size > 0) { + PIString path = dir.absolutePath() + dir.separator + fi.entry.path; + if (work_file.path() != path || !work_file.isOpened()) { + if (!work_file.open(path, PIIODevice::ReadOnly)) { + break_ = true; + state_string = "ERROR! while open file " + fi.entry.path; + piCoutObj << state_string; + return ret; + } + } + work_file.seek(fi.fstart); + ba.resize(fi.fsize); + int rs = work_file.read(ba.data(), ba.size()); + if (rs != fi.fsize) { + break_ = true; + state_string = "ERROR! while read file " + fi.entry.path + " (must " + PIString::fromNumber(fi.fsize) + ", but read " + PIString::fromNumber(rs) + ")"; + piCoutObj << state_string; + return ret; + } + ret << ba; + } + } + EntryInfo cfile = session[id].back(); + state_string = "sending: " + cfile.entry.path; + bytes_file_all = cfile.entry.size; + bytes_file_cur = cfile.fstart; + uint scrc = crc.calculate(ret); + ret << scrc;*/ + //piCoutObj << "packet" << header.id << "send crc" << scrc; + return ret; +} + + +bool PIBaseTransfer::finish_send(bool ok) { + if (ok) state_string = "send done"; + else state_string = "send failed"; +// piCoutObj << state_string << PIString::readableSize(bytes_total_all); + is_sending = false; + bytes_all = bytes_cur = 0; + header.id = 0; + if (!ok) sendBreak(header.session_id); + else sendReply(pt_ReplySuccess); + finishSend(ok); + return ok; +} + + +void PIBaseTransfer::finish_receive(bool ok) { + if (ok) state_string = "receive done"; + else state_string = "receive failed"; +// piCoutObj << state_string << PIString::readableSize(bytes_total_all); + is_receiving = false; + bytes_all = bytes_cur = 0; + if (!ok) sendBreak(header.session_id); + finishReceive(ok); +} +PIByteArray PIDataTransfer::buildPacket(int id) { + ; +} + diff --git a/src/io/pidatatransfer.h b/src/io/pidatatransfer.h new file mode 100644 index 00000000..a56f619f --- /dev/null +++ b/src/io/pidatatransfer.h @@ -0,0 +1,116 @@ +#ifndef PIDATATRANSFER_H +#define PIDATATRANSFER_H + +#include "picrc.h" +#include "pitimer.h" + +class PIBaseTransfer : public PIObject +{ + PIOBJECT(PIBaseTransfer) +public: + PIBaseTransfer(); + ~PIBaseTransfer(); + + struct PacketHeader { + uint sig; + int type; // PacketType + uint session_id; + uint id; + uint crc; + bool check_sig() {return (sig == signature);} + }; + + struct Part { + Part(uint id_ = 0, ullong size_ = 0, ullong start_ = 0) : id(id_), size(size_), start(start_) {} + uint id; + ullong size; + ullong start; + }; + + virtual void stopSend(); + virtual void stopReceive(); + + virtual bool isSending() const {return is_sending;} + virtual bool isReceiving() const {return is_receiving;} + + void setPacketSize(int size) {packet_size = size;} + int packetSize() const {return packet_size;} + + void setTimeout(double sec) {timeout_ = sec;} + double timeout() const {return timeout_;} + + const PIString & stateString() const {return state_string;} + llong bytesAll() const {return bytes_all;} + llong bytesCur() const {return bytes_cur;} + const PIString * stateString_ptr() const {return &state_string;} + const llong * bytesAll_ptr() const {return &bytes_all;} + const llong * bytesCur_ptr() const {return &bytes_cur;} + + EVENT(startReceive) + EVENT1(finishReceive, bool, ok) + EVENT(startSend) + EVENT1(finishSend, bool, ok) + EVENT1(sendRequest, PIByteArray &, data) + EVENT_HANDLER1(void, received, PIByteArray &, data); + +protected: + uint packet_header_size, part_header_size; + bool break_, is_sending, is_receiving; + PIString state_string; + llong bytes_all, bytes_cur; + + void buildSession(PIVector parts); + virtual PIByteArray buildPacket(int id) = 0; + virtual void receivePart(Part fi, PIByteArray ba, PIByteArray header) = 0; + +private: + + enum PacketType {pt_Unknown, pt_Data, pt_ReplySuccess, pt_ReplyInvalid, pt_Break, pt_Start}; + + struct StartRequest { + uint packets; + ullong size; + }; + + + static const uint signature; + int packet_size; + double timeout_; + PIVector > session; + PIVector replies; + PacketHeader header; + CRC_16 crc; + + void processData(int id, PIByteArray &data); + PIByteArray build_packet(int id); + int checkSession(); + bool send_process(); + void sendBreak(int session_id); + void sendReply(PacketType reply); + bool getStartRequest(); + bool finish_send(bool ok); + void finish_receive(bool ok); +}; + +inline PIByteArray & operator <<(PIByteArray & s, const PIBaseTransfer::PacketHeader & v) {s << v.sig << v.type << v.session_id << v.id; return s;} +inline PIByteArray & operator >>(PIByteArray & s, PIBaseTransfer::PacketHeader & v) {s >> v.sig >> v.type >> v.session_id >> v.id; return s;} + +inline PIByteArray & operator <<(PIByteArray & s, const PIBaseTransfer::Part & v) {s << v.id << v.size << v.start; return s;} +inline PIByteArray & operator >>(PIByteArray & s, PIBaseTransfer::Part & v) {s >> v.id >> v.size >> v.start; return s;} + + +class PIDataTransfer : public PIBaseTransfer +{ + PIOBJECT_SUBCLASS(PIDataTransfer, PIBaseTransfer) +public: + PIDataTransfer() {;} + ~PIDataTransfer() {;} + virtual PIByteArray buildPacket(int id); + virtual void receivePart(Part fi, PIByteArray ba, PIByteArray header) {;} + +private: + PIByteArray data; +}; + + +#endif // PIDATATRANSFER_H diff --git a/src/io/pidiagnostics.cpp b/src/io/pidiagnostics.cpp new file mode 100755 index 00000000..b21c01f3 --- /dev/null +++ b/src/io/pidiagnostics.cpp @@ -0,0 +1,166 @@ +/* + PIP - Platform Independent Primitives + Speed and quality in/out diagnostics + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pidiagnostics.h" + + +/** \class PIDiagnostics + * \brief Connection quality diagnostics + * \details + * \section PIDiagnostics_sec0 Synopsis + * This class provide abstract connection quality diagnostics and + * counting. You should create instance of %PIDiagnostics and on + * packet receive call function \a received(), on packet send call + * function \a sended(). %PIDiagnostics calculates correct, wrong + * and sended counters, packets per second, bytes per seconds, + * immediate and integral receive frequencies and receive/send speeds + * in human readable representation. There statistics are calculates + * one time per period, by default 1 second. To calculate them you + * should start %PIDiagnostics with function \a start() or pass \b true + * to constructor. + * */ + + +PIDiagnostics::PIDiagnostics(bool start_): PITimer() { + reset(); + if (start_) start(); +} + + +void PIDiagnostics::reset() { + setDisconnectTimeout(3.); + lock(); + qual = PIDiagnostics::Unknown; + speedIn = speedOut = PIString::readableSize(0) + "/s"; + ifreq = immediate_freq = integral_freq = 0.f; + cur_pckt = rec_once = 0; + wrong_count = receive_count = send_count = 0; + packets_in_sec = packets_out_sec = bytes_in_sec = bytes_out_sec = 0; + unlock(); +} + + +void PIDiagnostics::received(int size, bool correct) { + lock(); + rec_once = 1; + if (correct) { + float el = tm.elapsed_s(); + tm.reset(); + if (el > 0.f) immediate_freq = ifreq = 1.f / el; + else immediate_freq = ifreq = 0.f; + receive_count++; + } else { + immediate_freq = ifreq = 0.f; + wrong_count++; + } + addToHistory(history_rec, size, correct); + unlock(); +} + + +void PIDiagnostics::sended(int size) { + lock(); + send_count++; + addToHistory(history_send, size); + unlock(); +} + + +void PIDiagnostics::tick(void * data, int delimiter) { + lock(); + checkHistory(history_rec); + checkHistory(history_send); + PIDiagnostics::Quality diag; + immediate_freq = ifreq; + ifreq = 0.f; + int bps[2]; + int cpckt[2]; + bps[0] = bps[1] = 0; + cpckt[0] = cpckt[1] = 0; + packets_in_sec = packets_out_sec = 0; + piForeachC (Entry & e, history_rec) { + if (e.ok) { + bps[0] += e.bytes; + packets_in_sec++; + } + cpckt[e.ok ? 1 : 0]++; + } + piForeachC (Entry & e, history_send) { + bps[1] += e.bytes; + packets_out_sec++; + } + bytes_in_sec = bps[0] / disconn_; + bytes_out_sec = bps[1] / disconn_; + packets_in_sec /= disconn_; + packets_out_sec /= disconn_; + speedIn = PIString::readableSize(bytes_in_sec) + "/s"; + speedOut = PIString::readableSize(bytes_out_sec) + "/s"; + int arc = cpckt[0] + cpckt[1]; + float good_percents = 0.f; + if (arc > 0) good_percents = (float)cpckt[1] / arc * 100.f; + if (disconn_ > 0.) integral_freq = cpckt[1] / disconn_; + else integral_freq = 0.; + if (rec_once == 0) { + diag = PIDiagnostics::Unknown; + } else { + if (good_percents == 0.f) diag = PIDiagnostics::Failure; + else if (good_percents <= 20.f) diag = PIDiagnostics::Bad; + else if (good_percents > 20.f && good_percents <= 80.f) diag = PIDiagnostics::Average; + else diag = PIDiagnostics::Good; + } + if (diag != qual) { + qualityChanged(diag, qual); + qual = diag; + } + unlock(); +} + + +void PIDiagnostics::addToHistory(PIVector & hist, int bytes, bool ok) { + Entry e; + e.time = PISystemTime::current(true); + e.bytes = bytes; + e.ok = ok; + checkHistory(hist); + hist << e; +} + + +void PIDiagnostics::checkHistory(PIVector< PIDiagnostics::Entry > & hist) { + PISystemTime ctm = PISystemTime::current(true); + for (int i = 0; i < hist.size_s(); ++i) { + if ((ctm - hist[i].time).abs() > disconn_st) { + hist.remove(i); + --i; + } + } +} + + +void PIDiagnostics::propertyChanged(const PIString &) { + disconn_ = property("disconnectTimeout").toFloat(); + changeDisconnectTimeout(); +} + + +void PIDiagnostics::changeDisconnectTimeout() { + lock(); + disconn_st = PISystemTime::fromSeconds(disconn_); + unlock(); +} diff --git a/src/io/pidiagnostics.h b/src/io/pidiagnostics.h new file mode 100755 index 00000000..77f61b65 --- /dev/null +++ b/src/io/pidiagnostics.h @@ -0,0 +1,190 @@ +/*! \file pidiagnostics.h + * \brief Connection quality diagnostics +*/ +/* + PIP - Platform Independent Primitives + Speed and quality in/out diagnostics + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIDIAGNOSTICS_H +#define PIDIAGNOSTICS_H + +#include "pitimer.h" + + +class PIP_EXPORT PIDiagnostics: private PITimer +{ + PIOBJECT_SUBCLASS(PIDiagnostics, PITimer) + friend class PIConnection; +public: + + //! Constructs an empty diagnostics and if "strat_" start it + PIDiagnostics(bool start_ = true); + + virtual ~PIDiagnostics() {;} + + //! Connection quality + enum Quality { + Unknown /** Unknown, no one packet received yet */ = 1, + Failure /** No connection, no one correct packet received for last period */ = 2, + Bad /** Bad connection, correct packets received <= 20% */ = 3, + Average /** Average connection, correct packets received > 20% and <= 80% */ = 4, + Good /** Good connection, correct packets received > 80% */ = 5 + }; + + + //! Returns period of full disconnect in seconds and period of averaging frequency + float disconnectTimeout() const {return disconn_;} + + //! Returns period of full disconnect in seconds and period of averaging frequency + void setDisconnectTimeout(float s) {setProperty("disconnectTimeout", s); disconn_ = s; changeDisconnectTimeout();} + + + //! Returns immediate receive frequency, packets/s + float immediateFrequency() const {return immediate_freq;} + + //! Returns integral receive frequency for \a disconnectTimeout() seconds, packets/s + float integralFrequency() const {return integral_freq;} + + //! Returns correct received packets per second + ullong receiveCountPerSec() const {return packets_in_sec;} + + //! Returns sended packets per second + ullong sendCountPerSec() const {return packets_out_sec;} + + //! Returns correct received bytes per second + ullong receiveBytesPerSec() const {return bytes_in_sec;} + + //! Returns sended bytes per second + ullong sendBytesPerSec() const {return bytes_out_sec;} + + //! Returns overall correct received packets count + ullong receiveCount() const {return receive_count;} + + //! Returns overall wrong received packets count + ullong wrongCount() const {return wrong_count;} + + //! Returns overall sended packets count + ullong sendCount() const {return send_count;} + + //! Returns connection quality + PIDiagnostics::Quality quality() const {return qual;} + + //! Returns receive speed in format "n {B|kB|MB|GB|TB}/s" + PIString receiveSpeed() const {return speedIn;} + + //! Returns send speed in format "n {B|kB|MB|GB|TB}/s" + PIString sendSpeed() const {return speedOut;} + + + //! Returns immediate receive frequency pointer, packets/s. Useful for output to PIConsole + const float * immediateFrequency_ptr() const {return &immediate_freq;} + + //! Returns integral receive frequency pointer for period, packets/s. Useful for output to PIConsole + const float * integralFrequency_ptr() const {return &integral_freq;} + + //! Returns correct received packets per second pointer. Useful for output to PIConsole + const ullong * receiveCountPerSec_ptr() const {return &packets_in_sec;} + + //! Returns sended packets per second pointer. Useful for output to PIConsole + const ullong * sendCountPerSec_ptr() const {return &packets_out_sec;} + + //! Returns correct received bytes per second pointer. Useful for output to PIConsole + const ullong * receiveBytesPerSec_ptr() const {return &bytes_in_sec;} + + //! Returns sended bytes per second pointer. Useful for output to PIConsole + const ullong * sendBytesPerSec_ptr() const {return &bytes_out_sec;} + + //! Returns overall correct received packets count pointer. Useful for output to PIConsole + const ullong * receiveCount_ptr() const {return &receive_count;} + + //! Returns overall wrong received packets count pointer. Useful for output to PIConsole + const ullong * wrongCount_ptr() const {return &wrong_count;} + + //! Returns overall sended packets count pointer. Useful for output to PIConsole + const ullong * sendCount_ptr() const {return &send_count;} + + //! Returns connection quality pointer. Useful for output to PIConsole + const int * quality_ptr() const {return (int * )&qual;} + + //! Returns receive speed pointer in format "n {B|kB|MB|GB|TB}/s". Useful for output to PIConsole + const PIString * receiveSpeed_ptr() const {return &speedIn;} + + //! Returns send speed pointer in format "n {B|kB|MB|GB|TB}/s". Useful for output to PIConsole + const PIString * sendSpeed_ptr() const {return &speedOut;} + + EVENT_HANDLER0(void, start) {start(1000.); changeDisconnectTimeout();} + EVENT_HANDLER1(void, start, double, msecs) {if (msecs > 0.) {PITimer::start(msecs); changeDisconnectTimeout();}} + EVENT_HANDLER0(void, reset); + + EVENT_HANDLER1(void, received, int, size) {received(size, true);} + EVENT_HANDLER2(void, received, int, size, bool, correct); + EVENT_HANDLER1(void, sended, int, size); + + EVENT2(qualityChanged, PIDiagnostics::Quality, new_quality, PIDiagnostics::Quality, old_quality) + +//! \handlers +//! \{ + + //! \fn void start(double msecs = 1000.) + //! \brief Start diagnostics evaluations with period "msecs" milliseconds + + //! \fn void reset() + //! \brief Reset diagnostics counters + + //! \fn void received(int size, bool correct = true) + //! \brief Notify diagnostics about "correct" corected received packet + + //! \fn void sended(int size) + //! \brief Notify diagnostics about sended packet + +//! \} +//! \events +//! \{ + + //! \fn void qualityChanged(PIDiagnostics::Quality new_quality, PIDiagnostics::Quality old_quality) + //! \brief Raise on change receive quality from "old_quality" to "new_quality" + +//! \} + +private: + struct Entry { + Entry() {ok = true; bytes = 0;} + PISystemTime time; + bool ok; + int bytes; + }; + + void tick(void * data, int delimiter); + void addToHistory(PIVector & hist, int bytes, bool ok = true); + void checkHistory(PIVector & hist); + void propertyChanged(const PIString & ); + void changeDisconnectTimeout(); + + PIDiagnostics::Quality qual; + PIString speedIn, speedOut; + float ifreq, immediate_freq, integral_freq, disconn_; + PIVector history_rec, history_send; + PISystemTime disconn_st; + PITimeMeasurer tm; + char cur_pckt, rec_once; + ullong wrong_count, receive_count, send_count; + ullong packets_in_sec, packets_out_sec, bytes_in_sec, bytes_out_sec; + +}; + +#endif // PIDIAGNOSTICS_H diff --git a/src/io/pidir.cpp b/src/io/pidir.cpp new file mode 100755 index 00000000..faac351a --- /dev/null +++ b/src/io/pidir.cpp @@ -0,0 +1,380 @@ +/* + PIP - Platform Independent Primitives + Directory + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pidir.h" + +//#if !defined(ANDROID) +const PIChar PIDir::separator = '/'; +#ifdef QNX +# define _stat_struct_ struct stat +# define _stat_call_ stat +# define _stat_link_ lstat +#else +# define _stat_struct_ struct stat64 +# define _stat_call_ stat64 +# define _stat_link_ lstat64 +#endif +#ifndef WINDOWS +# ifdef ANDROID +# include +# else +# include +# endif +# include +#endif + + +/*! \class PIDir + * \brief Local directory + * + * \section PIDir_sec0 Synopsis + * This class provide access to local file. You can manipulate + * binary content or use this class as text stream. To binary + * access there are function \a read(), \a write(), and many + * \a writeBinary() functions. For write variables to file in + * their text representation threr are many "<<" operators. + * + */ + + +PIDir::PIDir(const PIString & dir) { + path_ = dir; + cleanPath(); +} + + +PIDir::PIDir(const PIFile & file) { + path_ = file.path(); + cleanPath(); + if (isExists()) return; + int pos = path_.findLast(separator); + path_.cutRight(path_.size_s() - pos); +} + + +bool PIDir::operator ==(const PIDir & d) const { + return d.absolutePath() == absolutePath(); +} + + +bool PIDir::isAbsolute() const { + if (path_.isEmpty()) return false; +#ifdef WINDOWS + if (path_.size_s() < 2) return false; + return (path_.mid(1, 2).contains(":")); +#else + return (path_[0] == separator); +#endif +} + + +PIString PIDir::absolutePath() const { + if (isAbsolute()) return path_; + return PIDir(PIDir::current().path_ + separator + path_).path_; +} + + +PIDir & PIDir::cleanPath() { + PIString p(path_); + if (p.size() == 0) { + path_ = "."; + return *this; + } + path_.replaceAll(PIString(separator) + PIString(separator), PIString(separator)); + bool is_abs = isAbsolute(); + PIStringList l = PIString(p).split(separator); +#ifdef WINDOWS + PIString letter; + if (is_abs) letter = l.take_front(); +#endif + l.removeAll("."); + l.removeAll(""); + for (int i = 0; i < l.size_s() - 1; ++i) { + if (l[i] != ".." && l[i + 1] == "..") { + l.remove(i, 2); + i -= 2; + if (i < -1) i = -1; + } + } + if (is_abs) + while (!l.isEmpty()) { + if (l.front() == "..") + l.pop_front(); + else + break; + } + path_ = l.join(separator); + if (is_abs) { + path_.prepend(separator); +#ifdef WINDOWS + path_.prepend(letter); +#endif + } + if (path_.isEmpty()) path_ = "."; + return *this; +} + + +PIString PIDir::relative(const PIString & path) const { + PIDir td(path); + PIStringList dl(absolutePath().split(separator)), pl(td.absolutePath().split(separator)), rl; + while (!dl.isEmpty() && !pl.isEmpty()) { + if (dl.front() != pl.front()) break; + dl.pop_front(); + pl.pop_front(); + } + for (int i = 0; i < dl.size_s(); ++i) + rl << ".."; + rl << pl; + if (rl.isEmpty()) return "."; + return rl.join(separator); +} + + +PIDir & PIDir::setDir(const PIString & path) { + path_ = path; + cleanPath(); + return *this; +} + + +PIDir & PIDir::cd(const PIString & path) { + if (path_.isEmpty()) return *this; + if (path_.back() != separator) path_ += separator; + path_ += path; + return cleanPath(); +} + + +bool PIDir::make(bool withParents) { + PIDir d = cleanedPath(); + PIString tp; + bool is_abs = isAbsolute(); + if (withParents) { + PIStringList l = d.path_.split(separator); + for (int i = l.size_s() - 1; i >= 0; --i) { + if (i > 1) tp = PIStringList(l).remove(i, l.size_s() - i).join(separator); + else { + tp = separator; + if (!is_abs) tp.push_front('.'); + } + //cout << tp << endl; + if (isExists(tp)) { + for (int j = i + 1; j <= l.size_s(); ++j) { + tp = PIStringList(l).remove(j, l.size_s() - j).join(separator); + //cout << tp << endl; + if (makeDir(tp)) continue; + else return false; + } + break; + }; + } + } else + if (makeDir(d.path_)) return true; + return false; +} + + +PIVector PIDir::entries() { + PIVector l; + if (!isExists()) return l; + PIString dp = absolutePath(); + PIString p(dp); + if (dp == ".") dp.clear(); + else if (!dp.endsWith(separator)) dp += separator; + //piCout << "entries from" << p; +#ifdef WINDOWS + WIN32_FIND_DATA fd; memset(&fd, 0, sizeof(fd)); + p += "\\*"; + void * hf = FindFirstFile((LPCTSTR)(p.data()), &fd); + if (!hf) return l; + do { + l << PIFile::fileInfo(dp + PIString(fd.cFileName)); + memset(&fd, 0, sizeof(fd)); + } while (FindNextFile(hf, &fd) != 0); + FindClose(hf); +#else + dirent ** list; + int cnt = scandir( +# ifndef QNX + p.data(), &list +# else + const_cast(p.data()), 0 +# endif + , 0, versionsort); + for (int i = 0; i < cnt; ++i) { + l << PIFile::fileInfo(dp + PIString(list[i]->d_name)); + delete list[i]; + } + delete list; +#endif + return l; +} + + +PIVector PIDir::allEntries() { + return allEntries(absolutePath()); +} + + + +bool PIDir::isExists(const PIString & path) { +#ifdef WINDOWS + DWORD ret = GetFileAttributes((LPCTSTR)(path.data())); + return (ret != 0xFFFFFFFF) && (ret & FILE_ATTRIBUTE_DIRECTORY); +#else + DIR * dir_ = opendir(path.data()); + if (dir_ == 0) return false; + closedir(dir_); +#endif + return true; +} + + +PIDir PIDir::current() { + char rc[1024]; +#ifdef WINDOWS + memset(rc, 0, 1024); + if (GetCurrentDirectory(1024, (LPTSTR)rc) == 0) return PIString(); + PIString ret(rc); + ret.replaceAll("\\", PIDir::separator); + return PIDir(ret); +#else + if (getcwd(rc, 1024) == 0) return PIString(); +#endif + return PIDir(rc); +} + + +PIDir PIDir::home() { + char * rc = 0; +#ifdef WINDOWS + rc = new char[1024]; + memset(rc, 0, 1024); + if (ExpandEnvironmentStrings((LPCTSTR)"%HOMEPATH%", (LPTSTR)rc, 1024) == 0) { + delete[] rc; + return PIDir(); + } + PIString s(rc); + s.replaceAll("\\", PIDir::separator); + delete[] rc; + return PIDir(s); +#else + rc = getenv("HOME"); + if (rc == 0) return PIDir(); + return PIDir(rc); +#endif +} + + +PIDir PIDir::temporary() { + char * rc = 0; +#ifdef WINDOWS + rc = new char[1024]; + memset(rc, 0, 1024); + int ret = GetTempPath(1024, (LPTSTR)rc); + if (ret == 0) { + delete[] rc; + return PIDir(); + } + PIString s(rc); + s.replaceAll("\\", PIDir::separator); + delete[] rc; + return PIDir(s); +#else + rc = tmpnam(0); + if (rc == 0) return PIDir(); + PIString s(rc); + return PIDir(s.left(s.findLast(PIDir::separator))); +#endif +} + + +PIVector PIDir::allEntries(const PIString &path) { + PIVector ret; + PIVector dirs; + PIDir root; + root.setDir(path); + PIVector cds = root.entries(); + piForeachC (PIFile::FileInfo & de, cds) { + //piCout << " open" << de.name(); + if (de.name() == "." || de.name() == "..") continue; + if (de.isSymbolicLink()) continue; /// TODO: resolve symlinks + if (de.isDir()) { + dirs.push_front(de); + PIVector td = PIDir(de.path).allEntries(); + for (int i = 0; i < td.size_s(); i++) { + if (td[i].isDir()) dirs.push_front(td[i]); + else ret << td[i]; + } + } else ret << de; + } + ret.insert(0, dirs); + return ret; +} + + +bool PIDir::make(const PIString & path, bool withParents) { + PIDir d(path); + if (d.isExists()) return true; + return d.make(withParents); +} + + +bool PIDir::setCurrent(const PIString & path) { +#ifdef WINDOWS + if (SetCurrentDirectory((LPCTSTR)(path.data())) != 0) return true; +#else + if (chdir(path.data()) == 0) return true; +#endif + printf("[PIDir] setCurrent(\"%s\") error: %s\n", path.data(), errorString().data()); + return false; +} + + +bool PIDir::makeDir(const PIString & path) { +#ifdef WINDOWS + if (CreateDirectory((LPCTSTR)(path.data()), NULL) != 0) return true; +#else + if (mkdir(path.data(), 16877) == 0) return true; +#endif + printf("[PIDir] makeDir(\"%s\") error: %s\n", path.data(), errorString().data()); + return false; +} + + +bool PIDir::removeDir(const PIString & path) { +#ifdef WINDOWS + if (RemoveDirectory((LPCTSTR)(path.data())) != 0) return true; +#else + if (rmdir(path.data()) == 0) return true; +#endif + printf("[PIDir] removeDir(\"%s\") error: %s\n", path.data(), errorString().data()); + return false; +} + + +bool PIDir::renameDir(const PIString & path, const PIString & new_name) { + if (::rename(path.data(), new_name.data()) == 0) return true; + printf("[PIDir] renameDir(\"%s\", \"%s\") error: %s\n", path.data(), new_name.data(), errorString().data()); + return false; +} + + +//#endif diff --git a/src/io/pidir.h b/src/io/pidir.h new file mode 100755 index 00000000..a5f3ced4 --- /dev/null +++ b/src/io/pidir.h @@ -0,0 +1,130 @@ +/*! \file pidir.h + * \brief Local directory +*/ +/* + PIP - Platform Independent Primitives + Directory + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIDIR_H +#define PIDIR_H + +#include "pifile.h" +//#if !defined(ANDROID) + +class PIP_EXPORT PIDir +{ +public: + + //! Constructs directory with path "path" + PIDir(const PIString & dir = PIString()); + + //! Constructs directory with "file" directory path "path" + PIDir(const PIFile & file); + + + //! Returns if this directory is exists + bool isExists() const {return PIDir::isExists(path_);} + + //! Returns if path of this directory is absolute + bool isAbsolute() const; + + //! Returns if path of this directory is relative + bool isRelative() const {return !isAbsolute();} + + + //! Returns path of this directory + const PIString & path() const {return path_;} + + //! Returns absolute path of this directory + PIString absolutePath() const; + + /** \brief Simplify path of this directory + * \details This function remove repeatedly separators and + * resolve ".." in path. E.g. "/home/.//peri4/src/../.." will + * become "/home" \n This function returns reference to this %PIDir */ + PIDir & cleanPath(); + + //! Returns %PIDir with simplified path of this directory + PIDir cleanedPath() const {PIDir d(path_); d.cleanPath(); return d;} + + //! Returns relative to this directory path "path" + PIString relative(const PIString & path) const; + + //! Set this directory path to simplified "path" + PIDir & setDir(const PIString & path); + + //! Set this directory path as current for application + bool setCurrent() {return PIDir::setCurrent(path_);} + + + /** \brief Returns this directory content + * \details Scan this directory and returns all directories + * and files in one list, sorted alphabetically. This list + * contains also "." and ".." members. + * \attention This function doesn`t scan content of inner + * directories! */ + PIVector entries(); + + /** \brief Returns all this directory content + * \details Scan this directory recursively and returns all + * directories and files in one list, sorted alphabetically. + * This list doesn`t contains "." and ".." members. + * Files placed after directories in this list */ + PIVector allEntries(); + + bool make(bool withParents = true); + bool remove() {return PIDir::remove(path_);} + bool rename(const PIString & new_name) {if (!PIDir::rename(path_, new_name)) return false; path_ = new_name; return true;} + PIDir & cd(const PIString & path); + PIDir & up() {return cd("..");} + + bool operator ==(const PIDir & d) const; + bool operator !=(const PIDir & d) const {return !((*this) == d);} + + static const PIChar separator; + + static PIDir current(); + static PIDir home(); + static PIDir temporary(); + static PIVector allEntries(const PIString & path); + static bool isExists(const PIString & path); + static bool make(const PIString & path, bool withParents = true); + static bool remove(const PIString & path) {return removeDir(path);} + static bool rename(const PIString & path, const PIString & new_name) {return PIDir::renameDir(path, new_name);} + static bool setCurrent(const PIString & path); + static bool setCurrent(const PIDir & dir) {return setCurrent(dir.path_);} + +private: + static bool makeDir(const PIString & path); + static bool removeDir(const PIString & path); + static bool renameDir(const PIString & path, const PIString & new_name); + + PIString path_; + +}; + + +inline bool operator <(const PIFile::FileInfo & v0, const PIFile::FileInfo & v1) {return (v0.path < v1.path);} +inline bool operator >(const PIFile::FileInfo & v0, const PIFile::FileInfo & v1) {return (v0.path > v1.path);} +inline bool operator ==(const PIFile::FileInfo & v0, const PIFile::FileInfo & v1) {return (v0.path == v1.path);} +inline bool operator !=(const PIFile::FileInfo & v0, const PIFile::FileInfo & v1) {return (v0.path != v1.path);} + +inline PICout operator <<(PICout s, const PIDir & v) {s.setControl(0, true); s << "PIDir(\"" << v.path() << "\")"; s.restoreControl(); return s;} + + +#endif // PIDIR_H diff --git a/src/io/piethernet.cpp b/src/io/piethernet.cpp new file mode 100755 index 00000000..b12c40cc --- /dev/null +++ b/src/io/piethernet.cpp @@ -0,0 +1,989 @@ +/* + PIP - Platform Independent Primitives + Ethernet, UDP/TCP Broadcast/Multicast + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "piethernet.h" +#include "piconfig.h" +#ifdef QNX +# include +# include +# include +#endif +#ifdef WINDOWS +# include +# define ip_mreqn ip_mreq +# define imr_address imr_interface +#endif + + +/** \class PIEthernet + * \brief Ethernet device + * \details + * \section PIEthernet_sec0 Synopsis + * %PIEthernet designed to work with IPv4 network via two protocols: + * UDP and TCP. This class allow you send and receive packets to/from + * another computer through network. Also it supports broadcast and + * multicast extensions. + * + * \section PIEthernet_sec1 IPv4 + * + * + * \section PIEthernet_sec2 UDP + * User Datagram Protocol + * + * \section PIEthernet_sec3 TCP + * Transmission Control Protocol + * + * */ + +REGISTER_DEVICE(PIEthernet); + + +PIEthernet::PIEthernet(): PIIODevice("", ReadWrite) { + construct(); + setType(UDP); + setParameters(PIEthernet::ReuseAddress | PIEthernet::MulticastLoop); + //if (type_ != UDP) init(); +} + + +PIEthernet::PIEthernet(PIEthernet::Type type_, const PIString & ip_port, const PIFlags params_): PIIODevice(ip_port, ReadWrite) { + construct(); + parseAddress(ip_port, &ip_, &port_); + setType(type_); + setParameters(params_); + if (type_ != UDP) init(); +} + + +PIEthernet::PIEthernet(int sock_, PIString ip_port): PIIODevice("", ReadWrite) { + construct(); + parseAddress(ip_port, &ip_s, &port_s); + sock = sock_; + init_ = opened_ = connected_ = true; + setParameters(PIEthernet::ReuseAddress | PIEthernet::MulticastLoop); + setType(TCP_Client, false); + setPath(ip_port); +} + + +PIEthernet::~PIEthernet() { + piMonitor.ethernets--; + stop(); + closeDevice(); +} + + +void PIEthernet::construct() { + piMonitor.ethernets++; + connected_ = connecting_ = listen_threaded = server_bounded = false; + port_ = port_s = port_r = 0; + sock = sock_s = -1; + setReadTimeout(10000.); + setWriteTimeout(10000.); + setTTL(64); + setMulticastTTL(1); + server_thread_.setData(this); + server_thread_.setName("__S__server_thread"); + setThreadedReadBufferSize(65536); + setPriority(piHigh); +} + + +bool PIEthernet::init() { + //cout << "init " << type_ << endl; + if (sock_s == sock) + sock_s = -1; + closeSocket(sock); + closeSocket(sock_s); + int st = 0, pr = 0; + if (type() == UDP) { + st = SOCK_DGRAM; + pr = IPPROTO_UDP; + } else { + st = SOCK_STREAM; + pr = IPPROTO_TCP; + } + PIFlags params = parameters(); + sock = socket(AF_INET, st, pr); + if (params[SeparateSockets]) + sock_s = socket(AF_INET, st, pr); + else + sock_s = sock; + if (sock == -1 || sock_s == -1) { + piCoutObj << "Can`t create socket, " << ethErrorString(); + return false; + } + if (params[PIEthernet::ReuseAddress]) ethSetsockoptBool(sock, SOL_SOCKET, SO_REUSEADDR); + if (params[PIEthernet::Broadcast]) ethSetsockoptBool(sock, SOL_SOCKET, SO_BROADCAST); + applyTimeouts(); + applyOptInt(IPPROTO_IP, IP_TTL, TTL()); + //cout << "inited " << sock << ": bc = " << params << endl; + //fcntl(sock, F_SETFL, 0/*O_NONBLOCK*/); + return true; +} + + +void PIEthernet::parseAddress(const PIString & ipp, PIString * ip, int * port) { + if (ip != 0) *ip = ipp.left(ipp.find(":")); + if (port != 0) *port = ipp.right(ipp.length() - ipp.find(":") - 1).toInt(); +} + + +bool PIEthernet::openDevice() { + if (connected_) return true; + init(); + if (sock == -1 || path().isEmpty()) return false; + parseAddress(path(), &ip_, &port_); + if (type() == TCP_Client) + connecting_ = true; + if (type() != UDP || mode() == PIIODevice::WriteOnly) + return true; + memset(&addr_, 0, sizeof(addr_)); + addr_.sin_family = AF_INET; + addr_.sin_port = htons(port_); + PIFlags params = parameters(); + if (params[PIEthernet::Broadcast]) addr_.sin_addr.s_addr = INADDR_ANY; + else addr_.sin_addr.s_addr = inet_addr(ip_.data()); +#ifdef QNX + addr_.sin_len = sizeof(addr_); +#endif + //piCout << "bind to" << (params[PIEthernet::Broadcast] ? "255.255.255.255" : ip_) << ":" << port_ << " ..."; + int tries = 0; + while ((bind(sock, (sockaddr * )&addr_, sizeof(addr_)) == -1) && (tries < 10)) { + init(); + tries++; + } + if (tries == 10) { + piCoutObj << "Can`t bind to " << ip_ << ":" << port_ << ", " << ethErrorString(); + return false; + } + opened_ = true; + while (!mcast_queue.isEmpty()) + joinMulticastGroup(mcast_queue.dequeue()); + //cout << "!" << endl; + applyTimeouts(); + applyOptInt(IPPROTO_IP, IP_TTL, TTL()); + port_r = 0; + ip_r.clear(); + return true; +} + + +bool PIEthernet::closeDevice() { + //cout << "close\n"; + if (server_thread_.isRunning()) { + server_thread_.stop(); + if (!server_thread_.waitForFinish(100)) + server_thread_.terminate(); + } + if (sock_s == sock) + sock_s = -1; + closeSocket(sock); + closeSocket(sock_s); + piForeach (PIEthernet * i, clients_) + delete i; + clients_.clear(); + if (connected_) disconnected(false); + connected_ = false; + return true; +} + + +void PIEthernet::closeSocket(int & sd) { + if (sd != -1) + ethClosesocket(sd); + sd = -1; +} + + +void PIEthernet::applyTimeouts() { + if (sock < 0) return; + double rtm = readTimeout(), wtm = writeTimeout(); + applyTimeout(sock, SO_RCVTIMEO, rtm); + applyTimeout(sock, SO_SNDTIMEO, wtm); + if (sock_s != sock && sock_s != -1) { + applyTimeout(sock_s, SO_RCVTIMEO, rtm); + applyTimeout(sock_s, SO_SNDTIMEO, wtm); + } +} + + +void PIEthernet::applyTimeout(int fd, int opt, double ms) { + if (fd == 0) return; + double s = ms / 1000.; + timeval tm; + tm.tv_sec = piFloord(s); s -= tm.tv_sec; + tm.tv_usec = s * 1000000.; + //piCoutObj << "setReadIsBlocking" << yes; + ethSetsockopt(fd, SOL_SOCKET, opt, &tm, sizeof(tm)); +} + + +void PIEthernet::applyOptInt(int level, int opt, int val) { + if (sock < 0) return; + ethSetsockoptInt(sock, level, opt, val); + if (sock_s != sock && sock_s != -1) + ethSetsockoptInt(sock_s, level, opt, val); +} + + +void PIEthernet::setParameter(PIEthernet::Parameters parameter, bool on) { + PIFlags cp = (PIFlags)(property("parameters").toInt()); + cp.setFlag(parameter, on); + setParameters(cp); +} + + +bool PIEthernet::joinMulticastGroup(const PIString & group) { + if (sock == -1) init(); + if (sock == -1) return false; + if (type() != UDP) { + piCoutObj << "Only UDP sockets can join multicast groups"; + return false; + } + if (!opened_) { + if (mcast_queue.contains(group)) + return false; + mcast_queue.enqueue(group); + if (!mcast_groups.contains(group)) mcast_groups << group; + return true; + } + PIFlags params = parameters(); +#ifndef QNX + if (!params[Broadcast]) + ;//piCoutObj << "Warning: \"Broadcast\" parameter not set, \"joinMulticastGroup(\"" << group << "\")\" may be useless!"; + parseAddress(path(), &ip_, &port_); + struct ip_mreqn mreq; + memset(&mreq, 0, sizeof(mreq)); +#ifdef LINUX + //mreq.imr_address.s_addr = INADDR_ANY; + /*PIEthernet::InterfaceList il = interfaces(); + const PIEthernet::Interface * ci = il.getByAddress(ip_); + if (ci != 0) mreq.imr_ifindex = ci->index;*/ +#endif + if (params[PIEthernet::Broadcast]) mreq.imr_address.s_addr = INADDR_ANY; + else mreq.imr_address.s_addr = inet_addr(ip_.data()); +/*#ifndef WINDOWS + PIEthernet::InterfaceList il = interfaces(); + const PIEthernet::Interface * ci = il.getByAddress(ip_); + if (ci != 0) mreq.imr_ifindex = ci->index; +#endif*/ + //piCout << "join group" << group << "ip" << ip_ << "with index" << mreq.imr_ifindex << "socket" << sock; + mreq.imr_multiaddr.s_addr = inet_addr(group.data()); + if (ethSetsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) != 0) { + piCoutObj << "Can`t join multicast group " << group << ", " << ethErrorString(); + return false; + } + if (params[PIEthernet::MulticastLoop]) ethSetsockoptInt(sock, IPPROTO_IP, IP_MULTICAST_LOOP); + applyOptInt(IPPROTO_IP, IP_MULTICAST_TTL, multicastTTL()); + if (!mcast_groups.contains(group)) mcast_groups << group; +#endif + return true; +} + + +bool PIEthernet::leaveMulticastGroup(const PIString & group) { + if (sock == -1) init(); + if (sock == -1) return false; + if (type() != UDP) { + piCoutObj << "Only UDP sockets can leave multicast groups"; + return false; + } + PIFlags params = parameters(); +#ifndef QNX + /// TODO windows + parseAddress(path(), &ip_, &port_); + struct ip_mreqn mreq; + memset(&mreq, 0, sizeof(mreq)); + if (params[PIEthernet::Broadcast]) mreq.imr_address.s_addr = INADDR_ANY; + else mreq.imr_address.s_addr = inet_addr(ip_.data()); + mreq.imr_multiaddr.s_addr = inet_addr(group.data()); + if (ethSetsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) { + piCoutObj << "Can`t leave multicast group " << group << ", " << ethErrorString(); + return false; + } + mcast_groups.removeAll(group); +#endif + return true; +} + + +bool PIEthernet::connect() { + connecting_ = true; + return true; + /*if (sock == -1) return false; + memset(&addr_, 0, sizeof(addr_)); + parseAddress(path_, &ip_, &port_); + addr_.sin_port = htons(port_); + addr_.sin_addr.s_addr = inet_addr(ip_.data()); + addr_.sin_family = AF_INET; +#ifdef QNX + addr_.sin_len = sizeof(addr_); +#endif + //piCoutObj << "connect to " << ip << ":" << port_; + connected_ = (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) == 0); + if (!connected_) + piCoutObj << "Can`t connect to " << ip_ << ":" << port_ << ", " << ethErrorString(); + opened_ = connected_; + if (connected_) connected(); + return connected_;*/ +} + + +bool PIEthernet::listen(bool threaded) { + if (sock == -1) init(); + if (sock == -1) return false; + if (threaded) { + if (server_thread_.isRunning()) { + if (!server_bounded) return true; + server_thread_.stop(); + if (!server_thread_.waitForFinish(100)) + server_thread_.terminate(); + } + listen_threaded = true; + server_bounded = false; + server_thread_.start(server_func); + return true; + } + listen_threaded = server_bounded = false; + parseAddress(path(), &ip_, &port_); + memset(&addr_, 0, sizeof(addr_)); + addr_.sin_port = htons(port_); + addr_.sin_addr.s_addr = inet_addr(ip_.data()); + addr_.sin_family = AF_INET; +#ifdef QNX + addr_.sin_len = sizeof(addr_); +#endif + opened_ = false; + int tries = 0; + while ((bind(sock, (sockaddr * )&addr_, sizeof(addr_)) == -1) && (tries < 10)) { + init(); + tries++; + } + if (tries == 10) { + piCoutObj << "Can`t bind to " << ip_ << ":" << port_ << ", " << ethErrorString(); + return false; + } + if (::listen(sock, 64) == -1) { + piCoutObj << "Can`t listen on "<< ip_ << ":" << port_ << ", " << ethErrorString(); + return false; + } + opened_ = server_bounded = true; + //piCoutObj << "listen on " << ip_ << ":" << port_; + server_thread_.start(server_func); + return true; +} + + +int PIEthernet::read(void * read_to, int max_size) { + //cout << "read " << sock << endl; + if (sock == -1) init(); + if (sock == -1 || read_to == 0) return -1; + int rs = 0, s = 0, lerr = 0; + sockaddr_in client_addr; + socklen_t slen = sizeof(client_addr); + //piCoutObj << "read from " << ip_ << ":" << port_ << endl; + switch (type()) { + case TCP_SingleTCP: + ::listen(sock, 64); + s = accept(sock, (sockaddr * )&client_addr, &slen); + if (s == -1) { + //piCoutObj << "Can`t accept new connection, " << ethErrorString(); + msleep(1); + return -1; + } + rs = ethRecv(s, read_to, max_size); + closeSocket(s); + return rs; + case TCP_Client: + if (connecting_) { + memset(&addr_, 0, sizeof(addr_)); + parseAddress(path(), &ip_, &port_); + addr_.sin_port = htons(port_); + addr_.sin_addr.s_addr = inet_addr(ip_.data()); + addr_.sin_family = AF_INET; +#ifdef QNX + addr_.sin_len = sizeof(addr_); +#endif + //piCoutObj << "connect to " << ip_ << ":" << port_ << "..."; + connected_ = (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) == 0); + //piCoutObj << "connect to " << ip_ << ":" << port_ << connected_; + if (!connected_) + piCoutObj << "Can`t connect to " << ip_ << ":" << port_ << ", " << ethErrorString(); + opened_ = connected_; + if (connected_) { + connecting_ = false; + connected(); + } else + piMSleep(10); + //piCout << "connected to" << path(); + } + if (!connected_) return -1; + errorClear(); + rs = ethRecv(sock, read_to, max_size); + //piCoutObj << "readed" << rs; + if (rs <= 0) { + lerr = ethErrorCore(); +#ifdef WINDOWS + if (lerr == WSAEWOULDBLOCK || /*lerr == NO_ERROR ||*/ lerr == WSAETIMEDOUT) { +#else + if (lerr == EAGAIN || lerr == EWOULDBLOCK) { +#endif + //piCoutObj << errorString(); + piMSleep(10); + return -1; + } + if (connected_) { + init(); + disconnected(rs < 0); + } + connected_ = false; + //piCoutObj << "eth" << ip_ << "disconnected"; + } + if (rs > 0) received(read_to, rs); + return rs; + case UDP: + memset(&raddr_, 0, sizeof(raddr_)); + rs = ethRecvfrom(sock, read_to, max_size, 0, (sockaddr*)&raddr_); + //piCout << "eth" << path() << "read return" << rs << errorString(); + if (rs > 0) { + port_r = ntohs(raddr_.sin_port); + ip_r = inet_ntoa(raddr_.sin_addr); + //piCout << "received from" << lastReadAddress(); + received(read_to, rs); + } + return rs; + //return ::read(sock, read_to, max_size); + default: break; + //return ::read(sock, (char * )read_to, max_size); + } + return -1; +} + + +int PIEthernet::write(const void * data, int max_size) { + if (sock == -1) init(); + if (sock == -1 || !isWriteable()) { + //piCoutObj << "Can`t send to uninitialized socket"; + return -1; + } + //piCoutObj << "sending to " << ip_s << ":" << port_s << " " << max_size << " bytes"; + int ret = 0; + switch (type()) { + case TCP_SingleTCP: + memset(&addr_, 0, sizeof(addr_)); + addr_.sin_port = htons(port_s); + addr_.sin_addr.s_addr = inet_addr(ip_s.data()); + addr_.sin_family = AF_INET; +#ifdef QNX + addr_.sin_len = sizeof(addr_); +#endif + //piCoutObj << "connect SingleTCP" << ip_s << ":" << port_s << "..."; + if (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) != 0) { + //piCoutObj << "Can`t connect to " << ip_s << ":" << port_s << ", " << ethErrorString(); + msleep(1); + return -1; + } + //piCoutObj << "ok, write SingleTCP" << int(data) << max_size << "bytes ..."; + ret = ::send(sock, (const char *)data, max_size, 0); + //piCoutObj << "ok, ret" << ret; + closeSocket(sock); + init(); + return ret; + case UDP: + saddr_.sin_port = htons(port_s); + /*if (params[PIEthernet::Broadcast]) saddr_.sin_addr.s_addr = INADDR_BROADCAST; + else*/ saddr_.sin_addr.s_addr = inet_addr(ip_s.data()); + saddr_.sin_family = AF_INET; + //piCout << "[PIEth] write to" << ip_s << ":" << port_s << "socket" << sock_s << max_size << "bytes ..."; + return ethSendto(sock_s, data, max_size, 0, (sockaddr * )&saddr_, sizeof(saddr_)); + //piCout << "[PIEth] write to" << ip_s << ":" << port_s << "ok"; + case TCP_Client: + if (connecting_) { + memset(&addr_, 0, sizeof(addr_)); + parseAddress(path(), &ip_, &port_); + addr_.sin_port = htons(port_); + addr_.sin_addr.s_addr = inet_addr(ip_.data()); + addr_.sin_family = AF_INET; +#ifdef QNX + addr_.sin_len = sizeof(addr_); +#endif + //piCoutObj << "connect to " << ip << ":" << port_; + connected_ = (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) == 0); + if (!connected_) + piCoutObj << "Can`t connect to " << ip_ << ":" << port_ << ", " << ethErrorString(); + opened_ = connected_; + if (connected_) { + connecting_ = false; + connected(); + } + } + if (!connected_) return -1; + ret = ::send(sock, (const char *)data, max_size, 0); + if (ret < 0) { + connected_ = false; { + init(); + disconnected(true); + } + } + return ret; + default: break; + //return ::read(sock, read_to, max_size); + } + return -1; +} + +void PIEthernet::server_func(void * eth) { + PIEthernet * ce = (PIEthernet * )eth; + if (ce->listen_threaded) { + if (!ce->server_bounded) { + if (!ce->listen(false)) { + ce->listen_threaded = true; + piMSleep(100); + return; + } + } + } + sockaddr_in client_addr; + socklen_t slen = sizeof(client_addr); + int s = accept(ce->sock, (sockaddr * )&client_addr, &slen); + if (s == -1) { + if (ce->debug()) piCout << "[PIEthernet] Can`t accept new connection, " << ethErrorString(); + piMSleep(10); + return; + } + PIString ip(inet_ntoa(client_addr.sin_addr)); + ip += ":" + PIString::fromNumber(htons(client_addr.sin_port)); + ce->clients_ << new PIEthernet(s, ip); + ce->newConnection(ce->clients_.back()); + //cout << "connected " << ip << endl; + //char d[256]; + //cout << " recv " << recv(s, d, 256, 0) << endl; + //cout << recv(ce->clients_.back()->sock, d, 256, 0) << endl; + +} + + +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; + setReadIP(readDeviceSetting("ip", readIP(), em, ep)); + setReadPort(readDeviceSetting("port", readPort(), em, ep)); + setParameter(PIEthernet::Broadcast, readDeviceSetting("broadcast", isParameterSet(PIEthernet::Broadcast), em, ep)); + setParameter(PIEthernet::ReuseAddress, readDeviceSetting("reuseAddress", isParameterSet(PIEthernet::ReuseAddress), em, ep)); + return true; +} + + +void PIEthernet::propertyChanged(const PIString & name) { + if (name.endsWith("Timeout")) applyTimeouts(); + if (name == "TTL") applyOptInt(IPPROTO_IP, IP_TTL, TTL()); + if (name == "MulticastTTL") applyOptInt(IPPROTO_IP, IP_MULTICAST_TTL, multicastTTL()); +} + + +PIString PIEthernet::constructFullPath() const { + PIString ret(fullPathPrefix() + "://"); + ret << (type() == PIEthernet::UDP ? "UDP" : "TCP") << ":" << readIP() << ":" << readPort(); + if (type() == PIEthernet::UDP) { + ret << ":" << sendIP() << ":" << sendPort(); + piForeachC (PIString & m, multicastGroups()) + ret << ":mcast:" << m; + } + return ret; +} + + +void PIEthernet::configureFromFullPath(const PIString & full_path) { + PIStringList pl = full_path.split(":"); + bool mcast = false; + for (int i = 0; i < pl.size_s(); ++i) { + PIString p(pl[i]); + switch (i) { + case 0: + p = p.toLowerCase(); + if (p == "udp") setType(UDP); + if (p == "tcp") setType(TCP_Client); + break; + case 1: setReadIP(p); setSendIP(p); break; + case 2: setReadPort(p.toInt()); setSendPort(p.toInt()); break; + case 3: setSendIP(p); break; + case 4: setSendPort(p.toInt()); break; + } + if (i <= 4) continue; + if (i % 2 == 1) {if (p.toLowerCase() == "mcast") mcast = true;} + else {if (mcast) {joinMulticastGroup(p); mcast = false;}} + } +} + + +PIEthernet::InterfaceList PIEthernet::interfaces() { + PIEthernet::InterfaceList il; + Interface ci; + ci.index = -1; + ci.mtu = 1500; +#ifdef WINDOWS + PIP_ADAPTER_INFO pAdapterInfo, pAdapter = 0; + int ret = 0; + ulong ulOutBufLen = sizeof(IP_ADAPTER_INFO); + pAdapterInfo = (IP_ADAPTER_INFO * ) HeapAlloc(GetProcessHeap(), 0, (sizeof (IP_ADAPTER_INFO))); + if (pAdapterInfo == 0) { + piCout << "[PIEthernet] Error allocating memory needed to call GetAdaptersinfo"; + return il; + } + if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) { + HeapFree(GetProcessHeap(), 0, (pAdapterInfo)); + pAdapterInfo = (IP_ADAPTER_INFO *) HeapAlloc(GetProcessHeap(), 0, (ulOutBufLen)); + if (pAdapterInfo == 0) { + piCout << "[PIEthernet] Error allocating memory needed to call GetAdaptersinfo"; + return il; + } + } + if ((ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) { + pAdapter = pAdapterInfo; + while (pAdapter) { + ci.name = PIString(pAdapter->AdapterName); + ci.index = pAdapter->Index; + ci.address = PIString(pAdapter->IpAddressList.IpAddress.String); + if (ci.address == "0.0.0.0") { + pAdapter = pAdapter->Next; + continue; + } + ci.mac = macFromBytes(PIByteArray(pAdapter->Address, pAdapter->AddressLength)); + ci.netmask = PIString(pAdapter->IpAddressList.IpMask.String); + ci.flags = PIEthernet::ifActive | PIEthernet::ifRunning; + //if (ret->ifa_flags & IFF_BROADCAST) ci.flags |= PIEthernet::ifBroadcast; + //if (ret->ifa_flags & IFF_MULTICAST) ci.flags |= PIEthernet::ifMulticast; + if (pAdapter->Type == MIB_IF_TYPE_PPP) ci.flags |= PIEthernet::ifPTP; + if (pAdapter->Type == MIB_IF_TYPE_LOOPBACK) ci.flags |= PIEthernet::ifLoopback; + ci.broadcast.clear(); + ci.ptp.clear(); + /*if (ci.flags[PIEthernet::ifBroadcast]) + ci.broadcast = getSockAddr(ret->ifa_broadaddr); + if (ci.flags[PIEthernet::ifPTP]) + ci.ptp = getSockAddr(ret->ifa_dstaddr);*/ + il << ci; + pAdapter = pAdapter->Next; + } + } else + piCout << "[PIEthernet] GetAdaptersInfo failed with error: " << ret; + if (pAdapterInfo) + HeapFree(GetProcessHeap(), 0, (pAdapterInfo)); +#else +/*# ifdef QNX + PIStringList il, sl; + PIProcess proc; + proc.setGrabOutput(true); + proc.exec(ifconfigPath.c_str(), "-l"); + if (!proc.waitForFinish(1000)) return sl; + PIString out(proc.readOutput()); + il = out.split(" "); + il.removeAll(""); + piForeachC (PIString & i, il) { + proc.exec(ifconfigPath.c_str(), i); + if (!proc.waitForFinish(1000)) return il; + sl << i.trimmed(); + out = proc.readOutput(); + int al = out.length(); + al = (al - out.replaceAll("alias", "").length()) / 5; + for (int j = 0; j < al; ++j) + sl << i.trimmed() + ":" + PIString::fromNumber(j); + } + return sl; +# else + PIStringList sl; + PIProcess proc; + proc.setGrabOutput(true); + proc.exec(ifconfigPath.c_str(), "-s"); + if (!proc.waitForFinish(1000)) return sl; + PIString out(proc.readOutput()); + out.cutLeft(out.find('\n') + 1); + while (!out.isEmpty()) { + sl << out.left(out.find(' ')); + out.cutLeft(out.find('\n') + 1); + } + return sl; +# endif*/ +# ifdef ANDROID + struct ifconf ifc; + int s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); + ifc.ifc_len = 256; + ifc.ifc_buf = new char[ifc.ifc_len]; + if (ioctl(s, SIOCGIFCONF, &ifc) < 0) { + piCout << "[PIEthernet] Can`t get interfaces:" << errorString(); + delete ifc.ifc_buf; + return il; + } + int icnt = ifc.ifc_len / sizeof(ifreq); + PIStringList inl; + struct ifreq ir; + for (int i = 0; i < icnt; ++i) { + PIString in(ifc.ifc_req[i].ifr_name); + if (in.isEmpty()) continue; + ci.name = in; + strcpy(ir.ifr_name, in.data()); + if (ioctl(s, SIOCGIFHWADDR, &ir) == 0) + ci.mac = macFromBytes(PIByteArray(ir.ifr_hwaddr.sa_data, 6)); + if (ioctl(s, SIOCGIFADDR, &ir) >= 0) + ci.address = getSockAddr(&ir.ifr_addr); + if (ioctl(s, SIOCGIFNETMASK, &ir) >= 0) + ci.netmask = getSockAddr(&ir.ifr_addr); + ioctl(s, SIOCGIFMTU, &ci.mtu); + il << ci; + } + delete ifc.ifc_buf; +# else + struct ifaddrs * ret; + int s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); + if (getifaddrs(&ret) == 0) { + while (ret != 0) { + if (ret->ifa_addr == 0) { + ret = ret->ifa_next; + continue; + } + if (ret->ifa_addr->sa_family != AF_INET) { + ret = ret->ifa_next; + continue; + } + ci.name = PIString(ret->ifa_name); + ci.address = getSockAddr(ret->ifa_addr); + ci.netmask = getSockAddr(ret->ifa_netmask); + ci.mac.clear(); +# ifdef QNX + int fd = ::open((PIString("/dev/io-net/") + ci.name).data(), O_RDONLY); + if (fd != 0) { + nic_config_t nic; + devctl(fd, DCMD_IO_NET_GET_CONFIG, &nic, sizeof(nic), 0); + ::close(fd); + ci.mac = macFromBytes(PIByteArray(nic.permanent_address, 6)); + } +# else +# ifdef MAC_OS + PIString req = PISystemInfo::instance()->ifconfigPath + " " + ci.name + " | grep ether"; + FILE * fp = popen(req.data(), "r"); + if (fp != 0) { + char in[256]; + if (fgets(in, 256, fp) != 0) { + req = PIString(in).trim(); + ci.mac = req.cutLeft(req.find(" ") + 1).trim().toUpperCase(); + } + pclose(fp); + } +# else + if (s != -1) { + struct ifreq ir; + strcpy(ir.ifr_name, ret->ifa_name); + if (ioctl(s, SIOCGIFHWADDR, &ir) == 0) { + ci.mac = macFromBytes(PIByteArray(ir.ifr_hwaddr.sa_data, 6)); + ci.mtu = ir.ifr_mtu; + } + } +# endif +# endif + ci.flags = 0; + if (ret->ifa_flags & IFF_UP) ci.flags |= PIEthernet::ifActive; + if (ret->ifa_flags & IFF_RUNNING) ci.flags |= PIEthernet::ifRunning; + if (ret->ifa_flags & IFF_BROADCAST) ci.flags |= PIEthernet::ifBroadcast; + if (ret->ifa_flags & IFF_MULTICAST) ci.flags |= PIEthernet::ifMulticast; + if (ret->ifa_flags & IFF_LOOPBACK) ci.flags |= PIEthernet::ifLoopback; + if (ret->ifa_flags & IFF_POINTOPOINT) ci.flags |= PIEthernet::ifPTP; + ci.broadcast.clear(); + ci.ptp.clear(); + if (ci.flags[PIEthernet::ifBroadcast]) + ci.broadcast = getSockAddr(ret->ifa_broadaddr); + if (ci.flags[PIEthernet::ifPTP]) + ci.ptp = getSockAddr(ret->ifa_dstaddr); + ci.index = if_nametoindex(ret->ifa_name); + il << ci; + ret = ret->ifa_next; + } + freeifaddrs(ret); + } else + piCout << "[PIEthernet] Can`t get interfaces:" << errorString(); + if (s != -1) ::close(s); +# endif +#endif + return il; +} + + +PIString PIEthernet::interfaceAddress(const PIString & interface_) { +#ifdef WINDOWS + piCout << "[PIEthernet] Not implemented on Windows, use \"PIEthernet::allAddresses\" or \"PIEthernet::interfaces\" instead"; + return PIString(); +#else + struct ifreq ifr; + memset(&ifr, 0, sizeof(ifr)); + strcpy(ifr.ifr_name, interface_.data()); + int s = socket(AF_INET, SOCK_DGRAM, 0); + ioctl(s, SIOCGIFADDR, &ifr); + ::close(s); + struct sockaddr_in * sa = (struct sockaddr_in * )&ifr.ifr_addr; + return PIString(inet_ntoa(sa->sin_addr)); +#endif + +} + + +PIStringList PIEthernet::allAddresses() { +/*#ifdef WINDOWS + PIStringList al; + PIString ca; + PIP_ADAPTER_INFO pAdapterInfo, pAdapter = 0; + int ret = 0; + ulong ulOutBufLen = sizeof(IP_ADAPTER_INFO); + pAdapterInfo = (IP_ADAPTER_INFO * ) HeapAlloc(GetProcessHeap(), 0, (sizeof (IP_ADAPTER_INFO))); + if (pAdapterInfo == 0) { + piCout << "[PIEthernet] Error allocating memory needed to call GetAdaptersinfo"; + return PIStringList(); + } + if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) { + HeapFree(GetProcessHeap(), 0, (pAdapterInfo)); + pAdapterInfo = (IP_ADAPTER_INFO *) HeapAlloc(GetProcessHeap(), 0, (ulOutBufLen)); + if (pAdapterInfo == 0) { + piCout << "[PIEthernet] Error allocating memory needed to call GetAdaptersinfo"; + return PIStringList(); + } + } + if ((ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) { + pAdapter = pAdapterInfo; + while (pAdapter) { + ca = PIString(pAdapter->IpAddressList.IpAddress.String); + if (ca != "0.0.0.0") al << ca; + pAdapter = pAdapter->Next; + } + } else + piCout << "[PIEthernet] GetAdaptersInfo failed with error: " << ret; + if (pAdapterInfo) + HeapFree(GetProcessHeap(), 0, (pAdapterInfo)); + return al; +#else*/ + PIEthernet::InterfaceList il = interfaces(); + PIStringList al; + piForeachC (PIEthernet::Interface & i, il) + al << i.address; + return al.removeStrings("0.0.0.0"); +//#endif +} + + +// System wrap + + +int PIEthernet::ethErrorCore() { +#ifdef WINDOWS + return WSAGetLastError(); +#else + return errno; +#endif + +} + + +PIString PIEthernet::ethErrorString() { +#ifdef WINDOWS + char * msg; + int err = WSAGetLastError(); + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msg, 0, NULL); + return "code " + PIString::fromNumber(err) + " - " + PIString(msg); +#else + return errorString(); +#endif +} + + +int PIEthernet::ethRecv(int sock, void * buf, int size, int flags) { + if (sock < 0) return -1; + return recv(sock, +#ifdef WINDOWS + (char*) +#endif + buf, size, flags); +} + + +int PIEthernet::ethRecvfrom(int sock, void * buf, int size, int flags, sockaddr * addr) { + if (sock < 0) return -1; +#ifdef QNX + return recv(sock, buf, size, flags); +#else + socklen_t len = sizeof(sockaddr); + return recvfrom(sock, +# ifdef WINDOWS + (char*) +# endif + buf, size, flags, addr, &len); +#endif +} + + +int PIEthernet::ethSendto(int sock, const void * buf, int size, int flags, sockaddr * addr, int addr_len) { + if (sock < 0) return -1; + return sendto(sock, +#ifdef WINDOWS + (const char*) +#endif + buf, size, flags, addr, addr_len); +} + + +void PIEthernet::ethClosesocket(int sock) { + if (sock < 0) return; +#ifdef WINDOWS + shutdown(sock, SD_BOTH); + closesocket(sock); +#else + shutdown(sock, SHUT_RDWR); + ::close(sock); +#endif +} + + +int PIEthernet::ethSetsockopt(int sock, int level, int optname, const void * optval, int optlen) { + if (sock < 0) return -1; + return setsockopt(sock, level, optname, +#ifdef WINDOWS + (char*) +#endif + optval, optlen); +} + + +int PIEthernet::ethSetsockoptInt(int sock, int level, int optname, int value) { + if (sock < 0) return -1; +#ifdef WINDOWS + DWORD +#else + int +#endif + so = value; + return ethSetsockopt(sock, level, optname, &so, sizeof(so)); +} + + +int PIEthernet::ethSetsockoptBool(int sock, int level, int optname, bool value) { + if (sock < 0) return -1; +#ifdef WINDOWS + BOOL +#else + int +#endif + so = (value ? 1 : 0); + return ethSetsockopt(sock, level, optname, &so, sizeof(so)); +} diff --git a/src/io/piethernet.h b/src/io/piethernet.h new file mode 100755 index 00000000..daee7cbf --- /dev/null +++ b/src/io/piethernet.h @@ -0,0 +1,424 @@ +/*! \file piethernet.h + * \brief Ethernet device +*/ +/* + PIP - Platform Independent Primitives + Ethernet, UDP/TCP Broadcast/Multicast + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIETHERNET_H +#define PIETHERNET_H + +#include "pitimer.h" +#include "piiodevice.h" +#include "piprocess.h" + +class PIP_EXPORT PIEthernet: public PIIODevice +{ + PIIODEVICE(PIEthernet) + friend class PIPeer; +public: + + //! Contructs UDP %PIEthernet with empty read address + PIEthernet(); + + //! \brief Type of %PIEthernet + enum PIP_EXPORT Type { + UDP /** UDP - User Datagram Protocol */ , + TCP_Client /** TCP client - allow connection to TCP server */ , + TCP_Server /** TCP server - receive connections from TCP clients */ , + TCP_SingleTCP + }; + + //! \brief Parameters of %PIEthernet + enum PIP_EXPORT Parameters { + ReuseAddress /** Rebind address if there is already binded. Enabled by default */ = 0x1, + Broadcast /** Broadcast send. Disabled by default */ = 0x2, + SeparateSockets /** If this parameter is set, %PIEthernet will initialize two different sockets, + for receive and send, instead of single one. Disabled by default */ = 0x4, + MulticastLoop /** Enable receiving multicast packets from same host. Enabled by default */ = 0x8 + }; + + //! Contructs %PIEthernet with type "type", read address "ip_port" and parameters "params" + PIEthernet(Type type, const PIString & ip_port = PIString(), const PIFlags params = 0); + + virtual ~PIEthernet(); + + + //! Set read address + void setReadAddress(const PIString & ip, int port) {setPath(ip + ":" + PIString::fromNumber(port));} + + //! Set read address in format "i.i.i.i:p" + void setReadAddress(const PIString & ip_port) {setPath(ip_port);} + + //! Set read IP + void setReadIP(const PIString & ip) {parseAddress(path(), &ip_, &port_); setPath(ip + ":" + PIString::fromNumber(port_));} + + //! Set read port + void setReadPort(int port) {parseAddress(path(), &ip_, &port_); setPath(ip_ + ":" + PIString::fromNumber(port));} + + + //! Set send address + void setSendAddress(const PIString & ip, int port) {ip_s = ip; port_s = port;} + + //! Set send address in format "i.i.i.i:p" + void setSendAddress(const PIString & ip_port) {parseAddress(ip_port, &ip_s, &port_s);} + + //! Set send IP + void setSendIP(const PIString & ip) {ip_s = ip;} + + //! Set send port + void setSendPort(int port) {port_s = port;} + + + //! Returns read address in format "i.i.i.i:p" + PIString readAddress() const {return path();} + + //! Returns read IP + PIString readIP() const {parseAddress(path(), &ip_, &port_); return ip_;} + + //! Returns read port + int readPort() const {parseAddress(path(), &ip_, &port_); return port_;} + + + //! Returns send address in format "i.i.i.i:p" + PIString sendAddress() const {return ip_s + ":" + PIString::fromNumber(port_s);} + + //! Returns send IP + PIString sendIP() const {return ip_s;} + + //! Returns send port + int sendPort() const {return port_s;} + + + //! Returns address of last received UDP packet in format "i.i.i.i:p" + PIString lastReadAddress() const {return ip_r + ":" + PIString::fromNumber(port_r);} + + //! Returns IP of last received UDP packet + PIString lastReadIP() const {return ip_r;} + + //! Returns port of last received UDP packet + int lastReadPort() const {return port_r;} + + + //! Set parameters to "parameters_". You should to reopen %PIEthernet to apply them + void setParameters(PIFlags parameters_) {setProperty("parameters", (int)parameters_);} + + //! Set parameter "parameter" to state "on". You should to reopen %PIEthernet to apply this + void setParameter(PIEthernet::Parameters parameter, bool on = true); + + //! Returns if parameter "parameter" is set + bool isParameterSet(PIEthernet::Parameters parameter) const {return ((PIFlags)(property("parameters").toInt()))[parameter];} + + //! Returns parameters + PIFlags parameters() const {return (PIFlags)(property("parameters").toInt());} + + //PIByteArray macAddress() {if (!init_) init(); struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); memcpy(ifr.ifr_name, "eth0", 5); ioctl(sock, SIOCSIFHWADDR, &ifr); return PIByteArray(&ifr.ifr_hwaddr.sa_data, 6);} + + //! Returns %PIEthernet type + Type type() const {return (Type)(property("type").toInt());} + + //! Returns read timeout + double readTimeout() const {return property("readTimeout").toDouble();} + + //! Returns write timeout + double writeTimeout() const {return property("writeTimeout").toDouble();} + + //! Set timeout for read + void setReadTimeout(double ms) {setProperty("readTimeout", ms);} + + //! Set timeout for write + void setWriteTimeout(double ms) {setProperty("writeTimeout", ms);} + + + //! Returns TTL (Time To Live) + int TTL() const {return property("TTL").toInt();} + + //! Returns multicast TTL (Time To Live) + int multicastTTL() const {return property("MulticastTTL").toInt();} + + //! Set TTL (Time To Live), default is 64 + void setTTL(int ttl) {setProperty("TTL", ttl);} + + //! Set multicast TTL (Time To Live), default is 1 + void setMulticastTTL(int ttl) {setProperty("MulticastTTL", ttl);} + + + //! Join to multicast group with address "group". Use only for UDP + bool joinMulticastGroup(const PIString & group); + + //! Leave multicast group with address "group". Use only for UDP + bool leaveMulticastGroup(const PIString & group); + + //! Returns joined multicast groups. Use only for UDP + const PIStringList & multicastGroups() const {return mcast_groups;} + + + //! Connect to TCP server with address \a readAddress(). Use only for TCP_Client + bool connect(); + + //! Connect to TCP server with address "ip":"port". Use only for TCP_Client + bool connect(const PIString & ip, int port) {setPath(ip + ":" + PIString::fromNumber(port)); return connect();} + + //! Connect to TCP server with address "ip_port". Use only for TCP_Client + bool connect(const PIString & ip_port) {setPath(ip_port); return connect();} + + //! Returns if %PIEthernet connected to TCP server. Use only for TCP_Client + bool isConnected() const {return connected_;} + + + //! Start listen for incoming TCP connections on address \a readAddress(). Use only for TCP_Server + bool listen(bool threaded = false); + + //! Start listen for incoming TCP connections on address "ip":"port". Use only for TCP_Server + bool listen(const PIString & ip, int port, bool threaded = false) {setReadAddress(ip, port); return listen(threaded);} + + //! Start listen for incoming TCP connections on address "ip_port". Use only for TCP_Server + bool listen(const PIString & ip_port, bool threaded = false) {setReadAddress(ip_port); return listen(threaded);} + + PIEthernet * client(int index) {return clients_[index];} + int clientsCount() const {return clients_.size_s();} + PIVector clients() const {return clients_;} + + + //! Send data "data" with size "size" to address \a sendAddress() for UDP or \a readAddress() for TCP_Client + bool send(const void * data, int size, bool threaded = false) {if (threaded) {writeThreaded(data, size); return true;} return (write(data, size) == size);} + + //! Send data "data" with size "size" to address "ip":"port" + bool send(const PIString & ip, int port, const void * data, int size, bool threaded = false) {ip_s = ip; port_s = port; if (threaded) {writeThreaded(data, size); return true;} return send(data, size);} + + //! Send data "data" with size "size" to address "ip_port" + bool send(const PIString & ip_port, const void * data, int size, bool threaded = false) {parseAddress(ip_port, &ip_s, &port_s); if (threaded) {writeThreaded(data, size); return true;} return send(data, size);} + + //! Send data "data" to address \a sendAddress() for UDP or \a readAddress() for TCP_Client + bool send(const PIByteArray & data, bool threaded = false) {if (threaded) {writeThreaded(data); return true;} return (write(data) == data.size_s());} + + //! Send data "data" to address "ip":"port" for UDP + bool send(const PIString & ip, int port, const PIByteArray & data, bool threaded = false) {ip_s = ip; port_s = port; if (threaded) {writeThreaded(data); return true;} return send(data);} + + //! Send data "data" to address "ip_port" for UDP + bool send(const PIString & ip_port, const PIByteArray & data, bool threaded = false) {parseAddress(ip_port, &ip_s, &port_s); if (threaded) {writeThreaded(data); return true;} return (write(data) == data.size_s());} + + + //! Wait for some data and read it to "read_to" + int read(void * read_to, int max_size); + + //! Send data "read_to" with size "max_size" to address \a sendAddress() for UDP or \a readAddress() for TCP_Client + int write(const void * data, int max_size); + + //! Send data "data" to address \a sendAddress() for UDP or \a readAddress() for TCP_Client + int write(const PIByteArray & data) {return write(data.data(), data.size_s());} + + virtual bool canWrite() const {return mode() & WriteOnly;} + + PIString constructFullPath() const; + + EVENT1(newConnection, PIEthernet * , client) + EVENT0(connected) + EVENT1(disconnected, bool, withError) + + + //! Flags of network interface + enum PIP_EXPORT InterfaceFlag { + ifActive /** Is active */ = 0x1, + ifRunning /** Is running */ = 0x2, + ifBroadcast /** Support broadcast */ = 0x4, + ifMulticast /** Support multicast */ = 0x8, + ifLoopback /** Is loopback */ = 0x10, + ifPTP /** Is point-to-point */ = 0x20 + }; + + //! %PIFlags of network interface flags + typedef PIFlags InterfaceFlags; + + + //! Network interface descriptor + struct PIP_EXPORT Interface { + + //! System index + int index; + + //! MTU + int mtu; + + //! System name + PIString name; + + //! MAC address in format "hh:hh:hh:hh:hh:hh" or empty if there is no MAC address + PIString mac; + + //! IP address in format "i.i.i.i" or empty if there is no IP address + PIString address; + + //! Netmask of IP address in format "i.i.i.i" or empty if there is no netmask + PIString netmask; + + //! Broadcast address in format "i.i.i.i" or empty if there is no broadcast address + PIString broadcast; + + //! Point-to-point address or empty if there is no point-to-point address + PIString ptp; + + //! Flags of interface + InterfaceFlags flags; + + //! Returns if interface is active + bool isActive() const {return flags[PIEthernet::ifActive];} + + //! Returns if interface is running + bool isRunning() const {return flags[PIEthernet::ifRunning];} + + //! Returns if interface support broadcast + bool isBroadcast() const {return flags[PIEthernet::ifBroadcast];} + + //! Returns if interface support multicast + bool isMulticast() const {return flags[PIEthernet::ifMulticast];} + + //! Returns if interface is loopback + bool isLoopback() const {return flags[PIEthernet::ifLoopback];} + + //! Returns if interface is point-to-point + bool isPTP() const {return flags[PIEthernet::ifPTP];} + }; + + + //! Array of \a Interface with some features + class PIP_EXPORT InterfaceList: public PIVector { + public: + InterfaceList(): PIVector() {} + + //! Get interface with system index "index" or 0 if there is no one + const Interface * getByIndex(int index) const {for (int i = 0; i < size_s(); ++i) if ((*this)[i].index == index) return &((*this)[i]); return 0;} + + //! Get interface with system name "name" or 0 if there is no one + const Interface * getByName(const PIString & name) const {for (int i = 0; i < size_s(); ++i) if ((*this)[i].name == name) return &((*this)[i]); return 0;} + + //! Get interface with IP address "address" or 0 if there is no one + const Interface * getByAddress(const PIString & address) const {for (int i = 0; i < size_s(); ++i) if ((*this)[i].address == address) return &((*this)[i]); return 0;} + + //! Get loopback interface or 0 if there is no one + const Interface * getLoopback() const {for (int i = 0; i < size_s(); ++i) if ((*this)[i].isLoopback()) return &((*this)[i]); return 0;} + }; + + + //! Returns all system network interfaces + static InterfaceList interfaces(); + + static PIString interfaceAddress(const PIString & interface_); + + //! Returns all system network IP addresses + static PIStringList allAddresses(); + + static void parseAddress(const PIString & ipp, PIString * ip, int * port); + static PIString macFromBytes(const PIByteArray & mac) {PIString r; for (int i = 0; i < mac.size_s(); ++i) {r += PIString::fromNumber(mac[i], 16).expandLeftTo(2, '0'); if (i < mac.size_s() - 1) r += ":";} return r;} + static PIByteArray macToBytes(const PIString & mac) {PIByteArray r; PIStringList sl = mac.split(":"); piForeachC (PIString & i, sl) r << uchar(i.toInt(16)); return r;} + static PIString applyMask(const PIString & ip, const PIString & mask) {struct in_addr ia; ia.s_addr = inet_addr(ip.data()) & inet_addr(mask.data()); return PIString(inet_ntoa(ia));} + static PIString getBroadcast(const PIString & ip, const PIString & mask) {struct in_addr ia; ia.s_addr = inet_addr(ip.data()) | ~inet_addr(mask.data()); return PIString(inet_ntoa(ia));} + +//! \events +//! \{ + + //! \fn void newConnection(PIEthernet * client) + //! \brief Raise on new TCP connection received + + //! \fn void connected() + //! \brief Raise if succesfull TCP connection + + //! \fn void disconnected(bool withError) + //! \brief Raise if TCP connection was closed + +//! \} +//! \ioparams +//! \{ +#ifdef DOXYGEN + //! \brief read ip, default "" + string ip; + + //! \brief read port, default 0 + int port; + + //! \brief ethernet parameters + int parameters; + + //! \brief read timeout, default 1000 ms + double readTimeout; + + //! \brief write timeout, default 1000 ms + double writeTimeout; + + //! \brief time-to-live, default 64 + int TTL; + + //! \brief time-to-live for multicast, default 1 + int multicastTTL; +#endif +//! \} + +protected: + PIEthernet(int sock, PIString ip_port); + + void propertyChanged(const PIString & name); + + PIString fullPathPrefix() const {return "eth";} + void configureFromFullPath(const PIString & full_path); + bool configureDevice(const void * e_main, const void * e_parent = 0); + + //! Executes when any read function was successful. Default implementation does nothing + virtual void received(const void * data, int size) {;} + + void construct(); + bool init(); + bool openDevice(); + bool closeDevice(); + void closeSocket(int & sd); + void applyTimeouts(); + void applyTimeout(int fd, int opt, double ms); + void applyOptInt(int level, int opt, int val); +#ifndef WINDOWS + static PIString getSockAddr(sockaddr * s) {return s == 0 ? PIString() : PIString(inet_ntoa(((sockaddr_in*)s)->sin_addr));} +#endif + + + int sock, sock_s, wrote; + mutable int port_, port_s, port_c, port_r; + bool connected_, connecting_, listen_threaded, server_bounded; + sockaddr_in addr_, saddr_, raddr_; + mutable PIString ip_, ip_s, ip_c, ip_r; + PIThread server_thread_; + PIVector clients_; + PIQueue mcast_queue; + PIStringList mcast_groups; + +private: + static void server_func(void * eth); + void setType(Type t, bool reopen = true) {setProperty("type", (int)t); if (reopen && isOpened()) {closeDevice(); init(); openDevice();}} + + inline static int ethErrorCore(); + inline static PIString ethErrorString(); + inline static int ethRecv(int sock, void * buf, int size, int flags = 0); + inline static int ethRecvfrom(int sock, void * buf, int size, int flags, sockaddr * addr); + inline static int ethSendto(int sock, const void * buf, int size, int flags, sockaddr * addr, int addr_len); + inline static void ethClosesocket(int sock); + inline static int ethSetsockopt(int sock, int level, int optname, const void * optval, int optlen); + inline static int ethSetsockoptInt(int sock, int level, int optname, int value = 1); + inline static int ethSetsockoptBool(int sock, int level, int optname, bool value = true); + +}; + +inline bool operator <(const PIEthernet::Interface & v0, const PIEthernet::Interface & v1) {return (v0.name < v1.name);} + +#endif // PIETHERNET_H diff --git a/src/io/pifile.cpp b/src/io/pifile.cpp new file mode 100755 index 00000000..7e9c134b --- /dev/null +++ b/src/io/pifile.cpp @@ -0,0 +1,317 @@ +/* + PIP - Platform Independent Primitives + File + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pifile.h" +#include "pidir.h" +#ifdef WINDOWS +# undef S_IFDIR +# undef S_IFREG +# undef S_IFLNK +# undef S_IFBLK +# undef S_IFCHR +# undef S_IFSOCK +# define S_IFDIR 0x01 +# define S_IFREG 0x02 +# define S_IFLNK 0x04 +# define S_IFBLK 0x08 +# define S_IFCHR 0x10 +# define S_IFSOCK 0x20 +#endif +#define S_IFHDN 0x40 +#ifdef QNX +# define _stat_struct_ struct stat +# define _stat_call_ stat +# define _stat_link_ lstat +#else +# define _stat_struct_ struct stat64 +# define _stat_call_ stat64 +# define _stat_link_ lstat64 +#endif + + +/*! \class PIFile + * \brief Local file + * + * \section PIFile_sec0 Synopsis + * This class provide access to local file. You can manipulate + * binary content or use this class as text stream. To binary + * access there are function \a read(), \a write(), and many + * \a writeBinary() functions. For write variables to file in + * their text representation threr are many "<<" operators. + * + * \section PIFile_sec1 Position + * Each opened file has a read/write position - logical position + * in the file content you read from or you write to. You can + * find out current position with function \a pos(). Function + * \a seek(llong position) move position to position "position", + * \a seekToBegin() move position to the begin of file, + * \a seekToEnd() move position to the end of file. + * + */ + +REGISTER_DEVICE(PIFile); + + +PIString PIFile::FileInfo::name() const { + if (path.isEmpty()) return PIString(); + return path.mid(path.findLast(PIDir::separator) + 1); +} + + +PIString PIFile::FileInfo::baseName() const { + if (path.isEmpty()) return PIString(); + PIString n = name(), e = extension(); + if (e.isEmpty()) return n; + return n.cutRight(e.size_s() + 1); +} + + +PIString PIFile::FileInfo::extension() const { + PIString n = name(); + if (n.isEmpty()) return PIString(); + while (n.startsWith(".")) + n.pop_front(); + if (n.isEmpty()) return PIString(); + int i = n.find("."); + if (i < 0) return PIString(); + return n.mid(i + 1); +} + + +PIString PIFile::FileInfo::dir() const { + if (path.isEmpty()) return PIString(); + PIString ret = path.mid(0, path.findLast(PIDir::separator)); + if (ret.isEmpty()) ret = PIDir::separator; + return ret; +} + + + + +PIFile::PIFile(): PIIODevice() { + setPrecision(5); +} + + +PIFile::PIFile(const PIString & path, PIIODevice::DeviceMode mode): PIIODevice(path, mode) { + setPrecision(5); + if (!path.isEmpty()) + openDevice(); +} + + +bool PIFile::openDevice() { + close(); + PIString p = path(); + if (p.isEmpty()) return false; + //piCout << "fopen " << path_.data() << ": " << strType(mode_).data() << fd; + if ((mode_ & PIIODevice::WriteOnly) == PIIODevice::WriteOnly) { + if (!isExists(p)) { + FILE * fd = fopen(p.data(), "w"); + if (fd != 0) fclose(fd); + } + } + fd = fopen(p.data(), strType(mode_).data()); + opened_ = (fd != 0); +#ifndef WINDOWS + if (opened_) fcntl(fileno(fd), F_SETFL, O_NONBLOCK); +#endif + seekToBegin(); + //piCout << "open file" << fd << opened_; + return opened_; +} + + +bool PIFile::closeDevice() { + //piCout << "close file" << fd << opened_; + if (!opened_ || fd == 0) return true; + bool cs = (fclose(fd) == 0); + if (cs) fd = 0; + //piCout << "closed file" << fd << opened_; + return cs; +} + + +PIString PIFile::readLine() { + PIString str; + if (!opened_) return str; + int cc, cp = 0; + while (!isEnd() && cp < 4095) { + cc = fgetc(fd); + if (char(cc) == '\n' || cc == EOF) break; + str.push_back(char(cc)); + } + //cout << "readline: " << str << endl; + return str; +} + + +llong PIFile::readAll(void * data) { + llong cp = pos(), s = size(), i = -1; + seekToBegin(); + if (s < 0) { + while (!isEnd()) + read(&(((char*)data)[++i]), 1); + } else + read((char * )data, s); + seek(cp); + return s; +} + + +PIByteArray PIFile::readAll(bool forceRead) { + PIByteArray a; + llong cp = pos(); + if (forceRead) { + seekToBegin(); + while (!isEnd()) + a.push_back(readChar()); + seek(cp); + return a; + } + llong s = size(); + if (s < 0) return a; + a.resize(s); + s = readAll(a.data()); + seek(cp); + if (s >= 0) a.resize(s); + return a; +} + + +llong PIFile::size() const { + if (!opened_) return -1; + llong s, cp = pos(); + fseek(fd, 0, SEEK_END); clearerr(fd); + s = pos(); + fseek(fd, cp, SEEK_SET); clearerr(fd); + return s; +} + + +void PIFile::resize(llong new_size, uchar fill_) { + llong ds = new_size - size(); + if (ds == 0) return; + if (ds > 0) { + uchar * buff = new uchar[ds]; + memset(buff, fill_, ds); + write(buff, ds); + delete[] buff; + return; + } + if (new_size == 0) { + clear(); + return; + } + piCoutObj << "Downsize is not supported yet :-("; +} + + + +bool PIFile::isExists(const PIString & path) { + FILE * f = fopen(PIString(path).data(), "r"); + bool ok = (f != 0); + if (ok) fclose(f); + return ok; +} + + +PIString PIFile::constructFullPath() const { + return fullPathPrefix() + "://" + path(); +} + + +void PIFile::configureFromFullPath(const PIString & full_path) { + setPath(full_path); +} + + +PIString PIFile::strType(const PIIODevice::DeviceMode type) { + switch (type) { + case PIIODevice::ReadOnly: return "rb"; + case PIIODevice::ReadWrite: + case PIIODevice::WriteOnly: return "r+b"; + } + return "rb"; +} + + +PIFile::FileInfo PIFile::fileInfo(const PIString & path) { + FileInfo ret; + if (path.isEmpty()) return ret; + ret.path = path; + PIString n = ret.name(); + //piCout << "open" << path; +#ifdef WINDOWS + DWORD attr = GetFileAttributes((LPCTSTR)(path.data())); + if (attr == 0xFFFFFFFF) return ret; + HANDLE hFile = 0; + if ((attr & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY) { + hFile = CreateFile(path.data(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); + } else { + hFile = CreateFile(path.data(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + } + if (!hFile) return ret; + BY_HANDLE_FILE_INFORMATION fi; + memset(&fi, 0, sizeof(fi)); + if (GetFileInformationByHandle(hFile, &fi) != 0) { + LARGE_INTEGER filesize; + filesize.LowPart = filesize.HighPart = 0; + if (fi.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ret.flags |= FileInfo::Hidden; + if (fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ret.flags |= FileInfo::Dir; + else { + ret.flags |= FileInfo::File; + filesize.LowPart = fi.nFileSizeLow; + filesize.HighPart = fi.nFileSizeHigh; + } + PIString ext = ret.extension(); + ret.perm_user = FileInfo::Permissions(true, (attr & FILE_ATTRIBUTE_READONLY) != FILE_ATTRIBUTE_READONLY, ext == "bat" || ext == "exe"); + ret.perm_group = ret.perm_other = ret.perm_user; + ret.size = filesize.QuadPart; + ret.time_access = PIDateTime(fi.ftLastAccessTime); + ret.time_modification = PIDateTime(fi.ftLastWriteTime); + } + CloseHandle(hFile); +#else + _stat_struct_ fs; + memset(&fs, 0, sizeof(fs)); + _stat_call_(path.data(), &fs); + int mode = fs.st_mode; + ret.size = fs.st_size; + ret.id_user = fs.st_uid; + ret.id_group = fs.st_gid; + ret.time_access = PIDateTime::fromSystemTime(PISystemTime(fs.st_atim.tv_sec, fs.st_atim.tv_nsec)); + ret.time_modification = PIDateTime::fromSystemTime(PISystemTime(fs.st_mtim.tv_sec, fs.st_mtim.tv_nsec)); + ret.perm_user = FileInfo::Permissions((mode & S_IRUSR) == S_IRUSR, (mode & S_IWUSR) == S_IWUSR, (mode & S_IXUSR) == S_IXUSR); + ret.perm_group = FileInfo::Permissions((mode & S_IRGRP) == S_IRGRP, (mode & S_IWGRP) == S_IWGRP, (mode & S_IXGRP) == S_IXGRP); + ret.perm_other = FileInfo::Permissions((mode & S_IROTH) == S_IROTH, (mode & S_IWOTH) == S_IWOTH, (mode & S_IXOTH) == S_IXOTH); + memset(&fs, 0, sizeof(fs)); + _stat_link_(path.data(), &fs); + mode &= ~S_IFLNK; + mode |= S_IFLNK & fs.st_mode; + if (n.startsWith(".")) mode |= S_IFHDN; + if ((mode & S_IFDIR) == S_IFDIR) ret.flags |= FileInfo::Dir; + if ((mode & S_IFREG) == S_IFREG) ret.flags |= FileInfo::File; + if ((mode & S_IFLNK) == S_IFLNK) ret.flags |= FileInfo::SymbolicLink; + if ((mode & S_IFHDN) == S_IFHDN) ret.flags |= FileInfo::Hidden; +#endif + if (n == ".") ret.flags = FileInfo::Dir | FileInfo::Dot; + if (n == "..") ret.flags = FileInfo::Dir | FileInfo::DotDot; + return ret; +} diff --git a/src/io/pifile.h b/src/io/pifile.h new file mode 100755 index 00000000..9e1c8565 --- /dev/null +++ b/src/io/pifile.h @@ -0,0 +1,309 @@ +/*! \file pifile.h + * \brief Local file +*/ +/* + PIP - Platform Independent Primitives + File + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIFILE_H +#define PIFILE_H + +#include "piiodevice.h" +#include + +class PIP_EXPORT PIFile: public PIIODevice +{ + PIIODEVICE(PIFile) +public: + + //! Constructs an empty file + PIFile(); + + struct FileInfo { + FileInfo() {size = 0; id_group = id_user = 0;} + + enum Flag { + File = 0x01, + Dir = 0x02, + Dot = 0x04, + DotDot = 0x08, + SymbolicLink = 0x10, + Hidden = 0x20 + }; + typedef PIFlags Flags; + struct Permissions { + Permissions(uchar r = 0): raw(r) {} + Permissions(bool r, bool w, bool e): raw(0) {read = w; write = w; exec = e;} + PIString toString() const {return PIString(read ? "r" : "-") + PIString(write ? "w" : "-") + PIString(exec ? "x" : "-");} + union { + uchar raw; + struct { + uchar read : 1; + uchar write: 1; + uchar exec : 1; + }; + }; + }; + + PIString path; + llong size; + PIDateTime time_access; + PIDateTime time_modification; + Flags flags; + uint id_user; + uint id_group; + Permissions perm_user; + Permissions perm_group; + Permissions perm_other; + + PIString name() const; + PIString baseName() const; + PIString extension() const; + PIString dir() const; + bool isDir() const {return flags[Dir];} + bool isFile() const {return flags[File];} + bool isSymbolicLink() const {return flags[SymbolicLink];} + bool isHidden() const {return flags[Hidden];} + }; + + //! Constructs a file with path "path" nad open mode "type" + PIFile(const PIString & path, DeviceMode mode = ReadWrite); + + ~PIFile() {close();} + + //PIFile & operator =(const PIFile & f) {path_ = f.path_; type_ = f.type_; return *this;} + + + //! Immediate write all buffered data to disk + void flush() {if (opened_) fflush(fd);} + + //! Move read/write position to "position" + void seek(llong position) {if (!opened_) return; fseek(fd, position, SEEK_SET); clearerr(fd);} + + //! Move read/write position to the begin of the file + void seekToBegin() {if (!opened_) return; fseek(fd, 0, SEEK_SET); clearerr(fd);} + + //! Move read/write position to the end of the file + void seekToEnd() {if (!opened_) return; fseek(fd, 0, SEEK_END); clearerr(fd);} + + //! Move read/write position to text line number "line" + void seekToLine(llong line) {if (!opened_) return; seekToBegin(); piForTimes (line) readLine(); clearerr(fd);} // line 0 - begin of file + //void fill(char c) {stream.fill(c);} + + //! Read one char and return it + char readChar() {return (char)fgetc(fd);} + + //! Read one text line and return it + PIString readLine(); + + //! Read all file content to "data" and return readed bytes count. Position leaved unchanged + llong readAll(void * data); + + //! Read all file content to byte array and return it. Position leaved unchanged + PIByteArray readAll(bool forceRead = false); + + + //! Set file path to "path" and reopen file if need + void setPath(const PIString & path) {PIIODevice::setPath(path); if (opened_) openDevice();} + + //! Returns file size + llong size() const; + + //! Returns read/write position + llong pos() const {if (!opened_) return -1; return ftell(fd);} + + //! Returns if position is at the end of file + bool isEnd() const {if (!opened_) return true; return (feof(fd) || ferror(fd));} + + //! Returns if file is empty + bool isEmpty() const {return (size() <= 0);} + + //! Returns FileInfo of current file + FileInfo fileInfo() const {return fileInfo(path());} + + + //! Returns float numbers write precision + int precision() const {return prec_;} + + //! Set float numbers write precision to "prec_" digits + void setPrecision(int prec) {prec_ = prec; if (prec_ >= 0) prec_str = "." + itos(prec_); else prec_str = "";} + + + //! Read from file to "read_to" no more than "max_size" and return readed bytes count + int read(void * read_to, int max_size) {if (!canRead() || fd == 0) return -1; return fread(read_to, 1, max_size, fd);} + + //! Write to file "data" with size "max_size" and return written bytes count + int write(const void * data, int max_size) {if (!canWrite() || fd == 0) return -1; return fwrite(data, 1, max_size, fd);} + + PIFile & writeToBinLog(ushort id, const void * data, int size) {if (!isWriteable() || fd == 0) return *this; writeBinary(id).writeBinary((ushort)size); write(data, size); flush(); return *this;} + + + //! Write to file binary content of "v" + PIFile & writeBinary(const char v) {write(&v, sizeof(v)); return *this;} + //! Write to file binary content of "v" + PIFile & writeBinary(const short v) {write(&v, sizeof(v)); return *this;} + //! Write to file binary content of "v" + PIFile & writeBinary(const int v) {write(&v, sizeof(v)); return *this;} + //! Write to file binary content of "v" + PIFile & writeBinary(const long v) {write(&v, sizeof(v)); return *this;} + //! Write to file binary content of "v" + PIFile & writeBinary(const llong v) {write(&v, sizeof(v)); return *this;} + //! Write to file binary content of "v" + PIFile & writeBinary(const uchar v) {write(&v, sizeof(v)); return *this;} + //! Write to file binary content of "v" + PIFile & writeBinary(const ushort v) {write(&v, sizeof(v)); return *this;} + //! Write to file binary content of "v" + PIFile & writeBinary(const uint v) {write(&v, sizeof(v)); return *this;} + //! Write to file binary content of "v" + PIFile & writeBinary(const ulong v) {write(&v, sizeof(v)); return *this;} + //! Write to file binary content of "v" + PIFile & writeBinary(const ullong v) {write(&v, sizeof(v)); return *this;} + //! Write to file binary content of "v" + PIFile & writeBinary(const float v) {write(&v, sizeof(v)); return *this;} + //! Write to file binary content of "v" + PIFile & writeBinary(const double v) {write(&v, sizeof(v)); return *this;} + + PIFile & operator =(const PIFile & f) {PIIODevice::setPath(f.path()); mode_ = f.mode_; return *this;} + + //! Write to file text representation of "v" + PIFile & operator <<(const char v) {if (canWrite() && fd != 0) write(&v, 1); return *this;} + //PIFile & operator <<(const string & v) {write(v.c_str(), v.size()); return *this;} + //! Write to file string "v" + PIFile & operator <<(const PIString & v) {if (canWrite() && fd != 0) write(v.data(), v.lengthAscii()); return *this;} + //! Write to file text representation of "v" + PIFile & operator <<(const PIByteArray & v) {if (canWrite() && fd != 0) write(v.data(), v.size()); return *this;} + //! Write to file text representation of "v" + PIFile & operator <<(short v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%hd", v); return *this;} + //! Write to file text representation of "v" + PIFile & operator <<(int v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%d", v); return *this;} + //! Write to file text representation of "v" + PIFile & operator <<(long v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%ld", v); return *this;} + //! Write to file text representation of "v" + PIFile & operator <<(llong v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%lld", v); return *this;} + //! Write to file text representation of "v" + PIFile & operator <<(uchar v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%u", int(v)); return *this;} + //! Write to file text representation of "v" + PIFile & operator <<(ushort v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%hu", v); return *this;} + //! Write to file text representation of "v" + PIFile & operator <<(uint v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%u", v); return *this;} + //! Write to file text representation of "v" + PIFile & operator <<(ulong v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%lu", v); return *this;} + //! Write to file text representation of "v" + PIFile & operator <<(ullong v) {if (canWrite() && fd != 0) ret = fprintf(fd, "%llu", v); return *this;} + //! Write to file text representation of "v" with precision \a precision() + PIFile & operator <<(float v) {if (canWrite() && fd != 0) ret = fprintf(fd, ("%" + prec_str + "f").c_str(), v); return *this;} + //! Write to file text representation of "v" with precision \a precision() + PIFile & operator <<(double v) {if (canWrite() && fd != 0) ret = fprintf(fd, ("%" + prec_str + "lf").c_str(), v); return *this;} + + + //! Read from file text representation of "v" + PIFile & operator >>(char & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%hhn", &v); return *this;} + //! Read from file text representation of "v" + PIFile & operator >>(short & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%hn", &v); return *this;} + //! Read from file text representation of "v" + PIFile & operator >>(int & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%n", &v); return *this;} + //! Read from file text representation of "v" + PIFile & operator >>(long & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%ln", &v); return *this;} + //! Read from file text representation of "v" + PIFile & operator >>(llong & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%lln", &v); return *this;} + //! Read from file text representation of "v" + PIFile & operator >>(uchar & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%hhn", &v); return *this;} + //! Read from file text representation of "v" + PIFile & operator >>(ushort & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%hn", &v); return *this;} + //! Read from file text representation of "v" + PIFile & operator >>(uint & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%n", &v); return *this;} + //! Read from file text representation of "v" + PIFile & operator >>(ulong & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%ln", &v); return *this;} + //! Read from file text representation of "v" + PIFile & operator >>(ullong & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%lln", &v); return *this;} + //! Read from file text representation of "v" + PIFile & operator >>(float & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%f", &v); return *this;} + //! Read from file text representation of "v" + PIFile & operator >>(double & v) {if (canRead() && fd != 0) ret = fscanf(fd, "%lf", &v); return *this;} + + PIString constructFullPath() const; + + EVENT_HANDLER(void, clear) {close(); fd = fopen(path().data(), "w"); if (fd != 0) fclose(fd); fd = 0; opened_ = false; open();} + EVENT_HANDLER0(void, remove) {close(); std::remove(path().data());} + EVENT_HANDLER1(void, resize, llong, new_size) {resize(new_size, 0);} + EVENT_HANDLER2(void, resize, llong, new_size, uchar, fill); + + + //! Returns not opened temporary file with open mode "mode" + static PIFile openTemporary(PIIODevice::DeviceMode mode = PIIODevice::ReadWrite) {return PIFile(PIString(tmpnam(0)), mode);} + + //! Returns if file with path "path" does exists + static bool isExists(const PIString & path); + + //! Remove file with path "path" and returns if remove was successful + static bool remove(const PIString & path) {return std::remove(path.data()) == 0;} + + //! Rename file with path "from" to path "to" and returns if rename was successful + static bool rename(const PIString & from, const PIString & to) {return ::rename(from.data(), to.data()) == 0;} + + //! Returns FileInfo of file or dir with path "path" + static FileInfo fileInfo(const PIString & path); + +//! \handlers +//! \{ + + //! \fn void clear() + //! \brief Clear content of file + + //! \fn void resize(llong new_size) + //! \brief Resize file to "new_size" with "fill" filling + + //! \fn void resize(llong new_size, uchar fill) + //! \brief Resize file to "new_size" with "fill" filling + + //! \fn void remove() + //! \brief Remove file + +//! \} +//! \ioparams +//! \{ +#ifdef DOXYGEN +#endif +//! \} + +protected: + PIString fullPathPrefix() const {return "file";} + void configureFromFullPath(const PIString & full_path); + bool openDevice(); + bool closeDevice(); + +private: + PIString strType(const PIIODevice::DeviceMode type); + + FILE * fd; + int ret, prec_; + string prec_str; + +}; + +inline PICout operator <<(PICout s, const PIFile::FileInfo & v) { + s.setControl(0, true); + s << "FileInfo(\"" << v.path << "\", " << PIString::readableSize(v.size) << ", " + << v.perm_user.toString() << " " << v.perm_group.toString() << " " << v.perm_other.toString() << ", " + << v.time_access.toString() << ", " << v.time_modification.toString() + << ", 0x" << Hex << v.flags << ")"; + s.restoreControl(); + return s; +} + +#endif // PIFILE_H diff --git a/src/io/pifiletransfer.cpp b/src/io/pifiletransfer.cpp new file mode 100644 index 00000000..7dbd919c --- /dev/null +++ b/src/io/pifiletransfer.cpp @@ -0,0 +1,470 @@ +#include "pifiletransfer.h" + +const char PIFileTransfer::sign[] = {'P', 'F', 'T'}; + +PIFileTransfer::PIFileTransfer(): crc(standardCRC_16()) { + for (uint i = 0; i < sizeof(sign); i++) + header.sig[i] = sign[i]; + header.version = PIFILETRANSFER_VERSION; + header.session_id = 0; + dir = PIDir::current(); + fileinfo_size = sizeof(EntryInfo) + sizeof(PIByteArray) + 100; + min_packet_size = sizeof(PacketHeader) + sizeof(uint) + fileinfo_size; + is_sending = is_receiving = false; + bytes_file_all = bytes_file_cur = bytes_total_all = bytes_total_cur = 0; + timeout_ = 1.; + setPacketSize(4096); + srand(PISystemTime::current().toMilliseconds()); +} + + +PIFileTransfer::~PIFileTransfer() { + break_ = true; + session.clear(); + replies.clear(); +} + + +bool PIFileTransfer::send(const PIString & file) { + return sendFiles(PIVector() << PIFile::fileInfo(file)); +} + + +bool PIFileTransfer::send(PIVector entries) { + PIVector allEntries; + for (int i = 0; i < entries.size_s(); i++) { + allEntries << entries[i]; + if (entries[i].isDir()) + allEntries << PIDir::allEntries(dir.absolutePath() + dir.separator + entries[i].path); + } + return sendFiles(allEntries); +} + + +void PIFileTransfer::stopSend() { + if (!is_sending) return; + break_ = true; +} + + +void PIFileTransfer::stopReceive() { + if (!is_receiving) return; + break_ = true; + finish_receive(false); +} + + +void PIFileTransfer::received(PIByteArray & ba) { + if (ba.size() < sizeof(PacketHeader)) return; + PacketHeader h; + memcpy(&h, ba.data(), sizeof(PacketHeader)); + PacketType pt = (PacketType)h.type; +// piCoutObj << "receive" << h.session_id << h.type << h.id; + switch (pt) { + case pt_Data: + if (h.session_id != header.session_id || !is_receiving) { + sendBreak(h.session_id); + return; + } else { + uint rcrc = *(uint *)(ba.data(ba.size_s() - sizeof(uint))); + uint ccrc = crc.calculate(ba.data(), ba.size_s() - sizeof(uint)); + if (rcrc != ccrc) { + header.id = h.id; + sendReply(Invalid); + } else { + ba >> h; + ba.resize(ba.size_s() - sizeof(uint)); + processData(h.id, ba); + } + } + break; + case pt_Reply: + if (h.session_id != header.session_id) return; + ba >> h; + if (ba.size() == sizeof(int)) { + int rci; + ba >> rci; + ReplyCode rc = (ReplyCode)rci; +// piCoutObj << "reply received" << rci; + if (rc == Break) { + break_ = true; + if (is_receiving) { + stopReceive(); + return; + } + if (is_sending) { + stopSend(); + return; + } + } + if (is_sending) { + if (h.id >= 0 && h.id < replies.size()) + replies[h.id] = rc; + } + if (is_receiving && h.id == 0) { + if (checkSession() == 0) finish_receive(true); + } + } + break; + case pt_SendRequest: + if (is_sending) { + sendBreak(h.session_id); + return; + } + if (header.session_id != h.session_id && is_receiving) { + sendBreak(h.session_id); + return; + } + ba >> h; + if (ba.size() != sizeof(uint) + sizeof(llong)) return; + uint pcts; + ba >> pcts; + bytes_file_all = pcts; + ba >> bytes_total_all; + header.session_id = h.session_id; + header.id = 0; + bool ok = true; + state_string = "receive request"; + receiveRequest(&ok); + if (ok) { + session.clear(); + replies.clear(); + session.resize(pcts); + replies.resize(pcts + 1); + replies.fill(Unknown); + is_receiving = true; + state_string = "receiving"; + replies[0] = Success; + sendReply(Success); + } else { + sendReply(Invalid); + state_string = "wait user permit"; + } + break; + } +} + + +bool PIFileTransfer::sendFiles(PIVector files) { + PIStringList names; + for(int i=0; i 0) { + ba = buildPacket(chk - 1); + sendRequest(ba); + } +// if (chk == -1) return finish_send(false); + if (break_) return finish_send(false); + prev_chk = chk; + piMSleep(1); + } + return finish_send(false);; +} + + +int PIFileTransfer::checkSession() { + int miss = 0; + for (int i = 1; i < replies.size_s(); i++) { + if ((ReplyCode)replies[i] != Success) miss++; + if ((ReplyCode)replies[i] == Invalid) return i; + } + for (int i = 1; i < replies.size_s(); i++) { + if ((ReplyCode)replies[i] == Unknown) return i; + } + if (miss > 0) { + piCoutObj << "missing" << miss << "packets"; + return -miss; + } else return 0; +} + + +void PIFileTransfer::buildSession(PIVector files) { + state_string = "calculating files..."; + session.clear(); + header.session_id = rand(); + bytes_file_cur = 0; + bytes_file_all = files.size(); + bytes_total_all = bytes_total_cur = 0; +// PIMap sizes; +// for (int i=0; i indexes = sizes.values(); + EntryInfo fi; + PIVector lfi; + int cur_size = min_packet_size; + for (int i = 0; i < files.size_s(); i++) { + bytes_file_cur = i; + fi.entry = files[i]; + bytes_total_all += fi.entry.size; +// fi.size = fi.entry.size; + fi.fstart = 0; + fi.part_index = 1; + int rest = fi.entry.size - (max_packet_size - cur_size); +// piCout << i << fi.entry << rest; + if (rest <= 0) { + fi.parts = 1; + fi.fsize = fi.entry.size; + lfi << fi; + cur_size += fi.fsize + fileinfo_size; + } else { + fi.fsize = fi.entry.size - rest; + fi.parts = 1 + 1 + piMaxi(1, rest / (max_packet_size - min_packet_size)); +// piCout << fi.parts; + lfi << fi; + session << lfi; + lfi.clear(); + cur_size = min_packet_size; + llong fs = fi.fsize; + for (uint j = 1; j < fi.parts; j++) { + fi.part_index++; + fi.fstart = fs; + fi.fsize = piMinll(fi.entry.size - fs, max_packet_size - min_packet_size); + lfi << fi; + cur_size += fi.fsize + sizeof(PIByteArray); + if (fi.part_index != fi.parts) { + session << lfi; + lfi.clear(); + cur_size = min_packet_size; + fs += fi.fsize; + } + } + } + if (max_packet_size - cur_size < min_packet_size) { + session << lfi; + lfi.clear(); + cur_size = min_packet_size; + } + } + if (cur_size > min_packet_size) session << lfi; +} + + +void PIFileTransfer::sendBreak(int session_id) { + uint psid = header.session_id; + header.session_id = session_id; + sendReply(Break); + header.session_id = psid; +} + + +void PIFileTransfer::sendReply(PIFileTransfer::ReplyCode reply) { +// if (is_send_result) header.type = pt_SendResult; +// else + header.type = pt_Reply; + PIByteArray ba; + ba << header << (int)reply; + sendRequest(ba); +} + + +bool PIFileTransfer::getSendRequest() { + PITimeMeasurer tm; + header.type = pt_SendRequest; + header.id = 0; + PIByteArray ba; + ba << header; + ba << (uint)session.size() << bytes_total_all; + state_string = "send request"; + for (int i = 0; i < 3; i++) { + tm.reset(); + sendRequest(ba); + while (tm.elapsed_s() < timeout_) { + if (break_) return false; + //piCoutObj << send_replyes[0]; + if (replies[0] == Success) { + state_string = "send permited!"; + return true; + } + if (replies[0] == Invalid) { + state_string = "waiting for permit"; + tm.reset(); + } + piMSleep(10); + } + } + return false; +} + + +void PIFileTransfer::processData(int id, PIByteArray & data) { +// piCoutObj << "received packet" << id << ", size" << data.size(); + if (id < 1 || id > replies.size_s()) return; + if (!session[id - 1].isEmpty()) { + header.id = id; + replies[id] = Success; + sendReply(Success); + if (checkSession() == 0) state_string = "receive ok"; + return; + } + EntryInfo fi; + PIByteArray ba; + while (!data.isEmpty()) { + ba.clear(); + data >> fi; + if (fi.entry.size > 0) data >> ba; + fi.fsize = ba.size(); + bytes_total_cur += fi.fsize; + bytes_file_all = fi.entry.size; + bytes_file_cur = fi.fstart; +// piCoutObj << "recv" << fi; + session[id - 1] << fi; + state_string = "receiving " + fi.entry.path; + PIString path = dir.absolutePath() + dir.separator + fi.entry.path; + if (fi.entry.isDir()) { +// piCoutObj << "make dir" << fi.entry.path; + if (!PIDir::make(path, false)) { + state_string = "ERROR! while create directory " + path; + piCoutObj << state_string; + finish_receive(false); + return; + } + } + if (fi.entry.isFile()) { + if (work_file.path() != path || !work_file.isOpened()) { + work_file.close(); + if (!work_file.open(path, PIIODevice::ReadWrite)) { + state_string = "ERROR! while open file " + path; + piCoutObj << state_string; + finish_receive(false); + return; + } + if (work_file.size() > fi.entry.size) { + piCoutObj << "*** error size" << work_file.size() << fi.entry.size; + work_file.clear(); + work_file.resize(fi.entry.size); + piCoutObj << "*** correct size" << work_file.size() << fi.entry.size; + } + } +// piCoutObj << "write file" << path << work_file.path() << work_file.size() << fi.entry.size << work_file.pos() << fi.fstart << fi.fsize; + if (work_file.size() < fi.fstart) { +// piCoutObj << "error pos size" << work_file.pos() << fi.fstart; + work_file.resize(fi.fstart); +// piCoutObj << "correct pos size" << work_file.pos() << fi.fstart; + } + if (work_file.size() > fi.entry.size) { + piCoutObj << "!!! error size" << work_file.size() << fi.entry.size; + work_file.clear(); + work_file.resize(fi.entry.size); + piCoutObj << "!!! correct size" << work_file.size() << fi.entry.size; + } +// if (fi.fstart != work_file.pos()) piCoutObj << "error pos" << work_file.pos() << fi.fstart; + work_file.seek(fi.fstart); + int rs = work_file.write(ba.data(), ba.size()); + if (rs != fi.fsize) { + state_string = "ERROR! while read file " + fi.entry.path + " (must " + PIString::fromNumber(fi.fsize) + ", but read " + PIString::fromNumber(rs) + ")"; + piCoutObj << state_string; + finish_receive(false); + return; + } + } + } + header.id = id; + replies[id] = Success; + if (checkSession() == 0) state_string = "receive ok"; + sendReply(Success); +} + + +PIByteArray PIFileTransfer::buildPacket(int id) { + PIByteArray ret; + PIByteArray ba; + header.id = id + 1; + header.type = pt_Data; + //piCoutObj << "Packet" << header.id; + //piCoutObj << "session id" << header.session_id; + ret << header; + for (int i = 0; i < session[id].size_s(); i++) { + EntryInfo fi = session[id][i]; +// piCoutObj << "send" << fi; + bytes_total_cur += fi.fsize; + ret << fi; + if (fi.entry.size > 0) { + PIString path = dir.absolutePath() + dir.separator + fi.entry.path; + if (work_file.path() != path || !work_file.isOpened()) { + if (!work_file.open(path, PIIODevice::ReadOnly)) { + break_ = true; + state_string = "ERROR! while open file " + fi.entry.path; + piCoutObj << state_string; + return ret; + } + } + work_file.seek(fi.fstart); + ba.resize(fi.fsize); + int rs = work_file.read(ba.data(), ba.size()); + if (rs != fi.fsize) { + break_ = true; + state_string = "ERROR! while read file " + fi.entry.path + " (must " + PIString::fromNumber(fi.fsize) + ", but read " + PIString::fromNumber(rs) + ")"; + piCoutObj << state_string; + return ret; + } + ret << ba; + } + } + EntryInfo cfile = session[id].back(); + state_string = "sending: " + cfile.entry.path; + bytes_file_all = cfile.entry.size; + bytes_file_cur = cfile.fstart; + uint scrc = crc.calculate(ret); + ret << scrc; + //piCoutObj << "packet" << header.id << "send crc" << scrc; + return ret; +} + + +bool PIFileTransfer::finish_send(bool ok) { + if (ok) state_string = "send done"; + else state_string = "send failed"; +// piCoutObj << state_string << PIString::readableSize(bytes_total_all); + is_sending = false; + work_file.close(); + work_file.setPath(""); + bytes_file_all = bytes_file_cur = 0; + bytes_total_all = bytes_total_cur = 0; + header.id = 0; + if (!ok) sendBreak(header.session_id); + else sendReply(Success); + finishSend(ok); + return ok; +} + + +void PIFileTransfer::finish_receive(bool ok) { + if (ok) state_string = "receive done"; + else state_string = "receive failed"; +// piCoutObj << state_string << PIString::readableSize(bytes_total_all); + is_receiving = false; + work_file.close(); + work_file.setPath(""); + bytes_file_all = bytes_file_cur = 0; + bytes_total_all = bytes_total_cur = 0; + if (!ok) sendBreak(header.session_id); + finishReceive(ok); +} + diff --git a/src/io/pifiletransfer.h b/src/io/pifiletransfer.h new file mode 100644 index 00000000..1e8d1bb8 --- /dev/null +++ b/src/io/pifiletransfer.h @@ -0,0 +1,138 @@ +#ifndef PIFILETRANSFER_H +#define PIFILETRANSFER_H + +#include "pidir.h" +#include "picrc.h" + +#define PIFILETRANSFER_VERSION 1 + +class PIFileTransfer : public PIObject +{ + PIOBJECT(PIFileTransfer) +public: + PIFileTransfer(); + ~PIFileTransfer(); + + enum ReplyCode {Unknown = 0, Success, Invalid, Break}; + enum PacketType {pt_Data = 1, pt_Reply, pt_SendRequest};//, pt_SendResult}; + + + struct PacketHeader { + union { + struct { + char sig[3]; // PFT + uchar version; + }; + uint raw_sig; + }; + int type; // PacketType + uint session_id; + uint id; + bool check_sig() { + if (sig[0] != sign[0] || sig[1] != sign[1] || sig[2] != sign[2] || version != PIFILETRANSFER_VERSION) return false; + return true; + } +// uint crc; + }; + + struct PartHeader { + uint id; + uint total_size; + uint part_start; + uint part_size; + }; + + struct EntryInfo { + EntryInfo() { + fstart = fsize = 0; + parts = part_index = 0; + } + PIFile::FileInfo entry; + llong fstart; + llong fsize; + uint parts; + uint part_index; + }; + + //bool send(const PIFile & file); + bool send(const PIString & file); +// bool send(const PIStringList &files); + bool send(PIFile::FileInfo entry) {return send(PIVector() << entry);} + bool send(PIVector entries); + + void stopSend(); + void stopReceive(); + + bool isSending() const {return is_sending;} + bool isReceiving() const {return is_receiving;} + + void setPacketSize(int size) {max_packet_size = size;} + int packetSize() const {return max_packet_size;} + + void setTimeout(double sec) {timeout_ = sec;} + double timeout() const {return timeout_;} + + void setDirectory(const PIDir &d) {dir = d;} + void setDirectory(const PIString &path) {dir.setDir(path);} + PIDir directory() const {return dir;} + + const PIString & stateString() const {return state_string;} + llong bytesTotalAll() const {return bytes_total_all;} + llong bytesTotalCur() const {return bytes_total_cur;} + llong bytesFileAll() const {return bytes_file_all;} + llong bytesFileCur() const {return bytes_file_cur;} + const PIString * stateString_ptr() const {return &state_string;} + const llong * bytesTotalAll_ptr() const {return &bytes_total_all;} + const llong * bytesTotalCur_ptr() const {return &bytes_total_cur;} + const llong * bytesFileAll_ptr() const {return &bytes_file_all;} + const llong * bytesFileCur_ptr() const {return &bytes_file_cur;} + + EVENT(startReceive) + EVENT1(receiveRequest, bool *, ok) + EVENT1(finishReceive, bool, ok) + EVENT(startSend) + EVENT1(finishSend, bool, ok) + + EVENT1(sendRequest, PIByteArray &, data) + EVENT_HANDLER1(void, received, PIByteArray &, data); + +private: + static const char sign[]; + int max_packet_size, min_packet_size, fileinfo_size; + bool break_, is_sending, is_receiving; + double timeout_; + + PIVector > session; + PIVector replies; + PIString state_string; + llong bytes_total_all, bytes_total_cur, bytes_file_all, bytes_file_cur; + PacketHeader header; + PIDir dir; + PIFile work_file; + CRC_16 crc; + + bool sendFiles(PIVector files); + int checkSession(); + void buildSession(PIVector files); + void sendBreak(int session_id); + void sendReply(ReplyCode reply); + bool getSendRequest(); + void processData(int id, PIByteArray &data); + PIByteArray buildPacket(int id); + bool finish_send(bool ok); + void finish_receive(bool ok); +}; + +inline PIByteArray & operator <<(PIByteArray & s, const PIFileTransfer::PacketHeader & v) {s << v.raw_sig << v.type << v.session_id << v.id; return s;} +inline PIByteArray & operator >>(PIByteArray & s, PIFileTransfer::PacketHeader & v) {s >> v.raw_sig >> v.type >> v.session_id >> v.id; return s;} + +inline PIByteArray & operator <<(PIByteArray & s, const PIFileTransfer::PartHeader & v) {s << v.id << v.total_size << v.part_start << v.part_size; return s;} +inline PIByteArray & operator >>(PIByteArray & s, PIFileTransfer::PartHeader & v) {s >> v.id >> v.total_size >> v.part_start >> v.part_size; return s;} + +inline PIByteArray & operator <<(PIByteArray & s, const PIFileTransfer::EntryInfo & v) {s << v.entry.path << v.entry.size << v.entry.time_modification << v.entry.time_access << int(v.entry.flags) + << v.entry.id_user << v.entry.id_group << v.fstart; return s;} +inline PIByteArray & operator >>(PIByteArray & s, PIFileTransfer::EntryInfo & v) {s >> v.entry.path >> v.entry.size >> v.entry.time_modification >> v.entry.time_access >> (int&)(v.entry.flags) + >> v.entry.id_user >> v.entry.id_group >> v.fstart; return s;} +inline PICout operator <<(PICout s, const PIFileTransfer::EntryInfo & v) {s.setControl(0, true); s << "FileInfo(\"" << v.entry.path << "\", " << PIString::fromNumber(v.entry.flags, 16) << PIString::readableSize(v.entry.size) << " b | " << PIString::readableSize(v.fsize) << " b)"; s.restoreControl(); return s;} + +#endif // PIFILETRANSFER_H diff --git a/src/io/piiodevice.cpp b/src/io/piiodevice.cpp new file mode 100755 index 00000000..51d0571b --- /dev/null +++ b/src/io/piiodevice.cpp @@ -0,0 +1,315 @@ +/* + PIP - Platform Independent Primitives + Abstract input/output device + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "piiodevice.h" +#include "piconfig.h" + + +/*! \class PIIODevice + * \brief Base class for input/output classes + * + * \section PIIODevice_sec0 Synopsis + * This class provide open/close logic, threaded read/write and virtual input/output + * functions \a read() and \a write(). You should implement pure virtual + * function \a openDevice() in your subclass. + * + * \section PIIODevice_sec1 Open and close + * PIIODevice have boolean variable indicated open status. Returns of functions + * \a openDevice() and \a closeDevice() change this variable. + * + * \section PIIODevice_sec2 Threaded read + * PIIODevice based on PIThread, so it`s overload \a run() to exec \a read() + * in background thread. If read is successful virtual function \a threadedRead() + * is executed. Default implementation of this function execute external static + * function set by \a setThreadedReadSlot() with data set by \a setThreadedReadData(). + * Extrenal static function should have format \n + * bool func_name(void * Threaded_read_data, uchar * readed_data, int readed_size)\n + * Threaded read starts with function \a startThreadedRead(). + * + * \section PIIODevice_sec3 Threaded write + * PIIODevice aggregate another PIThread to perform a threaded write by function + * \a writeThreaded(). This function add task to internal queue and return + * queue entry ID. You should start write thread by function \a startThreadedWrite. + * On successful write event \a threadedWriteEvent is raised with two arguments - + * task ID and written bytes count. + * + * \section PIIODevice_sec4 Internal buffer + * PIIODevice have internal buffer for threaded read, and \a threadedRead() function + * receive pointer to this buffer in first argument. You can adjust size of this buffer + * by function \a setThreadedReadBufferSize() \n + * Default size of this buffer is 4096 bytes. + * + * \section PIIODevice_sec5 Reopen + * When threaded read is begin its call \a open() if device is closed. While threaded + * read running PIIODevice check if device opened every read and if not call \a open() + * every reopen timeout if reopen enabled. Reopen timeout is set by \a setReopenTimeout(), + * reopen enable is set by \a setReopenEnabled(). + * + * \section PIIODevice_sec6 Configuration + * This is virtual function \a configureDevice() which executes when \a configure() + * executes. This function takes two arguments: "e_main" and "e_parent" as void*. There + * are pointers to PIConfig::Entry entries of section "section" and their parent. If + * there is no parent "e_parent" = 0. Function \a configure() set three parameters of + * device: "reopenEnabled", "reopenTimeout" and "threadedReadBufferSize", then execute + * function \a configureDevice(). + * \n Each ancestor of %PIIODevice reimlements \a configureDevice() function to be able + * to be confured from configuration file. This parameters described at section + * "Configurable parameters" in the class reference. \n Usage example: + * \snippet piiodevice.cpp configure + * Implementation example: + * \snippet piiodevice.cpp configureDevice + * + * \section PIIODevice_sec7 Creating devices by unambiguous string + * There are some virtual functions to describe child class without its declaration. + * \n \a fullPathPrefix() should returns unique prefix of device + * \n \a constructFullPath() should returns full unambiguous string, contains prefix and all device parameters + * \n \a configureFromFullPath() provide configuring device from full unambiguous string without prefix and "://" + * \n Macro PIIODEVICE should be used instead of PIOBJECT + * \n Macro REGISTER_DEVICE should be used after definition of class, i.e. at the last line of *.cpp file + * \n \n If custom I/O device corresponds there rules, it can be returned by function \a createFromFullPath(). + * \n Each PIP I/O device has custom unambiguous string description: + * * PIFile: "file://" + * * PIBinaryLog: "binlog://[:][:]" + * * PISerial: "ser://:[:][:][:]" + * * PIEthernet: UDP "eth://UDP::::[:)>]" + * * PIEthernet: TCP "eth://TCP::" + * * PIUSB: "usb://:[:][:][:]" + * \n \n Examples: + * * PIFile: "file://../text.txt" + * * PIBinaryLog: "binlog://../logs/:mylog_:1" + * * PISerial: "ser:///dev/ttyUSB0:9600:8:N:1", equivalent "ser:///dev/ttyUSB0:9600" + * * PIEthernet: "eth://TCP:127.0.0.1:16666", "eth://UDP:192.168.0.5:16666:192.168.0.6:16667:mcast:234.0.2.1:mcast:234.0.2.2" + * * PIUSB: "usb://0bb4:0c86:1:1:2" + * \n \n + * So, custom I/O device can be created with next call: + * \code{cpp} + * // creatring devices + * PISerial * ser = (PISerial * )PIIODevice::createFromFullPath("ser://COM1:115200"); + * PIEthernet * eth = (PIEthernet * )PIIODevice::createFromFullPath("eth://UDP:127.0.0.1:4001:127.0.0.1:4002"); + * // examine devices + * piCout << ser << ser->properties(); + * piCout << eth << eth->properties(); + * \endcode + * + * \section PIIODevice_ex0 Example + * \snippet piiodevice.cpp 0 + */ + + +PIIODevice::PIIODevice(): PIThread() { + mode_ = ReadOnly; + _init(); + setPath(PIString()); +} + + +/*! \brief Constructs a PIIODevice with path and mode + * \param path path to device + * \param type mode for open */ +PIIODevice::PIIODevice(const PIString & path, PIIODevice::DeviceMode mode): PIThread() { + mode_ = mode; + _init(); + setPath(path); +} + + +PIIODevice::~PIIODevice() { + stop(); + if (opened_) { + closeDevice(); + if (!opened_) + closed(); + } +} + + +void PIIODevice::_init() { + opened_ = init_ = thread_started_ = false; + raise_threaded_read_ = true; + ret_func_ = 0; + ret_data_ = 0; + tri = 0; + setReopenEnabled(true); + setReopenTimeout(1000); + setThreadedReadBufferSize(4096); + timer.setName("__S__reopen_timer"); + write_thread.setName("__S__write_thread"); + CONNECT2(void, void * , int, &timer, tickEvent, this, check_start); + CONNECT(void, &write_thread, started, this, write_func); +} + + +void PIIODevice::check_start(void * data, int delim) { + //cout << "check " << tread_started_ << endl; + if (open()) { + thread_started_ = true; + timer.stop(); + } +} + + +void PIIODevice::write_func() { + while (!write_thread.isStopping()) { + while (!write_queue.isEmpty()) { + if (write_thread.isStopping()) return; + write_thread.lock(); + PIPair item(write_queue.dequeue()); + write_thread.unlock(); + int ret = write(item.first); + threadedWriteEvent(item.second, ret); + } + msleep(1); + } +} + + +void PIIODevice::terminate() { + thread_started_ = false; + if (!isInitialized()) return; + if (isRunning()) { + stop(); + PIThread::terminate(); + } +} + + +void PIIODevice::begin() { + //cout << " begin\n"; + thread_started_ = false; + if (!opened_) { + if (open()) { + thread_started_ = true; + //cout << " open && ok\n"; + return; + } + } else { + thread_started_ = true; + //cout << " ok\n"; + return; + } + //init(); + if (!timer.isRunning() && isReopenEnabled()) timer.start(reopenTimeout()); +} + + +void PIIODevice::run() { + if (!isReadable()) { + //cout << "not readable\n"; + PIThread::stop(); + return; + } + if (!thread_started_) { + msleep(5); + //cout << "not started\n"; + return; + } + readed_ = read(buffer_tr.data(), buffer_tr.size_s()); + if (readed_ <= 0) { + msleep(10); + //cout << readed_ << ", " << errno << ", " << errorString() << endl; + return; + } + //piCoutObj << "readed" << readed_;// << ", " << errno << ", " << errorString(); + threadedRead(buffer_tr.data(), readed_); + if (raise_threaded_read_) threadedReadEvent(buffer_tr.data(), readed_); +} + + +PIByteArray PIIODevice::readForTime(double timeout_ms) { + PIByteArray str; + if (timeout_ms <= 0.) return str; + int ret; + uchar * td = new uchar[threadedReadBufferSize()]; + tm.reset(); + while (tm.elapsed_m() < timeout_ms) { + ret = read(td, threadedReadBufferSize()); + if (ret <= 0) msleep(1); + else str.append(td, ret); + } + delete td; + return str; +} + + +ullong PIIODevice::writeThreaded(const PIByteArray & data) { + write_thread.lock(); + write_queue.enqueue(PIPair(data, tri)); + ++tri; + write_thread.unlock(); + return tri - 1; +} + + +bool PIIODevice::configure(const PIString & config_file, const PIString & section, bool parent_section) { + PIConfig conf(config_file, PIIODevice::ReadOnly); + if (!conf.isOpened()) return false; + bool ex = true; + PIConfig::Entry em; + if (section.isEmpty()) em = conf.rootEntry(); + else em = conf.getValue(section, PIString(), &ex); + if (!ex) return false; + PIConfig::Entry * ep = 0; + if (parent_section) ep = em.parent(); + if (ep != 0) { + setReopenEnabled(ep->getValue("reopenEnabled", isReopenEnabled(), &ex)); + if (!ex) setReopenEnabled(em.getValue("reopenEnabled", isReopenEnabled())); + setReopenTimeout(ep->getValue("reopenTimeout", reopenTimeout(), &ex)); + if (!ex) setReopenTimeout(em.getValue("reopenTimeout", reopenTimeout())); + setThreadedReadBufferSize(ep->getValue("threadedReadBufferSize", int(buffer_tr.size_s()), &ex)); + if (!ex) setThreadedReadBufferSize(em.getValue("threadedReadBufferSize", int(buffer_tr.size_s()))); + } else { + setReopenEnabled(em.getValue("reopenEnabled", isReopenEnabled())); + setReopenTimeout(em.getValue("reopenTimeout", reopenTimeout())); + setThreadedReadBufferSize(em.getValue("threadedReadBufferSize", int(buffer_tr.size_s()))); + } + return configureDevice(&em, ep); +} + + +PIIODevice * PIIODevice::createFromFullPath(const PIString & full_path) { + PIString prefix = full_path.left(full_path.find(":")); + if (prefix.isEmpty()) return 0; + PIVector rd(PICollection::groupElements("__PIIODevices__")); + piForeachC (PIObject * d, rd) { + if (prefix == ((const PIIODevice * )d)->fullPathPrefix()) { + PIIODevice * nd = ((const PIIODevice * )d)->copy(); + if (nd) nd->configureFromFullPath(full_path.mid(prefix.length() + 3)); + return nd; + } + } + return 0; +} + + +PIString PIIODevice::normalizeFullPath(const PIString & full_path) { + static PIMutex nfp_mutex; + static PIMap nfp_cache; + PIMutexLocker nfp_ml(nfp_mutex); + PIString ret = nfp_cache.value(full_path); + if (!ret.isEmpty()) + return ret; + //piCout << "normalizeFullPath" << full_path; + PIIODevice * d = createFromFullPath(full_path); + //piCout << "normalizeFullPath" << d; + if (d == 0) return PIString(); + ret = d->constructFullPath(); + delete d; + nfp_cache[full_path] = ret; + return ret; +} diff --git a/src/io/piiodevice.h b/src/io/piiodevice.h new file mode 100755 index 00000000..985ebb42 --- /dev/null +++ b/src/io/piiodevice.h @@ -0,0 +1,333 @@ +/*! \file piiodevice.h + * \brief Abstract input/output device +*/ +/* + PIP - Platform Independent Primitives + Abstract input/output device + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIIODEVICE_H +#define PIIODEVICE_H + +#include "piinit.h" +#include "picollection.h" +#include "pivariant.h" +#include "pitimer.h" + +// function executed from threaded read, pass ThreadedReadData, readedData, sizeOfData +typedef bool (*ReadRetFunc)(void * , uchar * , int ); + +#ifdef DOXYGEN + +//! \relatesalso PIIODevice \brief Use this macro to enable automatic creation instances of your class with \a createFromFullPath() function +# define REGISTER_DEVICE(class) + +//! \relatesalso PIIODevice \brief Use this macro instead of PIOBJECT when describe your own PIIODevice +# define PIIODEVICE(class) + +#else + +# define REGISTER_DEVICE(class) ADD_NEW_TO_COLLECTION_WITH_NAME(__PIIODevices__, class, __S__collection_##class##__) +# define PIIODEVICE(class) PIOBJECT_SUBCLASS(class, PIIODevice) PIIODevice * copy() const {return new class();} + +#endif + +class PIP_EXPORT PIIODevice: public PIThread +{ + PIOBJECT_SUBCLASS(PIIODevice, PIThread) +public: + + //! Constructs a empty PIIODevice + PIIODevice(); + + //! \brief Open modes for PIIODevice + enum DeviceMode { + ReadOnly /*! Device can only read */ = 0x01, + WriteOnly /*! Device can only write */ = 0x02, + ReadWrite /*! Device can both read and write */ = 0x03 + }; + + PIIODevice(const PIString & path, DeviceMode mode = ReadWrite); + virtual ~PIIODevice(); + + //! Current open mode of device + DeviceMode mode() const {return mode_;} + + //! Current path of device + PIString path() const {return property("path").toString();} + + //! Set path of device + void setPath(const PIString & path) {setProperty("path", path);} + + //! Return \b true if mode is ReadOnly or ReadWrite + bool isReadable() const {return (mode_ & ReadOnly);} + + //! Return \b true if mode is WriteOnly or ReadWrite + bool isWriteable() const {return (mode_ & WriteOnly);} + + bool isInitialized() const {return init_;} + + //! Return \b true if device is successfully opened + bool isOpened() const {return opened_;} + + //! Return \b true if device is closed + bool isClosed() const {return !opened_;} + + //! Return \b true if device can read \b now + virtual bool canRead() const {return opened_ && (mode_ & ReadOnly);} + + //! Return \b true if device can write \b now + virtual bool canWrite() const {return opened_ && (mode_ & WriteOnly);} + + + //! Set execution of \a open enabled while threaded read on closed device + void setReopenEnabled(bool yes = true) {setProperty("reopenEnabled", yes);} + + //! Set timeout in milliseconds between \a open tryings if reopen is enabled + void setReopenTimeout(int msecs) {setProperty("reopenTimeout", msecs);} + + + //! Return reopen enable + bool isReopenEnabled() const {return property("reopenEnabled").toBool();} + + //! Return reopen timeout + int reopenTimeout() {return property("reopenTimeout").toInt();} + + + /** \brief Set "threaded read slot" + * \details Set external static function of threaded read that will be executed + * at every successful threaded read. Function should have format + * "bool func(void * data, uchar * readed, int size)" */ + void setThreadedReadSlot(ReadRetFunc func) {ret_func_ = func;} + + //! Set custom data that will be passed to "threaded read slot" + void setThreadedReadData(void * d) {ret_data_ = d;} + + /** \brief Set size of threaded read buffer + * \details Default size is 4096 bytes. If your device can read at single read + * more than 4096 bytes you should use this function to adjust buffer size */ + void setThreadedReadBufferSize(int new_size) {buffer_tr.resize(new_size);} + + //! Return size of threaded read buffer + int threadedReadBufferSize() const {return buffer_tr.size_s();} + + //! Return content of threaded read buffer + const uchar * threadedReadBuffer() const {return buffer_tr.data();} + + //! Return custom data that will be passed to "threaded read slot" + void * threadedReadData() const {return ret_data_;} + + + //! Return \b true if threaded read is started + bool isThreadedRead() const {return isRunning();} + + //! Start threaded read + void startThreadedRead() {if (!isRunning()) PIThread::start();} + + //! Start threaded read and assign "threaded read slot" to "func" + void startThreadedRead(ReadRetFunc func) {ret_func_ = func; if (!isRunning()) PIThread::start();} + + //! Stop threaded read + void stopThreadedRead() {PIThread::terminate();} + + + //! Return \b true if threaded write is started + bool isThreadedWrite() const {return write_thread.isRunning();} + + //! Start threaded write + void startThreadedWrite() {if (!write_thread.isRunning()) write_thread.startOnce();} + + //! Stop threaded write + void stopThreadedWrite() {write_thread.terminate();} + + //! Clear threaded write task queue + void clearThreadedWriteQueue() {write_thread.lock(); write_queue.clear(); write_thread.unlock();} + + + //! Start both threaded read and threaded write + void start() {startThreadedRead(); startThreadedWrite();} + + //! Stop both threaded read and threaded write and if "wait" block until both threads are stop + void stop(bool wait = false) {stopThreadedRead(); stopThreadedWrite(); if (wait) while (write_thread.isRunning() || isRunning()) msleep(1);} + + + //! Reimplement this function to read from your device + virtual int read(void * read_to, int max_size) {piCoutObj << "\"read\" is not implemented!"; return -2;} + + //! Reimplement this function to write to your device + virtual int write(const void * data, int max_size) {piCoutObj << "\"write\" is not implemented!"; return -2;} + + + //! Read from device maximum "max_size" bytes and return them as PIByteArray + PIByteArray read(int max_size) {buffer_in.resize(max_size); int ret = read(buffer_in.data(), max_size); if (ret < 0) return PIByteArray(); return buffer_in.resized(ret);} + + //! Read from device for "timeout_ms" milliseconds and return readed data as PIByteArray. Timeout should to be greater than 0 + PIByteArray readForTime(double timeout_ms); + + //! Write "data" to device + int write(const PIByteArray & data) {return write(data.data(), data.size_s());} + + + //! Add task to threaded write queue and return task ID + ullong writeThreaded(const void * data, int max_size) {return writeThreaded(PIByteArray(data, uint(max_size)));} + + //! Add task to threaded write queue and return task ID + ullong writeThreaded(const PIByteArray & data); + + + //! Configure device from section "section" of file "config_file", if "parent_section" parent section also will be read + bool configure(const PIString & config_file, const PIString & section, bool parent_section = false); + + + //! Reimplement to construct full unambiguous string prefix. \ref PIIODevice_sec7 + virtual PIString fullPathPrefix() const {return PIString();} + + //! Reimplement to construct full unambiguous string, describes this device, default returns \a fullPathPrefix() + "://" + \a path() + virtual PIString constructFullPath() const {return fullPathPrefix() + "://" + path();} + + //! \brief Try to determine suitable device, create new one, configure it with \a configureFromFullPath() and returns it. + //! \details To function \a configureFromFullPath() "full_path" passed without \a fullPathPrefix() + "://". + //! See \ref PIIODevice_sec7 + static PIIODevice * createFromFullPath(const PIString & full_path); + + static PIString normalizeFullPath(const PIString & full_path); + + + EVENT_HANDLER(bool, open) {if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;} + EVENT_HANDLER1(bool, open, const PIString &, _path) {setPath(_path); if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;} + EVENT_HANDLER1(bool, open, const DeviceMode &, _mode) {mode_ = _mode; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;} + EVENT_HANDLER2(bool, open, const PIString &, _path, const DeviceMode &, _mode) {setPath(_path); mode_ = _mode; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;} + EVENT_HANDLER(bool, close) {opened_ = !closeDevice(); if (!opened_) closed(); return !opened_;} + EVENT_HANDLER(bool, initialize) {init_ = init(); return init_;} + + EVENT_VHANDLER(void, flush) {;} + + EVENT(opened) + EVENT(closed) + EVENT2(threadedReadEvent, uchar * , readed, int, size) + EVENT2(threadedWriteEvent, ullong, id, int, written_size) + +//! \handlers +//! \{ + + //! \fn bool open() + //! \brief Open device + + //! \fn bool open(const PIString & path) + //! \brief Open device with path "path" + + //! \fn bool open(const DeviceMode & mode) + //! \brief Open device with mode "mode" + + //! \fn bool open(const PIString & path, const DeviceMode & mode) + //! \brief Open device with path "path" and mode "mode" + + //! \fn bool close() + //! \brief Close device + + //! \fn bool initialize() + //! \brief Initialize device + +//! \} +//! \vhandlers +//! \{ + + //! \fn void flush() + //! \brief Immediate write all buffers + +//! \} +//! \events +//! \{ + + //! \fn void opened() + //! \brief Raise if succesfull open + + //! \fn void closed() + //! \brief Raise if succesfull close + + //! \fn void threadedReadEvent(uchar * readed, int size) + //! \brief Raise if read thread succesfull read some data + + //! \fn void threadedWriteEvent(ullong id, int written_size) + //! \brief Raise if write thread succesfull write some data of task with ID "id" + +//! \} +//! \ioparams +//! \{ +#ifdef DOXYGEN + //! \brief setReopenEnabled, default "true" + bool reopenEnabled; + + //! \brief setReopenTimeout in ms, default 1000 + int reopenTimeout; + + //! \brief setThreadedReadBufferSize in bytes, default 4096 + int threadedReadBufferSize; +#endif +//! \} + +protected: + + //! Function executed before first \a openDevice() or from constructor + virtual bool init() {return true;} + + //! Reimplement to configure device from entries "e_main" and "e_parent", cast arguments to \a PIConfig::Entry* + virtual bool configureDevice(const void * e_main, const void * e_parent = 0) {return true;} + + //! Reimplement to open device, return value will be set to "opened_" variable + virtual bool openDevice() = 0; // use path_, type_, opened_, init_ variables + + //! Reimplement to close device, inverse return value will be set to "opened_" variable + virtual bool closeDevice() {return true;} // use path_, type_, opened_, init_ variables + + //! Function executed when thread read some data, default implementation execute external slot "ret_func_" + virtual bool threadedRead(uchar * readed, int size) {if (ret_func_ != 0) return ret_func_(ret_data_, readed, size); return true;} + + + //! Reimplement to configure your device with parameters of full unambiguous string. Default implementation does nothing + virtual void configureFromFullPath(const PIString & full_path) {;} + + + void terminate(); + + + DeviceMode mode_; + ReadRetFunc ret_func_; + bool init_, opened_, thread_started_, raise_threaded_read_; + void * ret_data_; + +private: + EVENT_HANDLER2(void, check_start, void * , data, int, delim); + EVENT_HANDLER(void, write_func); + + virtual PIIODevice * copy() const {return 0;} + void _init(); + void begin(); + void run(); + void end() {terminate();} + + PITimer timer; + PITimeMeasurer tm; + PIThread write_thread; + PIByteArray buffer_in, buffer_tr; + PIQueue > write_queue; + ullong tri; + int readed_; + +}; + +#endif // PIIODEVICE_H diff --git a/src/io/piiostring.cpp b/src/io/piiostring.cpp new file mode 100644 index 00000000..00dd5f8e --- /dev/null +++ b/src/io/piiostring.cpp @@ -0,0 +1,106 @@ +/* + PIP - Platform Independent Primitives + PIIODevice wrapper around PIString + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "piiostring.h" + + +/*! \class PIIOString + * \brief PIIODevice wrapper around PIString + * + * \section PIIOString_sec0 Synopsis + * This class sllow you to use PIString as PIIODevice and pass it to, e.g. PIConfig + */ + +//REGISTER_DEVICE(PIIOString); + + +PIIOString::PIIOString(PIString * string, PIIODevice::DeviceMode mode_) { + open(string, mode_); +} + + +PIIOString::PIIOString(const PIString & string) { + open(string); +} + + +PIIOString::~PIIOString() { +} + + +bool PIIOString::open(PIString * string, PIIODevice::DeviceMode mode_) { + str = string; + return PIIODevice::open(mode_); +} + + +bool PIIOString::open(const PIString & string) { + str = const_cast(&string); + return PIIODevice::open(PIIODevice::ReadOnly); +} + + +PIString PIIOString::readLine() { + if (!canRead() || !str) return PIString(); + int np = pos; + while (++np < str->size_s()) + if ((*str)[np] == '\n') + break; + PIString ret = str->mid(pos, np - pos); + pos = piMini(np + 1, str->size_s()); + return ret; +} + + +int PIIOString::read(void * read_to, int max_size) { + if (!canRead() || !str) return -1; + PIString rs = str->mid(pos, max_size); + pos += max_size; + if (pos > str->size_s()) pos = str->size_s(); + int ret = rs.lengthAscii(); + memcpy(read_to, rs.data(), rs.lengthAscii()); + return ret; +} + + +int PIIOString::write(const void * data, int max_size) { + if (!canWrite() || !str) return -1; + //piCout << "write" << data; + if (pos > str->size_s()) pos = str->size_s(); + PIString rs = PIString((const char *)data); + if (rs.size_s() > max_size) rs.resize(max_size); + str->insert(pos, rs); + pos += rs.size_s(); + return rs.lengthAscii(); +} + + +int PIIOString::writeString(const PIString & string) { + if (!canWrite() || !str) return -1; + if (pos > str->size_s()) pos = str->size_s(); + str->insert(pos, string); + pos += string.size_s(); + return string.lengthAscii(); +} + + +bool PIIOString::openDevice() { + pos = 0; + return (str != 0); +} diff --git a/src/io/piiostring.h b/src/io/piiostring.h new file mode 100644 index 00000000..845a5af8 --- /dev/null +++ b/src/io/piiostring.h @@ -0,0 +1,86 @@ +/*! \file piiostring.h + * \brief PIIODevice wrapper around PIString +*/ +/* + PIP - Platform Independent Primitives + PIIODevice wrapper around PIString + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIIOSTRING_H +#define PIIOSTRING_H + +#include "piiodevice.h" + + +class PIP_EXPORT PIIOString: public PIIODevice +{ + PIIODEVICE(PIIOString) +public: + + //! Contructs %PIIOString with \"string\" content and \"mode\" open mode + PIIOString(PIString * string = 0, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); + + //! Contructs %PIIOString with \"string\" content only for read + PIIOString(const PIString & string); + + ~PIIOString(); + + + //! Returns content + PIString * string() const {return str;} + + //! Clear content string + void clear() {if (str) str->clear(); pos = 0;} + + //! Open \"string\" content with \"mode\" open mode + bool open(PIString * string, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); + + //! Open \"string\" content only for read + bool open(const PIString & string); + + //! Returns if position is at the end of content + bool isEnd() const {if (!str) return true; return pos >= str->size_s();} + + + //! Move read/write position to \"position\" + void seek(llong position) {pos = position;} + + //! Move read/write position to the begin of the string + void seekToBegin() {if (str) pos = 0;} + + //! Move read/write position to the end of the string + void seekToEnd() {if (str) pos = str->size_s();} + + + //! Read one text line and return it + PIString readLine(); + + int read(void * read_to, int max_size); + int write(const void * data, int max_size); + + //! Insert string \"string\" into content at current position + int writeString(const PIString & string); + +protected: + bool openDevice(); + + ssize_t pos; + PIString * str; + +}; + +#endif // PIIOSTRING_H diff --git a/src/io/pimultiprotocol.cpp b/src/io/pimultiprotocol.cpp new file mode 100755 index 00000000..422263cf --- /dev/null +++ b/src/io/pimultiprotocol.cpp @@ -0,0 +1,21 @@ +/* + PIP - Platform Independent Primitives + Multiprotocol + Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pimultiprotocol.h" + diff --git a/src/io/pimultiprotocol.h b/src/io/pimultiprotocol.h new file mode 100755 index 00000000..d7bc65d8 --- /dev/null +++ b/src/io/pimultiprotocol.h @@ -0,0 +1,93 @@ +/* + PIP - Platform Independent Primitives + Multiprotocol + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIMULTIPROTOCOL_H +#define PIMULTIPROTOCOL_H + +#include "piprotocol.h" + +class PIMultiProtocol: public PIMultiProtocolBase +{ +public: + PIMultiProtocol() {;} + virtual ~PIMultiProtocol() {clear();} + + void addProtocol(PIProtocol & prot) {prots.push_back(&prot); prot.setMultiProtocolOwner(this); prot.new_mp_prot = false;} + void addProtocol(PIProtocol * prot) {prots.push_back(prot); prot->setMultiProtocolOwner(this); prot->new_mp_prot = false;} + void addProtocol(const PIString & config, const PIString & name, void * recHeaderPtr = 0, int recHeaderSize = 0, + void * recDataPtr = 0, int recDataSize = 0, void * sendDataPtr = 0, int sendDataSize = 0) {; + prots.push_back(new PIProtocol(config, name, recHeaderPtr, recHeaderSize, recDataPtr, recDataSize, sendDataPtr, sendDataSize)); + prots.back()->setMultiProtocolOwner(this); + prots.back()->new_mp_prot = true; + } + PIProtocol * protocol(const PIString & name) {piForeach (PIProtocol * i, prots) if (i->name() == name) return i; return 0;} + PIProtocol * protocol(const int index) {return prots[index];} + PIProtocol * operator [](const int index) {return prots[index];} + + void startSend() {piForeach (PIProtocol * i, prots) i->startSend();} + void startReceive() {piForeach (PIProtocol * i, prots) i->startReceive();} + void start() {piForeach (PIProtocol * i, prots) i->start();} + + void stopSend() {piForeach (PIProtocol * i, prots) i->stopSend();} + void stopReceive() {piForeach (PIProtocol * i, prots) i->stopReceive();} + void stop() {piForeach (PIProtocol * i, prots) i->stop();} + + PIProtocol::Quality worseQuality() const {PIProtocol::Quality cq = PIProtocol::Good; piForeachC (PIProtocol * i, prots) if (cq > i->quality()) cq = i->quality(); return cq;} + PIProtocol::Quality bestQuality() const {PIProtocol::Quality cq = PIProtocol::Unknown; piForeachC (PIProtocol * i, prots) if (cq < i->quality()) cq = i->quality(); return cq;} + + int count() const {return prots.size_s();} + void clear() {stop(); piForeach (PIProtocol * i, prots) if (i->new_mp_prot) delete i; prots.clear();} + +private: + PIVector prots; + +}; + +class PIRepeater: public PIMultiProtocol { +public: + PIRepeater(const PIString & config, const PIString & name_) { + PIConfig conf(config, PIIODevice::ReadOnly); + if (!conf.isOpened()) { + piCoutObj << "[PIRepeater \"" << name_ << "\"] Can`t open \"" << config << "\"!"; + return; + } + PIConfig::Entry & b(conf.getValue(name_)); + if (b.childCount() != 2) { + piCoutObj << "[PIRepeater \"" << name_ << "\"] \"" << config << "\" should consist 2 nodes!"; + return; + } + addProtocol(config, b.child(0)->fullName()); + addProtocol(config, b.child(1)->fullName()); + start(); + } + + PIString firstChannelName() {if (count() == 2) return protocol(0)->receiverDeviceName() + " -> " + protocol(1)->senderDeviceName(); return "Config error";} + PIString secondChannelName() {if (count() == 2) return protocol(1)->receiverDeviceName() + " -> " + protocol(0)->senderDeviceName(); return "Config error";} + + ullong receiveCount() {if (count() == 2) return protocol(0)->receiveCount(); return 0;} + const ullong * receiveCount_ptr() {if (count() == 2) return protocol(0)->receiveCount_ptr(); return 0;} + ullong sendCount() {if (count() == 2) return protocol(0)->sendCount(); return 0;} + const ullong * sendCount_ptr() {if (count() == 2) return protocol(0)->sendCount_ptr(); return 0;} + +private: + void received(PIProtocol * prot, bool , uchar * data, int size) {if (prot == protocol(0)) protocol(1)->send(data, size); else protocol(0)->send(data, size);} + +}; + +#endif // PIMULTIPROTOCOL_H diff --git a/src/io/pipacketextractor.cpp b/src/io/pipacketextractor.cpp new file mode 100755 index 00000000..64d7d083 --- /dev/null +++ b/src/io/pipacketextractor.cpp @@ -0,0 +1,301 @@ +/* + PIP - Platform Independent Primitives + Packets extractor + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pipacketextractor.h" + + +/** \class PIPacketExtractor + * \brief Packets extractor + * \details + * \section PIPacketExtractor_main Synopsis + * This class implements packet recognition by various algorithms and custom + * validating from data stream. Stream is formed from child %PIIODevice + * passed from contructor or with function \a setDevice(). + * + * \section PIPacketExtractor_work Principle of work + * %PIPacketExtractor works with child %PIIODevice. \a read and \a write + * functions directly call child device functions. You should start threaded + * read of \b extractor (not child device) to proper work. Extractor read data + * from child device, try to detect packet from readed data and raise + * \a packetReceived() event on success. + * + * \section PIPacketExtractor_algorithms Algorithms + * There are 6 algorithms: \n + * * PIPacketExtractor::None \n + * Packet is successfully received on every read without any validation. \n \n + * * PIPacketExtractor::Header \n + * Wait for at least \a header() bytes + \a payloadSize(), then validate + * header with virtual function \a validateHeader() and if it fail, shifts + * for next 1 byte. If header is successfully validated check payload with + * function \a validatePayload() and if it fail, shifts for next 1 byte. If + * all validations were successful raise \a packetReceived() event. \n \n + * * PIPacketExtractor::Footer \n + * This algorithm similar to previous, but instead of \a header() first validate + * \a footer() at after \a payloadSize() bytes with function \a validateFooter(). \n \n + * * PIPacketExtractor::HeaderAndFooter \n + * Wait for at least \a header() bytes + \a footer() bytes, then validate + * header with virtual function \a validateHeader() and if it fail, shifts + * for next 1 byte. If header is successfully validated check footer with + * function \a validateFooter() and if it fail, shifts footer position for + * next 1 byte. Then validate payload and if it fail, search header again, + * starts from next byte of previous header. If all validations were successful + * raise \a packetReceived() event. \n \n + * * PIPacketExtractor::Size \n + * Wait for at least \a packetSize() bytes, then validate packet with function + * \a validatePayload() and if it fail, shifts for next 1 byte. If validating + * was successfull raise \a packetReceived() event. \n \n + * * PIPacketExtractor::Timeout \n + * Wait for first read, then read for \a timeout() milliseconds and raise + * \a packetReceived() event. \n + * + * \section PIPacketExtractor_control Control validating + * There are three parameters: + * * header content + * * header size + * * payload size + * + * Extractor can detect packet with compare your header with readed data. + * It is default implementation of function \a packetHeaderValidate(). + * If header validating passed, function \a packetValidate() will be called. + * If either of this function return \b false extractor shifts by one byte + * and takes next header. If both functions returns \b true extractor shifts + * by whole packet size. + * \image html packet_detection.png + * + * */ + +REGISTER_DEVICE(PIPacketExtractor); + + +PIPacketExtractor::PIPacketExtractor(PIIODevice * device_, PIPacketExtractor::SplitMode mode) { + init_(); + setDevice(device_); + setSplitMode(mode); +} + + +void PIPacketExtractor::init_() { + ret_func_header = ret_func_footer = 0; + setPayloadSize(0); + setTimeout(100); + setThreadedReadBufferSize(65536); + setBufferSize(65536); + setDevice(0); + setPacketSize(0); + setSplitMode(None); + allReaded = addSize = curInd = missed = missed_packets = footerInd = 0; + header_found = false; +} + + +void PIPacketExtractor::propertyChanged(const PIString &) { + packetSize_ = property("packetSize").toInt(); + mode_ = (SplitMode)(property("splitMode").toInt()); + dataSize = property("payloadSize").toInt(); + src_header = property("header").toByteArray(); + src_footer = property("footer").toByteArray(); + packetSize_hf = src_header.size_s() + src_footer.size_s() + payloadSize(); +} + + +void PIPacketExtractor::setDevice(PIIODevice * device_) { + dev = device_; + if (dev == 0) return; +} + + +void PIPacketExtractor::setPayloadSize(int size) { + setProperty("payloadSize", size); + dataSize = size; + packetSize_hf = src_header.size_s() + src_footer.size_s() + payloadSize(); +} + + +void PIPacketExtractor::setHeader(const PIByteArray & data) { + setProperty("header", data); + src_header = data; + packetSize_hf = src_header.size_s() + src_footer.size_s() + payloadSize(); +} + + +void PIPacketExtractor::setFooter(const PIByteArray & data) { + setProperty("footer", data); + src_footer = data; + packetSize_hf = src_header.size_s() + src_footer.size_s() + payloadSize(); +} + + +bool PIPacketExtractor::threadedRead(uchar * readed, int size_) { + //piCoutObj << "readed" << size_; + int ss; + switch (mode_) { + case PIPacketExtractor::None: + if (validatePayload(readed, size_)) + packetReceived(readed, size_); + break; + case PIPacketExtractor::Header: + tmpbuf.append(readed, size_); + ss = src_header.size_s() + dataSize; + while (tmpbuf.size_s() >= ss) { + while (!validateHeader(src_header.data(), tmpbuf.data(), src_header.size_s())) { + tmpbuf.pop_front(); + ++missed; + if (tmpbuf.size_s() < ss) return true; + } + while (!validatePayload(tmpbuf.data(src_header.size_s()), dataSize)) { + tmpbuf.pop_front(); + ++missed; + if (tmpbuf.size_s() < ss) return true; + } + packetReceived(tmpbuf.data(), ss); + tmpbuf.remove(0, ss); + } + break; + case PIPacketExtractor::Footer: + /*memcpy(buffer.data(allReaded), readed, size_); + allReaded += size_; + footer_ = (mode_ == PIPacketExtractor::Footer); + while (allReaded >= packetSize_hf + addSize && allReaded > 0) { + if (!src_header.isEmpty()) { + if (allReaded + curInd >= buffer_size) { + memcpy(sbuffer.data(), buffer.data(), buffer_size); + memcpy(buffer.data(), sbuffer.data(buffer_size - packetSize_hf), allReaded); + allReaded = packetSize_hf; + addSize = curInd = 0; + } + bool brk = false; + while (!validateHeader((uchar * )(footer_ ? src_footer.data() : src_header.data()), buffer.data(curInd + (footer_ ? dataSize : 0)), footer_ ? src_footer.size_s() : src_header.size_s())) { + ++curInd; ++missed; + if (packetSize_hf > 0) missed_packets = missed / packetSize_hf; + if (curInd > addSize) { + addSize += packetSize_hf; + brk = true; + break; + } + } + if (brk) continue; + //memcpy(mheader.data(), buffer.data(curInd + (footer_ ? dataSize : 0)), src_header.size_s()); + if (!src_header.isEmpty()) memcpy(src_header.data(), buffer.data(curInd), src_header.size_s()); + if (!validatePayload(buffer.data(curInd + src_header.size_s()), dataSize)) { + ++curInd; ++missed; + if (packetSize_hf > 0) missed_packets = missed / packetSize_hf; + continue; + } + packetReceived(buffer.data(curInd), packetSize_hf); + memcpy(sbuffer.data(), buffer.data(), allReaded); + memcpy(buffer.data(), sbuffer.data(packetSize_hf + curInd), allReaded); + allReaded -= packetSize_hf + curInd; + curInd = addSize = 0; + } else { + if (dataSize == 0) { + if (validatePayload(buffer.data(), size_)) + packetReceived(buffer.data(), size_); + memcpy(sbuffer.data(), buffer.data(), allReaded); + memcpy(buffer.data(), sbuffer.data(size_), allReaded); + allReaded -= size_; + } else { + if (validatePayload(buffer.data(), dataSize)) + packetReceived(buffer.data(), dataSize); + memcpy(sbuffer.data(), buffer.data(), allReaded); + memcpy(buffer.data(), sbuffer.data(packetSize_hf), allReaded); + allReaded -= packetSize_hf; + } + } + }*/ + tmpbuf.append(readed, size_); + ss = src_footer.size_s() + dataSize; + while (tmpbuf.size_s() >= ss) { + while (!validateFooter(src_footer.data(), tmpbuf.data(dataSize), src_footer.size_s())) { + tmpbuf.pop_front(); + ++missed; + if (tmpbuf.size_s() < ss) return true; + } + while (!validatePayload(tmpbuf.data(), dataSize)) { + tmpbuf.pop_front(); + ++missed; + if (tmpbuf.size_s() < ss) return true; + } + packetReceived(tmpbuf.data(), ss); + tmpbuf.remove(0, ss); + } + break; + case PIPacketExtractor::HeaderAndFooter: + tmpbuf.append(readed, size_); + ss = src_header.size_s() + src_footer.size_s(); + while (tmpbuf.size_s() >= ss) { + if (!header_found) { + if (tmpbuf.size_s() < ss) return true; + while (!validateHeader(src_header.data(), tmpbuf.data(), src_header.size_s())) { + tmpbuf.pop_front(); + ++missed; + if (tmpbuf.size_s() < ss) return true; + } + header_found = true; + footerInd = src_header.size_s(); + } else { + if (tmpbuf.size_s() < footerInd + src_footer.size_s()) return true; + while (!validateFooter(src_footer.data(), tmpbuf.data(footerInd), src_footer.size_s())) { + ++footerInd; + if (tmpbuf.size_s() < footerInd + src_footer.size_s()) return true; + } + //piCout << "footer found at" << footerInd; + header_found = false; + if (!validatePayload(tmpbuf.data(src_header.size_s()), footerInd - src_header.size_s())) { + tmpbuf.pop_front(); + ++missed; + continue; + } + packetReceived(tmpbuf.data(), footerInd + src_footer.size_s()); + tmpbuf.remove(0, footerInd + src_footer.size_s()); + footerInd = src_header.size_s(); + } + } + break; + case PIPacketExtractor::Size: + tmpbuf.append(readed, size_); + if (packetSize_ <= 0) { + tmpbuf.clear(); + return true; + } + while (tmpbuf.size_s() >= packetSize_) { + if (!validatePayload(tmpbuf.data(), packetSize_)) { + tmpbuf.pop_front(); + ++missed; + missed_packets = missed / packetSize_; + continue; + } + packetReceived(tmpbuf.data(), packetSize_); + tmpbuf.remove(0, packetSize_); + } + break; + case PIPacketExtractor::Timeout: + memcpy(buffer.data(), readed, size_); + trbuf = dev->readForTime(time_); + memcpy(buffer.data(size_), trbuf.data(), trbuf.size()); + if (size_ + trbuf.size() > 0) + packetReceived(buffer.data(), size_ + trbuf.size()); + break; + }; + return true; +} + + +PIString PIPacketExtractor::constructFullPath() const { + return fullPathPrefix() + "://"; +} diff --git a/src/io/pipacketextractor.h b/src/io/pipacketextractor.h new file mode 100755 index 00000000..e9b0c0d4 --- /dev/null +++ b/src/io/pipacketextractor.h @@ -0,0 +1,187 @@ +/*! \file pipacketextractor.h + * \brief Packets extractor +*/ +/* + PIP - Platform Independent Primitives + Packets extractor + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +#ifndef PIPACKETEXTRACTOR_H +#define PIPACKETEXTRACTOR_H + +#include "piiodevice.h" + +// Pass data, recHeaderPtr, received_data, recHeaderSize. Return true if packet is correct nor return false. +typedef bool (*PacketExtractorCheckFunc)(void * , uchar * , uchar * , int ); + +class PIP_EXPORT PIPacketExtractor: public PIIODevice +{ + PIIODEVICE(PIPacketExtractor) + friend class PIConnection; +public: + + //! Extract algorithms + enum SplitMode { + None /** No data processing */ , + Header /** Detect packets with \a header() and following \a payloadSize() */ , + Footer /** Detect packets with \a footer() and leading \a payloadSize() */ , + HeaderAndFooter /** Detect packets with \a header() and \a footer() without \a payloadSize() */ , + Size /** Detect packets with \a packetSize() */ , + Timeout /** Wait for first read, then read for \a timeout() milliseconds */ + }; + + //! Contructs extractor with child device "device_" and extract algorithm "mode" + PIPacketExtractor(PIIODevice * device_ = 0, SplitMode mode = None); + + virtual ~PIPacketExtractor() {stop();} + + + //! Returns child %device + PIIODevice * device() {return dev;} + + //! Set child %device to "device_" + void setDevice(PIIODevice * device_); + + + //! Returns buffer size + int bufferSize() const {return buffer_size;} + + //! Set buffer size to "new_size" bytes, should be at least greater than whole packet size + void setBufferSize(int new_size) {buffer_size = new_size; buffer.resize(buffer_size); sbuffer.resize(buffer_size); memset(buffer.data(), 0, buffer.size()); memset(sbuffer.data(), 0, sbuffer.size());} + + void setHeaderCheckSlot(PacketExtractorCheckFunc f) {ret_func_header = f;} + void setFooterCheckSlot(PacketExtractorCheckFunc f) {ret_func_footer = f;} + void setPayloadCheckSlot(ReadRetFunc f) {ret_func_ = f;} + + + //! Set extract algorithm + void setSplitMode(SplitMode mode) {setProperty("splitMode", int(mode)); mode_ = mode;} + + //! Set payload size, used for PIPacketExtractor::Header and PIPacketExtractor::Footer algorithms + void setPayloadSize(int size); + + //! Set header data, used for PIPacketExtractor::Header and PIPacketExtractor::HeaderAndFooter algorithms + void setHeader(const PIByteArray & data); + + //! Set footer data, used for PIPacketExtractor::Footer and PIPacketExtractor::HeaderAndFooter algorithms + void setFooter(const PIByteArray & data); + + //! Set packet size, used for PIPacketExtractor::Size algorithm + void setPacketSize(int size) {setProperty("packetSize", size); packetSize_ = size;} + + //! Set timeout in milliseconds, used for PIPacketExtractor::Timeout algorithm + void setTimeout(double msecs) {setProperty("timeout", msecs); time_ = msecs;} + + + //! Returns current extract algorithm + SplitMode splitMode() const {return (SplitMode)(property("splitMode").toInt());} + + //! Returns current payload size, used for PIPacketExtractor::Header and PIPacketExtractor::Footer algorithms + int payloadSize() const {return property("payloadSize").toInt();} + + //! Returns current header data, used for PIPacketExtractor::Header and PIPacketExtractor::HeaderAndFooter algorithms + PIByteArray header() const {return src_header;} + + //! Returns current footer data, used for PIPacketExtractor::Footer and PIPacketExtractor::HeaderAndFooter algorithms + PIByteArray footer() const {return src_footer;} + + //! Returns current packet size, used for PIPacketExtractor::Size algorithm + int packetSize() const {return property("packetSize").toInt();} + + //! Returns current timeout in milliseconds, used for PIPacketExtractor::Timeout algorithm + double timeout() const {return property("timeout").toDouble();} + + + //! Returns missed by validating functions bytes count + ullong missedBytes() const {return missed;} + + // //! Returns missed by validating functions packets count, = missedBytes() / packetSize + ullong missedPackets() const {/*if (packetSize_hf == 0) return missed; return missed / packetSize_hf*/; return missed_packets;} + + //! Returns pointer to \a missedBytes() count. Useful for output to PIConsole + const ullong * missedBytes_ptr() const {return &missed;} + + // //! Returns pointer to \a missedPackets() count. Useful for output to PIConsole + const ullong * missedPackets_ptr() const {return &missed_packets;} + + + // //! Returns last successfully validated header as byte array + PIByteArray lastHeader() {return mheader;} + + + //! Directly call \a read() function of child %device + int read(void * read_to, int max_size) {if (dev == 0) return -1; return dev->read(read_to, max_size);} + + //! Directly call \a write() function of child %device + int write(const void * data, int max_size) {if (dev == 0) return -1; return dev->write(data, max_size);} + + PIString constructFullPath() const; + + EVENT2(packetReceived, uchar * , data, int, size) + +//! \events +//! \{ + + //! \fn void packetReceived(uchar * data, int size) + //! \brief Raise on successfull \a packetValidate() function + +//! \} + +protected: + + /** \brief Function to validate header + * \param src Your header content + * \param rec Received header + * \param size Header size + * \details Default implementation returns by-byte "src" with "rec" compare result */ + virtual bool validateHeader(uchar * src, uchar * rec, int size) {if (ret_func_header != 0) return ret_func_header(ret_data_, src, rec, size); for (int i = 0; i < size; ++i) if (src[i] != rec[i]) return false; return true;} + + /** \brief Function to validate footer + * \param src Your footer content + * \param rec Received footer + * \param size Footer size + * \details Default implementation returns by-byte "src" with "rec" compare result */ + virtual bool validateFooter(uchar * src, uchar * rec, int size) {if (ret_func_footer != 0) return ret_func_footer(ret_data_, src, rec, size); for (int i = 0; i < size; ++i) if (src[i] != rec[i]) return false; return true;} + + /** \brief Function to validate payload + * \param rec Received payload + * \param size payload size + * \details Default implementation returns \b true */ + virtual bool validatePayload(uchar * rec, int size) {if (ret_func_ != 0) return ret_func_(ret_data_, rec, size); return true;} + +private: + void init_(); + void propertyChanged(const PIString & ); + bool threadedRead(uchar * readed, int size); + PIString fullPathPrefix() const {return "pckext";} + bool openDevice() {if (dev == 0) return false; return dev->open();} + + PIIODevice * dev; + PIByteArray mheader, buffer, sbuffer, tmpbuf, src_header, src_footer, trbuf; + PacketExtractorCheckFunc ret_func_header, ret_func_footer; + SplitMode mode_; + void * data; + int buffer_size, dataSize, packetSize_hf, allReaded, addSize, curInd, footerInd, packetSize_; + double time_; + bool header_found; + ullong missed, missed_packets; + + +}; + +#endif // PIPACKETEXTRACTOR_H diff --git a/src/io/pipeer.cpp b/src/io/pipeer.cpp new file mode 100755 index 00000000..19376f7e --- /dev/null +++ b/src/io/pipeer.cpp @@ -0,0 +1,632 @@ +/* + PIP - Platform Independent Primitives + Peer - named I/O ethernet node + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pipeer.h" + +#define _PIPEER_MSG_SIZE 8192 +#define _PIPEER_MULTICAST_TTL 4 +#define _PIPEER_MULTICAST_IP "232.13.3.12" +#define _PIPEER_LOOPBACK_PORT_S 13313 +#define _PIPEER_LOOPBACK_PORT_E (13313+32) +#define _PIPEER_MULTICAST_PORT 13360 +#define _PIPEER_BROADCAST_PORT 13361 +#define _PIPEER_TRAFFIC_PORT_S 13400 +#define _PIPEER_TRAFFIC_PORT_E 14000 + + +PIPeer::PeerInfo::Address::Address(const PIString & a, const PIString & m): address(a), netmask(m) { + ping = -1.; + wait_ping = false; + last_ping = PISystemTime::current(true); +} + + +int PIPeer::PeerInfo::ping() const { + int ret = -1; + piForeachC (Address & a, addresses) + if (a.ping > 0.) + ret = piMaxi(ret, piRoundd(a.ping)); + return ret; +} + + +PIPeer::PIPeer(const PIString & name_): PIObject() { + setName(name_); + self_info.name = name_; + self_info.dist = 0; + self_info.time = PISystemTime::current(); + //joinMulticastGroup("239.240.241.242"); + srand(uint(PISystemTime::current(true).toMicroseconds())); + //id_ = self_info.name + "_" + PIString::fromNumber(rand()); + CONNECTU(&timer, tickEvent, this, timerEvent); + PIStringList sl = PIEthernet::allAddresses(); + initEths(sl); + sl.removeAll("127.0.0.1"); + initMBcasts(sl); + sendSelfInfo(); + timer.addDelimiter(5); + timer.start(200); +} + + +PIPeer::~PIPeer() { + piForeach (PIEthernet * i, eths_traffic) { + i->stopThreadedRead(); + delete i; + } + eths_traffic.clear(); + piForeach (PIEthernet * i, eths_mcast) + i->stopThreadedRead(); + piForeach (PIEthernet * i, eths_bcast) + i->stopThreadedRead(); + eth_send.stopThreadedRead(); + eth_lo.stopThreadedRead(); + sendSelfRemove(); + destroyMBcasts(); +} + + +void PIPeer::timerEvent(void * data, int delim) { + switch (delim) { + case 5: // 1 s + syncPeers(); + break; + } + //send("broadcast", 9); +} + + +void PIPeer::initEths(PIStringList al) { + PIEthernet * ce; + PIEthernet::InterfaceList il = PIEthernet::interfaces(); + const PIEthernet::Interface * cint = 0; + piForeachC (PIString & a, al) { + ce = new PIEthernet(); + ce->setDebug(false); + ce->setName("__S__PIPeer_traffic_eth_rec_" + a); + ce->setParameters(0); + ce->setThreadSafe(true); + bool ok = false; + for (int p = _PIPEER_TRAFFIC_PORT_S; p < _PIPEER_TRAFFIC_PORT_E; ++p) { + ce->setReadAddress(a, p); + if (ce->open()) { + eths_traffic << ce; + cint = il.getByAddress(a); + self_info.addresses << PeerInfo::Address(ce->path(), cint == 0 ? "255.255.255.0" : cint->netmask); + CONNECTU(ce, threadedReadEvent, this, dataRead); + ce->startThreadedRead(); + //piCout << "dc binded to" << ce->path(); + //piCout << "add eth" << ta; + ok = true; + break; + } + } + if (!ok) delete ce; + } + eth_send.setDebug(false); + eth_send.setName("__S__PIPeer_traffic_eth_send"); + eth_send.setParameters(0); +} + + +void PIPeer::initMBcasts(PIStringList al) { + destroyMBcasts(); + PIEthernet * ce; + PIEthernet::InterfaceList il = PIEthernet::interfaces(); + const PIEthernet::Interface * cint; + PIString nm; + al << _PIPEER_MULTICAST_IP; + piForeachC (PIString & a, al) { + piCout << "mcast try" << a; + ce = new PIEthernet(); + ce->setDebug(false); + ce->setName("__S__PIPeer_mcast_eth_" + a); + ce->setParameters(0); + ce->setSendAddress(_PIPEER_MULTICAST_IP, _PIPEER_MULTICAST_PORT); + ce->setReadAddress(a, _PIPEER_MULTICAST_PORT); + ce->setMulticastTTL(_PIPEER_MULTICAST_TTL); + ce->joinMulticastGroup(_PIPEER_MULTICAST_IP); + eths_mcast << ce; + CONNECTU(ce, threadedReadEvent, this, mbcastRead); + ce->startThreadedRead(); + } + piForeachC (PIString & a, al) { + ce = new PIEthernet(); + ce->setDebug(false); + ce->setName("__S__PIPeer_bcast_eth_" + a); + ce->setParameters(PIEthernet::Broadcast); + cint = il.getByAddress(a); + nm = (cint == 0) ? "255.255.255.0" : cint->netmask; + ce->setSendAddress(PIEthernet::getBroadcast(a, nm), _PIPEER_BROADCAST_PORT); + ce->setReadAddress(a, _PIPEER_BROADCAST_PORT); + //piCout << "mc BC try" << a << nm << ce->sendIP(); + piCout << "bcast try" << a << nm; + eths_bcast << ce; + CONNECTU(ce, threadedReadEvent, this, mbcastRead); + ce->startThreadedRead(); + } + eth_lo.setDebug(false); + eth_lo.setName("__S__PIPeer_eth_loopback"); + eth_lo.setParameters(0); + cint = il.getByAddress("127.0.0.1"); + for (int p = _PIPEER_LOOPBACK_PORT_S; p <= _PIPEER_LOOPBACK_PORT_E; ++p) { + eth_lo.setReadAddress("127.0.0.1", p); + if (eth_lo.open()) { + eth_lo.setSendIP("127.0.0.1"); + CONNECTU(ð_lo, threadedReadEvent, this, mbcastRead); + eth_lo.startThreadedRead(); + piCout << "lo binded to" << eth_lo.readAddress(); + //piCout << "add eth" << ta; + break; + } + } + if (eths_mcast.isEmpty()) piCoutObj << "Warning! Can`t find suitable network interface for multicast receive, check for exists at least one interface with multicasting enabled!"; + if (eths_bcast.isEmpty()) piCoutObj << "Warning! Can`t find suitable network interface for broadcast receive, check for exists at least one interface with broadcasting enabled!"; +} + + +void PIPeer::destroyMBcasts() { + piForeach (PIEthernet * i, eths_mcast) { + i->leaveMulticastGroup(_PIPEER_MULTICAST_IP); + delete i; + } + piForeach (PIEthernet * i, eths_bcast) + delete i; + eth_lo.stop(); + eth_lo.close(); + eths_mcast.clear(); + eths_bcast.clear(); +} + + +PIPeer::PeerInfo * PIPeer::quickestPeer(const PIString & to) { + if (!addresses_map.contains(to)) return 0; + //piCout << "*** search quickest peer" << to; + PIVector tp = addresses_map[to]; + PeerInfo * dp = 0; + int mping = 0x7FFFFFFF; + for (int i = 0; i < tp.size_s(); ++i) { + if (mping > tp[i]->ping()) { + mping = tp[i]->ping(); + dp = tp[i]; + } + } + //piCout << "*** search quickest peer: found" << dp->name; + return dp; +} + + +bool PIPeer::send(const PIString & to, const void * data, int size) { + PeerInfo * dp = quickestPeer(to); + if (dp == 0) { + //piCoutObj << "Can`t find peer \"" << to << "\"!"; + return false; + } + PIByteArray ba; + ba << int(4) << self_info.name << to << int(0) << size; + PIByteArray fmsg(data, size), cmsg; + int msg_count = (size - 1) / _PIPEER_MSG_SIZE + 1; + //piCout << "[PIPeer] send" << size << "bytes in" << msg_count << "packets ..."; + for (int i = 0; i < msg_count; ++i) { + int csize = (i == msg_count - 1) ? ((size - 1) % _PIPEER_MSG_SIZE + 1) : _PIPEER_MSG_SIZE; + cmsg = ba; + cmsg << msg_count << i; + cmsg.append(fmsg.data(i * _PIPEER_MSG_SIZE), csize); + if (!sendToNeighbour(dp, cmsg)) return false; + } + //piCout << "[PIPeer] send" << size << "bytes ok"; + return true; +} + + +bool PIPeer::dataRead(uchar * readed, int size) { + if (size < 16) return true; + PIByteArray ba(readed, size), sba; + int type, cnt, rec_size; + PIString from, to; + ba >> type; + PIMutexLocker locker(eth_mutex); + //piCout << "[PIPeer \"" + name_ + "\"] Received packet" << type; + if (type == 5) { // ping + PIString addr; + PISystemTime time, ptime, ctime = PISystemTime::current(true); + ba >> to >> from >> addr >> time; + if (to == self_info.name) { // ping echo + piForeach (PeerInfo & p, peers) { + if (!p.isNeighbour()) continue; + if (p.name != from) continue; + piForeach (PeerInfo::Address & a, p.addresses) { + if (a.address != addr) continue; + if (a.last_ping >= time) piBreak; + ptime = ctime - time; + a.last_ping = time; + a.wait_ping = false; + if (a.ping < 0) a.ping = ptime.toMilliseconds(); + else a.ping = 0.6 * a.ping + 0.4 * ptime.toMilliseconds(); + piCout << "*** ping echo" << p.name << a.address << a.ping; + return true; + } + } + return true; + } + // send ping back + piForeachC (PeerInfo & p, peers) { + if (!p.isNeighbour()) continue; + if (p.name != to) continue; + sba = PIByteArray(readed, size); + //piCout << "ping from" << to << addr << ", send back to" << p.name; + piForeachC (PeerInfo::Address & a, p.addresses) { + if (eth_send.send(a.address, sba)) + diag_s.received(sba.size_s()); + } + return true; + } + //PIEthernet * eth = (PIEthernet*)emitter(); + //()->send(); + return true; + } + if (type != 4) return true; + diag_d.received(size); + ba >> from >> to >> cnt >> rec_size; + //piCout << "[PIPeer \"" + name_ + "\"] Received packet" << /*type << from << to << cnt <<*/ rec_size; + if (type == 4) { // data packet + if (to == self_info.name) { // my packet + int msg_count, cmsg; + ba >> msg_count >> cmsg; + //piCout << "[PIPeer \"" + name_ + "\"] Received packet" << type << from << to << cnt << rec_size << msg_count << cmsg; + if (cmsg == 0 && msg_count == 1) { + dataReceived(from, ba); + dataReceivedEvent(from, ba); + return true; + } + PeerInfo * fp = const_cast(getPeerByName(from)); + if (fp == 0) return true; + PeerData & pd(fp->_data); + if (cmsg == 0) { + //piCout << "[PIPeer \"" + name_ + "\"] Packet clear" << rec_size; + pd.clear(); + pd.msg_count = msg_count; + } + //piCout << "[PIPeer \"" + name_ + "\"] Packet add" << cmsg << ba.size_s(); + pd.addData(ba); + if (pd.isFullReceived()) { + dataReceived(from, pd.data); + dataReceivedEvent(from, pd.data); + //piCout << "[PIPeer \"" + name_ + "\"] Packet received" << pd.data.size_s(); + } + return true; + } + PeerInfo * dp = quickestPeer(to); + if (dp == 0) { + //piCoutObj << "Can`t find peer \"" << to << "\"!"; + return true; + } + cnt++; + if (cnt > 100 || from == dp->name) return true; + sba << type << from << to << cnt << rec_size; + sba.append(ba); + //piCoutObj << "Translate data packet" << type << from << to << cnt << rec_size; + sendToNeighbour(dp, sba); + } + return true; +} + + +bool PIPeer::mbcastRead(uchar * data, int size) { + if (size < 8) return true; + int type, dist; + PIByteArray ba(data, size); + ba >> type; + if (type <= 0 || type >= 4) return true; + PeerInfo pi; + const PeerInfo * rpi = 0; + PIVector rpeers; + ba >> pi.name; + //piCout << "read type" << type << "from" << pi.name; + if (pi.name == self_info.name) return true; + PIMutexLocker locker(mc_mutex); + diag_s.received(size); + //piCout << "analyz ..."; + switch (type) { + case 1: // new peer + //piCout << "new peer packet ..."; + if (hasPeer(pi.name)) break; + ba >> pi; + pi.sync = 0; + if (pi.dist == 0) { + pi.addNeighbour(self_info.name); + self_info.addNeighbour(pi.name); + } + peers << pi; + piCoutObj << "new peer \"" << pi.name << "\"" << " dist " << pi.dist; + pi.dist++; + sendSelfInfo(); + sendPeerInfo(pi); + findNearestAddresses(); + peerConnected(pi.name); + peerConnectedEvent(pi.name); + //piCout << "new peer packet ok"; + break; + case 2: // remove peer + //piCout << "remove peer packet ..." << pi.name; + rpi = getPeerByName(pi.name); + if (!rpi) break; + dist = rpi->dist; + addToRemoved(*rpi); + removePeer(pi.name); + piCoutObj << "remove peer \"" << pi.name << "\""; + if (dist == 0) + self_info.removeNeighbour(pi.name); + sendPeerRemove(pi.name); + findNearestAddresses(); + peerDisconnected(pi.name); + peerDisconnectedEvent(pi.name); + //piCout << "remove peer packet ok"; + break; + case 3: // sync peers + //piCout << "sync packet ..."; + ba >> pi >> rpeers; + rpeers << pi; + //piCoutObj << "rec sync " << rpeers.size_s() << " peers"; + piForeach (PeerInfo & rpeer, rpeers) { + //piCout << " to sync " << rpeer.name; + if (rpeer.name == self_info.name) continue; + bool exist = false; + piForeach (PeerInfo & peer, peers) { + if (peer.name == rpeer.name) exist = true; + if (exist && isPeerRecent(peer, rpeer)) { + //piCout << "synced " << peer.name; + for (int z = 0; z < rpeer.addresses.size_s(); ++z) { + PeerInfo::Address & ra(rpeer.addresses[z]); + for (int k = 0; k < peer.addresses.size_s(); ++k) { + PeerInfo::Address & a(peer.addresses[k]); + if (ra.address == a.address) { + ra.ping = a.ping; + ra.wait_ping = a.wait_ping; + ra.last_ping = a.last_ping; + piBreak; + } + } + } + peer.addresses = rpeer.addresses; + peer.cnt = rpeer.cnt; + peer.time = rpeer.time; + peer.addNeighbours(rpeer.neighbours); + rpeer.neighbours = peer.neighbours; + if (peer.name == pi.name) peer.sync = 0; + piBreak; + } + } + if (exist || isRemoved(rpeer)) continue; + rpeer.dist++; + peers << rpeer; + findNearestAddresses(); + peerConnected(rpeer.name); + peerConnectedEvent(rpeer.name); + } + //piCout << "***"; + //piCout << self_info.name << self_info.neighbours; + piForeach (PeerInfo & i, peers) { + if (i.dist == 0) { + self_info.addNeighbour(i.name); + i.addNeighbour(self_info.name); + } + //piCout << i.name << i.neighbours; + } + //piCoutObj << "after sync " << peers.size_s() << " peers"; + break; + } + return true; +} + + +bool PIPeer::sendToNeighbour(PIPeer::PeerInfo * peer, const PIByteArray & ba) { + //if (peer->_neth == 0) return false; + piCout << "[PIPeer] sendToNeighbour" << peer->name << peer->_naddress << ba.size_s() << "bytes ..."; + //bool ok = peer->_neth->send(peer->_naddress, ba.data(), ba.size_s()); + bool ok = eth_send.send(peer->_naddress, ba); + //piCout << "[PIPeer] sendToNeighbour" << (ok ? "ok" : "fail"); + if (ok) diag_d.sended(ba.size_s()); + return ok; +} + + +void PIPeer::sendMBcast(const PIByteArray & ba) { + //piCout << "sendMBcast" << ba.size() << "bytes ..."; + piForeach (PIEthernet * e, eths_mcast) { + //errorClear(); + //piCout << "send to" << e->path() << e->sendAddress();// << e->send(ba); + //piCout << PIEthernet::ethErrorString(); + if (e->isOpened()) + if (e->send(ba)) + diag_s.sended(ba.size_s()); + } + piForeach (PIEthernet * e, eths_bcast) { + //errorClear(); + //piCout << "send to" << e->path() << e->sendAddress();// << e->send(ba); + //piCout << PIEthernet::ethErrorString(); + if (e->isOpened()) + if (e->send(ba)) + diag_s.sended(ba.size_s()); + } + for (int p = _PIPEER_LOOPBACK_PORT_S; p <= _PIPEER_LOOPBACK_PORT_E; ++p) { + eth_lo.setSendPort(p); + if (eth_lo.send(ba)) + diag_s.sended(ba.size_s()); + } + //piCout << "send muticast ok"; +} + + +void PIPeer::sendPeerInfo(const PeerInfo & info) { + PIByteArray ba; + ba << int(1) << info.name << info; + sendMBcast(ba); +} + + +void PIPeer::sendPeerRemove(const PIString & peer) { + PIByteArray ba; + ba << int(2) << peer; + sendMBcast(ba); +} + + +void PIPeer::pingNeighbours() { + PIByteArray ba, sba; + ba << int(5) << self_info.name; + //piCout << "pingNeighbours" << peers.size(); + piForeach (PeerInfo & p, peers) { + //piCout << " ping neighbour" << p.name; + if (!p.isNeighbour()) continue; + piForeach (PeerInfo::Address & a, p.addresses) { + //piCout << " address" << a.address << a.wait_ping; + if (a.wait_ping) continue; + a.wait_ping = true; + sba = ba; + sba << p.name << a.address << PISystemTime::current(true); + //piCout << "ping" << p.name << a.address << a.last_ping; + if (eth_send.send(a.address, sba)) + diag_s.sended(sba.size_s()); + } + } +} + + +void PIPeer::syncPeers() { + //piCout << "[PIPeer \"" + self_info.name + "\"] sync " << peers.size_s() << " peers"; + PIMutexLocker locker(eth_mutex); + PIString pn; + bool change = false; + for (uint i = 0; i < peers.size(); ++i) { + PeerInfo & cp(peers[i]); + if (cp.sync > 3 && cp.dist == 0) { + pn = cp.name; + //piCoutObj << "sync: remove " << pn; + addToRemoved(cp); + peers.remove(i); + sendPeerRemove(pn); + --i; + piForeach (PeerInfo & p, peers) + p.removeNeighbour(pn); + self_info.removeNeighbour(pn); + peerDisconnected(pn); + peerDisconnectedEvent(pn); + change = true; + continue; + } + cp.sync++; + } + pingNeighbours(); + if (change) findNearestAddresses(); + self_info.cnt++; + self_info.time = PISystemTime::current(); + PIByteArray ba; + ba << int(3) << self_info.name << self_info << peers; + sendMBcast(ba); +} + + +void PIPeer::findNearestAddresses() { + //piCout << "[PIPeer \"" + name_ + "\"] findNearestAddresses"; + addresses_map.clear(); + int max_dist = -1; + static PIMap peers_; + peers_.clear(); + self_info._nuses.resize(self_info.neighbours.size()); + self_info._nuses.fill(0); + self_info._first = &self_info; + peers_[self_info.name] = &self_info; + piForeach (PeerInfo & i, peers) { + i._nuses.resize(i.neighbours.size()); + i._nuses.fill(0); + i._first = 0; + peers_[i.name] = &i; + if (max_dist < i.dist) + max_dist = i.dist; + if (i.dist > 0) continue; + i._naddress.clear(); + i._neth = 0; + PIString mma, ma; + bool af = false; + for (int mi = 0; mi < self_info.addresses.size_s(); ++mi) { + PeerInfo::Address & a(self_info.addresses[mi]); + if (af) break; + ma = a.address; + //mma = m.left(m.findLast(".")); + mma = PIEthernet::applyMask(a.address, a.netmask); + for (int ii = 0; ii < i.addresses.size_s(); ++ii) { + PeerInfo::Address & r(i.addresses[ii]); + if (!r.isAvailable()) continue; + if (mma == PIEthernet::applyMask(r.address, r.netmask)) { + i._naddress = r.address; + //piCout << "_naddress" << i.name << "=" << r; + af = true; + break; + } + } + } + if (!af) continue; + //piCout << " peer" << i.name << ma; + piForeach (PIEthernet * e, eths_traffic) + if (e->readAddress() == ma) { + i._neth = e; + break; + } + //piCout << i.name << i._naddress; + } + PIVector cwave, nwave; + PeerInfo * npeer; + cwave << &self_info; + for (int d = 0; d <= max_dist; ++d) { + if (cwave.isEmpty()) break; + nwave.clear(); + piForeach (PeerInfo * p, cwave) { + int ns = p->neighbours.size_s(); + for (int n = 0; n < ns; ++n) { + if (p->_nuses[n] >= ns) continue; + p->_nuses[n]++; + npeer = peers_[p->neighbours[n]]; + if (npeer == 0) continue; + if (d == 0) npeer->_first = npeer; + else { + if (d == 1) npeer->_first = p; + else npeer->_first = p->_first; + } + nwave << npeer; + } + } + cwave = nwave; + //piCout << "wave" << d; + for (int i = 0; i < cwave.size_s(); ++i) { + //piCout << " peer" << cwave[i]->name << Hex << (uint)(cwave[i]->_first); + if (cwave[i]->_first == 0) {cwave.remove(i); --i; continue;} + if (addresses_map.contains(cwave[i]->name)) {cwave.remove(i); --i; continue;} + } + for (int i = 0; i < cwave.size_s(); ++i) { + PIVector & pl(addresses_map[cwave[i]->name]); + if (!pl.contains(cwave[i]->_first)) + pl << cwave[i]->_first; + } + } + /*piCout << " ** addresses map **"; + piForeachC (napair & i, addresses_map) + piCout << i.first << i.second; + piCout << " ** addresses map end **";*/ +} diff --git a/src/io/pipeer.h b/src/io/pipeer.h new file mode 100755 index 00000000..3cf11895 --- /dev/null +++ b/src/io/pipeer.h @@ -0,0 +1,185 @@ +/*! \file pipeer.h + * \brief Peering net node +*/ +/* + PIP - Platform Independent Primitives + Peer - named I/O ethernet node, forming self-organized peering network + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIPEER_H +#define PIPEER_H + +#include "piethernet.h" +#include "pidiagnostics.h" + +class PIP_EXPORT PIPeer: public PIObject +{ + PIOBJECT(PIPeer) +private: + struct PeerData { + PeerData() {msg_count = msg_rec = 0;} + void clear() {msg_count = msg_rec = 0; data.clear();} + bool isEmpty() const {return msg_count == 0;} + bool isFullReceived() const {return msg_count == msg_rec;} + void addData(const PIByteArray & ba) {data.append(ba); msg_rec++;} + void setData(const PIByteArray & ba) {data = ba; msg_rec = 0; msg_count = (data.size_s() - 1) / 4096 + 1;} + PIByteArray data; + int msg_count; + int msg_rec; + }; + +public: + PIPeer(const PIString & name); + virtual ~PIPeer(); + + class PeerInfo { + friend class PIPeer; + friend PIByteArray & operator <<(PIByteArray & s, const PIPeer::PeerInfo & v); + friend PIByteArray & operator >>(PIByteArray & s, PIPeer::PeerInfo & v); + public: + PeerInfo() {dist = sync = cnt = 0; _neth = 0; _first = 0;} + + struct Address { + Address(const PIString & a = PIString(), const PIString & m = "255.255.255.0"); + bool isAvailable() const {return ping > 0;} + //inline const Address & operator =(const Address & v) {address = v.address; netmask = v.netmask; piCout << "!!!!!!!!!" << last_ping; return *this;} + PIString address; + PIString netmask; + double ping; // ms + bool wait_ping; + PISystemTime last_ping; + }; + + PIString name; + PIVector
addresses; + int dist; + + bool isNeighbour() const {return dist == 0;} + int ping() const; + + protected: + void addNeighbour(const PIString & n) {if (!neighbours.contains(n)) neighbours << n;} + void addNeighbours(const PIStringList & l) {piForeachC (PIString & n, l) if (!neighbours.contains(n)) neighbours << n;} + void removeNeighbour(const PIString & n) {neighbours.removeAll(n);} + + PIString nearest_address; + PIStringList neighbours; + int sync, cnt; + PISystemTime time; + PIString _naddress; + PIEthernet * _neth; + PIVector _nuses; + PeerInfo * _first; + PeerData _data; + + }; + + friend PIByteArray & operator <<(PIByteArray & s, const PIPeer::PeerInfo & v); + friend PIByteArray & operator >>(PIByteArray & s, PIPeer::PeerInfo & v); + + bool send(const PIString & to, const PIByteArray & data) {return send(to, data.data(), data.size_s());} + bool send(const PIString & to, const PIString & data) {return send(to, data.data(), data.size_s());} + bool send(const PIString & to, const void * data, int size); + bool send(const PeerInfo & to, const PIByteArray & data) {return send(to.name, data.data(), data.size_s());} + bool send(const PeerInfo & to, const PIString & data) {return send(to.name, data.data(), data.size_s());} + bool send(const PeerInfo & to, const void * data, int size) {return send(to.name, data, size);} + bool send(const PeerInfo * to, const PIByteArray & data) {if (to == 0) return false; return send(to->name, data.data(), data.size_s());} + bool send(const PeerInfo * to, const PIString & data) {if (to == 0) return false; return send(to->name, data.data(), data.size_s());} + bool send(const PeerInfo * to, const void * data, int size) {if (to == 0) return false; return send(to->name, data, size);} + void sendToAll(const PIByteArray & data) {piForeachC (PeerInfo & i, peers) send(i.name, data.data(), data.size_s());} + void sendToAll(const PIString & data) {piForeachC (PeerInfo & i, peers) send(i.name, data.data(), data.size_s());} + void sendToAll(const void * data, int size) {piForeachC (PeerInfo & i, peers) send(i.name, data, size);} + + bool isMulticastReceive() const {return !eths_mcast.isEmpty();} + bool isBroadcastReceive() const {return !eths_bcast.isEmpty();} + + PIDiagnostics & diagnosticService() {return diag_s;} + PIDiagnostics & diagnosticData() {return diag_d;} + + const PIVector & allPeers() const {return peers;} + bool isPeerExists(const PIString & name) const {return getPeerByName(name) != 0;} + + const PeerInfo * getPeerByName(const PIString & name) const {piForeachC (PeerInfo & i, peers) if (i.name == name) return &i; return 0;} + + void lock() {mc_mutex.lock();} + void unlock() {mc_mutex.unlock();} + + EVENT2(dataReceivedEvent, const PIString &, from, const PIByteArray &, data); + EVENT1(peerConnectedEvent, const PIString &, name); + EVENT1(peerDisconnectedEvent, const PIString &, name); + +protected: + virtual void dataReceived(const PIString & from, const PIByteArray & data) {;} + virtual void peerConnected(const PIString & name) {;} + virtual void peerDisconnected(const PIString & name) {;} + + EVENT_HANDLER2(bool, dataRead, uchar *, readed, int, size); + EVENT_HANDLER2(bool, mbcastRead, uchar *, readed, int, size); + +private: + EVENT_HANDLER2(void, timerEvent, void * , data, int, delim); + + bool hasPeer(const PIString & name) {piForeachC (PeerInfo & i, peers) if (i.name == name) return true; return false;} + bool removePeer(const PIString & name) {for (uint i = 0; i < peers.size(); ++i) if (peers[i].name == name) {peers.remove(i); return true;} return false;} + + void sendPeerInfo(const PeerInfo & info); + void sendPeerRemove(const PIString & peer); + void sendSelfInfo() {sendPeerInfo(self_info);} + void sendSelfRemove() {sendPeerRemove(self_info.name);} + void syncPeers(); + void findNearestAddresses(); + void initEths(PIStringList al); + void initMBcasts(PIStringList al); + void destroyMBcasts(); + void sendMBcast(const PIByteArray & ba); + void pingNeighbours(); + void addToRemoved(const PeerInfo & pi) {removed[pi.name] = PIPair(pi.cnt, pi.time);} + bool isRemoved(const PeerInfo & pi) const {return (removed.value(pi.name) == PIPair(pi.cnt, pi.time));} + + PeerInfo * quickestPeer(const PIString & to); + bool sendToNeighbour(PeerInfo * peer, const PIByteArray & ba); + inline static bool isPeerRecent(const PeerInfo & my, const PeerInfo & income) {return (my.cnt < income.cnt) || (my.time < income.time);} + + // 1 - new peer, 2 - remove peer, 3 - sync peers, 4 - data, 5 - ping + // Data packet: 4, from, to, ticks, data_size, data + + typedef PIPair > napair; + + PIVector eths_traffic, eths_mcast, eths_bcast; + PIEthernet eth_send, eth_lo; + PITimer timer; + PIMutex mc_mutex, eth_mutex; + + PeerInfo self_info; + PIVector peers; + PIMap > addresses_map; // map {"to" = list of nearest peers} + PIMap > removed; + PIDiagnostics diag_s, diag_d; + //PIString id_; + +}; + +inline PICout operator <<(PICout c, const PIPeer::PeerInfo::Address & v) {c.space(); c << "PeerAddress(" << v.address << ", " << v.netmask << ", " << v.ping << ")"; return c;} +inline PICout operator <<(PICout c, const PIPeer::PeerInfo & v) {c.space(); c << "PeerInfo(" << v.name << ", " << v.dist << ", " << v.addresses << ")"; return c;} + +inline PIByteArray & operator <<(PIByteArray & s, const PIPeer::PeerInfo::Address & v) {s << v.address << v.netmask << v.ping; return s;} +inline PIByteArray & operator >>(PIByteArray & s, PIPeer::PeerInfo::Address & v) {s >> v.address >> v.netmask >> v.ping; return s;} + +inline PIByteArray & operator <<(PIByteArray & s, const PIPeer::PeerInfo & v) {s << v.name << v.addresses << v.dist << v.neighbours << v.cnt << v.time; return s;} +inline PIByteArray & operator >>(PIByteArray & s, PIPeer::PeerInfo & v) {s >> v.name >> v.addresses >> v.dist >> v.neighbours >> v.cnt >> v.time; return s;} + +#endif // PIPEER_H diff --git a/src/io/piprotocol.cpp b/src/io/piprotocol.cpp new file mode 100755 index 00000000..df3be9bb --- /dev/null +++ b/src/io/piprotocol.cpp @@ -0,0 +1,792 @@ +/* + PIP - Platform Independent Primitives + Protocol, input/output channel (COM, UDP) + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "piprotocol.h" + + +/** \class PIProtocol + * \brief + * \details + * \section PIProtocol_sec0 Synopsis + * + * + * + * */ + + +PIProtocol::PIProtocol(const PIString & config, const PIString & name_, void * recHeaderPtr, int recHeaderSize, void * recDataPtr, int recDataSize, void * sendDataPtr_, int sendDataSize_): PIObject() { + init(); + protName = name_; + PIObject::setName(name_); + PIConfig conf(config, PIIODevice::ReadOnly); + if (!conf.isOpened()) { + piCoutObj << "Can`t open \"" << config << "\"!"; + devReceiverState = devSenderState = "Config error"; + return; + } + PIConfig::Entry & b(conf.getValue(name_)), + & rb(b.getValue("receiver")), + & sb(b.getValue("sender")); + + init_receiver(b, rb, config); + init_sender(b, sb, config); + + headerPtr = (uchar * )recHeaderPtr; + headerSize = recHeaderSize; + dataPtr = (uchar * )recDataPtr; + dataSize = recDataSize; + sendDataPtr = (uchar * )sendDataPtr_; + sendDataSize = sendDataSize_; + packet_ext->setHeader(PIByteArray(recHeaderPtr, recHeaderSize)); + packet_ext->setPayloadSize(recDataSize); + packet_ext->setPacketSize(recDataSize); + packet_ext->setSplitMode(PIPacketExtractor::Header); + bool null_h = (recHeaderPtr == 0 || recHeaderSize == 0), null_d = (recDataPtr == 0 || recDataSize == 0); + if (null_h && null_d) packet_ext->setSplitMode(PIPacketExtractor::None); + else { + if (null_h) packet_ext->setSplitMode(PIPacketExtractor::Size); + } +} + + +PIProtocol::~PIProtocol() { + //cout << "prot " << protName << " delete\n"; + if (history_write_rec) { + if (history_file_rec.isEmpty()) { + history_file_rec.close(); + history_file_rec.remove(); + } + history_file_rec.close(); + } + if (history_write_send) { + if (history_file_send.isEmpty()) { + history_file_send.close(); + history_file_send.remove(); + } + history_file_send.close(); + } + delete diagTimer; + delete sendTimer; + delete secTimer; + delete packet_ext; + if (eth != 0) delete eth; + if (ser != 0) delete ser; +} + + +void PIProtocol::init() { + packet_ext = new PIPacketExtractor(0, PIPacketExtractor::None); + packet_ext->setThreadedReadData(this); + packet_ext->setThreadedReadSlot(receiveEvent); + packet_ext->setHeaderCheckSlot(headerValidateEvent); + packet_ext->setName("__S__PIProtocol::packet_ext"); + work = new_mp_prot = history_write_rec = history_write_send = false; + eth = 0; + ser = 0; + ret_func = 0; + mp_owner = 0; + net_diag = PIProtocol::Unknown; + cur_pckt = 0; + packets[0] = packets[1] = pckt_cnt = pckt_cnt_max = 0; + diagTimer = 0; + timeout_ = 3.f; + sendTimer = new PITimer(sendEvent, this); + diagTimer = new PITimer(diagEvent, this); + secTimer = new PITimer(secEvent, this); + sendTimer->setName("__S__PIProtocol::sendTimer"); + diagTimer->setName("__S__PIProtocol::diagTimer"); + secTimer->setName("__S__PIProtocol::secTimer"); + wrong_count = receive_count = send_count = missed_count = 0; + packets_in_sec = packets_out_sec = bytes_in_sec = bytes_out_sec = 0; + immediate_freq = integral_freq = ifreq = 0.f; + headerPtr = dataPtr = sendDataPtr = 0; + headerSize = dataSize = sendDataSize = 0; + type_rec = type_send = PIProtocol::None; + devSenderState = devReceiverState = "Unknown"; + devSenderName = devReceiverName = "no device"; + history_rsize_rec = history_rsize_send = "no file"; + history_file_rec.setName("__S__PIProtocol::history_file_rec"); + history_file_send.setName("__S__PIProtocol::history_file_send"); + secTimer->start(1000.); + /*addEvent("receiver started"); + addEvent("receiver stopped"); + addEvent("sender started"); + addEvent("sender stopped"); + addEvent("received"); + addEvent("quality changed"); + addEventHandler(HANDLER(PIProtocol, startReceive)); + addEventHandler(HANDLER(PIProtocol, startSend)); + addEventHandler(HANDLER(PIProtocol, start)); + addEventHandler(HANDLER(PIProtocol, stopReceive)); + addEventHandler(HANDLER(PIProtocol, stopSend)); + addEventHandler(HANDLER(PIProtocol, stop));*/ +} + + +void PIProtocol::init_sender(PIConfig::Entry & b, PIConfig::Entry & sb, const PIString & config) { + int ps, gps; + bool ok, gok, flag, gflag, has_dev = false; + float freq, gfreq; + PIFlags pp(0); + PIString dev, gdev; + + if (sb.isEntryExists("ip") && sb.isEntryExists("device")) { + piCoutObj << "Ambiguous sender type in \"" << config << "\"!"; + devSenderState = "Config error"; + return; + } + dev = sb.getValue("ip", "", &ok); + gdev = b.getValue("ip", "", &gok); + has_dev = false; + if (ok || gok) { + if (gok && !ok) dev = gdev; + if (gok && ok && (dev != gdev)) { + piCoutObj << "Ambiguous sender type in \"" << config << "\"!"; + devSenderState = "Config error"; + return; + } + ps = sb.getValue("port", 0, &ok); + gps = b.getValue("port", 0, &gok); + if (ok || gok) { + if (gok && !ok) ps = gps; + if (gok && ok && (ps != gps)) { + piCoutObj << "Ambiguous send port in \"" << config << "\"!"; + devSenderState = "Config error"; + return; + } + type_send = PIProtocol::Ethernet; + if (eth == 0) eth = new PIEthernet(); + eth->setName("__S__PIProtocol::eth"); + setSenderAddress(dev, ps); + //setReceiverAddress(dev, ps); + has_dev = true; + flag = sb.getValue("reconnectEnabled", true, &ok); + gflag = b.getValue("reconnectEnabled", true, &gok); + if (ok || gok) { + if (gok && !ok) flag = gflag; + if (gok && ok && (flag != gflag)) { + piCoutObj << "Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!"; + devReceiverState = "Config error"; + return; + } + eth->setReopenEnabled(flag); + } + freq = sb.getValue("reconnectTimeout", 1., &ok); + gfreq = b.getValue("reconnectTimeout", 1., &gok); + if (ok || gok) { + if (gok && !ok) freq = gfreq; + if (gok && ok && (freq != gfreq)) { + piCoutObj << "Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!"; + devReceiverState = "Config error"; + return; + } + eth->setReopenTimeout(freq * 1000); + } + /*if (sendDataPtr_ == 0) + piCoutObj << "Warning: null send data pointer!"; + if (sendDataSize_ == 0) + piCoutObj << "Warning: null send data size!";*/ + } else { + piCoutObj << "Can`t find \"" << name() << ".sender.port\" or \"" << name() << ".port\" in \"" << config << "\"!"; + devSenderState = "Config error"; + return; + } + } + dev = sb.getValue("device", "", &ok); + gdev = b.getValue("device", "", &gok); + if (ok || gok) { + if (gok && !ok) dev = gdev; + if (gok && ok && (dev != gdev)) { + piCoutObj << "Ambiguous sender type in \"" << config << "\"!"; + devSenderState = "Config error"; + return; + } + ps = sb.getValue("speed", 0, &ok); + gps = b.getValue("speed", 0, &gok); + if (ok || gok) { + if (gok && !ok) ps = gps; + if (gok && ok && (ps != gps)) { + piCoutObj << "Ambiguous send \"speed\" in \"" << config << "\"!"; + devSenderState = "Config error"; + return; + } + flag = sb.getValue("parity", false, &ok); + gflag = b.getValue("parity", false, &gok); + if (ok || gok) { + if (gok && !ok) flag = gflag; + if (gok && ok && (flag != gflag)) { + piCoutObj << "Ambiguous send \"parity\" in \"" << config << "\"!"; + devSenderState = "Config error"; + return; + } + pp.setFlag(PISerial::ParityControl, flag); + } + flag = sb.getValue("twoStopBits", false, &ok); + gflag = b.getValue("twoStopBits", false, &gok); + if (ok || gok) { + if (gok && !ok) flag = gflag; + if (gok && ok && (flag != gflag)) { + piCoutObj << "Ambiguous send \"twoStopBits\" parity in \"" << config << "\"!"; + devSenderState = "Config error"; + return; + } + pp.setFlag(PISerial::TwoStopBits, flag); + } + } else { + piCoutObj << "Can`t find \"" << name() << ".sender.speed\" or \"" << name() << ".speed\" in \"" << config << "\"!"; + devSenderState = "Config error"; + return; + } + type_send = PIProtocol::Serial; + if (ser == 0) ser = new PISerial(dev); + ser->setName("__S__PIProtocol::ser"); + setSenderDevice(dev, (PISerial::Speed)ps); + ser->setOutSpeed((PISerial::Speed)ps); + ser->setParameters(pp); + has_dev = true; + /*if (sendDataPtr_ == 0) + piCoutObj << "Warning: null send data pointer!"; + if (sendDataSize_ == 0) + piCoutObj << "Warning: null send data size!";*/ + } + history_write_send = sb.getValue("writeHistory", false, &ok); + bool ghist = b.getValue("writeHistory", false, &gok); + if (ok || gok) { + if (gok && !ok) history_write_send = ghist; + if (gok && ok && (history_write_send != ghist)) { + piCoutObj << "Ambiguous sender history in \"" << config << "\"!"; + devSenderState = "Config error"; + return; + } + if (history_write_send) { + history_path_send = sb.getValue("historyFile", "./history_" + protName + "_send_" + + PIDate::current().toString("__dd_mm_yyyy_") + + PITime::current().toString("_hh_mm_ss_")).value(); + history_id_send = sb.getValue("historyID", 0, &ok); + if (!ok) { + history_id_send = ushort(protName.toByteArray().checksumPlain32()) + 1; + piCoutObj << "Warning: no sender history ID defined, write with ID = " << history_id_send; + } + history_file_send.open(history_path_send, PIIODevice::WriteOnly); + } + } + freq = sb.getValue("frequency", -1.f, &ok); + gfreq = b.getValue("frequency", -1.f, &gok); + if (gok && !ok) freq = gfreq; + if (gok && ok && (freq != gfreq)) { + piCoutObj << "Ambiguous sender frequency in \"" << config << "\"!"; + devSenderState = "Config error"; + return; + } + if (freq > 0.f && !has_dev) + piCoutObj << "Warning: no sender device and not null send frequency!"; + setSenderFrequency(freq); +} + + +void PIProtocol::init_receiver(PIConfig::Entry & b, PIConfig::Entry & rb, const PIString & config) { + int ps, gps; + bool ok, gok, flag, gflag, has_dev = false; + float freq, gfreq; + PIFlags pp(0); + PIString dev, gdev; + + if (rb.isEntryExists("ip") && rb.isEntryExists("device")) { + piCoutObj << "Ambiguous receiver type in \"" << config << "\"!"; + devReceiverState = "Config error"; + return; + } + dev = rb.getValue("ip", "", &ok); + gdev = b.getValue("ip", "", &gok); + if (ok || gok) { + if (gok && !ok) dev = gdev; + if (gok && ok && (dev != gdev)) { + piCoutObj << "Ambiguous receiver type in \"" << config << "\"!"; + devReceiverState = "Config error"; + return; + } + ps = rb.getValue("port", 0, &ok); + gps = b.getValue("port", 0, &gok); + if (ok || gok) { + if (gok && !ok) ps = gps; + if (gok && ok && (ps != gps)) { + piCoutObj << "Ambiguous receive port in \"" << config << "\"!"; + devReceiverState = "Config error"; + return; + } + type_rec = PIProtocol::Ethernet; + eth = new PIEthernet(); + eth->setName("__S__PIProtocol::eth"); + packet_ext->setDevice(eth); + //setSenderAddress(dev, ps); + setReceiverAddress(dev, ps); + has_dev = true; + flag = rb.getValue("reconnectEnabled", true, &ok); + gflag = b.getValue("reconnectEnabled", true, &gok); + if (ok || gok) { + if (gok && !ok) flag = gflag; + if (gok && ok && (flag != gflag)) { + piCoutObj << "Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!"; + devReceiverState = "Config error"; + return; + } + eth->setReopenEnabled(flag); + } + freq = rb.getValue("reconnectTimeout", 1., &ok); + gfreq = b.getValue("reconnectTimeout", 1., &gok); + if (ok || gok) { + if (gok && !ok) freq = gfreq; + if (gok && ok && (freq != gfreq)) { + piCoutObj << "Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!"; + devReceiverState = "Config error"; + return; + } + eth->setReopenTimeout(freq * 1000); + } + /*if (recDataPtr == 0) + piCoutObj << "Warning: null receive data pointer!"; + if (recDataSize == 0) + piCoutObj << "Warning: null receive data size!";*/ + } else { + piCoutObj << "Can`t find \"" << name() << ".receiver.port\" or \"" << name() << ".port\" in \"" << config << "\"!"; + devReceiverState = "Config error"; + return; + } + } + dev = rb.getValue("device", "", &ok); + gdev = b.getValue("device", "", &gok); + if (ok || gok) { + if (gok && !ok) dev = gdev; + if (gok && ok && (dev != gdev)) { + piCoutObj << "Ambiguous receiver type in \"" << config << "\"!"; + devReceiverState = "Config error"; + return; + } + ps = rb.getValue("speed", 0, &ok); + gps = b.getValue("speed", 0, &gok); + if (ok || gok) { + if (gok && !ok) ps = gps; + if (gok && ok && (ps != gps)) { + piCoutObj << "Ambiguous receive \"speed\" in \"" << config << "\"!"; + devReceiverState = "Config error"; + return; + } + flag = rb.getValue("parity", false, &ok); + gflag = b.getValue("parity", false, &gok); + if (ok || gok) { + if (gok && !ok) flag = gflag; + if (gok && ok && (flag != gflag)) { + piCoutObj << "Ambiguous receive \"parity\" in \"" << config << "\"!"; + devReceiverState = "Config error"; + return; + } + pp.setFlag(PISerial::ParityControl, flag); + } + flag = rb.getValue("twoStopBits", false, &ok); + gflag = b.getValue("twoStopBits", false, &gok); + if (ok || gok) { + if (gok && !ok) flag = gflag; + if (gok && ok && (flag != gflag)) { + piCoutObj << "Ambiguous receive \"twoStopBits\" parity in \"" << config << "\"!"; + devReceiverState = "Config error"; + return; + } + pp.setFlag(PISerial::TwoStopBits, flag); + } + type_rec = PIProtocol::Serial; + type_send = PIProtocol::Serial; + ser = new PISerial(dev); + ser->setName("__S__PIProtocol::ser"); + packet_ext->setDevice(ser); + //setSenderDevice(dev, (PISerial::Speed)ps); + setReceiverDevice(dev, (PISerial::Speed)ps); + ser->setInSpeed((PISerial::Speed)ps); + ser->setParameters(pp); + ps = rb.getValue("vtime", 1, &ok); + gps = b.getValue("vtime", 1, &gok); + if (ok || gok) { + if (gok && !ok) ps = gps; + if (gok && ok && (ps != gps)) { + piCoutObj << "Ambiguous receive \"vtime\" in \"" << config << "\"!"; + devReceiverState = "Config error"; + return; + } + ser->setVTime(ps); + } + has_dev = true; + /*if (recDataPtr == 0) + piCoutObj << "Warning: null receive data pointer!"; + if (recDataSize == 0) + piCoutObj << "Warning: null receive data size!";*/ + } else { + piCoutObj << "Can`t find \"" << name() << ".receiver.speed\" or \"" << name() << ".speed\" in \"" << config << "\"!"; + devReceiverState = "Config error"; + return; + } + } + history_write_rec = rb.getValue("writeHistory", false, &ok); + bool ghist = b.getValue("writeHistory", false, &gok); + if (ok || gok) { + if (gok && !ok) history_write_rec = ghist; + if (gok && ok && (history_write_rec != ghist)) { + piCoutObj << "Ambiguous receiver history in \"" << config << "\"!"; + devReceiverState = "Config error"; + return; + } + if (history_write_rec) { + history_path_rec = rb.getValue("historyFile", "./history_" + protName + "_rec_" + + PIDate::current().toString("__dd_mm_yyyy_") + + PITime::current().toString("_hh_mm_ss_")).value(); + history_id_rec = rb.getValue("historyID", 0, &ok); + if (!ok) { + history_id_rec = ushort(protName.toByteArray().checksumPlain32()); + piCoutObj << "Warning: no receiver history ID defined, write with ID = " << history_id_rec; + } + history_file_rec.open(history_path_rec, PIIODevice::WriteOnly); + } + } + freq = rb.getValue("frequency", -1.f, &ok); + gfreq = b.getValue("frequency", -1.f, &gok); + if (gok && !ok) freq = gfreq; + if (gok && ok && (freq != gfreq)) { + piCoutObj << "Ambiguous expected frequency in \"" << config << "\"!"; + devReceiverState = "Config error"; + return; + } + if (freq > 0.f && !has_dev) + piCoutObj << "Warning: no receiver device and not null expected frequency!"; + float tm = b.getValue("disconnectTimeout", 3.f); + if (tm <= 0.f) + piCoutObj << "Warning: diconnect timeout <= 0 s!"; + timeout_ = (tm < 0.f) ? 0.f : tm; + setExpectedFrequency(freq); +} + + +void PIProtocol::setReceiverDevice(const PIString & device, PISerial::Speed speed, bool force) { + if (force) { + type_send = type_rec = PIProtocol::Serial; + if (ser == 0) { + ser = new PISerial(); + ser->setName("__S__PIProtocol::ser"); + packet_ext->setDevice(ser); + } + } + if (type_rec == PIProtocol::Serial && ser != 0) { + ser->setDevice(device); + ser->setSpeed(speed); + devReceiverName = device; + devSenderName = device; + } +} + + +void PIProtocol::setReceiverAddress(const PIString & ip, int port, bool force) { + if (force) { + type_rec = PIProtocol::Ethernet; + if (eth == 0) { + eth = new PIEthernet(); + eth->setName("__S__PIProtocol::eth"); + packet_ext->setDevice(eth); + } + } + if (type_rec == PIProtocol::Ethernet && eth != 0) { + eth->setReadAddress(ip, port); + if (ip.trimmed().isEmpty()) devReceiverName = "no ip"; + else devReceiverName = ip + ":" + PIString::fromNumber(port); + } +} + + +void PIProtocol::setSenderDevice(const PIString & device, PISerial::Speed speed, bool force) { + if (force) { + type_send = type_rec = PIProtocol::Serial; + if (ser == 0) ser = new PISerial(); + ser->setName("__S__PIProtocol::ser"); + } + if (type_send == PIProtocol::Serial && ser != 0) { + ser->setDevice(device); + ser->setSpeed(speed); + ser->open(); + devSenderName = device; + } +} + + +void PIProtocol::setSenderAddress(const PIString & ip, int port, bool force) { + if (force) { + type_send = PIProtocol::Ethernet; + if (eth == 0) eth = new PIEthernet(); + eth->setName("__S__PIProtocol::eth"); + } + if (type_send == PIProtocol::Ethernet && eth != 0) { + eth->setSendAddress(ip, port); + if (ip.isEmpty()) devSenderName = "no ip"; + else devSenderName = ip + ":" + PIString::fromNumber(port); + } +} + + +void PIProtocol::setSenderIP(const PIString & ip, bool force) { + if (force) { + type_send = PIProtocol::Ethernet; + if (eth == 0) eth = new PIEthernet(); + } + if (type_send == PIProtocol::Ethernet && eth != 0) { + eth->setSendIP(ip); + if (ip.isEmpty()) devSenderName = "no ip"; + else devSenderName = ip + ":" + PIString::fromNumber(eth->sendPort()); + } +} + + +void PIProtocol::setSenderPort(int port, bool force) { + if (force) { + type_send = PIProtocol::Ethernet; + if (eth == 0) eth = new PIEthernet(); + eth->setName("__S__PIProtocol::eth"); + } + if (type_send == PIProtocol::Ethernet && eth != 0) { + eth->setSendPort(port); + if (eth->sendIP().isEmpty()) devSenderName = "no ip"; + else devSenderName = eth->sendIP() + ":" + PIString::fromNumber(port); + } +} + + +void PIProtocol::setExpectedFrequency(float frequency) { + exp_freq = frequency; + changeDisconnectTimeout(); +} + + +void PIProtocol::changeDisconnectTimeout() { + pckt_cnt_max = int(round(timeout_ * exp_freq)); + if (pckt_cnt_max < 3) pckt_cnt_max = 3; + last_packets.resize(pckt_cnt_max); +} + + +void PIProtocol::startReceive(float exp_frequency) { + if (exp_frequency > 0.f) exp_freq = exp_frequency; + //if (type_rec == PIProtocol::Serial) ser->start(); + //if (type_rec == PIProtocol::Ethernet) eth->start(); + packet_ext->startThreadedRead(); + msleep(1); + check_state(); + if (exp_freq <= 0.f) return; + setExpectedFrequency(exp_freq); + diagTimer->start(1000. / exp_freq); + diag_tm.reset(); + receiverStarted(); +} + + +void PIProtocol::startSend(float frequency) { + //cout << "** start send " << send_freq << ", " << frequency << endl; + if (frequency > 0.f) send_freq = frequency; + msleep(1); + check_state(); + if (send_freq <= 0.f) return; + sendTimer->start(1000. / send_freq); + diag_tm.reset(); + senderStarted(); +} + + +void PIProtocol::stopReceive() { + //if (type_rec == PIProtocol::Serial) ser->stop(); + //if (type_rec == PIProtocol::Ethernet) eth->stop(); + packet_ext->stop(); + diagTimer->stop(); + receiverStopped(); +} + + +bool PIProtocol::receiveEvent(void * t, uchar * data, int size) { + PIProtocol * p = (PIProtocol * )t; + if (!p->receive(data, size)) return false; + p->work = true; + //p->lock(); + if (p->validate()) { + if (p->history_write_rec) { + p->history_file_rec.writeToBinLog(p->history_id_rec, data, size); + p->history_rsize_rec.setReadableSize(p->history_file_rec.pos()); + } + p->received(true); + //p->unlock(); + p->ifreq = p->diag_tm.elapsed_m(); + if (p->ifreq > 0.) p->ifreq = 1000. / p->ifreq; + p->diag_tm.reset(); + p->receive_count++; + p->packets_in_sec++; + p->bytes_in_sec += size; + p->cur_pckt = 1; + if (p->ret_func != 0) p->ret_func(p); + if (p->mp_owner != 0) PIMultiProtocolBase::receiveEvent(p->mp_owner, p, true, data, size); + return true; + } + p->received(false); + //p->unlock(); + p->wrong_count++; + if (p->mp_owner != 0) PIMultiProtocolBase::receiveEvent(p->mp_owner, p, false, data, size); + return false; +} + + +void PIProtocol::diagEvent(void * t, int) { + PIProtocol * p = (PIProtocol * )t; + p->calc_freq(); + p->calc_diag(); + p->check_state(); + if (p->ser != 0) p->missed_count = p->packet_ext->missedPackets(); +} + + +void PIProtocol::secEvent(void * t, int ) { + PIProtocol * p = (PIProtocol * )t; + p->speedIn = PIString::readableSize(p->bytes_in_sec) + "/s"; + p->speedOut = PIString::readableSize(p->bytes_out_sec) + "/s"; + p->bytes_in_sec = p->bytes_out_sec = p->packets_in_sec = p->packets_out_sec = 0; + if (p->ser != 0) p->missed_count = p->packet_ext->missedPackets(); +} + + +void PIProtocol::calc_diag() { + PIProtocol::Quality diag; + if (!work) { + diag = PIProtocol::Unknown; + return; + } + if (pckt_cnt < pckt_cnt_max) { + last_packets[pckt_cnt] = cur_pckt; + pckt_cnt++; + } else { + packets[(int)last_packets.back()]--; + if (!last_packets.isEmpty()) last_packets.pop_back(); + last_packets.push_front(cur_pckt); + } + packets[(int)cur_pckt]++; + cur_pckt = 0; + float good_percents; + good_percents = (float)packets[1] / pckt_cnt * 100.f; + if (good_percents == 0.f) diag = PIProtocol::Failure; + else if (good_percents <= 20.f) diag = PIProtocol::Bad; + else if (good_percents > 20.f && good_percents <= 80.f) diag = PIProtocol::Average; + else diag = PIProtocol::Good; + if (diag != net_diag) { + qualityChanged(diag, net_diag); + net_diag = diag; + } +} + + +void PIProtocol::calc_freq() { + float tf;// = float(1000.f / diagTimer->elapsed_m()); + tf = immediate_freq = ifreq; + ifreq = 0.f; + if (last_freq.size_s() >= pckt_cnt_max && last_freq.size_s() > 0) last_freq.pop_front(); + last_freq.push_back(tf); + tf = last_freq[0]; + for (uint i = 1; i < last_freq.size(); ++i) + tf += last_freq[i]; + integral_freq = tf / last_freq.size(); +} + + +void PIProtocol::check_state() { + if (type_rec == PIProtocol::Serial) { + if (ser != 0) { + if (ser->isOpened()) devReceiverState = "Opened"; + else devReceiverState = "Not opened"; + } + else devReceiverState = "Not exists"; + } + if (type_rec == PIProtocol::Ethernet) { + if (eth != 0) { + if (eth->isOpened()) devReceiverState = "Opened"; + else devReceiverState = "Not opened"; + } + else devReceiverState = "Not exists"; + } + if (type_send == PIProtocol::Serial) { + if (ser != 0) { + if (ser->isOpened()) devSenderState = "Opened"; + else devSenderState = "Not opened"; + } + else devSenderState = "Not exists"; + } + if (type_send == PIProtocol::Ethernet) { + if (eth != 0) { + if (eth->isOpened()) devSenderState = "Opened"; + else devSenderState = "Not opened"; + } + else devSenderState = "Not exists"; + } +} + + +void PIProtocol::send(const void * data, int size, bool direct) { + if (!direct) { + if (data == 0 || size == 0) return; + if (!aboutSend()) return; + } + if (history_write_send) { + history_file_send.writeToBinLog(history_id_send, data, size); + history_rsize_send.setReadableSize(history_file_send.pos()); + } + if (type_send == PIProtocol::Serial) + if (ser->send(data, size)) { + send_count++; + packets_out_sec++; + bytes_out_sec += size; + } + if (type_send == PIProtocol::Ethernet) + if (eth->send(data, size)) { + send_count++; + packets_out_sec++; + bytes_out_sec += size; + } +} + + +void PIProtocol::send() { + //lock(); + //memcpy(packet, sendDataPtr, sendDataSize); + //unlock(); + //cout << "**send" << endl; + if (!aboutSend()) return; + if (sendDataPtr == 0 || sendDataSize == 0) return; + if (history_write_send) { + history_file_send.writeToBinLog(history_id_send, sendDataPtr, sendDataSize); + history_rsize_send.setReadableSize(history_file_send.pos()); + } + if (type_send == PIProtocol::Serial) + if (ser->send(sendDataPtr, sendDataSize)) { + send_count++; + packets_out_sec++; + bytes_out_sec += sendDataSize; + } + if (type_send == PIProtocol::Ethernet) + if (eth->send(sendDataPtr, sendDataSize)) { + send_count++; + packets_out_sec++; + bytes_out_sec += sendDataSize; + } +} diff --git a/src/io/piprotocol.h b/src/io/piprotocol.h new file mode 100755 index 00000000..5900e106 --- /dev/null +++ b/src/io/piprotocol.h @@ -0,0 +1,249 @@ +/*! \file piprotocol.h + * \brief Highly configurable from file I/O channel +*/ +/* + PIP - Platform Independent Primitives + Protocol, input/output channel (COM, UDP) + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIPROTOCOL_H +#define PIPROTOCOL_H + +#include "piserial.h" +#include "piethernet.h" +#include "pipacketextractor.h" +#include "pitimer.h" +#include "piconfig.h" +#include "math.h" + +class PIProtocol; + +class PIP_EXPORT PIMultiProtocolBase: protected PIObject +{ + PIOBJECT(PIMultiProtocolBase) + friend class PIProtocol; +public: + PIMultiProtocolBase() {;} + virtual ~PIMultiProtocolBase() {;} + +protected: + virtual void received(PIProtocol * prot, bool corrected, uchar * data, int size) {;} + +private: + static void receiveEvent(PIMultiProtocolBase * p, PIProtocol * prot, bool corrected, uchar * data, int size) {p->mutex_receive.lock(); p->received(prot, corrected, data, size); p->mutex_receive.unlock();} + + PIMutex mutex_receive; + +}; + +typedef void (*ReceiveFunc)(void * ); + +/// events: +/// void receiverStarted() +/// void receiverStopped() +/// void senderStarted() +/// void senderStopped() +/// void received(bool validate_is_ok) +/// void qualityChanged(PIProtocol::Quality old_quality, PIProtocol::Quality new_quality) +/// +/// handlers: +/// void startReceive(float exp_frequency = -1.f) +/// void stopReceive() +/// void startSend(float frequency = -1.f) +/// void stopSend() +/// void start() +/// void stop() +/// void send() +/// void send(const void * data, int size, bool direct = false) +class PIP_EXPORT PIProtocol: public PIObject +{ + PIOBJECT(PIProtocol) + friend class PIMultiProtocolBase; + friend class PIMultiProtocol; + enum Type {None, Serial, Ethernet}; +public: + + //! Contructs an empty unconfigured protocol + PIProtocol(): PIObject() {init();} + + //! Contructs protocol configured from file "config", config file section "name" + PIProtocol(const PIString & config, const PIString & name, void * recHeaderPtr = 0, int recHeaderSize = 0, + void * recDataPtr = 0, int recDataSize = 0, void * sendDataPtr = 0, int sendDataSize = 0); // from config + + virtual ~PIProtocol(); + + //! Connection quality + enum Quality { + Unknown /** Unknown, no one packet received yet */ = 1, + Failure /** No connection, no one correct packet received for last period */ = 2, + Bad /** Bad connection, correct packets received <= 20% */ = 3, + Average /** Average connection, correct packets received > 20% and <= 80% */ = 4, + Good /** Good connection, correct packets received > 80% */ = 5 + }; + + EVENT_HANDLER0(void, startReceive) {startReceive(-1.f);} + EVENT_HANDLER1(void, startReceive, float, exp_frequency); // if "frequency = -1" used last passed value + EVENT_HANDLER0(void, stopReceive); + void setExpectedFrequency(float frequency); // for connection quality diagnostic + void setReceiverDevice(const PIString & device, PISerial::Speed speed, bool force = false); // for Serial + void setReceiverData(void * dataPtr, int dataSize) {this->dataPtr = (uchar * )dataPtr; this->dataSize = dataSize; packet_ext->setHeader(PIByteArray(headerPtr, headerSize)); packet_ext->setPayloadSize(dataSize); packet_ext->setPacketSize(dataSize);} + void setReceiverDataHeader(void * headerPtr, int headerSize) {this->headerPtr = (uchar * )headerPtr; this->headerSize = headerSize; packet_ext->setHeader(PIByteArray(headerPtr, headerSize)); packet_ext->setPayloadSize(dataSize); packet_ext->setPacketSize(dataSize);} + void setReceiverAddress(const PIString & ip, int port, bool force = false); // for Ethernet + void setReceiverParameters(PIFlags parameters) {if (type_rec == PIProtocol::Serial || type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial + void setReceiveSlot(ReceiveFunc slot) {ret_func = slot;} + float expectedFrequency() const {return exp_freq;} + + EVENT_HANDLER0(void, startSend) {startSend(-1.f);} // if "frequency = -1" used last passed value + EVENT_HANDLER1(void, startSend, float, frequency); // if "frequency = -1" used last passed value + EVENT_HANDLER0(void, stopSend) {sendTimer->stop(); senderStopped();} + void setSenderFrequency(float frequency) {send_freq = frequency;} + void setSenderDevice(const PIString & device, PISerial::Speed speed, bool force = false); // for Serial + void setSenderData(void * dataPtr, int dataSize) {sendDataPtr = (uchar * )dataPtr; sendDataSize = dataSize;} + void setSenderAddress(const PIString & ip, int port, bool force = false); // for Ethernet + void setSenderIP(const PIString & ip, bool force = false); // for Ethernet + void setSenderPort(int port, bool force = false); // for Ethernet + void setSenderParameters(PIFlags parameters) {if (type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial + float senderFrequency() const {return send_freq;} + + EVENT_HANDLER0(void, start) {startReceive(); startSend();} + EVENT_HANDLER0(void, stop) {stopReceive(); stopSend();} + EVENT_HANDLER0(void, send); + EVENT_HANDLER2(void, send, const void *, data, int, size) {send(data, size, false);} + EVENT_HANDLER3(void, send, const void *, data, int, size, bool, direct); + + void setName(const PIString & name) {protName = name; PIObject::setName(name);} + PIString name() const {return protName;} + void setDisconnectTimeout(float timeout) {timeout_ = timeout; changeDisconnectTimeout();} + float disconnectTimeout() const {return timeout_;} + const float * disconnectTimeout_ptr() const {return &timeout_;} + float immediateFrequency() const {return immediate_freq;} + float integralFrequency() const {return integral_freq;} + const float * immediateFrequency_ptr() const {return &immediate_freq;} + const float * integralFrequency_ptr() const {return &integral_freq;} + ullong receiveCountPerSec() const {return packets_in_sec;} + const ullong * receiveCountPerSec_ptr() const {return &packets_in_sec;} + ullong sendCountPerSec() const {return packets_out_sec;} + const ullong * sendCountPerSec_ptr() const {return &packets_out_sec;} + ullong receiveBytesPerSec() const {return bytes_in_sec;} + const ullong * receiveBytesPerSec_ptr() const {return &bytes_in_sec;} + ullong sendBytesPerSec() const {return bytes_out_sec;} + const ullong * sendBytesPerSec_ptr() const {return &bytes_out_sec;} + ullong receiveCount() const {return receive_count;} + const ullong * receiveCount_ptr() const {return &receive_count;} + ullong wrongCount() const {return wrong_count;} + const ullong * wrongCount_ptr() const {return &wrong_count;} + ullong sendCount() const {return send_count;} + const ullong * sendCount_ptr() const {return &send_count;} + ullong missedCount() const {return missed_count;} + const ullong * missedCount_ptr() const {return &missed_count;} + PIProtocol::Quality quality() const {return net_diag;} // receive quality + const int * quality_ptr() const {return (int * )&net_diag;} // receive quality pointer + PIString receiverDeviceName() const {return devReceiverName;} + PIString senderDeviceName() const {return devSenderName;} + PIString receiverDeviceState() const {return devReceiverState;} + const PIString * receiverDeviceState_ptr() const {return &devReceiverState;} + PIString senderDeviceState() const {return devSenderState;} + const PIString * senderDeviceState_ptr() const {return &devSenderState;} + PIString receiveSpeed() const {return speedIn;} + const PIString * receiveSpeed_ptr() const {return &speedIn;} + PIString sendSpeed() const {return speedOut;} + const PIString * sendSpeed_ptr() const {return &speedOut;} + PIString receiverHistorySize() const {return history_rsize_rec;} + const PIString * receiverHistorySize_ptr() const {return &history_rsize_rec;} + PIString senderHistorySize() const {return history_rsize_send;} + const PIString * senderHistorySize_ptr() const {return &history_rsize_send;} + bool writeReceiverHistory() const {return history_write_rec;} + const bool * writeReceiverHistory_ptr() const {return &history_write_rec;} + bool writeSenderHistory() const {return history_write_send;} + const bool * writeSenderHistory_ptr() const {return &history_write_send;} + + void * receiveData() {return dataPtr;} + void * sendData() {return sendDataPtr;} + + PIPacketExtractor * packetExtractor() {return packet_ext;} + PIByteArray lastHeader() {return packet_ext->lastHeader();} + + EVENT0(receiverStarted) + EVENT0(receiverStopped) + EVENT0(senderStarted) + EVENT0(senderStopped) + EVENT1(received, bool, validate_is_ok) + EVENT2(qualityChanged, PIProtocol::Quality, new_quality, PIProtocol::Quality, old_quality) + +protected: + virtual bool receive(uchar * data, int size) {if (dataPtr != 0) memcpy(dataPtr, data, size); return true;} // executed when raw data received, break if 'false' return + virtual bool validate() {return true;} // function for validate algorithm and save data from dataPtr to external struct + virtual bool headerValidate(uchar * src, uchar * rec, int size) {for (int i = 0; i < size; ++i) if (src[i] != rec[i]) return false; return true;} // function for validate header (COM-port and headerSize > 0) + virtual uint checksum_i(void * data, int size) { // function for checksum (uint) + uint c = 0; + for (int i = 0; i < size; ++i) + c += ((uchar*)data)[i]; + return ~(c + 1); + } + virtual uchar checksum_c(void * data, int size) { // function for checksum (uchar) + uchar c = 0; + for (int i = 0; i < size; ++i) + c += ((uchar*)data)[i]; + return ~(c + 1); + } + virtual bool aboutSend() {return true;} // executed before send data, if return 'false' then data is not sending + + void init(); + void init_sender(PIConfig::Entry & b, PIConfig::Entry & sb, const PIString & config); + void init_receiver(PIConfig::Entry & b, PIConfig::Entry & rb, const PIString & config); + void check_state(); + void calc_freq(); + void calc_diag(); + + PISerial * ser; + PIEthernet * eth; + uint dataSize, headerSize, sendDataSize; + uchar * dataPtr, * headerPtr, * sendDataPtr; + +private: + static void sendEvent(void * e, int) {((PIProtocol * )e)->send();} + static bool receiveEvent(void * t, uchar * data, int size); + static bool headerValidateEvent(void * t, uchar * src, uchar * rec, int size) {return ((PIProtocol * )t)->headerValidate(src, rec, size);} + static void diagEvent(void * t, int); + static void secEvent(void * t, int); + + void setMultiProtocolOwner(PIMultiProtocolBase * mp) {mp_owner = mp;} + PIMultiProtocolBase * multiProtocolOwner() const {return mp_owner;} + void changeDisconnectTimeout(); + + ReceiveFunc ret_func; + PIPacketExtractor * packet_ext; + PITimer * diagTimer, * sendTimer, * secTimer; + PITimeMeasurer diag_tm; + PIMultiProtocolBase * mp_owner; + PIProtocol::Type type_send, type_rec; + PIProtocol::Quality net_diag; + PIDeque last_freq; + PIDeque last_packets; + PIString protName, devReceiverName, devReceiverState, devSenderName, devSenderState, speedIn, speedOut; + PIString history_path_rec, history_path_send, history_rsize_rec, history_rsize_send; + PIFile history_file_rec, history_file_send; + ushort history_id_rec, history_id_send; + bool work, new_mp_prot, history_write_rec, history_write_send; + float exp_freq, send_freq, ifreq, immediate_freq, integral_freq, timeout_; + int packets[2], pckt_cnt, pckt_cnt_max; + char cur_pckt; + ullong wrong_count, receive_count, send_count, missed_count, packets_in_sec, packets_out_sec, bytes_in_sec, bytes_out_sec; + +}; + +#endif // PIPROTOCOL_H diff --git a/src/io/piserial.cpp b/src/io/piserial.cpp new file mode 100755 index 00000000..50355682 --- /dev/null +++ b/src/io/piserial.cpp @@ -0,0 +1,664 @@ +/* + PIP - Platform Independent Primitives + COM + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "piserial.h" +#include "piconfig.h" +#include "pidir.h" + + +/*! \class PISerial + * \brief Serial device + * + * \section PISerial_sec0 Synopsis + * This class provide access to serial device, e.g. COM port. It can read, + * write, wait for write. There are several read and write functions. + * + * + */ + +REGISTER_DEVICE(PISerial); + + +PISerial::PISerial(): PIIODevice("", ReadWrite) { + _init(); +} + + +PISerial::PISerial(const PIString & device_, PISerial::Speed speed_, PIFlags params_): PIIODevice(device_, ReadWrite) { + _init(); + setPath(device_); + setSpeed(speed_); + setParameters(params_); +} + + +PISerial::~PISerial() { + piMonitor.serials--; +} + + +void PISerial::_init() { + fd = -1; + piMonitor.serials++; + setPriority(piHigh); + block_read = true; + vtime = 1; +#ifdef WINDOWS + block_write = true; + hCom = 0; +#endif + setParameters(0); + setSpeed(S115200); + setDataBitsCount(8); + //init(); +} + + +void PISerial::setParameter(PISerial::Parameters parameter, bool on) { + PIFlags cp = (PIFlags)(property("parameters").toInt()); + cp.setFlag(parameter, on); + setParameters(cp); +} + + +bool PISerial::isParameterSet(PISerial::Parameters parameter) const { + PIFlags cp = (PIFlags)(property("parameters").toInt()); + return cp[parameter]; +} + + +bool PISerial::setPin(int number, bool on) { + switch (number) { + case 1: return setCAR(on); break; + case 2: return setSR(on); break; + case 3: return setST(on); break; + case 4: return setDTR(on); break; + case 5: + piCoutObj << "Pin number 5 is ground"; + return false; + case 6: return setDSR(on); break; + case 7: return setRTS(on); break; + case 8: return setCTS(on); break; + case 9: return setRNG(on); break; + default: + piCoutObj << "Pin number " << number << " doesn`t exists!"; + return false; + } + return false; +} + + +bool PISerial::isPin(int number) const { + switch (number) { + case 1: return isCAR(); break; + case 2: return isSR(); break; + case 3: return isST(); break; + case 4: return isDTR(); break; + case 5: return false; + case 6: return isDSR(); break; + case 7: return isRTS(); break; + case 8: return isCTS(); break; + case 9: return isRNG(); break; + default: + piCoutObj << "Pin number " << number << " doesn`t exists!"; + return false; + } + return false; +} + + +bool PISerial::setBit(int bit, bool on, const PIString & bname) { +#ifndef WINDOWS + if (fd < 0) { + piCoutObj << "setBit" << bname << " error: \"" << path() << "\" is not opened!"; + return false; + } + if (ioctl(fd, on ? TIOCMBIS : TIOCMBIC, &bit) < 0) { + piCoutObj << "setBit" << bname << " error: " << errorString(); + return false; + } + return true; +#else + piCoutObj << "setBit" << bname << " doesn`t implemented on Windows, sorry :-("; + return false; +#endif +} + + +bool PISerial::isBit(int bit, const PIString & bname) const { +#ifndef WINDOWS + if (fd < 0) { + piCoutObj << "isBit" << bname << " error: \"" << path() << "\" is not opened!"; + return false; + } + int ret = 0; + if (ioctl(fd, TIOCMGET, &ret) < 0) + piCoutObj << "isBit" << bname << " error: " << errorString(); + return ret & bit; +#else + piCoutObj << "isBit" << bname << " doesn`t implemented on Windows, sorry :-("; + return false; +#endif +} + + +bool PISerial::closeDevice() { + if (!isInitialized()) return true; + if (isRunning()) { + stop(); + PIThread::terminate(); + } + if (fd != -1) { +#ifdef WINDOWS + SetCommState(hCom, &sdesc); + SetCommMask(hCom, mask); + CloseHandle(hCom); + hCom = 0; +#else + tcsetattr(fd, TCSANOW, &sdesc); + ::close(fd); +#endif + fd = -1; + } + return true; +} + + +int PISerial::convertSpeed(PISerial::Speed speed) { + switch (speed) { + case S50: return B50; + case S75: return B75; + case S110: return B110; + case S300: return B300; + case S600: return B600; + case S1200: return B1200; + case S2400: return B2400; + case S4800: return B4800; + case S9600: return B9600; + case S19200: return B19200; + case S38400: return B38400; + case S57600: return B57600; + case S115200: return B115200; + case S1500000: return B1500000; + case S2000000: return B2000000; + case S2500000: return B2500000; + case S3000000: return B3000000; + case S3500000: return B3500000; + case S4000000: return B4000000; + default: break; + } + return B115200; +} + + +/** \brief Advanced read function +* \details Read to pointer "read_to" no more than "max_size" and no longer +* than "timeout_ms" milliseconds. If "timeout_ms" < 0 function will be +* wait forever until "max_size" will be readed. If size <= 0 function +* immediate returns \b false. For read data with unknown size use function +* \a readData(). +* \returns \b True if readed bytes count = "max_size", else \b false +* \sa \a readData() */ +bool PISerial::read(void * data, int size, double timeout_ms) { + if (data == 0 || size <= 0) return false; + int ret, all = 0; + if (timeout_ms > 0.) { + setReadIsBlocking(false); + all = read(data, 1); + tm_.reset(); + while (all < size && tm_.elapsed_m() < timeout_ms) { + ret = read(&((uchar * )data)[all], size - all); + if (ret > 0) all += ret; + else msleep(1); + } + received(data, all); + return (all == size); + } else { + setReadIsBlocking(true); + all = read(data, 1); + while (all < size) { + ret = read(&((uchar * )data)[all], size - all); + if (ret > 0) all += ret; + } + received(data, all); + return (all == size); + } + return false; +} + + +/** \brief Advanced read function +* \details Read all or no more than "size" and no longer than +* "timeout_ms" milliseconds. If "timeout_ms" < 0 function will be +* wait forever until "size" will be readed. If "size" <= 0 +* function will be read all until "timeout_ms" elaped. \n If size <= 0 +* and "timeout_ms" <= 0 function immediate returns empty string. +* \n This function similar to \a readData() but returns data as string. +* \sa \a readData() */ +PIString PISerial::read(int size, double timeout_ms) { + PIString str; + if (size <= 0 && timeout_ms <= 0.) return str; + int ret, all = 0; + uchar td[1024]; + if (timeout_ms > 0.) { + setReadIsBlocking(false); + tm_.reset(); + if (size <= 0) { + while (tm_.elapsed_m() < timeout_ms) { + ret = read(td, 1024); + if (ret <= 0) msleep(1); + else str << PIString((char*)td, ret); + } + } else { + while (all < size && tm_.elapsed_m() < timeout_ms) { + ret = read(td, size - all); + if (ret <= 0) msleep(1); + else { + str << PIString((char*)td, ret); + all += ret; + } + } + } + } else { + setReadIsBlocking(true); + all = read(td, 1); + str << PIString((char*)td, all); + while (all < size) { + ret = read(td, size - all); + if (ret <= 0) msleep(1); + else { + str << PIString((char*)td, ret); + all += ret; + } + } + } + received(str.data(), str.size_s()); + return str; +} + + +/** \brief Advanced read function +* \details Read all or no more than "size" and no longer than +* "timeout_ms" milliseconds. If "timeout_ms" < 0 function will be +* wait forever until "size" will be readed. If "size" <= 0 +* function will be read all until "timeout_ms" elaped. \n If size <= 0 +* and "timeout_ms" <= 0 function immediate returns empty byte array. +* \n This function similar to \a read() but returns data as byte array. +* \sa \a read() */ +PIByteArray PISerial::readData(int size, double timeout_ms) { + PIByteArray str; + if (size <= 0 && timeout_ms <= 0.) return str; + int ret, all = 0; + uchar td[1024]; + if (timeout_ms > 0.) { + setReadIsBlocking(false); + tm_.reset(); + if (size <= 0) { + while (tm_.elapsed_m() < timeout_ms) { + ret = read(td, 1024); + if (ret <= 0) msleep(1); + else str.append(td, ret); + } + } else { + while (all < size && tm_.elapsed_m() < timeout_ms) { + ret = read(td, size - all); + if (ret <= 0) msleep(1); + else { + str.append(td, ret); + all += ret; + } + } + } + } else { + setReadIsBlocking(true); + all = read(td, 1); + str.append(td, all); + while (all < size) { + ret = read(td, size - all); + if (ret <= 0) msleep(1); + else { + str.append(td, ret); + all += ret; + } + } + } + received(str.data(), str.size_s()); + return str; +} + + +bool PISerial::openDevice() { + //piCout << "ser open" << path(); + if (path().isEmpty()) return false; +#ifdef WINDOWS + DWORD ds = 0, sm = 0; + if (isReadable()) {ds |= GENERIC_READ; sm |= FILE_SHARE_READ;} + if (isWriteable()) {ds |= GENERIC_WRITE; sm |= FILE_SHARE_WRITE;} + PIString wp = "//./" + path(); + hCom = CreateFileA(wp.data(), ds, sm, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0); + if (hCom == INVALID_HANDLE_VALUE) { + piCoutObj << "Unable to open \"" << path() << "\""; + fd = -1; + return false; + } + fd = 0; +#else + int om = 0; + switch (mode()) { + case PIIODevice::ReadOnly: om = O_RDONLY; break; + case PIIODevice::WriteOnly: om = O_WRONLY; break; + case PIIODevice::ReadWrite: om = O_RDWR; break; + } + //cout << "init ser " << path_ << " mode " << om << " param " << params << endl; + fd = ::open(path().data(), O_NOCTTY | om); + if (fd == -1) { + piCoutObj << "Unable to open \"" << path() << "\""; + return false; + } + tcgetattr(fd, &desc); + sdesc = desc; + //piCoutObj << "Initialized " << path_; +#endif + applySettings(); + return true; +} + + +void PISerial::applySettings() { +#ifdef WINDOWS + if (fd == -1) return; + COMMTIMEOUTS times; + times.ReadIntervalTimeout = block_read ? vtime : MAXDWORD; + times.ReadTotalTimeoutConstant = block_read ? 0 : 1; + times.ReadTotalTimeoutMultiplier = block_read ? 0 : MAXDWORD; + times.WriteTotalTimeoutConstant = 0; + times.WriteTotalTimeoutMultiplier = block_write ? 0 : 1; + if (SetCommTimeouts(hCom, ×) == -1) + piCoutObj << "Unable to set timeouts for \"" << path() << "\""; + GetCommMask(hCom, &mask); + SetCommMask(hCom, EV_RXCHAR); + GetCommState(hCom, &sdesc); + desc = sdesc; + desc.DCBlength = sizeof(desc); + desc.BaudRate = convertSpeed(outSpeed()); + if (dataBitsCount() >= 5 && dataBitsCount() <= 8) + desc.ByteSize = dataBitsCount(); + else + desc.ByteSize = 8; + PIFlags params = parameters(); + if (params[PISerial::ParityControl]) { + desc.fParity = 1; + desc.Parity = params[PISerial::ParityOdd] ? 1 : 2; + } + desc.StopBits = params[PISerial::TwoStopBits] ? TWOSTOPBITS : ONESTOPBIT; + if (SetCommState(hCom, &desc) == -1) { + piCoutObj << "Unable to set comm state for \"" << path() << "\""; + return; + } +#else + if (fd == -1) return; + tcgetattr(fd, &desc); + desc.c_oflag = desc.c_lflag = desc.c_cflag = 0; + desc.c_iflag = IGNBRK; + desc.c_cflag = CLOCAL | HUPCL; + switch (dataBitsCount()) { + case 5: desc.c_cflag |= (CSIZE & CS5); break; + case 6: desc.c_cflag |= (CSIZE & CS6); break; + case 7: desc.c_cflag |= (CSIZE & CS7); break; + case 8: default: desc.c_cflag |= (CSIZE & CS8); break; + }; + if (isReadable()) desc.c_cflag |= CREAD; + PIFlags params = parameters(); + if (params[PISerial::TwoStopBits]) desc.c_cflag |= CSTOPB; + if (params[PISerial::ParityControl]) { + desc.c_iflag |= INPCK; + desc.c_cflag |= PARENB; + if (params[PISerial::ParityOdd]) desc.c_cflag |= PARODD; + } + desc.c_cc[VMIN] = 1; + desc.c_cc[VTIME] = vtime; + + cfsetispeed(&desc, convertSpeed(inSpeed())); + cfsetospeed(&desc, convertSpeed(outSpeed())); + + tcflush(fd, TCIOFLUSH); + fcntl(fd, F_SETFL, block_read ? 0 : O_NONBLOCK); + + if(tcsetattr(fd, TCSANOW, &desc) < 0) { + piCoutObj << "Can`t set attributes for \"" << path() << "\""; + return; + } +#endif +} + + +void PISerial::setReadIsBlocking(bool yes) { + block_read = yes; +#ifdef WINDOWS + COMMTIMEOUTS times; + times.ReadIntervalTimeout = block_read ? vtime : MAXDWORD; + times.ReadTotalTimeoutConstant = block_read ? 0 : 1; + times.ReadTotalTimeoutMultiplier = block_read ? 0 : MAXDWORD; + times.WriteTotalTimeoutConstant = 0; + times.WriteTotalTimeoutMultiplier = block_write ? 0 : 1; + if (isOpened()) SetCommTimeouts(hCom, ×); +#else + if (isOpened()) fcntl(fd, F_SETFL, yes ? 0 : O_NONBLOCK); +#endif +} + + +/** \brief Basic read function +* \details Read to pointer "read_to" no more than "max_size". If read is +* set to blocking this function will be wait at least one byte. +* \returns Readed bytes count +* \sa \a readData() */ +int PISerial::read(void * read_to, int max_size) { +#ifdef WINDOWS + if (!canRead()) return -1; + WaitCommEvent(hCom, 0, 0); + ReadFile(hCom, read_to, max_size, &readed, 0); + return readed; +#else + if (!canRead()) return -1; + return ::read(fd, read_to, max_size); +#endif +} + + +int PISerial::write(const void * data, int max_size, bool wait) { + //piCoutObj << "send " << max_size << ": " << PIString((char*)data, max_size); + if (fd == -1 || !canWrite()) { + //piCoutObj << "Can`t write to uninitialized COM"; + return -1; + } +#ifdef WINDOWS + if (block_write != wait) { + block_write = wait; + setReadIsBlocking(block_read); + } + DWORD wrote; + WriteFile(hCom, data, max_size, &wrote, 0); +#else + int wrote; + wrote = ::write(fd, data, max_size); + if (wait) tcdrain(fd); +#endif + return (int)wrote; + //piCoutObj << "Error while sending"; + //piCoutObj << "Wrote " << wrote << " bytes in " << path_; +} + + +bool PISerial::configureDevice(const void * e_main, const void * e_parent) { + PIConfig::Entry * em = (PIConfig::Entry * )e_main; + PIConfig::Entry * ep = (PIConfig::Entry * )e_parent; + setDevice(readDeviceSetting("device", device(), em, ep)); + setSpeed((PISerial::Speed)(readDeviceSetting("speed", (int)outSpeed(), em, ep))); + setDataBitsCount(readDeviceSetting("dataBitsCount", dataBitsCount(), em, ep)); + setParameter(PISerial::ParityControl, readDeviceSetting("parityControl", isParameterSet(PISerial::ParityControl), em, ep)); + setParameter(PISerial::ParityOdd, readDeviceSetting("parityOdd", isParameterSet(PISerial::ParityOdd), em, ep)); + setParameter(PISerial::TwoStopBits, readDeviceSetting("twoStopBits", isParameterSet(PISerial::TwoStopBits), em, ep)); + return true; +} + + +PIString PISerial::constructFullPath() const { + PIString ret(fullPathPrefix() + "://"); + ret << path() << ":" << int(inSpeed()) << ":" << dataBitsCount(); + if (parameters()[ParityControl]) { + if (parameters()[ParityOdd]) ret << ":O"; + else ret << ":E"; + } else ret << ":N"; + if (parameters()[TwoStopBits]) ret << ":2"; + else ret << ":1"; + return ret; +} + + +void PISerial::configureFromFullPath(const PIString & full_path) { + PIStringList pl = full_path.split(":"); + for (int i = 0; i < pl.size_s(); ++i) { + PIString p(pl[i]); + switch (i) { + case 0: setPath(p); break; + case 1: setSpeed((Speed)(p.toInt())); break; + case 2: setDataBitsCount(p.toInt()); break; + case 3: + p = p.toLowerCase(); + if (p != "n") setParameter(ParityControl); + if (p == "o") setParameter(ParityOdd); + break; + case 4: if (p.toInt() == 2) setParameter(TwoStopBits); break; + } + } +} + + +PIVector PISerial::availableSpeeds() { + PIVector spds; + spds << 50 << 75 << 110 << 300 << 600 << 1200 << 2400 << 4800 << + 9600 << 19200 << 38400 << 57600 << 115200 << 1500000 << + 2000000 << 2500000 << 3000000 << 3500000 << 4000000; + return spds; +} + + +PIStringList PISerial::availableDevices(bool test) { + PIStringList dl; +#ifdef WINDOWS + HKEY key = 0; + RegOpenKey(HKEY_LOCAL_MACHINE, (LPCTSTR)"HARDWARE\\DEVICEMAP\\SERIALCOMM", &key); + if (key != 0) { + char name[1024], data[1024]; + DWORD name_len = 1024, data_len = 1024, type = 0, index = 0; + LONG ret; + while ((ret = RegEnumValue(key, index, (LPTSTR)name, &name_len, NULL, &type, (uchar * )data, &data_len)) != ERROR_NO_MORE_ITEMS) { + dl << PIString(data); + index++; + } + RegCloseKey(key); + } +#else +# ifndef ANDROID + PIStringList prefixes; +# ifdef QNX + prefixes << "ser"; +# else + prefixes << "ttyS" << "ttyO" << "ttyUSB" << "ttyACM" << "ttyGS" + << "ttyMI" << "ttymxc" << "ttyAMA" << "rfcomm" << "ircomm"; +# ifdef FREE_BSD + prefixes << "cu"; +# endif + PIFile file_prefixes("/proc/tty/drivers", PIIODevice::ReadOnly); + if (file_prefixes.open()) { + PIString fc = file_prefixes.readAll(true), line, cpref; + PIStringList words; + file_prefixes.close(); + while (!fc.isEmpty()) { + words.clear(); + line = fc.takeLine(); + if (line.isEmpty()) break; + while (!line.isEmpty()) + words << line.takeWord(); + if (words.size_s() < 2) break; + if (words.back() != "serial") continue; + cpref = words[1]; + int li = cpref.findLast("/"); + if (li > 0) cpref.cutLeft(li + 1); + prefixes << cpref; + } + prefixes.removeDuplicates(); + } +# endif + PIDir dir("/dev"); + PIVector de = dir.entries(); + piForeachC (PIFile::FileInfo & e, de) { // TODO changes in FileInfo + piForeachC (PIString & p, prefixes) { + if (e.path.left(p.size_s()) != p) continue; + dl << "/dev/" + e.path; + } + } +# endif +#endif + if (test) { + for (int i = 0; i < dl.size_s(); ++i) { +#ifdef WINDOWS + void * hCom = CreateFileA(dl[i].data(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0); + if (hCom == INVALID_HANDLE_VALUE) { +#else + int fd = ::open(dl[i].data(), O_NOCTTY | O_RDONLY); + if (fd == -1) { +#endif + dl.remove(i); + --i; + continue; + } + int void_ = 0; + bool rok = true; +#ifdef WINDOWS + /*COMMTIMEOUTS times; + times.ReadIntervalTimeout = MAXDWORD; + times.ReadTotalTimeoutConstant = 0; + times.ReadTotalTimeoutMultiplier = 0; + times.WriteTotalTimeoutConstant = 1; + times.WriteTotalTimeoutMultiplier = 0; + SetCommTimeouts(hCom, ×); + if (ReadFile(hCom, &void_, 1, &readed_, 0) == 0) + rok = GetLastError() == ;*/ +#else + fcntl(fd, F_SETFL, O_NONBLOCK); + if (::read(fd, &void_, 1) == -1) + rok = errno != EIO; + +#endif + if (!rok) { + dl.remove(i); + --i; + continue; + } +#ifdef WINDOWS + CloseHandle(hCom); +#else + ::close(fd); +#endif + } + } + return dl; +} diff --git a/src/io/piserial.h b/src/io/piserial.h new file mode 100755 index 00000000..773141f4 --- /dev/null +++ b/src/io/piserial.h @@ -0,0 +1,310 @@ +/*! \file piserial.h + * \brief Serial device +*/ +/* + PIP - Platform Independent Primitives + COM + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PISERIAL_H +#define PISERIAL_H + +#include "pitimer.h" +#include "piiodevice.h" +#ifndef WINDOWS +# include +# include +# include +# ifndef B50 +# define B50 0000001 +# endif +# ifndef B75 +# define B75 0000002 +# endif +# ifndef B1500000 +# define B1500000 0010012 +# endif +# ifndef B2000000 +# define B2000000 0010013 +# endif +# ifndef B2500000 +# define B2500000 0010014 +# endif +# ifndef B3000000 +# define B3000000 0010015 +# endif +# ifndef B3500000 +# define B3500000 0010016 +# endif +# ifndef B4000000 +# define B4000000 0010017 +# endif +#else +# define TIOCM_LE 1 +# define TIOCM_DTR 4 +# define TIOCM_RTS 7 +# define TIOCM_CTS 8 +# define TIOCM_ST 3 +# define TIOCM_SR 2 +# define TIOCM_CAR 1 +# define TIOCM_RNG 9 +# define TIOCM_DSR 6 +# define B50 50 +# define B75 75 +# define B110 110 +# define B300 300 +# define B600 600 +# define B1200 1200 +# define B2400 2400 +# define B4800 4800 +# define B9600 9600 +# define B14400 14400 +# define B19200 19200 +# define B38400 38400 +# define B57600 57600 +# define B115200 115200 +# define B128000 128000 +# define B256000 256000 +# define B1500000 1500000 +# define B2000000 2000000 +# define B2500000 2500000 +# define B3000000 3000000 +# define B3500000 3500000 +# define B4000000 4000000 +#endif +#ifndef CRTSCTS +# define CRTSCTS 020000000000 +#endif + + +class PIP_EXPORT PISerial: public PIIODevice +{ + PIIODEVICE(PISerial) +public: + + //! Contructs an empty %PISerial + PISerial(); + + //! \brief Parameters of PISerial + enum Parameters { + ParityControl /*! Enable parity check and generate */ = 0x1, + ParityOdd /*! Parity is odd instead of even */ = 0x2, + TwoStopBits /*! Two stop bits instead of one */ = 0x4 + }; + + //! \brief Speed of PISerial + enum Speed { + S50 /*! 50 baud */ = 50, + S75 /*! 75 baud */ = 75, + S110 /*! 110 baud */ = 110, + S300 /*! 300 baud */ = 300, + S600 /*! 600 baud */ = 600, + S1200 /*! 1200 baud */ = 1200, + S2400 /*! 2400 baud */ = 2400, + S4800 /*! 4800 baud */ = 4800, + S9600 /*! 9600 baud */ = 9600, + S19200 /*! 19200 baud */ = 19200, + S38400 /*! 38400 baud */ = 38400, + S57600 /*! 57600 baud */ = 57600, + S115200 /*! 115200 baud */ = 115200, + S1500000 = 1500000, // Linux only + S2000000 = 2000000, // Linux only + S2500000 = 2500000, // Linux only + S3000000 = 3000000, // Linux only + S3500000 = 3500000, // Linux only + S4000000 = 4000000 // Linux only + }; + + //! Contructs %PISerial with device name "device", speed "speed" and parameters "params" + PISerial(const PIString & device, PISerial::Speed speed = S115200, PIFlags params = 0); + + ~PISerial(); + + + //! Set both input and output speed to "speed" + void setSpeed(PISerial::Speed speed) {setProperty("outSpeed", (int)speed); setProperty("inSpeed", (int)speed); applySettings();} + + //! Set output speed to "speed" + void setOutSpeed(PISerial::Speed speed) {setProperty("outSpeed", (int)speed); applySettings();} + + //! Set input speed to "speed" + void setInSpeed(PISerial::Speed speed) {setProperty("inSpeed", (int)speed); applySettings();} + + //! Set device name to "dev" + void setDevice(const PIString & dev) {setPath(dev); if (isOpened()) {close(); open();};} + + + //! Set parameters to "parameters_" + void setParameters(PIFlags parameters_) {setProperty("parameters", (int)parameters_); applySettings();} + + //! Set parameter "parameter" to "on" state + void setParameter(PISerial::Parameters parameter, bool on = true); + + //! Returns if parameter "parameter" is set + bool isParameterSet(PISerial::Parameters parameter) const; + + //! Returns parameters + PIFlags parameters() const {return (PIFlags)(property("parameters").toInt());} + + + //! Set data bits count. Valid range is from 5 to 8, befault is 8 + void setDataBitsCount(int bits) {setProperty("dataBitsCount", bits); applySettings();} + + //! Returns data bits count + int dataBitsCount() const {return property("dataBitsCount").toInt();} + + + //! Set pin number "number" to logic level "on". Valid numbers are 4 (DTR) and 7 (RTS) + bool setPin(int number, bool on); + + //! Returns pin number "number" logic level. Valid numbers range is from 1 to 9 + bool isPin(int number) const; + + bool setLE(bool on) {return setBit(TIOCM_LE, on, "LE");} // useless function, just formally + bool setDTR(bool on) {return setBit(TIOCM_DTR, on, "DTR");} + bool setRTS(bool on) {return setBit(TIOCM_RTS, on, "RTS");} + bool setCTS(bool on) {return setBit(TIOCM_CTS, on, "CTS");} // useless function, just formally + bool setST(bool on) {return setBit(TIOCM_ST, on, "ST");} // useless function, just formally + bool setSR(bool on) {return setBit(TIOCM_SR, on, "SR");} // useless function, just formally + bool setCAR(bool on) {return setBit(TIOCM_CAR, on, "CAR");} // useless function, just formally + bool setRNG(bool on) {return setBit(TIOCM_RNG, on, "RNG");} // useless function, just formally + bool setDSR(bool on) {return setBit(TIOCM_DSR, on, "DSR");} // useless function, just formally + + bool isLE() const {return isBit(TIOCM_LE, "LE");} + bool isDTR() const {return isBit(TIOCM_DTR, "DTR");} + bool isRTS() const {return isBit(TIOCM_RTS, "RTS");} + bool isCTS() const {return isBit(TIOCM_CTS, "CTS");} + bool isST() const {return isBit(TIOCM_ST, "ST");} + bool isSR() const {return isBit(TIOCM_SR, "SR");} + bool isCAR() const {return isBit(TIOCM_CAR, "CAR");} + bool isRNG() const {return isBit(TIOCM_RNG, "RNG");} + bool isDSR() const {return isBit(TIOCM_DSR, "DSR");} + + void setVTime(int t) {vtime = t; applySettings();} + + + //! Set read is blocking for function read(void * read_to, int max_size) + void setReadIsBlocking(bool yes); + + + //! Returns device name + PIString device() const {return path();} + + //! Returns output speed + PISerial::Speed outSpeed() const {return (PISerial::Speed)(property("outSpeed").toInt());} + + //! Returns input speed + PISerial::Speed inSpeed() const {return (PISerial::Speed)(property("inSpeed").toInt());} + + int VTime() const {return vtime;} + + + //! Discard all buffered input and output data + void flush() { +#ifndef WINDOWS + if (fd != -1) tcflush(fd, TCIOFLUSH); +#endif + } + + int read(void * read_to, int max_size); + bool read(void * read_to, int max_size, double timeout_ms); + PIString read(int size = -1, double timeout_ms = 1000.); + PIByteArray readData(int size = -1, double timeout_ms = 1000.); + + + //! \brief Write to device data "data" with maximum size "max_size" and wait for data written if "wait" is \b true. + //! \returns sended bytes count + int write(const void * data, int max_size, bool wait = false); + + //! \brief Write to device data "data" with maximum size "size" and wait for data written if "wait" is \b true. + //! \returns \b true if sended bytes count = "size" + bool send(const void * data, int size, bool wait = false) {return (write(data, size, wait) == size);} + + //! \brief Write to device string "data" and wait for data written if "wait" is \b true. + //! \returns \b true if sended bytes count = size of string + bool send(const PIString & data, bool wait = false) {return (write(data.data(), data.lengthAscii(), wait) == data.size_s());} + + //! \brief Write to device byte array "data" and wait for data written if "wait" is \b true. + //! \returns \b true if sended bytes count = size of string + bool send(const PIByteArray & data, bool wait = false) {return (write(data.data(), data.size_s(), wait) == data.size_s());} + + PIString constructFullPath() const; + + + //! \brief Returns all available speeds for serial devices + static PIVector availableSpeeds(); + + //! \brief Returns all available system devices. If "test" each device will be tried to open + static PIStringList availableDevices(bool test = false); + +//! \ioparams +//! \{ +#ifdef DOXYGEN + //! \brief device, default "" + string device; + + //! \brief input/output speed, default 115200 + int speed; + + //! \brief dataBitsCount, default 8 + int dataBitsCount; + + //! \brief parityControl, default false + bool parityControl; + + //! \brief parityOdd, default false + bool parityOdd; + + //! \brief twoStopBits, default false + bool twoStopBits; +#endif +//! \} + +protected: + PIString fullPathPrefix() const {return "ser";} + void configureFromFullPath(const PIString & full_path); + bool configureDevice(const void * e_main, const void * e_parent = 0); + int write(const void * data, int max_size) {return write(data, max_size, true);} + + //! Executes when any read function was successful. Default implementation does nothing + virtual void received(const void * data, int size) {;} + + void _init(); + void applySettings(); + int convertSpeed(PISerial::Speed speed); + bool setBit(int bit, bool on, const PIString & bname); + bool isBit(int bit, const PIString & bname) const; + + bool openDevice(); + bool closeDevice(); + +#ifdef WINDOWS + DCB desc, sdesc; + void * hCom; + DWORD readed, mask; + bool block_write; +#else + termios desc, sdesc; + uint readed; +#endif + int fd, vtime; + bool block_read; + PITimeMeasurer tm_; + +}; + +#endif // PISERIAL_H diff --git a/src/io/piusb.cpp b/src/io/piusb.cpp new file mode 100755 index 00000000..d1f6decb --- /dev/null +++ b/src/io/piusb.cpp @@ -0,0 +1,410 @@ +#include "piusb.h" +#include "piconfig.h" + +#ifdef PIP_USB +# ifdef WINDOWS +# include +# else +# include +# endif +#endif + +REGISTER_DEVICE(PIUSB); + + +PIUSB::PIUSB(ushort vid, ushort pid): PIIODevice("", ReadWrite) { + vid_ = vid; + pid_ = pid; + intefrace_ = 0; + hdev = 0; + interface_claimed = -1; + setPath(PIString::fromNumber(vid_, 16).expandLeftTo(4, "0") + ":" + PIString::fromNumber(pid_, 16).expandLeftTo(4, "0")); + setDeviceNumber(1); + setTimeoutRead(1000); + setTimeoutWrite(1000); +} + + +void PIUSB::Endpoint::parse() { + direction = Write; + transfer_type = Control; + synchronisation_type = NoSynchonisation; + usage_type = DataEndpoint; + direction = (Direction)((address >> 7) & 1); + transfer_type = (TransferType)(attributes & 3); + if (transfer_type == Isochronous) { + synchronisation_type = (SynchronisationType)((attributes >> 2) & 3); + usage_type = (UsageType)((attributes >> 4) & 3); + } +} + + +PIUSB::Endpoint PIUSB::getEndpointByAddress(uchar address) { + piForeachC (Endpoint & i, eps) + if (i.address == address) + return i; + return Endpoint(); +} + + +PIVector PIUSB::endpointsRead() { + PIVector ret; + piForeachC (Endpoint & i, eps) + if (i.direction == Endpoint::Read) + ret << i; + return ret; +} + + +PIVector PIUSB::endpointsWrite() { + PIVector ret; + piForeachC (Endpoint & i, eps) + if (i.direction == Endpoint::Write) + ret << i; + return ret; +} + + +bool PIUSB::setConfiguration(uchar value) { +#ifdef PIP_USB + if (hdev == 0) return false; + bool found = false; + piForeachC (Configuration & c, desc_.configurations) + if (c.value_to_select == value) {found = true; conf_ = c; break;} + if (!found) { + piCoutObj << "Can`t find configuration with \"value_to_select\" =" << value; + return false; + } + if (interface_claimed >= 0) + usb_release_interface(hdev, interface_claimed); + interface_claimed = -1; + return setInterface(conf_.interfaces.front().value_to_select); +#else + return false; +#endif +} + + +bool PIUSB::setInterface(uchar value) { +#ifdef PIP_USB + if (hdev == 0) return false; + bool found = false; + piForeachC (Interface & i, conf_.interfaces) + if (i.value_to_select == value) {found = true; iface_ = i; break;} + if (!found) { + piCoutObj << "Can`t find interface with \"value_to_select\" =" << value; + return false; + } + if (interface_claimed >= 0) + usb_release_interface(hdev, interface_claimed); + interface_claimed = -1; + if (usb_claim_interface(hdev, iface_.value_to_select) < 0) { + piCoutObj << "Error: Cant`t claim interface!"; + return false; + } + eps.clear(); + eps = iface_.endpoints; + ep_read = ep_write = Endpoint(); + for (int i = 0; i < eps.size_s(); ++i) { + if (eps[i].direction == Endpoint::Read && ep_read.isNull()) + ep_read = eps[i]; + if (eps[i].direction == Endpoint::Write && ep_write.isNull()) + ep_write = eps[i]; + } + interface_claimed = value; + return true; +#else + return false; +#endif +} + + +bool PIUSB::configureDevice(const void * e_main, const void * e_parent) { +#ifdef PIP_USB + PIConfig::Entry * em = (PIConfig::Entry * )e_main; + PIConfig::Entry * ep = (PIConfig::Entry * )e_parent; + PIString vp = readDeviceSetting("device", "", em, ep); + ushort v, p; + if (vp.isEmpty()) { + v = readDeviceSetting("vid", vendorID(), em, ep); + p = readDeviceSetting("pid", productID(), em, ep); + } else { + v = vp.left(vp.find(":")).toInt(16); + p = vp.right(vp.length() - vp.find(":") - 1).toInt(16); + } + setVendorID(v); + setProductID(p); + setDeviceNumber(readDeviceSetting("deviceNumber", deviceNumber(), em, ep)); + setConfiguration(readDeviceSetting("configuration", currentConfiguration().value_to_select, em, ep)); + setInterface(readDeviceSetting("interface", currentInterface().value_to_select, em, ep)); + setEndpointRead(Endpoint(readDeviceSetting("endpointRead", endpointRead().address, em, ep))); + setEndpointWrite(Endpoint(readDeviceSetting("endpointWrite", endpointWrite().address, em, ep))); + return true; +#else + return false; +#endif +} + + +bool PIUSB::openDevice() { +#ifdef PIP_USB + if (path().size_s() >= 8) { + vid_ = path().left(4).toInt(16); + pid_ = path().right(4).toInt(16); + } + if (hdev != 0) closeDevice(); + hdev = 0; + interface_claimed = -1; + ep_write = ep_read = Endpoint(); + usb_init(); + //usb_set_debug(4); + if (usb_find_busses() < 0) { + piCoutObj << "Error: Cant`t find busses!"; + return false; + } + if (usb_find_devices() < 0) { + piCoutObj << "Error: Cant`t find devices!"; + return false; + } + + //piCoutObj << "Search for device ... " << flush; + int cur_num = 1; + bool found = false; + struct usb_device * dev; + struct usb_bus * bus; + for (bus = usb_get_busses(); bus; bus = bus->next) { + for (dev = bus->devices; dev; dev = dev->next) { + if (dev->descriptor.idVendor == vid_ && dev->descriptor.idProduct == pid_) { + if (cur_num == deviceNumber()) { + struct usb_device_descriptor & dd(dev->descriptor); + desc_.usb_spec_number = dd.bcdUSB; + desc_.device_class = dd.bDeviceClass; + desc_.device_subclass = dd.bDeviceSubClass; + desc_.device_protocol = dd.bDeviceProtocol; + desc_.max_packet_size = dd.bMaxPacketSize0; + desc_.id_vendor = dd.idVendor; + desc_.id_product = dd.idProduct; + desc_.id_device_release = dd.bcdDevice; + desc_.index_manufacturer = dd.iManufacturer; + desc_.index_product = dd.iProduct; + desc_.index_serial = dd.iSerialNumber; + desc_.configurations.clear(); + for (int c = 0; c < dd.bNumConfigurations; ++c) { + desc_.configurations << Configuration(); + Configuration & conf(desc_.configurations.back()); + struct usb_config_descriptor & dc(dev->config[c]); + conf.index = c; + conf.value_to_select = dc.bConfigurationValue; + conf.attributes = dc.bmAttributes; + conf.max_power = ushort(dc.MaxPower) * 2; + conf.self_powered = (conf.attributes >> 6) & 1; + conf.remote_wakeup = (conf.attributes >> 5) & 1; + conf.interfaces.clear(); + for (int i = 0; i < dc.bNumInterfaces; ++i) { + conf.interfaces << Interface(); + Interface & infc(conf.interfaces.back()); + struct usb_interface_descriptor * di(dc.interface[c].altsetting); + infc.index = i; + infc.value_to_select = di->bAlternateSetting; + infc.class_code = di->bInterfaceClass; + infc.subclass_code = di->bInterfaceSubClass; + infc.protocol_code = di->bInterfaceProtocol; + infc.endpoints.clear(); + for (int e = 0; e < di->bNumEndpoints; ++e) { + infc.endpoints << Endpoint(di->endpoint[e].bEndpointAddress, + di->endpoint[e].bmAttributes, + di->endpoint[e].wMaxPacketSize); + } + } + } + if (!desc_.configurations.isEmpty()) + conf_ = desc_.configurations.front(); + + struct usb_interface_descriptor * is = dev->config->interface->altsetting; + int epn = is->bNumEndpoints; + eps.clear(); + for (int i = 0; i < epn; ++i) { + eps << Endpoint(is->endpoint[i].bEndpointAddress, + is->endpoint[i].bmAttributes, + is->endpoint[i].wMaxPacketSize); + if (eps.back().direction == Endpoint::Write && (eps.back().address == ep_write.address || ep_write.address == 0)) ep_write = eps.back(); + if (eps.back().direction == Endpoint::Read && (eps.back().address == ep_read.address || ep_read.address == 0)) ep_read = eps.back(); + } + + //piCoutObj << "Device found at address:" << "Bus: " << dev->bus->dirname << ", Device: " << dev->filename; + found = true; + break; + } else cur_num++; + } + } + if (found) break; + } + if (!found) { + piCoutObj << "Error: Cant`t find device!"; + return false; + } + //piCoutObj << "Open ... " << flush; + hdev = usb_open(dev); + if (hdev == 0) { + piCoutObj << "Error: Cant`t open device:" << usb_strerror(); + return false; + }// else piCoutObj << "ok"; + //usb_reset(hdev); + + //usb_set_configuration(hdev, 1); + //usb_set_altinterface(hdev, 0); + +# ifndef WINDOWS + char tbuff[256]; + //piCoutObj << "Check for bounded driver ... " << flush; + if (usb_get_driver_np(hdev, intefrace_, tbuff, sizeof(tbuff) - 1) >= 0) { + //piCoutObj << "yes" << "Found driver: " << tbuff; + //piCoutObj << "Detach driver ... " << flush; + if (usb_detach_kernel_driver_np(hdev, intefrace_)< 0) { + piCoutObj << "Error: Cant`t detach bounded driver!"; + return false; + }// else piCoutObj << "ok"; + }// else piCoutObj << "no"; +# endif + + //piCoutObj << "Claim interface ... " << flush; + if (usb_claim_interface(hdev, intefrace_) < 0) { + piCoutObj << "Error: Cant`t claim interface:" << usb_strerror(); + return false; + } // else piCoutObj << "ok"; + interface_claimed = intefrace_; + + return true; +#else + return false; +#endif +} + + +bool PIUSB::closeDevice() { +#ifdef PIP_USB + if (hdev == 0) return true; + //usb_reset(hdev); + usb_release_interface(hdev, intefrace_); + usb_close(hdev); + hdev = 0; + interface_claimed = -1; + return true; +#else + return false; +#endif +} + + +int PIUSB::read(void * read_to, int max_size) { +#ifdef PIP_USB + if (!opened_ || ep_read.isNull()) return -1; + switch (ep_read.transfer_type) { + case Endpoint::Bulk: /*piCoutObj << "bulk read" << max_size;*/ return usb_bulk_read(hdev, ep_read.address, (char * )read_to, max_size, timeout_r); break; + case Endpoint::Interrupt: return usb_interrupt_read(hdev, ep_read.address, (char * )read_to, max_size, timeout_r); break; + default: break; + } + return -1; +#else + return -1; +#endif +} + + +int PIUSB::write(const void * data, int max_size) { +#ifdef PIP_USB + if (!opened_ || ep_write.isNull()) return -1; + switch (ep_read.transfer_type) { + case Endpoint::Bulk: /*piCoutObj << "bulk write" << max_size;*/ return usb_bulk_write(hdev, ep_write.address, (char * )const_cast(data), max_size, timeout_w); break; + case Endpoint::Interrupt: return usb_interrupt_write(hdev, ep_read.address, (char * )data, max_size, timeout_w); break; + default: break; + } + return -1; +#else + return -1; +#endif +} + + +int PIUSB::controlWrite(const void * data, int max_size) { +#ifdef PIP_USB + if (!opened_) return -1; + //return usb_control_msg(hdev, ); + return -1; +#else + return -1; +#endif +} + + +void PIUSB::flush() { +#ifdef PIP_USB + if (!opened_) return; + if (!ep_read.isNull()) usb_resetep(hdev, ep_read.address); + if (!ep_write.isNull()) usb_resetep(hdev, ep_write.address); +#endif +} + + +PICout operator<<(PICout s, const PIUSB::Endpoint & v) { + s.setControl(0, true); + s << NewLine << "{" << NewLine; + if (v.isNull()) + s << " " << "Null Endpoint"; + else { + s << " " << "Address: " << v.address << NewLine; + s << " " << "Attributes: " << v.attributes << NewLine; + s << " " << "Direction: " << (v.direction == PIUSB::Endpoint::Write ? "Write" : "Read") << NewLine; + s << " " << "Transfer Type: "; + switch (v.transfer_type) { + case PIUSB::Endpoint::Control: s << "Control" << NewLine; break; + case PIUSB::Endpoint::Bulk: s << "Bulk" << NewLine; break; + case PIUSB::Endpoint::Interrupt: s << "Interrupt" << NewLine; break; + case PIUSB::Endpoint::Isochronous: s << "Isochronous" << NewLine; break; + default: break; + } + if (v.transfer_type == PIUSB::Endpoint::Isochronous) { + s << " " << "Synchronisation Type: "; + switch (v.synchronisation_type) { + case PIUSB::Endpoint::NoSynchonisation: s << "No Synchonisation" << NewLine; break; + case PIUSB::Endpoint::Asynchronous: s << "Asynchronous" << NewLine; break; + case PIUSB::Endpoint::Adaptive: s << "Adaptive" << NewLine; break; + case PIUSB::Endpoint::Synchronous: s << "Synchronous" << NewLine; break; + default: break; + } + s << " " << "Usage Type: "; + switch (v.usage_type) { + case PIUSB::Endpoint::DataEndpoint: s << "Data Endpoint" << NewLine; break; + case PIUSB::Endpoint::FeedbackEndpoint: s << "Feedback Endpoint" << NewLine; break; + case PIUSB::Endpoint::ExplicitFeedbackDataEndpoint: s << "Explicit Feedback Data Endpoint" << NewLine; break; + default: break; + } + } + s << " " << "Max Packet Size: " << v.max_packet_size << NewLine; + } + s << "}" << NewLine; + s.restoreControl(); + return s; +} + + +PIString PIUSB::constructFullPath() const { + PIString ret(fullPathPrefix() + "://"); + ret << PIString::fromNumber(vendorID(), 16).toLowerCase() << ":" << PIString::fromNumber(productID(), 16).toLowerCase() << ":" << deviceNumber() << ":" << endpointRead().address << ":" << endpointWrite().address; + return ret; +} + + +void PIUSB::configureFromFullPath(const PIString & full_path) { + PIStringList pl = full_path.split(":"); + for (int i = 0; i < pl.size_s(); ++i) { + PIString p(pl[i]); + switch (i) { + case 0: setVendorID(p.toUShort(16)); break; + case 1: setProductID(p.toUShort(16)); break; + case 2: setDeviceNumber(p.toInt()); break; + case 3: setEndpointRead(Endpoint(p.toInt())); break; + case 4: setEndpointWrite(Endpoint(p.toInt())); break; + } + } +} diff --git a/src/io/piusb.h b/src/io/piusb.h new file mode 100755 index 00000000..437c1b5b --- /dev/null +++ b/src/io/piusb.h @@ -0,0 +1,153 @@ +/*! \file piusb.h + * \brief USB device +*/ +/* + PIP - Platform Independent Primitives + USB, based on libusb + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIUSB_H +#define PIUSB_H + +#include "piiodevice.h" + +struct usb_dev_handle; + +class PIP_EXPORT PIUSB: public PIIODevice +{ + PIIODEVICE(PIUSB) +public: + PIUSB(ushort vid = 0, ushort pid = 0); + + struct Endpoint { + Endpoint(uchar a = 0, uchar at = 0, ushort mps = 0) {address = a; attributes = at; max_packet_size = mps; parse();} + + enum Direction {Write = 0, Read = 1}; + enum TransferType {Control = 0, Isochronous = 1, Bulk = 2, Interrupt = 3}; + enum SynchronisationType {NoSynchonisation= 0, Asynchronous = 2, Adaptive = 1, Synchronous = 3}; + enum UsageType {DataEndpoint = 0, FeedbackEndpoint = 2, ExplicitFeedbackDataEndpoint = 1}; + + void parse(); + bool isNull() const {return address == 0;} + + uchar address; + uchar attributes; + ushort max_packet_size; + Direction direction; + TransferType transfer_type; + SynchronisationType synchronisation_type; + UsageType usage_type; + }; + + struct Interface { + Interface() {index = value_to_select = class_code = subclass_code = protocol_code = 0;} + uchar index; + uchar value_to_select; + ushort class_code; + ushort subclass_code; + ushort protocol_code; + PIVector endpoints; + }; + + struct Configuration { + Configuration() {index = value_to_select = attributes = max_power = 0; self_powered = remote_wakeup = false;} + uchar index; + uchar value_to_select; + uchar attributes; + ushort max_power; // mA + bool self_powered; + bool remote_wakeup; + PIVector interfaces; + }; + + struct Descriptor { + Descriptor() {memset(this, 0, sizeof(Descriptor));} + ushort usb_spec_number; + uchar device_class; + uchar device_subclass; + uchar device_protocol; + uchar max_packet_size; + ushort id_vendor; + ushort id_product; + ushort id_device_release; + uchar index_manufacturer; + uchar index_product; + uchar index_serial; + PIVector configurations; + }; + + const PIUSB::Descriptor & currentDescriptor() const {return desc_;} + const PIUSB::Configuration & currentConfiguration() const {return conf_;} + const PIUSB::Interface & currentInterface() const {return iface_;} + + ushort vendorID() const {return vid_;} + ushort productID() const {return pid_;} + + int deviceNumber() const {return property("deviceNumber").toInt();} + int timeoutRead() const {return property("timeoutRead").toInt();} + int timeoutWrite() const {return property("timeoutWrite").toInt();} + const PIUSB::Endpoint & endpointRead() const {return ep_read;} + const PIUSB::Endpoint & endpointWrite() const {return ep_write;} + + const PIVector & endpoints() const {return eps;} + PIVector endpointsRead(); + PIVector endpointsWrite(); + PIUSB::Endpoint getEndpointByAddress(uchar address); + + void setVendorID(ushort vid) {vid_ = vid; setPath(PIString::fromNumber(vid_, 16).expandLeftTo(4, "0") + ":" + PIString::fromNumber(pid_, 16).expandLeftTo(4, "0"));} + void setProductID(ushort pid) {pid_ = pid; setPath(PIString::fromNumber(vid_, 16).expandLeftTo(4, "0") + ":" + PIString::fromNumber(pid_, 16).expandLeftTo(4, "0"));} + + bool setConfiguration(uchar value); + bool setInterface(uchar value); + + void setEndpointRead(const PIUSB::Endpoint & ep) {ep_read = ep;} + void setEndpointWrite(const PIUSB::Endpoint & ep) {ep_write = ep;} + void setDeviceNumber(int dn) {setProperty("deviceNumber", dn);} + void setTimeoutRead(int t) {setProperty("timeoutRead", t);} + void setTimeoutWrite(int t) {setProperty("timeoutWrite", t);} + + int read(void * read_to, int max_size); + int write(const void * data, int max_size); + int controlWrite(const void * data, int max_size); + + void flush(); + + PIString constructFullPath() const; + +protected: + PIString fullPathPrefix() const {return "usb";} + void configureFromFullPath(const PIString & full_path); + bool configureDevice(const void * e_main, const void * e_parent = 0); + //bool init(); + bool openDevice(); + bool closeDevice(); + + PIVector eps; + ushort vid_, pid_; + int intefrace_, timeout_r, timeout_w; + int interface_claimed; + PIUSB::Endpoint ep_read, ep_write; + Descriptor desc_; + Configuration conf_; + Interface iface_; + usb_dev_handle * hdev; + +}; + +PICout operator <<(PICout s, const PIUSB::Endpoint & v); + +#endif // PIUSB_H diff --git a/src/math/picrc.h b/src/math/picrc.h new file mode 100755 index 00000000..7f179893 --- /dev/null +++ b/src/math/picrc.h @@ -0,0 +1,244 @@ +/*! \file picrc.h + * \brief CRC checksum calculator +*/ +/* + PIP - Platform Independent Primitives + CRC checksum calculator + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PICRC_H +#define PICRC_H + +#include "pistring.h" + +template +class PIP_EXPORT uint_cl { +public: + uint_cl() {for (int i = 0; i < L / 8; ++i) data_[i] = 0;} + uint_cl(const uint_cl & v) {for (int i = 0; i < L / 8; ++i) data_[i] = v.data_[i];} + uint_cl(uchar v) {for (int i = 0; i < L / 8; ++i) data_[i] = (i == 0 ? v : 0);} + uint_cl(char v) {for (int i = 0; i < L / 8; ++i) data_[i] = (i == 0 ? v : 0);} + uint_cl(ushort v) {int l = piMin(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;} + uint_cl(short v) {int l = piMin(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;} + uint_cl(uint v) {int l = piMin(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;} + uint_cl(int v) {int l = piMin(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;} + uint_cl(ulong v) {int l = piMin(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;} + uint_cl(long v) {int l = piMin(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;} + uint_cl(ullong v) {int l = piMin(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;} + uint_cl(llong v) {int l = piMin(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;} + + operator bool() {for (int i = 0; i < L / 8; ++i) if (data_[i] > 0) return true; return false;} + operator char() {return (char)data_[0];} + operator short() {short t(0); int l = piMin(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;} + operator int() {int t(0); int l = piMin(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;} + operator long() {long t(0); int l = piMin(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;} + operator llong() {llong t(0); int l = piMin(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;} + operator uchar() {return data_[0];} + operator ushort() {ushort t(0); int l = piMin(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;} + operator uint() {uint t(0); int l = piMin(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;} + operator ulong() {ulong t(0); int l = piMin(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;} + operator ullong() {ullong t(0); int l = piMin(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;} + + uint_cl operator +(const uint_cl & v) { + uint_cl t; + uint cv; + bool ov = false; + for (int i = 0; i < L / 8; ++i) { + cv = v.data_[i] + data_[i]; + if (ov) ++cv; + ov = cv > 255; + t.data_[i] = ov ? cv - 256 : cv; + } + return t; + } + + uint_cl operator &(const uint_cl & v) const {uint_cl t; for (int i = 0; i < L / 8; ++i) t.data_[i] = v.data_[i] & data_[i]; return t;} + uint_cl operator &(const uchar & v) const {return *this & uint_cl(v);} + uint_cl operator &(const ushort & v) const {return *this & uint_cl(v);} + uint_cl operator &(const uint & v) const {return *this & uint_cl(v);} + uint_cl operator &(const ulong & v) const {return *this & uint_cl(v);} + uint_cl operator &(const ullong & v) const {return *this & uint_cl(v);} + uint_cl operator &(const char & v) const {return *this & uint_cl(v);} + uint_cl operator &(const short & v) const {return *this & uint_cl(v);} + uint_cl operator &(const int & v) const {return *this & uint_cl(v);} + uint_cl operator &(const long & v) const {return *this & uint_cl(v);} + uint_cl operator &(const llong & v) const {return *this & uint_cl(v);} + + uint_cl operator |(const uint_cl & v) const {uint_cl t; for (int i = 0; i < L / 8; ++i) t.data_[i] = v.data_[i] | data_[i]; return t;} + uint_cl operator |(const uchar & v) const {return *this | uint_cl(v);} + uint_cl operator |(const ushort & v) const {return *this | uint_cl(v);} + uint_cl operator |(const uint & v) const {return *this | uint_cl(v);} + uint_cl operator |(const ulong & v) const {return *this | uint_cl(v);} + uint_cl operator |(const ullong & v) const {return *this | uint_cl(v);} + uint_cl operator |(const char & v) const {return *this | uint_cl(v);} + uint_cl operator |(const short & v) const {return *this | uint_cl(v);} + uint_cl operator |(const int & v) const {return *this | uint_cl(v);} + uint_cl operator |(const long & v) const {return *this | uint_cl(v);} + uint_cl operator |(const llong & v) const {return *this | uint_cl(v);} + + uint_cl operator ^(const uint_cl & v) const {uint_cl t; for (int i = 0; i < L / 8; ++i) t.data_[i] = v.data_[i] ^ data_[i]; return t;} + uint_cl operator ^(const uchar & v) const {return *this ^ uint_cl(v);} + uint_cl operator ^(const ushort & v) const {return *this ^ uint_cl(v);} + uint_cl operator ^(const uint & v) const {return *this ^ uint_cl(v);} + uint_cl operator ^(const ulong & v) const {return *this ^ uint_cl(v);} + uint_cl operator ^(const ullong & v) const {return *this ^ uint_cl(v);} + uint_cl operator ^(const char & v) const {return *this ^ uint_cl(v);} + uint_cl operator ^(const short & v) const {return *this ^ uint_cl(v);} + uint_cl operator ^(const int & v) const {return *this ^ uint_cl(v);} + uint_cl operator ^(const long & v) const {return *this ^ uint_cl(v);} + uint_cl operator ^(const llong & v) const {return *this ^ uint_cl(v);} + + bool operator <(const uint_cl & v) const {for (int i = 0; i < L / 8; ++i) {if (v.data_[i] > data_[i]) return true; if (v.data_[i] < data_[i]) return false;} return false;} + bool operator <=(const uint_cl & v) const {for (int i = 0; i < L / 8; ++i) {if (v.data_[i] > data_[i]) return true; if (v.data_[i] < data_[i]) return false;} return true;} + bool operator >(const uint_cl & v) const {for (int i = 0; i < L / 8; ++i) {if (v.data_[i] < data_[i]) return true; if (v.data_[i] > data_[i]) return false;} return false;} + bool operator >=(const uint_cl & v) const {for (int i = 0; i < L / 8; ++i) {if (v.data_[i] < data_[i]) return true; if (v.data_[i] > data_[i]) return false;} return true;} + bool operator ==(const uint_cl & v) const {for (int i = 0; i < L / 8; ++i) if (v.data_[i] != data_[i]) return false; return true;} + bool operator !=(const uint_cl & v) const {for (int i = 0; i < L / 8; ++i) if (v.data_[i] != data_[i]) return true; return false;} + bool operator <=(const uint_cl<8> & v1) {return (*(uchar*)data()) <= (*(uchar*)v1.data());} + + uint_cl operator >>(const int & c) const { + uint_cl t; + int l = L - c; + bool bit; + if (l <= 0) return t; + for (int i = 0; i < l; ++i) { + bit = 1 & (data_[(i + c) / 8] >> ((i + c) % 8)); + if (bit) t.data_[i / 8] |= (1 << (i % 8)); + else t.data_[i / 8] &= ~(1 << (i % 8)); + } + return t; + } + uint_cl operator >>(const uint & c) const {return (*this << (int)c);} + uint_cl operator <<(const int & c) const { + uint_cl t; + int l = L - c; + bool bit; + if (l <= 0) return t; + for (int i = c; i < L; ++i) { + bit = 1 & (data_[(i - c) / 8] >> ((i - c) % 8)); + if (bit) t.data_[i / 8] |= (1 << (i % 8)); + else t.data_[i / 8] &= ~(1 << (i % 8)); + } + return t; + } + uint_cl operator <<(const uint & c) const {return (*this >> (int)c);} + + uint_cl & inverse() const {for (int i = 0; i < L / 8; ++i) data_[i] = ~data_[i]; return *this;} + uint_cl inversed() const {uint_cl t(*this); for (int i = 0; i < L / 8; ++i) t.data_[i] = ~t.data_[i]; return t;} + uint_cl reversed() const { + uint_cl t; + bool bit; + for (int i = 0; i < L; ++i) { + bit = 1 & (data_[(L - i - 1) / 8] >> ((L - i - 1) % 8)); + if (bit) t.data_[i / 8] |= (1 << (i % 8)); + else t.data_[i / 8] &= ~(1 << (i % 8)); + } + return t; + } + + const uchar * data() const {return data_;} + uchar * data() {return data_;} + uint length() const {return L / 8;} + +private: + uchar data_[L / 8]; + +}; + +template +inline std::ostream & operator <<(std::ostream & s, const uint_cl & v) {std::ios::fmtflags f = s.flags(); s << std::hex; for (uint i = 0; i < v.length(); ++i) {s << int(v.data()[i]); if (v.data()[i] < 0x10) s << '0'; s << ' ';} s.flags(f); return s;} + +inline uchar reverseByte(uchar b) { + uchar ret = 0; + bool bit; + for (int i = 0; i < 8; ++i) { + bit = 1 & (b >> (7 - i)); + if (bit) ret |= (1 << i); + } + return ret; +} + +template > +class PIP_EXPORT PICRC { +public: + PICRC(const N & poly = N()) {poly_ = poly; reverse_poly = true; init_ = inversed(N(0)); out_ = inversed(N(0)); reverse_before_xor = reverse_data = false; initTable();} + PICRC(const N & poly, bool reverse_poly_, const N & initial, const N & out_xor) {poly_ = poly; reverse_poly = reverse_poly_; init_ = initial; out_ = out_xor; reverse_before_xor = reverse_data = false; initTable();} + + void setInitial(const N & v) {init_ = v;} + void setOutXor(const N & v) {out_ = v;} + void setReversePolynome(bool yes) {reverse_poly = yes; initTable();} + void setReverseOutBeforeXOR(bool yes) {reverse_before_xor = yes;} + void setReverseDataBytes(bool yes) {reverse_data = yes;} + + void initTable() { + N tmp, pol = reverse_poly ? reversed(poly_) : poly_; + //cout << std::hex << "poly " << (uint)N(poly_) << " -> " << (uint)N(pol) << endl; + for (int i = 0; i < 256; ++i) { + tmp = uchar(i); + for (int j = 0; j < 8; ++j) + tmp = ((tmp & 1) ? ((tmp >> 1) ^ pol) : (tmp >> 1)); + table[i] = tmp; + } + + } + + N calculate(const void * data, int size) { + N crc = init_; + uchar * data_ = (uchar * )data, cb; + //cout << "process " << size << endl; + uchar nTemp; + for (int i = 0; i < size; ++i) { + cb = data_[i]; + if (reverse_data) cb = reverseByte(cb); + nTemp = cb ^ uchar(crc); + crc = crc >> 8; + crc = crc ^ table[nTemp]; + } + if (reverse_before_xor) crc = reversed(crc); + return crc ^ out_; + + } + N calculate(const PIByteArray & d) {return calculate(d.data(), d.size());} + N calculate(const char * str) {string s(str); return calculate((void * )s.data(), s.size());} + +private: + inline N reversed(const N & v) {return v.reversed();} + inline N inversed(const N & v) {return v.inversed();} + + N table[256]; + N poly_, init_, out_; + bool reverse_poly, reverse_before_xor, reverse_data; + +}; + +template <> inline uchar PICRC<8, uchar>::reversed(const uchar & v) {return reverseByte(v);} +template <> inline ushort PICRC<16, ushort>::reversed(const ushort & v) {return uint_cl<16>(v).reversed();} +template <> inline uint PICRC<32, uint>::reversed(const uint & v) {return uint_cl<32>(v).reversed();} +template <> inline uchar PICRC<8, uchar>::inversed(const uchar & v) {return ~v;} +template <> inline ushort PICRC<16, ushort>::inversed(const ushort & v) {return ~v;} +template <> inline uint PICRC<32, uint>::inversed(const uint & v) {return ~v;} + +typedef PICRC<32, uint> CRC_32; +typedef PICRC<24> CRC_24; +typedef PICRC<16, ushort> CRC_16; +typedef PICRC<8, uchar> CRC_8; + +inline CRC_32 standardCRC_32() {return CRC_32(0x04C11DB7, true, 0xFFFFFFFF, 0xFFFFFFFF);} +inline CRC_16 standardCRC_16() {return CRC_16(0x8005, true, 0x0, 0x0);} +inline CRC_8 standardCRC_8() {return CRC_8(0xD5, true, 0x0, 0x0);} + +#endif // CRC_H diff --git a/src/math/pievaluator.cpp b/src/math/pievaluator.cpp new file mode 100755 index 00000000..2bbdfb9d --- /dev/null +++ b/src/math/pievaluator.cpp @@ -0,0 +1,1254 @@ +/* + PIP - Platform Independent Primitives + Evaluator designed for stream computing + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pievaluator.h" + + +/*! \class PIEvaluator + * \brief This class provide mathematical evaluations of custom expression + * + * \section PIEvaluator_sec0 Synopsis + * %PIEvaluator developed for stream evaluations of once set expression. + * It`s create internal list of instructions on function \a check() and + * executes very fast on function \a evaluate(). Once given expression + * can be evaluated any times with different variable values. Evaluator + * supports many common mathematic functions described below. Also it`s + * automatic puts unnecessarily signs and bracets. Processed expression + * can be obtains with function \a expression(). If there is an error + * in expression you can get it with function \a error(). Last evaluated + * result you can get with function \a lastResult(). + * \section PIEvaluator_sec1 Using + * First you should set your variables with function \a setVariable(). + * Next give your expression with function \a check() and check for error + * with functions \a isCorrect() and \a error(). If expression is correct + * you can get processed expression with function \a expression() and + * evaluate it with function \a evaluate(). You can change variable values + * without rechecking expression. + * + * \section PIEvaluator_sec2 Functions + * %PIEvaluator supports arithmetical operations with complex numbers, this + * is their list in priority order: + * * ^ (power) + * * * (multiply) + * * / (divide) + * * % (residue) + * * + (add) + * * - (subtract) + * + * In addition there are compare and logical operations: + * * == (equal) + * * != (not equal) + * * > (greater) + * * < (smaller) + * * >= (greater or equal) + * * <= (smaller or equal) + * * && (and) + * * || (or) + * + * Compare and logical functions works with real operators part and returns 0 or 1. + * + * Mathematical functions: + * * sin(x) - sine + * * cos(x) - cosine + * * tg(x) - tangent + * * ctg(x) - cotangent + * * arcsin(x) - arcsine + * * arccos(x) - arccosine + * * arctg(x) -arccotangent + * * arcctg(x) - arctangent + * * sh(x) - hyperbolical sine + * * ch(x) - hyperbolical cosine + * * th(x) - hyperbolical tangent + * * cth(x) - hyperbolical cotangent + * * sqr(x) - square + * * sqrt(x) - square root + * * abs(x) - absolute value + * * sign(x) - sign of real part (-1 or 1) + * * exp(x) - exponent + * * pow(x, p) - x in power p + * * ln(x) - natural logarithm + * * lg(x) - decimal logarithm + * * log(x, b) - logarithm of x with base b + * * im(x) - imaginary part of complex number + * * re(x) - real part of complex number + * * arg(x) - argument of complex number + * * len(x) - length of complex number + * * conj(x) - length of complex number + * * rad(x) - convert degrees to radians + * * deg(x) - convert radians to degrees + * * j0(x) - Bessel function first kind order 0 + * * j1(x) - Bessel function first kind order 1 + * * jn(x, n) - Bessel function first kind order n + * * y0(x) - Bessel function second kind order 0 + * * y1(x) - Bessel function second kind order 1 + * * yn(x, n) - Bessel function second kind order n + * * random(s, f) - regular random number in range [s, f] + * * min(x0, x1, ...) - minimum of x0, x1, ... + * * max(x0, x1, ...) - maximum of x0, x1, ... + * * clamp(x, a, b) - trim x on range [a, b] + * * step(x, s) - 0 if x < s, else 1 + * * mix(x, a, b) - interpolate between a and b linear for x (a * (1 - x) + b * x) + * + * There are some built-in constans: + * * i (imaginary 1) + * * e + * * pi + * + * All trigonometric functions takes angle in radians. + * + * \section PIEvaluator_sec3 Example + * \snippet pievaluator.cpp main + */ + + +PIEvaluatorContent::PIEvaluatorContent() { + addFunction("arcsin", 1); + addFunction("arccos", 1); + addFunction("arctg", 1); + addFunction("arcctg", 1); + addFunction("random", 2); + addFunction("sin", 1); + addFunction("cos", 1); + addFunction("ctg", 1); + addFunction("tg", 1); + addFunction("exp", 1); + addFunction("cth", 1); + addFunction("sh", 1); + addFunction("ch", 1); + addFunction("th", 1); + addFunction("sqrt", 1); + addFunction("sqr", 1); + addFunction("pow", 2); + addFunction("abs", 1); + addFunction("ln", 1); + addFunction("lg", 1); + addFunction("log", 2); + addFunction("im", 1); + addFunction("re", 1); + addFunction("arg", 1); + addFunction("len", 1); + addFunction("conj", 1); + addFunction("sign", 1); + addFunction("rad", 1); + addFunction("deg", 1); + addFunction("j0", 1); + addFunction("j1", 1); + addFunction("jn", 2); + addFunction("y0", 1); + addFunction("y1", 1); + addFunction("yn", 2); + addFunction("min", -2); // (x0,x1,...) + addFunction("max", -2); // (x0,x1,...) + addFunction("clamp", 3); // (x,a,b) = x < a ? a : (x > b ? b : x) + addFunction("step", 2); // (x,s) = x >= s ? 1. : 0. (1 if 'x' >= 's', else 0) + addFunction("mix", 3); // (x,a,b) = a*(1.-x) + b*x (interpolate between 'a' and 'b' linear for 'x') + addFunction("defined", 1); + clearCustomVariables(); + //addVariable("n", 0.); + //addVariable("x1", 123); +} + + +bool PIEvaluatorContent::setVariableValue(int index, complexd new_value) { + if (index < 0 || index >= variables.size_s()) return false; + variables[index].value = new_value; + return true; +} + + +bool PIEvaluatorContent::setVariableName(int index, const PIString & new_name) { + if (index < 0 || index >= variables.size_s()) return false; + variables[index].name = new_name; + return true; +} + + +void PIEvaluatorContent::clearCustomVariables() { + variables.clear(); + addVariable("i", complexd_i); + addVariable("pi", atan(1.) * 4.); + addVariable("e", exp(1.)); + cv_count = variables.size(); +} + + +void PIEvaluatorContent::sortVariables() { + //PIEvaluatorTypes::Variable tv; + for (uint i = 0; i < variables.size(); i++) { + for (uint j = variables.size() - 1; j > i; j--) { + if (variables[j].name.length() <= variables[i].name.length()) continue; + piSwap(variables[i], variables[j]); + } + } + /* + * qDebug() << "---"; + * for (int i = 0; i < variables.size(); i++) { + * qDebug() << variables[i].name; + } + */ +} + + +PIEvaluatorTypes::BaseFunctions PIEvaluatorContent::getBaseFunction(const PIString & name) { + if (name == "sin") return PIEvaluatorTypes::bfSin; + if (name == "cos") return PIEvaluatorTypes::bfCos; + if (name == "tg") return PIEvaluatorTypes::bfTg; + if (name == "ctg") return PIEvaluatorTypes::bfCtg; + if (name == "arcsin") return PIEvaluatorTypes::bfArcsin; + if (name == "arccos") return PIEvaluatorTypes::bfArccos; + if (name == "arctg") return PIEvaluatorTypes::bfArctg; + if (name == "arcctg") return PIEvaluatorTypes::bfArcctg; + if (name == "exp") return PIEvaluatorTypes::bfExp; + if (name == "random") return PIEvaluatorTypes::bfRandom; + if (name == "sh") return PIEvaluatorTypes::bfSh; + if (name == "ch") return PIEvaluatorTypes::bfCh; + if (name == "th") return PIEvaluatorTypes::bfTh; + if (name == "cth") return PIEvaluatorTypes::bfCth; + if (name == "sqrt") return PIEvaluatorTypes::bfSqrt; + if (name == "sqr") return PIEvaluatorTypes::bfSqr; + if (name == "pow") return PIEvaluatorTypes::bfPow; + if (name == "abs") return PIEvaluatorTypes::bfAbs; + if (name == "ln") return PIEvaluatorTypes::bfLn; + if (name == "lg") return PIEvaluatorTypes::bfLg; + if (name == "log") return PIEvaluatorTypes::bfLog; + if (name == "im") return PIEvaluatorTypes::bfIm; + if (name == "re") return PIEvaluatorTypes::bfRe; + if (name == "arg") return PIEvaluatorTypes::bfArg; + if (name == "len") return PIEvaluatorTypes::bfLen; + if (name == "conj") return PIEvaluatorTypes::bfConj; + if (name == "sign") return PIEvaluatorTypes::bfSign; + if (name == "rad") return PIEvaluatorTypes::bfRad; + if (name == "deg") return PIEvaluatorTypes::bfDeg; + if (name == "j0") return PIEvaluatorTypes::bfJ0; + if (name == "j1") return PIEvaluatorTypes::bfJ1; + if (name == "jn") return PIEvaluatorTypes::bfJN; + if (name == "y0") return PIEvaluatorTypes::bfY0; + if (name == "y1") return PIEvaluatorTypes::bfY1; + if (name == "yn") return PIEvaluatorTypes::bfYN; + if (name == "min") return PIEvaluatorTypes::bfMin; + if (name == "max") return PIEvaluatorTypes::bfMax; + if (name == "clamp") return PIEvaluatorTypes::bfClamp; + if (name == "step") return PIEvaluatorTypes::bfStep; + if (name == "mix") return PIEvaluatorTypes::bfMix; + if (name == "defined") return PIEvaluatorTypes::bfDefined; + return PIEvaluatorTypes::bfUnknown; +} + +const PIString & PIEvaluator::prepare(const PIString & string) { + currentString = string.trimmed(); + if (currentString.isEmpty()) currentString = "0"; + replaceOperators(); + removeSpaces(); + checkBrackets(); + while (fillElements()) checkBrackets(); + while (setSignes()) fillElements(); + removeJunk(); + findUnknownVariables(); + return currentString; +} + + +void PIEvaluator::removeSpaces() { + PIString tmps = currentString; + for (int i = 0; i < tmps.length(); i++) { + if (tmps[i] == ' ' || tmps[i] == '\t') { + tmps.remove(i, 1); + i--; + } + } + currentString = tmps; +} + + +void PIEvaluator::removeJunk() { + PIChar cc; + bool junk = true; + int bcnt; + while (junk) { + if (currentString.left(1) != "(" || currentString.right(1) != ")") return; + bcnt = 1; + junk = false; + for (int i = 1; i < currentString.length(); i++) { + cc = currentString[i]; + if (cc == '(') bcnt++; + if (cc == ')') bcnt--; + if (bcnt == 0) { + if (i == currentString.length() - 1) { + currentString = currentString.mid(1, currentString.length() - 2); + elements.pop_front(); + elements.pop_back(); + junk = true; + break; + } else break; + } + } + } +} + + +void PIEvaluator::replaceOperators() { + currentString.replaceAll("==", "="); + currentString.replaceAll("!=", ":"); + currentString.replaceAll(">=", "}"); + currentString.replaceAll("<=", "{"); + currentString.replaceAll("&&", "&"); + currentString.replaceAll("||", "|"); +} + + +void PIEvaluator::makeOutput(PIString & string) { + string.replaceAll(":", "≠"); + string.replaceAll("}", "≥"); + string.replaceAll("{", "≤"); + string.replaceAll("&", "â‹€"); + string.replaceAll("|", "â‹"); +} + + +void PIEvaluator::findUnknownVariables() { + PIString cvar; + unknownVars.clear(); + for (int i = 0; i < currentString.length(); i++) { + if (elements[i].var_num == -666) cvar += currentString[i]; + else { + if (cvar.length() == 0) continue; + unknownVars << cvar; + cvar = ""; + } + } + if (cvar.length() > 0) unknownVars << cvar; + unknownVars.removeDuplicates(); +} + + +bool PIEvaluator::isSign(const PIChar & ch) { + return ch == '+' || ch == '-' || + ch == '*' || ch == '/' || + ch == '%' || ch == '^' || + ch == '=' || ch == ':' || + ch == '>' || ch == '<' || + ch == '}' || ch == '{' || + ch == '&' || ch == '|'; +} + + +void PIEvaluator::checkBrackets() { + PIString tmps = currentString; + PIChar fc, sc; + int bcnt = 0, bpos = 0, inserted = 0; + currentString = tmps; + for (int i = 0; i < tmps.length(); i++) { + if (tmps[i] == '(') { + if (bcnt == 0) bpos = i; + bcnt++; + } + if (tmps[i] == ')') { + if (bcnt == 0) { + currentString.insert(bpos + inserted, "("); + inserted++; + } else bcnt--; + } + } + if (bcnt > 0) currentString += PIString(bcnt, ')'); + tmps = currentString; + for (int i = 0; i < tmps.length() - 1; i++) { + fc = tmps[i].toLower(); + sc = tmps[i + 1].toLower(); + if ((fc == ')' && sc == '(') || + (fc == ')' && sc >= '0' && sc <= '9') || + (fc == ')' && sc >= 'a' && sc <= 'z') ) tmps.insert(++i, '*'); + } + currentString = tmps; +} + + +bool PIEvaluator::fillElements() { + int fstart, flen, cnum = 0, cpart = 0, cfunc; + PIChar cc, nc, pc, fc = '!'; + bool numFound = false; + PIString curfind, tmps = currentString; + elements.resize(tmps.length()); + for (uint i = 0; i < elements.size(); i++) { + elements[i].type = PIEvaluatorTypes::etVariable; + elements[i].var_num = -666; + } + currentVariables.clear(); + //qDebug().nospace() << "search for functions ..."; + for (int i = 0; i < content.functionsCount(); i++) { + curfind = content.function(i).identifier; + cfunc = i; //(int)content.function(i).type; + flen = curfind.length(); + fstart = 0; + while (fstart >= 0) { + fstart = tmps.find(curfind, fstart); + if (fstart < 0) break; + if (tmps[fstart + flen] != '(') { + //currentString.insert(fstart + flen, "("); + //return true; + fstart++; + continue; + } + for (int j = fstart; j < fstart + flen; j++) { + elements[j].set(PIEvaluatorTypes::etFunction, cnum, cfunc); + tmps.replace(j, 1, fc); + } + cnum++; + } + } + cnum = 0; + //qDebug().nospace() << "search for variables ..."; + for (int i = 0; i < content.variablesCount(); i++) { + curfind = content.variable(i).name; + flen = curfind.length(); + fstart = 0; + while (fstart >= 0) { + fstart = tmps.find(curfind, fstart); + if (fstart < 0) break; + for (int j = fstart; j < fstart + flen; j++) { + elements[j].set(PIEvaluatorTypes::etVariable, cnum, i); + tmps.replace(j, 1, fc); + } + cnum++; + } + } + curfind = ""; + cnum = 1; + //qDebug().nospace() << "search for numbers ..."; + for (int i = 0; i < tmps.length(); i++) { + cc = tmps[i]; + /*if (cc == " " || cc == "(" || cc == ")") { + curfind = ""; + cpart = 0; + numFound = false; + continue; + }*/ + switch (cpart) { + case 0: + if ((cc >= '0' && cc <= '9')) {// || cc == '-' || cc == '+') { + curfind += cc; + cpart = 1; + continue; + } + if (cc == '.') { + curfind += cc; + cpart = 2; + continue; + } + if (cc == 'E') { + curfind += cc; + cpart = 3; + continue; + } + break; + case 1: + if (cc >= '0' && cc <= '9') { + curfind += cc; + continue; + } + if (cc == '.') { + curfind += cc; + cpart = 2; + continue; + } + if (cc == 'E') { + curfind += cc; + cpart = 3; + continue; + } + numFound = true; + break; + case 2: + if (cc >= '0' && cc <= '9') { + curfind += cc; + continue; + } + if (cc == 'E') { + curfind += cc; + cpart = 3; + continue; + } + numFound = true; + break; + case 3: + if ((cc >= '0' && cc <= '9') || cc == '-' || cc == '+') { + curfind += cc; + cpart = 4; + continue; + } + numFound = true; + break; + case 4: + if (cc >= '0' && cc <= '9') { + curfind += cc; + continue; + } + numFound = true; + break; + } + if (numFound) { + //qDebug().nospace() << "add " << cnum << ": " << curfind << " = " << curfind.toDouble(); + currentVariables.push_back(PIEvaluatorTypes::Variable("tmp" + PIString::fromNumber(cnum), curfind.toDouble())); + for (int j = i - curfind.length(); j < i; j++) { + elements[j].set(PIEvaluatorTypes::etNumber, cnum, -cnum); + tmps.replace(j, 1, fc); + } + curfind = ""; + cnum++; + cpart = 0; + numFound = false; + } + } + if (cpart > 0) { + //qDebug().nospace() << "add " << cnum << ": " << curfind << " = " << curfind.toDouble(); + currentVariables.push_back(PIEvaluatorTypes::Variable("tmp" + PIString::fromNumber(cnum), curfind.toDouble())); + for (int j = tmps.length() - curfind.length(); j < tmps.length(); j++) { + elements[j].set(PIEvaluatorTypes::etNumber, cnum, -cnum); + tmps.replace(j, 1, fc); + } + } + cc = nc = fc; + //qDebug().nospace() << "search for signes ..."; + for (int i = 0; i < tmps.length(); i++) { + cc = tmps[i]; + if (i > 0) pc = tmps[i - 1]; + else pc = fc; + if (i < tmps.length() - 1) nc = tmps[i + 1]; + else nc = fc; + if (cc == '(' || cc == ')' || cc == ',') { + elements[i].set(PIEvaluatorTypes::etOperator, -1); + continue; + } + if (cc == '-' || cc == '+') { + elements[i].set(PIEvaluatorTypes::etOperator, -1); + if (i < tmps.length() - 1) if (elements[i + 1].type == PIEvaluatorTypes::etVariable || + elements[i + 1].type == PIEvaluatorTypes::etFunction) continue; + if ((pc == '(' || isSign(pc) || i == 0) && i < tmps.length() - 1) { + if (elements[i + 1].type != PIEvaluatorTypes::etOperator) { + cnum = elements[i + 1].num; + elements[i].set(PIEvaluatorTypes::etNumber, cnum); + tmps.replace(i, 1, fc); + ///cout << "found sign " << cc << " :" << cnum - 1 << endl; + if (cc == '-' && currentVariables.size_s() >= cnum) + currentVariables[cnum - 1].value = -currentVariables[cnum - 1].value; + //i++; + continue; + } + } + } + if (isSign(cc)) { + elements[i].set(PIEvaluatorTypes::etOperator, -1); + continue; + } + } + /* + qDebug().nospace() << tmps; + cout << " "; + for (int i = 0; i < elements.size(); i++) { + switch (elements[i].type) { + case etFunction: cout << "f"; break; + case etNumber: cout << "n"; break; + case etOperator: cout << "o"; break; + case etVariable: cout << "v"; break; + } + } + cout << endl; + */ + return false; + //for (int i = 0; i < currentVariables.size(); i++) qDebug() << "var " << i << ": " << currentVariables[i].value.real(); +} + + +bool PIEvaluator::setSignes() { + int inserted = 0, ni, pi = 0, needInsert = 0; + PIChar fc, sc, pc; + PIString tmps = currentString; + for (int i = 0; i < tmps.length() - 1; i++) { + needInsert = 0; + ni = i + 1; + if (i > 0) pi = i - 1; + fc = tmps[i].toLower(); + sc = tmps[ni].toLower(); + pc = tmps[pi].toLower(); + //if (elements[i].type == etOperator || elements[ni].type == etVariable) continue; + if (fc == ',' || sc == ',') continue; + if (elements[i].type == PIEvaluatorTypes::etOperator && elements[ni].type == PIEvaluatorTypes::etOperator) continue; + if (fc == ')' && (elements[ni].type == PIEvaluatorTypes::etNumber || elements[ni].type == PIEvaluatorTypes::etVariable || elements[ni].type == PIEvaluatorTypes::etFunction)) needInsert = 1; + if (sc == '(' && (elements[i].type == PIEvaluatorTypes::etNumber || elements[i].type == PIEvaluatorTypes::etVariable)) needInsert = 1; + if (elements[i].type == PIEvaluatorTypes::etNumber && elements[ni].type == PIEvaluatorTypes::etNumber && elements[i].num != elements[ni].num) needInsert = 1; + if (elements[i].type == PIEvaluatorTypes::etVariable && elements[ni].type == PIEvaluatorTypes::etVariable && elements[i].num != elements[ni].num) needInsert = 1; + if ((elements[i].type == PIEvaluatorTypes::etNumber && elements[ni].type == PIEvaluatorTypes::etVariable) || (elements[i].type == PIEvaluatorTypes::etVariable && elements[ni].type == PIEvaluatorTypes::etNumber)) needInsert = 1; + if ((elements[i].type == PIEvaluatorTypes::etNumber || elements[i].type == PIEvaluatorTypes::etVariable) && elements[ni].type == PIEvaluatorTypes::etFunction) needInsert = 1; + if (elements[i].type == PIEvaluatorTypes::etFunction && elements[ni].type == PIEvaluatorTypes::etFunction && elements[i].num != elements[ni].num) needInsert = 2; + if (elements[i].type == PIEvaluatorTypes::etFunction && elements[ni].type != PIEvaluatorTypes::etFunction && sc != '(') needInsert = 2; + if (elements[pi].type == PIEvaluatorTypes::etOperator && (elements[ni].type == PIEvaluatorTypes::etFunction || elements[ni].type == PIEvaluatorTypes::etVariable) && fc == '-') needInsert = 3; + switch (needInsert) { + case 1: + currentString.insert(ni + inserted, "*"); + elements.insert(ni + inserted, PIEvaluatorTypes::Element(PIEvaluatorTypes::etOperator, -1)); + //inserted++; + //i++; + return true; + /*case 2: + currentString.insert(ni + inserted, ")"); + currentString.insert(ni + inserted, "("); + elements.insert(ni + inserted, Element(etOperator, -1)); + elements.insert(ni + inserted, Element(etOperator, -1)); + inserted++; + i++; + return true;*/ + case 3: + currentString.insert(ni + inserted, "1*"); + elements.insert(ni + inserted, PIEvaluatorTypes::Element(PIEvaluatorTypes::etOperator, -1)); + //inserted; + //i++; + return true; + } + } + /*if (elements[tmps.length() - 1].type == etFunction) { + currentString.insert(tmps.length() + inserted, ")"); + currentString.insert(tmps.length() + inserted, "("); + elements.insert(tmps.length() + inserted, Element(etOperator, -1)); + elements.insert(tmps.length() + inserted, Element(etOperator, -1)); + return true; + }*/ + return false; +} + + +void PIEvaluator::convert() { + int j; + PIEvaluatorTypes::Element ce, pe; + for (int i = 0; i < currentString.length(); i++) { + pe = elements[i]; + if (pe.type != PIEvaluatorTypes::etFunction) continue; + j = i + 1; + while (j < currentString.length()) { + ce = elements[j]; + if (ce != pe) break; + j++; + } + currentString.replace(i, j - i, " "); + for (int k = i + 1; k < j; k++) elements.remove(i); + //i++; + } + for (int i = 0; i < currentString.length(); i++) { + pe = elements[i]; + if (pe.type != PIEvaluatorTypes::etNumber) continue; + j = i + 1; + while (j < currentString.length()) { + ce = elements[j]; + if (ce != pe) break; + j++; + } + currentString.replace(i, j - i, " "); + for (int k = i + 1; k < j; k++) elements.remove(i); + //i++; + } + for (int i = 0; i < currentString.length(); i++) { + pe = elements[i]; + if (pe.type != PIEvaluatorTypes::etVariable) continue; + j = i + 1; + while (j < currentString.length()) { + ce = elements[j]; + if (ce != pe) break; + j++; + } + currentString.replace(i, j - i, " "); + for (int k = i + 1; k < j; k++) elements.remove(i); + //i++; + } + /*qDebug().nospace() << currentString; + cout << " "; + for (int i = 0; i < elements.size(); i++) { + switch (elements[i].type) { + case etFunction: cout << "f"; break; + case etNumber: cout << "n"; break; + case etOperator: cout << "o"; break; + case etVariable: cout << "v"; break; + } + } + cout << endl;*/ +} + + + +const PIString & PIEvaluator::preprocess(const PIString & string) { + static PIString ret; + int lind; + ret = prepare(string); + convert(); + instructions.clear(); + //qDebug() << preproc->currentString; + variables = currentVariables; + lind = parse(currentString); + if (instructions.size() == 0) { + variables.push_back(PIEvaluatorTypes::Variable()); + instructions.push_back(PIEvaluatorTypes::Instruction(PIEvaluatorTypes::oNone, PIVector(1, lind), -variables.size_s())); + } + kvars = &(content.variables); + /* + cout << endl << "variables:" << endl; + for (int i = 0; i < variables.size(); i++) + cout << i << " value = " << variables[i].value << endl; + + cout << endl << "instructions:" << endl; + for (int i = 0; i < instructions.size(); i++) { + cout << i << endl; + cout << " operation " << instructions[i].operation << endl; + cout << " operators: "; + for (int j = 0; j < instructions[i].operators.size(); j++) + cout << instructions[i].operators[j] << "; "; + cout << endl << " function " << instructions[i].function << endl; + cout << " out " << instructions[i].out << endl; + } + */ + makeOutput(ret); + return ret; +} + + +PIEvaluatorTypes::Operation PIEvaluator::operationInOrder(const int & index) { + switch (index) { + case 0: return PIEvaluatorTypes::oPower; + case 1: return PIEvaluatorTypes::oMultiply; + case 2: return PIEvaluatorTypes::oDivide; + case 3: return PIEvaluatorTypes::oResidue; + case 4: return PIEvaluatorTypes::oAdd; + case 5: return PIEvaluatorTypes::oSubtract; + case 6: return PIEvaluatorTypes::oEqual; + case 7: return PIEvaluatorTypes::oNotEqual; + case 8: return PIEvaluatorTypes::oGreaterEqual; + case 9: return PIEvaluatorTypes::oSmallerEqual; + case 10: return PIEvaluatorTypes::oGreater; + case 11: return PIEvaluatorTypes::oSmaller; + case 12: return PIEvaluatorTypes::oAnd; + case 13: return PIEvaluatorTypes::oOr; + default: return PIEvaluatorTypes::oNone; + } +} + + +int PIEvaluator::parse(const PIString & string, int offset) { + int slen = string.length(), /*facnt,*/ farg, bcnt, k; + PIChar cc; + PIEvaluatorTypes::Element ce; + PIEvaluatorTypes::Function cfunc; + PIEvaluatorTypes::Operation coper; + PIString sbrackets, carg; + PIVector args, atmp; + PIVector opers; + + ///qDebug() << "to parse :" + string; + ///cout << " "; for (int i = 0; i < slen; i++) cout << preproc->elements[i + offset].type; cout << endl; + + for (int i = 0; i < slen; i++) { + ce = elements[i + offset]; + cc = string[i]; + switch (ce.type) { + case PIEvaluatorTypes::etNumber: + args.push_back(ce.var_num); + continue; + case PIEvaluatorTypes::etVariable: + args.push_back(ce.var_num); + continue; + case PIEvaluatorTypes::etFunction: + i++; + cfunc = content.function(ce.var_num); + //facnt = cfunc.arguments; + atmp.clear(); + bcnt = farg = 1; + ///qDebug() << "function: " + cfunc.identifier; + //for (int k = 0; k < facnt; k++) { + bcnt = 1; + carg = ""; + k = i + 1; + //if (string.size_s() <= k || k < 0) return -666; + while (bcnt > 0) { + //if (k < facnt - 1) fcomma = string.indexOf(',', j); + cc = string[k]; + switch (cc.toAscii()) { + case '(': bcnt++; break; + case ')': + bcnt--; + if (bcnt == 0) { + ///qDebug() << "arument: " << carg; + atmp.push_back(parse(carg, k + offset - carg.length())); + k++; + carg = ""; + if (atmp.size_s() > 0) if (atmp.back() < 0 && farg > 0) farg = atmp.back(); + continue; + } + break; + case ',': + if (bcnt == 1) { + ///qDebug() << "arument: " << carg; + atmp.push_back(parse(carg, k + offset - carg.length())); + k++; + carg = ""; + if (atmp.size_s() > 0) if (atmp.back() < 0 && farg > 0) farg = atmp.back(); + continue; + } + break; + } + carg += cc; + k++; + } + i = k - 1; + if (farg > 0) { + variables.push_back(PIEvaluatorTypes::Variable()); + farg = -variables.size_s(); + } + instructions.push_back(PIEvaluatorTypes::Instruction(PIEvaluatorTypes::oFunction, atmp, farg, ce.var_num)); + args.push_back(farg); + //for (int i = 0; i < args.size_s(); i++) cout << preproc->currentVariables[-args[i]].value << endl; + //i = j + 1; + continue; + case PIEvaluatorTypes::etOperator: + //qDebug() << "operator: " << cc; + if (cc == '(') { + sbrackets = inBrackets(string.right(slen - i)); + args.push_back(parse(sbrackets, i + offset + 1)); + i += sbrackets.length() + 1; + continue; + } + if (cc == '+') {opers.push_back(PIEvaluatorTypes::oAdd); continue;} + if (cc == '-') {opers.push_back(PIEvaluatorTypes::oSubtract); continue;} + if (cc == '*') {opers.push_back(PIEvaluatorTypes::oMultiply); continue;} + if (cc == '/') {opers.push_back(PIEvaluatorTypes::oDivide); continue;} + if (cc == '%') {opers.push_back(PIEvaluatorTypes::oResidue); continue;} + if (cc == '^') {opers.push_back(PIEvaluatorTypes::oPower); continue;} + if (cc == '=') {opers.push_back(PIEvaluatorTypes::oEqual); continue;} + if (cc == ':') {opers.push_back(PIEvaluatorTypes::oNotEqual); continue;} + if (cc == '}') {opers.push_back(PIEvaluatorTypes::oGreaterEqual); continue;} + if (cc == '{') {opers.push_back(PIEvaluatorTypes::oSmallerEqual); continue;} + if (cc == '>') {opers.push_back(PIEvaluatorTypes::oGreater); continue;} + if (cc == '<') {opers.push_back(PIEvaluatorTypes::oSmaller); continue;} + if (cc == '&') {opers.push_back(PIEvaluatorTypes::oAnd); continue;} + if (cc == '|') {opers.push_back(PIEvaluatorTypes::oOr); continue;} + } + } + /* + cout << "stack: " << endl << "args: "; + for (int i = 0; i < args.size_s(); i++) cout << args[i] << ", "; + cout << endl << "opers: "; + for (int i = 0; i < opers.size_s(); i++) cout << opers[i] << ", "; + */ + if (opers.size_s() == 0) { + if (args.size_s() > 0) return args.back(); + else return -666; + } + for (int i = 0; i < PIEvaluatorTypes::operationCount; i++) { + coper = operationInOrder(i); + for (int j = 0; j < opers.size_s(); j++) { + if (coper == PIEvaluatorTypes::oDivide || coper == PIEvaluatorTypes::oMultiply) { + if (opers[j] != PIEvaluatorTypes::oDivide && opers[j] != PIEvaluatorTypes::oMultiply) continue; + } else { + if (opers[j] != coper) continue; + } + atmp.clear(); + if (j < args.size_s() && j >= 0) atmp.push_back(args[j]); + else atmp.push_back(-666); + if (j + 1 < args.size_s() && j >= -1) atmp.push_back(args[j + 1]); + else atmp.push_back(-666); + farg = 1; + if (atmp[0] < 0) farg = atmp[0]; + else { + if (atmp[1] < 0) farg = atmp[1]; + else { + variables.push_back(PIEvaluatorTypes::Variable()); + farg = -variables.size_s(); + } + } + instructions.push_back(PIEvaluatorTypes::Instruction(opers[j], atmp, farg)); + if (j >= 0 && j < args.size_s()) { + args.remove(j); + if (j < args.size_s()) args[j] = farg; + } + opers.remove(j); + j--; + } + } + return instructions.back().out; + ///cout << endl; +} + + +bool PIEvaluator::check() { + PIEvaluatorTypes::Instruction ci; + bool error; + if (unknownVars.size_s() > 0) { + lastError = "Unknown variables: \"" + unknownVars.join("\", \"") + "\""; + return false; + } + for (int i = 0; i < instructions.size_s(); i++) { + error = false; + ci = instructions[i]; + PIEvaluatorTypes::Function cf; + int fac, gac; + switch (ci.operation) { + case PIEvaluatorTypes::oNone: break; + case PIEvaluatorTypes::oFunction: + cf = content.function(ci.function); + fac = cf.arguments; + gac = ci.operators.size_s(); + for (int j = 0; j < ci.operators.size_s(); j++) { + if (ci.operators[j] == -666) { //(ci.operators[j] < -variables.size_s() || ci.operators[j] >= kvars->size()) { + error = true; + gac--; + } + } + if (fac > 0) { + if (gac != fac) { + lastError = "Invalid arguments count for function \"" + cf.identifier + + "\", expected " + PIString::fromNumber(fac) + " but " + + PIString::fromNumber(gac) + " given"; + return false; + } + if (error) { + lastError = "Invalid at least one of function \"" + cf.identifier + "\" argument"; + return false; + } + } + if (fac < 0) { + if (gac < -fac) { + lastError = "Invalid arguments count for function \"" + cf.identifier + + "\", expected at least " + PIString::fromNumber(-fac) + " but " + + PIString::fromNumber(gac) + " given"; + return false; + } + if (error) { + lastError = "Invalid at least one of function \"" + cf.identifier + "\" argument"; + return false; + } + } + break; + default: + if (ci.operators[0] == -666 || ci.operators[1] == -666) error = true; + if (ci.operators.size_s() != 2 || error) { + lastError = "Invalid arguments count for operation \" " + operationChar(ci.operation) + " \""; + return false; + } + break; + } + if (ci.out < -variables.size_s()) { + lastError = "Invalid variable index \"" + PIString::fromNumber(ci.out) + "\""; + return false; + } + for (int j = 0; j < ci.operators.size_s(); j++) { + if (ci.operators[j] < -variables.size_s() || ci.operators[j] >= kvars->size_s()) { + lastError = "Invalid variable index \"" + PIString::fromNumber(ci.operators[j]) + "\""; + return false; + } + } + } + return true; +} + + +PIString PIEvaluator::inBrackets(const PIString & string) { + int slen = string.length(), bcnt = 0; + PIChar cc; + for (int i = 0; i < slen; i++) { + cc = string[i]; + if (cc == '(') bcnt++; + if (cc == ')') { + bcnt--; + if (bcnt == 0) return string.mid(1, i - 1); + } + } + return PIString(); +} + + +PIString PIEvaluator::operationChar(const PIEvaluatorTypes::Operation & operation) { + switch (operation) { + case PIEvaluatorTypes::oAdd: return "+"; + case PIEvaluatorTypes::oSubtract: return "-"; + case PIEvaluatorTypes::oMultiply: return "*"; + case PIEvaluatorTypes::oDivide: return "/"; + case PIEvaluatorTypes::oPower: return "^"; + case PIEvaluatorTypes::oResidue: return "%"; + case PIEvaluatorTypes::oEqual: return "="; + case PIEvaluatorTypes::oNotEqual: return ("≠"); + case PIEvaluatorTypes::oGreaterEqual: return ("≥"); + case PIEvaluatorTypes::oSmallerEqual: return ("≤"); + case PIEvaluatorTypes::oGreater: return ">"; + case PIEvaluatorTypes::oSmaller: return "<"; + case PIEvaluatorTypes::oAnd: return ("â‹€"); + case PIEvaluatorTypes::oOr: return ("â‹"); + default: return "???"; + } +} + + +inline complexd PIEvaluator::residue(const complexd & f, const complexd & s) { + complexd ret; + if (s.real() != 0.) ret = complexd(f.real() - ((int)(f.real() / s.real())) * s.real(), 0.); + if (s.imag() != 0.) ret = complexd(ret.real(), f.imag() - ((int)(f.imag() / s.imag())) * s.imag()); + return ret; +} + + +inline void PIEvaluator::execFunction(const PIEvaluatorTypes::Instruction & ci) { + PIEvaluatorTypes::Function cfunc = content.function(ci.function); + int oi = -ci.out - 1; + complexd tmp, stmp, ttmp; + //qDebug() << "function " << (int)cfunc.type; + switch (cfunc.type) { + case PIEvaluatorTypes::bfSin: + tmpvars[oi].value = sin(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfCos: + tmpvars[oi].value = cos(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfTg: + tmpvars[oi].value = tan(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfCtg: + tmp = tan(value(ci.operators[0])); + if (tmp == complexd_0) tmpvars[oi].value = 0.; + else tmpvars[oi].value = complexd_1 / tmp; + break; + case PIEvaluatorTypes::bfArcsin: + tmpvars[oi].value = asinc(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfArccos: + tmpvars[oi].value = acosc(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfArctg: + tmpvars[oi].value = atanc(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfArcctg: + tmp = atanc(value(ci.operators[0])); + if (tmp == complexd_0) tmpvars[oi].value = 0.; + else tmpvars[oi].value = complexd_1 / tmp; + break; + case PIEvaluatorTypes::bfSh: + tmpvars[oi].value = sinh(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfCh: + tmpvars[oi].value = cosh(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfTh: + tmpvars[oi].value = tanh(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfCth: + tmp = tanh(value(ci.operators[0])); + if (tmp == complexd_0) tmpvars[oi].value = 0.; + else tmpvars[oi].value = complexd_1 / tmp; + break; + case PIEvaluatorTypes::bfAbs: + tmpvars[oi].value = abs(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfSqrt: + tmpvars[oi].value = sqrt(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfSqr: + tmpvars[oi].value = value(ci.operators[0]) * value(ci.operators[0]); + break; + case PIEvaluatorTypes::bfExp: + tmpvars[oi].value = exp(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfPow: + tmpvars[oi].value = pow(value(ci.operators[0]), value(ci.operators[1])); + break; + case PIEvaluatorTypes::bfLn: + tmpvars[oi].value = log(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfLg: + tmpvars[oi].value = log10(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfLog: + tmp = log(value(ci.operators[1])); + if (tmp == complexd_0) tmpvars[oi].value = 0.; + else tmpvars[oi].value = log(value(ci.operators[0])) / tmp; + break; + case PIEvaluatorTypes::bfRe: + tmpvars[oi].value = value(ci.operators[0]).real(); + break; + case PIEvaluatorTypes::bfIm: + tmpvars[oi].value = value(ci.operators[0]).imag(); + break; + case PIEvaluatorTypes::bfArg: + tmpvars[oi].value = arg(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfLen: + tmpvars[oi].value = abs(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfConj: + tmpvars[oi].value = conj(value(ci.operators[0])); + break; + case PIEvaluatorTypes::bfSign: + tmpvars[oi].value = value(ci.operators[0]).real() >= 0. ? complexd_1 : -complexd_1; + break; + case PIEvaluatorTypes::bfRad: + tmpvars[oi].value = value(ci.operators[0]) * complexd(deg2rad, 0.); + break; + case PIEvaluatorTypes::bfDeg: + tmpvars[oi].value = value(ci.operators[0]) * complexd(rad2deg, 0.); + break; + case PIEvaluatorTypes::bfJ0: + tmpvars[oi].value = piJ0(value(ci.operators[0]).real()); + break; + case PIEvaluatorTypes::bfJ1: + tmpvars[oi].value = piJ1(value(ci.operators[0]).real()); + break; + case PIEvaluatorTypes::bfJN: + tmpvars[oi].value = piJn(piRoundd(value(ci.operators[1]).real()), value(ci.operators[0]).real()); + break; + case PIEvaluatorTypes::bfY0: + tmpvars[oi].value = piY0(value(ci.operators[0]).real()); + break; + case PIEvaluatorTypes::bfY1: + tmpvars[oi].value = piY1(value(ci.operators[0]).real()); + break; + case PIEvaluatorTypes::bfYN: + tmpvars[oi].value = piYn(piRoundd(value(ci.operators[1]).real()), value(ci.operators[0]).real()); + break; + case PIEvaluatorTypes::bfMin: + tmp = value(ci.operators[0]); + for (int i = 1; i < ci.operators.size_s(); ++i) { + stmp = value(ci.operators[i]); + tmp = complexd(piMind(tmp.real(), stmp.real()), piMind(tmp.imag(), stmp.imag())); + } + tmpvars[oi].value = tmp; + break; + case PIEvaluatorTypes::bfMax: + tmp = value(ci.operators[0]); + for (int i = 1; i < ci.operators.size_s(); ++i) { + stmp = value(ci.operators[i]); + tmp = complexd(piMaxd(tmp.real(), stmp.real()), piMaxd(tmp.imag(), stmp.imag())); + } + tmpvars[oi].value = tmp; + break; + case PIEvaluatorTypes::bfClamp: + tmp = value(ci.operators[0]); + stmp = value(ci.operators[1]); + ttmp = value(ci.operators[2]); + tmpvars[oi].value = complexd(piClampd(tmp.real(), stmp.real(), ttmp.real()), piClampd(tmp.imag(), stmp.imag(), ttmp.imag())); + break; + case PIEvaluatorTypes::bfStep: + tmpvars[oi].value = complexd(value(ci.operators[0]).real() >= value(ci.operators[1]).real() ? complexld_1 : complexld_0); + break; + case PIEvaluatorTypes::bfMix: + tmp = value(ci.operators[0]); + stmp = value(ci.operators[1]); + ttmp = value(ci.operators[2]); + tmpvars[oi].value = stmp.real() * (1. - tmp.real()) + ttmp.real() * tmp.real(); + break; + case PIEvaluatorTypes::bfDefined: + tmpvars[oi].value = value(ci.operators[0]).real() > 0. ? complexd_1 : complexd_0; + break; + case PIEvaluatorTypes::bfRandom: + tmp = static_cast(rand()) / RAND_MAX; + stmp = value(ci.operators[1]) - value(ci.operators[0]); + tmpvars[oi].value = value(ci.operators[0]) + tmp * stmp; + break; + default: break; + } +} + + +inline bool PIEvaluator::execInstructions() { + PIEvaluatorTypes::Instruction ci; + int oi; + complexd tmp; + tmpvars = variables; + //cout << "var count " << tmpvars.size_s() << endl; + for (int i = 0; i < instructions.size_s(); i++) { + ci = instructions[i]; + oi = -ci.out - 1; + //cout << value(ci.operators[0]) << operationChar(ci.operation) << value(ci.operators[1]) << ", " << oi << endl; + switch (ci.operation) { + case PIEvaluatorTypes::oAdd: + tmpvars[oi].value = value(ci.operators[0]) + value(ci.operators[1]); + break; + case PIEvaluatorTypes::oSubtract: + tmpvars[oi].value = value(ci.operators[0]) - value(ci.operators[1]); + break; + case PIEvaluatorTypes::oMultiply: + tmpvars[oi].value = value(ci.operators[0]) * value(ci.operators[1]); + break; + case PIEvaluatorTypes::oDivide: + tmp = value(ci.operators[1]); + if (tmp == complexd(0., 0.)) tmpvars[oi].value = 0.; + else tmpvars[oi].value = value(ci.operators[0]) / tmp; + break; + case PIEvaluatorTypes::oResidue: + tmpvars[oi].value = residue(value(ci.operators[0]), value(ci.operators[1])); + break; + case PIEvaluatorTypes::oPower: + tmpvars[oi].value = pow(value(ci.operators[0]), value(ci.operators[1])); + break; + case PIEvaluatorTypes::oEqual: + tmpvars[oi].value = value(ci.operators[0]) == value(ci.operators[1]); + break; + case PIEvaluatorTypes::oNotEqual: + tmpvars[oi].value = value(ci.operators[0]) != value(ci.operators[1]); + break; + case PIEvaluatorTypes::oGreaterEqual: + tmpvars[oi].value = value(ci.operators[0]).real() >= value(ci.operators[1]).real(); + break; + case PIEvaluatorTypes::oSmallerEqual: + tmpvars[oi].value = value(ci.operators[0]).real() <= value(ci.operators[1]).real(); + break; + case PIEvaluatorTypes::oGreater: + tmpvars[oi].value = value(ci.operators[0]).real() > value(ci.operators[1]).real(); + break; + case PIEvaluatorTypes::oSmaller: + tmpvars[oi].value = value(ci.operators[0]).real() < value(ci.operators[1]).real(); + break; + case PIEvaluatorTypes::oAnd: + tmpvars[oi].value = value(ci.operators[0]).real() > 0. && value(ci.operators[1]).real() > 0.; + break; + case PIEvaluatorTypes::oOr: + tmpvars[oi].value = value(ci.operators[0]).real() > 0. || value(ci.operators[1]).real() > 0.; + break; + case PIEvaluatorTypes::oFunction: + execFunction(ci); + break; + case PIEvaluatorTypes::oNone: + tmpvars[oi].value = value(ci.operators[0]); + break; + } + } + if (!instructions.isEmpty()) + out = value(instructions.back().out); + return true; +} + + +bool PIEvaluator::check(const PIString & string) { + currentString = preprocess(string); + correct = check(); + if (!correct) { + instructions.clear(); + return false; + } + lastError = "Correct"; + return true; +} + + +complexd PIEvaluator::evaluate() { + if (!execInstructions()) out = 0.; + if (fabs(out.real()) < 1E-300) out = complexd(0., out.imag()); + if (fabs(out.imag()) < 1E-300) out = complexd(out.real(), 0.); + return out; +} diff --git a/src/math/pievaluator.h b/src/math/pievaluator.h new file mode 100755 index 00000000..9703a5d4 --- /dev/null +++ b/src/math/pievaluator.h @@ -0,0 +1,227 @@ +/*! \file pievaluator.h + * \brief Mathematic expressions calculator +*/ +/* + PIP - Platform Independent Primitives + Evaluator designed for stream calculations + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIEVALUATOR_H +#define PIEVALUATOR_H + +#include "pistring.h" +#include "pimath.h" + +typedef complexd (*FuncFunc)(void * , int, complexd * ); + +namespace PIEvaluatorTypes { + static const int operationCount = 14; + + enum eType {etNumber, etOperator, etVariable, etFunction}; + enum Operation {oNone, oAdd, oSubtract, oMultiply, oDivide, oResidue, oPower, + oEqual, oNotEqual, oGreater, oSmaller, oGreaterEqual, oSmallerEqual, + oAnd, oOr, oFunction + }; + enum BaseFunctions {bfUnknown, bfSin, bfCos, bfTg, bfCtg, + bfArcsin, bfArccos, bfArctg, bfArcctg, + bfExp, bfRandom, bfSh, bfCh, bfTh, bfCth, + bfSqrt, bfSqr, bfPow, bfAbs, + bfLn, bfLg, bfLog, bfSign, + bfIm, bfRe, bfArg, bfLen, bfConj, + bfRad, bfDeg, bfJ0, bfJ1, bfJN, + bfY0, bfY1, bfYN, bfMin, bfMax, + bfClamp, bfStep, bfMix, bfDefined, + bfCustom = 0xFFFF + }; + + struct Instruction { + Instruction() {;} + Instruction(Operation oper, PIVector opers, int out_ind, int func = -1) { + operation = oper; operators = opers; out = out_ind; function = func;} + Operation operation; + PIVector operators; + int out; + int function; + }; + struct Element { + Element() {;} + Element(eType new_type, int new_num, int new_var_num = -1) {set(new_type, new_num, new_var_num);} + void set(eType new_type, int new_num, int new_var_num = -1) {type = new_type; num = new_num; var_num = new_var_num;} + eType type; + int num; + int var_num; + }; + struct Function { + Function() {arguments = 0; type = bfUnknown; handler = 0;} + Function(const PIString & name, int args, BaseFunctions ftype) {identifier = name; arguments = args; type = ftype; handler = 0;} + Function(const PIString & name, int args, FuncFunc h) {identifier = name; arguments = args; type = bfCustom; handler = h;} + PIString identifier; + BaseFunctions type; + FuncFunc handler; + int arguments; + }; + struct Variable { + Variable() {value = 0.;} + Variable(const PIString & var_name, complexd val) {name = var_name; value = val;} + PIString name; + complexd value; + }; +}; +/* + ≠ : + ≥ } + ≤ { + â‹€ & + â‹ | +*/ + +class PIP_EXPORT PIEvaluatorContent +{ + friend class PIEvaluator; +public: + PIEvaluatorContent(); + ~PIEvaluatorContent() {;} + + void addFunction(const PIString & name, int args = 1) {functions.push_back(PIEvaluatorTypes::Function(name, args, getBaseFunction(name)));} + void addVariable(const PIString & name, const complexd & val = 0.) {variables.push_back(PIEvaluatorTypes::Variable(name, val)); sortVariables();} + void addCustomFunction(const PIString & name, int args_count, FuncFunc func) {functions << PIEvaluatorTypes::Function(name, args_count, func);} + int functionsCount() const {return functions.size();} + int variablesCount() const {return variables.size();} + int customVariablesCount() const {return variables.size() - cv_count;} + int findFunction(const PIString & name) const {for (uint i = 0; i < functions.size(); i++) if (functions[i].identifier == name) return i; return -1;} + int findVariable(const PIString & var_name) const {for (uint i = 0; i < variables.size(); i++) if (variables[i].name == var_name) return i; return -1;} + PIEvaluatorTypes::Function function(int index) {if (index < 0 || index >= functions.size_s()) return PIEvaluatorTypes::Function(); return functions[index];} + PIEvaluatorTypes::Variable variable(int index) {if (index < 0 || index >= variables.size_s()) return PIEvaluatorTypes::Variable(); return variables[index];} + PIEvaluatorTypes::Function function(const PIString & name) {return function(findFunction(name));} + PIEvaluatorTypes::Variable variable(const PIString & name) {return variable(findVariable(name));} + PIEvaluatorTypes::Variable customVariable(int index) {if (index < cv_count || index >= variables.size_s() + cv_count) return PIEvaluatorTypes::Variable(); return variables[index + cv_count];} + bool setVariableValue(int index, complexd new_value); + bool setVariableName(int index, const PIString & new_name); + bool setVariableValue(const PIString & var_name, const complexd & new_value) {return setVariableValue(findVariable(var_name), new_value);} + bool setVariableName(const PIString & var_name, const PIString & new_name) {return setVariableName(findVariable(var_name), new_name);} + void removeVariable(int index) {variables.remove(index);} + void removeVariable(const PIString & var_name) {removeVariable(findVariable(var_name));} + void clearCustomVariables(); + void sortVariables(); + PIEvaluatorTypes::BaseFunctions getBaseFunction(const PIString & name); + +private: + PIVector functions; + PIVector variables; + int cv_count; + +}; + + +class PIP_EXPORT PIEvaluator +{ +public: + + //! Constructs an empty evaluator + PIEvaluator() {correct = false; data_ = 0;} + + ~PIEvaluator() {;} + + + //! Returns custom data + void * data() {return data_;} + + //! Set custom data to "_data" + void setData(void * _data) {data_ = _data;} + + + //! Check mathematical expression and parse it to list of instructions + bool check(const PIString & string); + + //! Returns true if expression was checked succesfully + bool isCorrect() const {return correct;} + + //! Set variable value with name "name" to value "value". Add variable if it doesn`t exists + int setVariable(const PIString & name, complexd value = 0.) {if (content.findVariable(name) < 0) content.addVariable(name, value); else content.setVariableValue(name, value); return content.findVariable(name);} + + //! Set variable value with index "index" to value "value". Don`t add variable if it doesn`t exists + void setVariable(int index, complexd value = 0.) {if (index >= 0 && index < content.variablesCount()) content.setVariableValue(index, value);} + + void setCustomVariableValue(int index, complexd value = 0.) {content.variables[index + content.cv_count].value = value;} +/* + //! Add function "name" with arguments count "args_count" and handler "func". Three arguments will be passed to handler: \a data(), "args_count" and array of input values. + void addFunction(const PIString & name, int args_count, FuncFunc func) {content.addCustomFunction(name, args_count, func);} +*/ + //! Evaluate last successfully checked with function \a check() expression and returns result + complexd evaluate(); + + //! Remove variable with name "name" + void removeVariable(const PIString & name) {content.removeVariable(name);} + + //! Remove all manually added variables + void clearCustomVariables() {content.clearCustomVariables();} + + //! Returns index of variable with name "name" + int variableIndex(const PIString & name) const {return content.findVariable(name);} + + //! Returns all unknown variables founded in last expression passed to \a check() function + const PIStringList & unknownVariables() const {return unknownVars;} + + //! Returns processed last expression passed to \a check() function + const PIString & expression() const {return currentString;} + + //! Returns last error description occured in \a check() function + const PIString & error() const {return lastError;} + + //! Returns last result of \a evaluate() + const complexd & lastResult() const {return out;} + + PIEvaluatorContent content; + +private: + const PIString & prepare(const PIString & string); + const PIString & preprocess(const PIString & string); + int parse(const PIString & string, int offset = 0); + void convert(); + void checkBrackets(); + void removeSpaces(); + void findUnknownVariables(); + void removeJunk(); + void replaceOperators(); + void makeOutput(PIString & string); + bool fillElements(); + bool setSignes(); + bool isSign(const PIChar & ch); + PIString inverse(const PIString & string) {int len = string.length(); PIString s; for (int i = 0; i < len; i++) s += string[len - i - 1]; return s;} + bool check(); + bool execInstructions(); + PIString inBrackets(const PIString & string); + PIString operationChar(const PIEvaluatorTypes::Operation & operation); + PIEvaluatorTypes::Operation operationInOrder(const int & index); + complexd value(const int & index) {if (index < 0) return tmpvars[-index - 1].value; else return kvars->at(index).value;} + inline complexd residue(const complexd & f, const complexd & s); + inline void execFunction(const PIEvaluatorTypes::Instruction & ci); + + PIVector elements; + PIVector currentVariables, variables, tmpvars, * kvars; + PIVector instructions; + PIStringList unknownVars; + PIString currentString, lastError; + complexd out; + bool correct; + void * data_; +}; + +inline bool operator ==(PIEvaluatorTypes::Element e1, PIEvaluatorTypes::Element e2) {return (e1.type == e2.type && e1.num == e2.num);} +inline bool operator !=(PIEvaluatorTypes::Element e1, PIEvaluatorTypes::Element e2) {return (e1.type != e2.type || e1.num != e2.num);} + +#endif // PIEVALUATOR_H diff --git a/src/math/pifft.cpp b/src/math/pifft.cpp new file mode 100644 index 00000000..61814720 --- /dev/null +++ b/src/math/pifft.cpp @@ -0,0 +1,936 @@ +/* + PIP - Platform Independent Primitives + Class for FFT, IFFT and Hilbert transformations + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com, Andrey Bychkov work.a.b@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pifft.h" + + +PIFFT::PIFFT() { + prepared = false; +} + + +PIVector * PIFFT::calcFFT(const PIVector & val) { + result.clear(); + if (val.size_s() < 4) return &result; + fftc1d(val, val.size()); + return &result; +} + + +PIVector * PIFFT::calcFFTinverse(const PIVector & val) { + result.clear(); + if (val.size_s() < 4) return &result; + fftc1dinv(val, val.size()); + return &result; +} + + +PIVector * PIFFT::calcHilbert(const PIVector & val) { + result.clear(); + if (val.size_s() < 4) return &result; + fftc1r(val, val.size()); + for (uint i = 0; i < result.size() / 2; i++) result[i] = result[i] * 2.; + for (uint i = result.size() / 2; i < result.size(); i++) result[i] = 0; + fftc1dinv(result, result.size()); + return &result; +} + + +PIVector * PIFFT::calcFFT(const PIVector & val) { + result.clear(); + if (val.size_s() < 4) return &result; + fftc1r(val, val.size()); + return &result; +} + + +PIVector PIFFT::getAmplitude() { + PIVector a; + double tmp; + for (uint i = 0; i < result.size(); i++) { + tmp = sqrt(result[i].real() * result[i].real() + result[i].imag() * result[i].imag()); + a.push_back(tmp); + } + return a; +} + + +void PIFFT::fftc1d(const PIVector & a, uint n) { + createPlan(n); + uint i; + PIVector buf; + buf.resize(2 * n); + for (i = 0; i < n; i++) { + buf[2 * i + 0] = a[i].real(); + buf[2 * i + 1] = a[i].imag(); + } + ftbaseexecuteplan(&buf, 0, n, &curplan); + result.resize(n); + for (i = 0; i < n; i++) + result[i] = complexd(buf[2 * i + 0], buf[2 * i + 1]); +} + + +void PIFFT::fftc1r(const PIVector & a, uint n) { + uint i; + if (n % 2 == 0) { + PIVector buf; + uint n2 = n / 2; + buf = a; + createPlan(n2); + ftbaseexecuteplan(&buf, 0, n2, &curplan); + result.resize(n); + uint idx; + complexd hn, hmnc, v; + for (i = 0; i <= n2; i++) { + idx = 2 * (i % n2); + hn = complexd(buf[idx + 0], buf[idx + 1]); + idx = 2 * ((n2 - i) % n2); + hmnc = complexd(buf[idx + 0], -buf[idx + 1]); + v = complexd(sin(M_PI * i / n2), cos(M_PI * i / n2)); + result[i] = ((hn + hmnc) - (v * (hn - hmnc))); + result[i] *= 0.5; + } + for (i = n2 + 1; i < n; i++) + result[i] = conj(result[n - i]); + } else { + PIVector cbuf; + cbuf.resize(n); + for (i = 0; i < n; i++) + cbuf[i] = complexd(a[i], 0.); + fftc1d(cbuf, n); + } +} + + +void PIFFT::fftc1dinv(const PIVector & a, uint n) { + PIVector cbuf; + cbuf.resize(n); + uint i; + for (i = 0; i < n; i++) { + cbuf[i] = conj(a[i]); + } + fftc1d(cbuf, n); + for (i = 0; i < n; i++) { + result[i] = conj(result[i] / (double)n); + } +} + + +void PIFFT::createPlan(uint n) { + curplan.plan.clear(); + curplan.precomputed.clear(); + curplan.stackbuf.clear(); + curplan.tmpbuf.clear(); + if (n < 2) return; + ftbasegeneratecomplexfftplan(n, &curplan); + prepared = true; +} + + +void PIFFT::ftbasegeneratecomplexfftplan(uint n, ftplan * plan) { + int planarraysize; + int plansize; + int precomputedsize; + int tmpmemsize; + int stackmemsize; + ae_int_t stackptr; + planarraysize = 1; + plansize = 0; + precomputedsize = 0; + stackmemsize = 0; + stackptr = 0; + tmpmemsize = 2 * n; + curplan.plan.resize(planarraysize); + int ftbase_ftbasecffttask = 0; + ftbase_ftbasegenerateplanrec(n, ftbase_ftbasecffttask, plan, &plansize, &precomputedsize, &planarraysize, &tmpmemsize, &stackmemsize, stackptr); + if (stackptr != 0) { + return;//ae_assert(stackptr==0, "Internal error in FTBaseGenerateComplexFFTPlan: stack ptr!"); + } + curplan.stackbuf.resize(piMax(stackmemsize, 1)); //ae_vector_set_length(&curplan.stackbuf, ae_maxint(stackmemsize, 1)); + curplan.tmpbuf.resize(piMax(tmpmemsize, 1)); //ae_vector_set_length(&(curplan.tmpbuf), ae_maxint(tmpmemsize, 1)); + curplan.precomputed.resize(piMax(precomputedsize, 1)); //ae_vector_set_length(&curplan.precomputed, ae_maxint(precomputedsize, 1)); + stackptr = 0; + ftbase_ftbaseprecomputeplanrec(plan, 0, stackptr); + if (stackptr != 0) { + return;//ae_assert(stackptr==0, "Internal error in FTBaseGenerateComplexFFTPlan: stack ptr!"); + } +} + + +/************************************************************************* +Recurrent subroutine for the FFTGeneratePlan: + +PARAMETERS: + N plan size + IsReal whether input is real or not. + subroutine MUST NOT ignore this flag because real + inputs comes with non-initialized imaginary parts, + so ignoring this flag will result in corrupted output + HalfOut whether full output or only half of it from 0 to + floor(N/2) is needed. This flag may be ignored if + doing so will simplify calculations + Plan plan array + PlanSize size of used part (in integers) + PrecomputedSize size of precomputed array allocated yet + PlanArraySize plan array size (actual) + TmpMemSize temporary memory required size + BluesteinMemSize temporary memory required size + +-- ALGLIB -- + Copyright 01.05.2009 by Bochkanov Sergey +*************************************************************************/ +void PIFFT::ftbase_ftbasegenerateplanrec( +int n, +int tasktype, +ftplan * plan, +int * plansize, +int * precomputedsize, +int * planarraysize, +int * tmpmemsize, +int * stackmemsize, +ae_int_t stackptr, int debugi) { + int k, m, n1, n2, esize, entryoffset; + int ftbase_ftbaseplanentrysize = 8; + int ftbase_ftbasecffttask = 0; + int ftbase_fftcooleytukeyplan = 0; + int ftbase_fftbluesteinplan = 1; + int ftbase_fftcodeletplan = 2; + int ftbase_fftrealcooleytukeyplan = 5; + int ftbase_fftemptyplan = 6; + if (*plansize + ftbase_ftbaseplanentrysize > (*planarraysize)) { + curplan.plan.resize(8 * (*planarraysize)); + *planarraysize = 8 * (*planarraysize); + } + entryoffset = *plansize; + esize = ftbase_ftbaseplanentrysize; + *plansize = *plansize + esize; + if (n == 1) { + curplan.plan[entryoffset + 0] = esize; + curplan.plan[entryoffset + 1] = -1; + curplan.plan[entryoffset + 2] = -1; + curplan.plan[entryoffset + 3] = ftbase_fftemptyplan; + curplan.plan[entryoffset + 4] = -1; + curplan.plan[entryoffset + 5] = -1; + curplan.plan[entryoffset + 6] = -1; + curplan.plan[entryoffset + 7] = -1; + return; + } + ftbasefactorize(n, &n1, &n2); + if (n1 != 1) { + *tmpmemsize = piMax(*tmpmemsize, 2 * n1 * n2); + curplan.plan[entryoffset + 0] = esize; + curplan.plan[entryoffset + 1] = n1; + curplan.plan[entryoffset + 2] = n2; + if (tasktype == ftbase_ftbasecffttask) + curplan.plan[entryoffset + 3] = ftbase_fftcooleytukeyplan; + else + curplan.plan[entryoffset + 3] = ftbase_fftrealcooleytukeyplan; + curplan.plan[entryoffset + 4] = 0; + curplan.plan[entryoffset + 5] = *plansize; + debugi++; + ftbase_ftbasegenerateplanrec(n1, ftbase_ftbasecffttask, plan, plansize, precomputedsize, planarraysize, tmpmemsize, stackmemsize, stackptr, debugi); + curplan.plan[entryoffset + 6] = *plansize; + ftbase_ftbasegenerateplanrec(n2, ftbase_ftbasecffttask, plan, plansize, precomputedsize, planarraysize, tmpmemsize, stackmemsize, stackptr, debugi); + curplan.plan[entryoffset + 7] = -1; + return; + } else { + if (n >= 2 && n <= 5) { + curplan.plan[entryoffset + 0] = esize; + curplan.plan[entryoffset + 1] = n1; + curplan.plan[entryoffset + 2] = n2; + curplan.plan[entryoffset + 3] = ftbase_fftcodeletplan; + curplan.plan[entryoffset + 4] = 0; + curplan.plan[entryoffset + 5] = -1; + curplan.plan[entryoffset + 6] = -1; + curplan.plan[entryoffset + 7] = *precomputedsize; + if (n == 3) + *precomputedsize = *precomputedsize + 2; + if (n == 5) + *precomputedsize = *precomputedsize + 5; + return; + } else { + k = 2 * n2 - 1; + m = ftbasefindsmooth(k); + *tmpmemsize = piMax(*tmpmemsize, 2 * m); + curplan.plan[entryoffset + 0] = esize; + curplan.plan[entryoffset + 1] = n2; + curplan.plan[entryoffset + 2] = -1; + curplan.plan[entryoffset + 3] = ftbase_fftbluesteinplan; + curplan.plan[entryoffset + 4] = m; + curplan.plan[entryoffset + 5] = *plansize; + stackptr = stackptr + 2 * 2 * m; + *stackmemsize = piMax(*stackmemsize, stackptr); + ftbase_ftbasegenerateplanrec(m, ftbase_ftbasecffttask, plan, plansize, precomputedsize, planarraysize, tmpmemsize, stackmemsize, stackptr); + stackptr = stackptr - 2 * 2 * m; + curplan.plan[entryoffset + 6] = -1; + curplan.plan[entryoffset + 7] = *precomputedsize; + *precomputedsize = *precomputedsize + 2 * m + 2 * n; + return; + } + } +} + + +/************************************************************************* +Recurrent subroutine for precomputing FFT plans + +-- ALGLIB -- + Copyright 01.05.2009 by Bochkanov Sergey +*************************************************************************/ +void PIFFT::ftbase_ftbaseprecomputeplanrec(ftplan * plan, +int entryoffset, +ae_int_t stackptr) { + int n1, n2, n, m, offs; + double v, bx, by; + int ftbase_fftcooleytukeyplan = 0; + int ftbase_fftbluesteinplan = 1; + int ftbase_fftcodeletplan = 2; + int ftbase_fhtcooleytukeyplan = 3; + int ftbase_fhtcodeletplan = 4; + int ftbase_fftrealcooleytukeyplan = 5; + if ((curplan.plan[entryoffset + 3] == ftbase_fftcooleytukeyplan || curplan.plan[entryoffset + 3] == ftbase_fftrealcooleytukeyplan) || curplan.plan[entryoffset + 3] == ftbase_fhtcooleytukeyplan) { + ftbase_ftbaseprecomputeplanrec(plan, curplan.plan[entryoffset + 5], stackptr); + ftbase_ftbaseprecomputeplanrec(plan, curplan.plan[entryoffset + 6], stackptr); + return; + } + if (curplan.plan[entryoffset + 3] == ftbase_fftcodeletplan || curplan.plan[entryoffset + 3] == ftbase_fhtcodeletplan) { + n1 = curplan.plan[entryoffset + 1]; + n2 = curplan.plan[entryoffset + 2]; + n = n1 * n2; + if (n == 3) { + offs = curplan.plan[entryoffset + 7]; + curplan.precomputed[offs + 0] = cos(2 * M_PI / 3) - 1; + curplan.precomputed[offs + 1] = sin(2 * M_PI / 3); + return; + } + if (n == 5) { + offs = curplan.plan[entryoffset + 7]; + v = 2 * M_PI / 5; + curplan.precomputed[offs + 0] = (cos(v) + cos(2 * v)) / 2 - 1; + curplan.precomputed[offs + 1] = (cos(v) - cos(2 * v)) / 2; + curplan.precomputed[offs + 2] = -sin(v); + curplan.precomputed[offs + 3] = -(sin(v) + sin(2 * v)); + curplan.precomputed[offs + 4] = sin(v) - sin(2 * v); + return; + } + } + if (curplan.plan[entryoffset + 3] == ftbase_fftbluesteinplan) { + ftbase_ftbaseprecomputeplanrec(plan, curplan.plan[entryoffset + 5], stackptr); + n = curplan.plan[entryoffset + 1]; + m = curplan.plan[entryoffset + 4]; + offs = curplan.plan[entryoffset + 7]; + for (int i = 0; i <= 2 * m - 1; i++) + curplan.precomputed[offs + i] = 0; + for (int i = 0; i < n; i++) { + bx = cos(M_PI * sqr(i) / n); + by = sin(M_PI * sqr(i) / n); + curplan.precomputed[offs + 2 * i + 0] = bx; + curplan.precomputed[offs + 2 * i + 1] = by; + curplan.precomputed[offs + 2 * m + 2 * i + 0] = bx; + curplan.precomputed[offs + 2 * m + 2 * i + 1] = by; + if (i > 0) { + curplan.precomputed[offs + 2 * (m - i) + 0] = bx; + curplan.precomputed[offs + 2 * (m - i) + 1] = by; + } + } + ftbaseexecuteplanrec(&curplan.precomputed, offs, plan, curplan.plan[entryoffset + 5], stackptr); + return; + } +} + + +void PIFFT::ftbasefactorize(int n, int * n1, int * n2) { + *n1 = *n2 = 0; + int ftbase_ftbasecodeletrecommended = 5; + if ((*n1) * (*n2) != n) { + for (int j = ftbase_ftbasecodeletrecommended; j >= 2; j--) { + if (n % j == 0) { + *n1 = j; + *n2 = n / j; + break; + } + } + } + if ((*n1) * (*n2) != n) { + for (int j = ftbase_ftbasecodeletrecommended + 1; j <= n - 1; j++) { + if (n % j == 0) { + *n1 = j; + *n2 = n / j; + break; + } + } + } + if ((*n1) * (*n2) != n) { + *n1 = 1; + *n2 = n; + } + if ((*n2) == 1 && (*n1) != 1) { + *n2 = *n1; + *n1 = 1; + } +} + + +/************************************************************************* +Is number smooth? + +-- ALGLIB -- + Copyright 01.05.2009 by Bochkanov Sergey +*************************************************************************/ +void PIFFT::ftbase_ftbasefindsmoothrec(int n, int seed, int leastfactor, int * best) { + if (seed >= n) { + *best = piMini(*best, seed); + return; + } + if (leastfactor <= 2) + ftbase_ftbasefindsmoothrec(n, seed * 2, 2, best); + if (leastfactor <= 3) + ftbase_ftbasefindsmoothrec(n, seed * 3, 3, best); + if (leastfactor <= 5) + ftbase_ftbasefindsmoothrec(n, seed * 5, 5, best); +} + + +int PIFFT::ftbasefindsmooth(int n) { + int best, result; + best = 2; + while (best < n) + best = 2 * best; + ftbase_ftbasefindsmoothrec(n, 1, 2, &best); + result = best; + return result; +} + + +void PIFFT::ftbase_internalreallintranspose(PIVector * a, int m, int n, int astart, PIVector * buf) { + ftbase_fftirltrec(a, astart, n, buf, 0, m, m, n); + for (int i = 0; i < 2 * m * n; i++) (*a)[astart + i] = (*buf)[i]; +} + + +void PIFFT::ftbase_fftirltrec(PIVector * a, int astart, int astride, PIVector * b, int bstart, int bstride, int m, int n) { + int idx1, idx2; + int m1, n1; + if (m == 0 || n == 0) + return; + if (piMaxi(m, n) <= 8) { + for (int i = 0; i <= m - 1; i++) { + idx1 = bstart + i; + idx2 = astart + i * astride; + for (int j = 0; j <= n - 1; j++) { + (*b)[idx1] = a->at(idx2); + idx1 = idx1 + bstride; + idx2 = idx2 + 1; + } + } + return; + } + if (n > m) { + n1 = n / 2; + if (n - n1 >= 8 && n1 % 8 != 0) + n1 = n1 + (8 - n1 % 8); + ftbase_fftirltrec(a, astart, astride, b, bstart, bstride, m, n1); + ftbase_fftirltrec(a, astart + n1, astride, b, bstart + n1 * bstride, bstride, m, n - n1); + } else { + m1 = m / 2; + if (m - m1 >= 8 && m1 % 8 != 0) + m1 = m1 + (8 - m1 % 8); + ftbase_fftirltrec(a, astart, astride, b, bstart, bstride, m1, n); + ftbase_fftirltrec(a, astart + m1 * astride, astride, b, bstart + m1, bstride, m - m1, n); + } +} + + +void PIFFT::ftbase_internalcomplexlintranspose(PIVector * a, int m, int n, int astart, PIVector * buf) { + ftbase_ffticltrec(a, astart, n, buf, 0, m, m, n); + for (int i = 0; i < 2 * m * n; i++) + (*a)[astart + i] = (*buf)[i]; +} + + +void PIFFT::ftbase_ffticltrec(PIVector * a, int astart, int astride, PIVector * b, int bstart, int bstride, int m, int n) { + int idx1, idx2, m2, m1, n1; + if (m == 0 || n == 0) + return; + if (piMax(m, n) <= 8) { + m2 = 2 * bstride; + for (int i = 0; i <= m - 1; i++) { + idx1 = bstart + 2 * i; + idx2 = astart + 2 * i * astride; + for (int j = 0; j <= n - 1; j++) { + (*b)[idx1 + 0] = a->at(idx2 + 0); + (*b)[idx1 + 1] = a->at(idx2 + 1); + idx1 = idx1 + m2; + idx2 = idx2 + 2; + } + } + return; + } + if (n > m) { + n1 = n / 2; + if (n - n1 >= 8 && n1 % 8 != 0) + n1 = n1 + (8 - n1 % 8); + ftbase_ffticltrec(a, astart, astride, b, bstart, bstride, m, n1); + ftbase_ffticltrec(a, astart + 2 * n1, astride, b, bstart + 2 * n1 * bstride, bstride, m, n - n1); + } else { + m1 = m / 2; + if (m - m1 >= 8 && m1 % 8 != 0) + m1 = m1 + (8 - m1 % 8); + ftbase_ffticltrec(a, astart, astride, b, bstart, bstride, m1, n); + ftbase_ffticltrec(a, astart + 2 * m1 * astride, astride, b, bstart + 2 * m1, bstride, m - m1, n); + } +} + + +void PIFFT::ftbaseexecuteplan(PIVector * a, int aoffset, int n, ftplan * plan) { + ae_int_t stackptr; + stackptr = 0; + ftbaseexecuteplanrec(a, aoffset, plan, 0, stackptr); +} + + +/************************************************************************* +Recurrent subroutine for the FTBaseExecutePlan + +Parameters: + A FFT'ed array + AOffset offset of the FFT'ed part (distance is measured in doubles) + +-- ALGLIB -- + Copyright 01.05.2009 by Bochkanov Sergey +*************************************************************************/ +void PIFFT::ftbaseexecuteplanrec(PIVector * a, int aoffset, ftplan * plan, int entryoffset, ae_int_t stackptr) { + int n1, n2, n, m, offs, offs1, offs2, offsa, offsb, offsp; + double hk, hnk, x, y, bx, by, v0, v1, v2, v3; + double a0x, a0y, a1x, a1y, a2x, a2y, a3x, a3y; + double t1x, t1y, t2x, t2y, t3x, t3y, t4x, t4y, t5x, t5y; + double m1x, m1y, m2x, m2y, m3x, m3y, m4x, m4y, m5x, m5y; + double s1x, s1y, s2x, s2y, s3x, s3y, s4x, s4y, s5x, s5y; + double c1, c2, c3, c4, c5; + int ftbase_fftcooleytukeyplan = 0; + int ftbase_fftbluesteinplan = 1; + int ftbase_fftcodeletplan = 2; + int ftbase_fhtcooleytukeyplan = 3; + int ftbase_fhtcodeletplan = 4; + int ftbase_fftrealcooleytukeyplan = 5; + int ftbase_fftemptyplan = 6; + PIVector & tmpb(curplan.tmpbuf); + + if (curplan.plan[entryoffset + 3] == ftbase_fftemptyplan) + return; + if (curplan.plan[entryoffset + 3] == ftbase_fftcooleytukeyplan) { + n1 = curplan.plan[entryoffset + 1]; + n2 = curplan.plan[entryoffset + 2]; + ftbase_internalcomplexlintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf)); + for (int i = 0; i <= n2 - 1; i++) + ftbaseexecuteplanrec(a, aoffset + i * n1 * 2, plan, curplan.plan[entryoffset + 5], stackptr); + ftbase_ffttwcalc(a, aoffset, n1, n2); + ftbase_internalcomplexlintranspose(a, n2, n1, aoffset, &(curplan.tmpbuf)); + for (int i = 0; i <= n1 - 1; i++) + ftbaseexecuteplanrec(a, aoffset + i * n2 * 2, plan, curplan.plan[entryoffset + 6], stackptr); + ftbase_internalcomplexlintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf)); + return; + } + if (curplan.plan[entryoffset + 3] == ftbase_fftrealcooleytukeyplan) { + n1 = curplan.plan[entryoffset + 1]; + n2 = curplan.plan[entryoffset + 2]; + ftbase_internalcomplexlintranspose(a, n2, n1, aoffset, &(curplan.tmpbuf)); + for (int i = 0; i <= n1 / 2 - 1; i++) { + offs = aoffset + 2 * i * n2 * 2; + for (int k = 0; k <= n2 - 1; k++) + (*a)[offs + 2 * k + 1] = (*a)[offs + 2 * n2 + 2 * k + 0]; + ftbaseexecuteplanrec(a, offs, plan, curplan.plan[entryoffset + 6], stackptr); + tmpb[0] = (*a)[offs + 0]; + tmpb[1] = 0; + tmpb[2 * n2 + 0] = (*a)[offs + 1]; + tmpb[2 * n2 + 1] = 0; + for (int k = 1; k <= n2 - 1; k++) { + offs1 = 2 * k; + offs2 = 2 * n2 + 2 * k; + hk = (*a)[offs + 2 * k + 0]; + hnk = (*a)[offs + 2 * (n2 - k) + 0]; + tmpb[offs1 + 0] = 0.5 * (hk + hnk); + tmpb[offs2 + 1] = -0.5 * (hk - hnk); + hk = (*a)[offs + 2 * k + 1]; + hnk = (*a)[offs + 2 * (n2 - k) + 1]; + tmpb[offs2 + 0] = 0.5 * (hk + hnk); + tmpb[offs1 + 1] = 0.5 * (hk - hnk); + } + for (int k = 0; k < 2 * n2 * 2; k++) (*a)[offs + k] = tmpb[k]; + } + if (n1 % 2 != 0) + ftbaseexecuteplanrec(a, aoffset + (n1 - 1)*n2 * 2, plan, curplan.plan[entryoffset + 6], stackptr); + ftbase_ffttwcalc(a, aoffset, n2, n1); + ftbase_internalcomplexlintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf)); + for (int i = 0; i <= n2 - 1; i++) + ftbaseexecuteplanrec(a, aoffset + i * n1 * 2, plan, curplan.plan[entryoffset + 5], stackptr); + ftbase_internalcomplexlintranspose(a, n2, n1, aoffset, &(curplan.tmpbuf)); + return; + } + if (curplan.plan[entryoffset + 3] == ftbase_fhtcooleytukeyplan) { + n1 = curplan.plan[entryoffset + 1]; + n2 = curplan.plan[entryoffset + 2]; + n = n1 * n2; + ftbase_internalreallintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf)); + for (int i = 0; i <= n2 - 1; i++) + ftbaseexecuteplanrec(a, aoffset + i * n1, plan, curplan.plan[entryoffset + 5], stackptr); + for (int i = 0; i <= n2 - 1; i++) { + for (int j = 0; j <= n1 - 1; j++) { + offsa = aoffset + i * n1; + hk = (*a)[offsa + j]; + hnk = (*a)[offsa + (n1 - j) % n1]; + offs = 2 * (i * n1 + j); + tmpb[offs + 0] = -0.5 * (hnk - hk); + tmpb[offs + 1] = 0.5 * (hk + hnk); + } + } + ftbase_ffttwcalc(&(curplan.tmpbuf), 0, n1, n2); + for (int j = 0; j <= n1 - 1; j++) + (*a)[aoffset + j] = tmpb[2 * j + 0] + tmpb[2 * j + 1]; + if (n2 % 2 == 0) { + offs = 2 * (n2 / 2) * n1; + offsa = aoffset + n2 / 2 * n1; + for (int j = 0; j <= n1 - 1; j++) + (*a)[offsa + j] = tmpb[offs + 2 * j + 0] + tmpb[offs + 2 * j + 1]; + } + for (int i = 1; i <= (n2 + 1) / 2 - 1; i++) { + offs = 2 * i * n1; + offs2 = 2 * (n2 - i) * n1; + offsa = aoffset + i * n1; + for (int j = 0; j <= n1 - 1; j++) + (*a)[offsa + j] = tmpb[offs + 2 * j + 1] + tmpb[offs2 + 2 * j + 0]; + offsa = aoffset + (n2 - i) * n1; + for (int j = 0; j <= n1 - 1; j++) + (*a)[offsa + j] = tmpb[offs + 2 * j + 0] + tmpb[offs2 + 2 * j + 1]; + } + ftbase_internalreallintranspose(a, n2, n1, aoffset, &(curplan.tmpbuf)); + for (int i = 0; i <= n1 - 1; i++) + ftbaseexecuteplanrec(a, aoffset + i * n2, plan, curplan.plan[entryoffset + 6], stackptr); + ftbase_internalreallintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf)); + return; + } + if (curplan.plan[entryoffset + 3] == ftbase_fftcodeletplan) { + n1 = curplan.plan[entryoffset + 1]; + n2 = curplan.plan[entryoffset + 2]; + n = n1 * n2; + if (n == 2) { + a0x = (*a)[aoffset + 0]; + a0y = (*a)[aoffset + 1]; + a1x = (*a)[aoffset + 2]; + a1y = (*a)[aoffset + 3]; + v0 = a0x + a1x; + v1 = a0y + a1y; + v2 = a0x - a1x; + v3 = a0y - a1y; + (*a)[aoffset + 0] = v0; + (*a)[aoffset + 1] = v1; + (*a)[aoffset + 2] = v2; + (*a)[aoffset + 3] = v3; + return; + } + if (n == 3) { + offs = curplan.plan[entryoffset + 7]; + c1 = curplan.precomputed[offs + 0]; + c2 = curplan.precomputed[offs + 1]; + a0x = (*a)[aoffset + 0]; + a0y = (*a)[aoffset + 1]; + a1x = (*a)[aoffset + 2]; + a1y = (*a)[aoffset + 3]; + a2x = (*a)[aoffset + 4]; + a2y = (*a)[aoffset + 5]; + t1x = a1x + a2x; + t1y = a1y + a2y; + a0x = a0x + t1x; + a0y = a0y + t1y; + m1x = c1 * t1x; + m1y = c1 * t1y; + m2x = c2 * (a1y - a2y); + m2y = c2 * (a2x - a1x); + s1x = a0x + m1x; + s1y = a0y + m1y; + a1x = s1x + m2x; + a1y = s1y + m2y; + a2x = s1x - m2x; + a2y = s1y - m2y; + (*a)[aoffset + 0] = a0x; + (*a)[aoffset + 1] = a0y; + (*a)[aoffset + 2] = a1x; + (*a)[aoffset + 3] = a1y; + (*a)[aoffset + 4] = a2x; + (*a)[aoffset + 5] = a2y; + return; + } + if (n == 4) { + a0x = (*a)[aoffset + 0]; + a0y = (*a)[aoffset + 1]; + a1x = (*a)[aoffset + 2]; + a1y = (*a)[aoffset + 3]; + a2x = (*a)[aoffset + 4]; + a2y = (*a)[aoffset + 5]; + a3x = (*a)[aoffset + 6]; + a3y = (*a)[aoffset + 7]; + t1x = a0x + a2x; + t1y = a0y + a2y; + t2x = a1x + a3x; + t2y = a1y + a3y; + m2x = a0x - a2x; + m2y = a0y - a2y; + m3x = a1y - a3y; + m3y = a3x - a1x; + (*a)[aoffset + 0] = t1x + t2x; + (*a)[aoffset + 1] = t1y + t2y; + (*a)[aoffset + 4] = t1x - t2x; + (*a)[aoffset + 5] = t1y - t2y; + (*a)[aoffset + 2] = m2x + m3x; + (*a)[aoffset + 3] = m2y + m3y; + (*a)[aoffset + 6] = m2x - m3x; + (*a)[aoffset + 7] = m2y - m3y; + return; + } + if (n == 5) { + offs = curplan.plan[entryoffset + 7]; + c1 = curplan.precomputed[offs + 0]; + c2 = curplan.precomputed[offs + 1]; + c3 = curplan.precomputed[offs + 2]; + c4 = curplan.precomputed[offs + 3]; + c5 = curplan.precomputed[offs + 4]; + t1x = (*a)[aoffset + 2] + (*a)[aoffset + 8]; + t1y = (*a)[aoffset + 3] + (*a)[aoffset + 9]; + t2x = (*a)[aoffset + 4] + (*a)[aoffset + 6]; + t2y = (*a)[aoffset + 5] + (*a)[aoffset + 7]; + t3x = (*a)[aoffset + 2] - (*a)[aoffset + 8]; + t3y = (*a)[aoffset + 3] - (*a)[aoffset + 9]; + t4x = (*a)[aoffset + 6] - (*a)[aoffset + 4]; + t4y = (*a)[aoffset + 7] - (*a)[aoffset + 5]; + t5x = t1x + t2x; + t5y = t1y + t2y; + (*a)[aoffset + 0] = (*a)[aoffset + 0] + t5x; + (*a)[aoffset + 1] = (*a)[aoffset + 1] + t5y; + m1x = c1 * t5x; + m1y = c1 * t5y; + m2x = c2 * (t1x - t2x); + m2y = c2 * (t1y - t2y); + m3x = -c3 * (t3y + t4y); + m3y = c3 * (t3x + t4x); + m4x = -c4 * t4y; + m4y = c4 * t4x; + m5x = -c5 * t3y; + m5y = c5 * t3x; + s3x = m3x - m4x; + s3y = m3y - m4y; + s5x = m3x + m5x; + s5y = m3y + m5y; + s1x = (*a)[aoffset + 0] + m1x; + s1y = (*a)[aoffset + 1] + m1y; + s2x = s1x + m2x; + s2y = s1y + m2y; + s4x = s1x - m2x; + s4y = s1y - m2y; + (*a)[aoffset + 2] = s2x + s3x; + (*a)[aoffset + 3] = s2y + s3y; + (*a)[aoffset + 4] = s4x + s5x; + (*a)[aoffset + 5] = s4y + s5y; + (*a)[aoffset + 6] = s4x - s5x; + (*a)[aoffset + 7] = s4y - s5y; + (*a)[aoffset + 8] = s2x - s3x; + (*a)[aoffset + 9] = s2y - s3y; + return; + } + } + if (curplan.plan[entryoffset + 3] == ftbase_fhtcodeletplan) { + n1 = curplan.plan[entryoffset + 1]; + n2 = curplan.plan[entryoffset + 2]; + n = n1 * n2; + if (n == 2) { + a0x = (*a)[aoffset + 0]; + a1x = (*a)[aoffset + 1]; + (*a)[aoffset + 0] = a0x + a1x; + (*a)[aoffset + 1] = a0x - a1x; + return; + } + if (n == 3) { + offs = curplan.plan[entryoffset + 7]; + c1 = curplan.precomputed[offs + 0]; + c2 = curplan.precomputed[offs + 1]; + a0x = (*a)[aoffset + 0]; + a1x = (*a)[aoffset + 1]; + a2x = (*a)[aoffset + 2]; + t1x = a1x + a2x; + a0x = a0x + t1x; + m1x = c1 * t1x; + m2y = c2 * (a2x - a1x); + s1x = a0x + m1x; + (*a)[aoffset + 0] = a0x; + (*a)[aoffset + 1] = s1x - m2y; + (*a)[aoffset + 2] = s1x + m2y; + return; + } + if (n == 4) { + a0x = (*a)[aoffset + 0]; + a1x = (*a)[aoffset + 1]; + a2x = (*a)[aoffset + 2]; + a3x = (*a)[aoffset + 3]; + t1x = a0x + a2x; + t2x = a1x + a3x; + m2x = a0x - a2x; + m3y = a3x - a1x; + (*a)[aoffset + 0] = t1x + t2x; + (*a)[aoffset + 1] = m2x - m3y; + (*a)[aoffset + 2] = t1x - t2x; + (*a)[aoffset + 3] = m2x + m3y; + return; + } + if (n == 5) { + offs = curplan.plan[entryoffset + 7]; + c1 = curplan.precomputed[offs + 0]; + c2 = curplan.precomputed[offs + 1]; + c3 = curplan.precomputed[offs + 2]; + c4 = curplan.precomputed[offs + 3]; + c5 = curplan.precomputed[offs + 4]; + t1x = (*a)[aoffset + 1] + (*a)[aoffset + 4]; + t2x = (*a)[aoffset + 2] + (*a)[aoffset + 3]; + t3x = (*a)[aoffset + 1] - (*a)[aoffset + 4]; + t4x = (*a)[aoffset + 3] - (*a)[aoffset + 2]; + t5x = t1x + t2x; + v0 = (*a)[aoffset + 0] + t5x; + (*a)[aoffset + 0] = v0; + m2x = c2 * (t1x - t2x); + m3y = c3 * (t3x + t4x); + s3y = m3y - c4 * t4x; + s5y = m3y + c5 * t3x; + s1x = v0 + c1 * t5x; + s2x = s1x + m2x; + s4x = s1x - m2x; + (*a)[aoffset + 1] = s2x - s3y; + (*a)[aoffset + 2] = s4x - s5y; + (*a)[aoffset + 3] = s4x + s5y; + (*a)[aoffset + 4] = s2x + s3y; + return; + } + } + if (curplan.plan[entryoffset + 3] == ftbase_fftbluesteinplan) { + n = curplan.plan[entryoffset + 1]; + m = curplan.plan[entryoffset + 4]; + offs = curplan.plan[entryoffset + 7]; + for (int i = stackptr + 2 * n; i <= stackptr + 2 * m - 1; i++) + curplan.stackbuf[i] = 0; + offsp = offs + 2 * m; + offsa = aoffset; + offsb = stackptr; + for (int i = 0; i < n; i++) { + bx = curplan.precomputed[offsp + 0]; + by = curplan.precomputed[offsp + 1]; + x = (*a)[offsa + 0]; + y = (*a)[offsa + 1]; + curplan.stackbuf[offsb + 0] = x * bx - y * (-by); + curplan.stackbuf[offsb + 1] = x * (-by) + y * bx; + offsp = offsp + 2; + offsa = offsa + 2; + offsb = offsb + 2; + } + ftbaseexecuteplanrec(&curplan.stackbuf, stackptr, plan, curplan.plan[entryoffset + 5], stackptr + 2 * 2 * m); + offsb = stackptr; + offsp = offs; + for (int i = 0; i <= m - 1; i++) { + x = curplan.stackbuf[offsb + 0]; + y = curplan.stackbuf[offsb + 1]; + bx = curplan.precomputed[offsp + 0]; + by = curplan.precomputed[offsp + 1]; + curplan.stackbuf[offsb + 0] = x * bx - y * by; + curplan.stackbuf[offsb + 1] = -(x * by + y * bx); + offsb = offsb + 2; + offsp = offsp + 2; + } + ftbaseexecuteplanrec(&curplan.stackbuf, stackptr, plan, curplan.plan[entryoffset + 5], stackptr + 2 * 2 * m); + offsb = stackptr; + offsp = offs + 2 * m; + offsa = aoffset; + for (int i = 0; i < n; i++) { + x = curplan.stackbuf[offsb + 0] / m; + y = -curplan.stackbuf[offsb + 1] / m; + bx = curplan.precomputed[offsp + 0]; + by = curplan.precomputed[offsp + 1]; + (*a)[offsa + 0] = x * bx - y * (-by); + (*a)[offsa + 1] = x * (-by) + y * bx; + offsp = offsp + 2; + offsa = offsa + 2; + offsb = offsb + 2; + } + return; + } +} + + +/************************************************************************* +Twiddle factors calculation + +-- ALGLIB -- + Copyright 01.05.2009 by Bochkanov Sergey +*************************************************************************/ +void PIFFT::ftbase_ffttwcalc(PIVector * a, int aoffset, int n1, int n2) { + int n, idx, offs; + double x, y, twxm1, twy, twbasexm1, twbasey, twrowxm1, twrowy, tmpx, tmpy, v; + int ftbase_ftbaseupdatetw = 4; + n = n1 * n2; + v = -2 * M_PI / n; + twbasexm1 = -2 * sqr(sin(0.5 * v)); + twbasey = sin(v); + twrowxm1 = 0; + twrowy = 0; + for (int i = 0, j = 0; i <= n2 - 1; i++) { + twxm1 = 0; + twy = 0; + for (j = 0; j <= n1 - 1; j++) { + idx = i * n1 + j; + offs = aoffset + 2 * idx; + x = (*a)[offs + 0]; + y = (*a)[offs + 1]; + tmpx = x * twxm1 - y * twy; + tmpy = x * twy + y * twxm1; + (*a)[offs + 0] = x + tmpx; + (*a)[offs + 1] = y + tmpy; + if (j < n1 - 1) { + if (j % ftbase_ftbaseupdatetw == 0) { + v = -2 * M_PI * i * (j + 1) / n; + twxm1 = -2 * sqr(sin(0.5 * v)); + twy = sin(v); + } else { + tmpx = twrowxm1 + twxm1 * twrowxm1 - twy * twrowy; + tmpy = twrowy + twxm1 * twrowy + twy * twrowxm1; + twxm1 = twxm1 + tmpx; + twy = twy + tmpy; + } + } + } + + if (i < n2 - 1) { + if (j % ftbase_ftbaseupdatetw == 0) { + v = -2 * M_PI * (i + 1) / n; + twrowxm1 = -2 * sqr(sin(0.5 * v)); + twrowy = sin(v); + } else { + tmpx = twbasexm1 + twrowxm1 * twbasexm1 - twrowy * twbasey; + tmpy = twbasey + twrowxm1 * twbasey + twrowy * twbasexm1; + twrowxm1 = twrowxm1 + tmpx; + twrowy = twrowy + tmpy; + } + } + } +} diff --git a/src/math/pifft.h b/src/math/pifft.h new file mode 100644 index 00000000..4cdb8642 --- /dev/null +++ b/src/math/pifft.h @@ -0,0 +1,77 @@ +/*! \file pifft.h + * \brief Class for FFT, IFFT and Hilbert transformations +*/ +/* + PIP - Platform Independent Primitives + Class for FFT, IFFT and Hilbert transformations + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com, Andrey Bychkov work.a.b@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIFFT_H +#define PIFFT_H + +#include "pimathbase.h" + +class PIP_EXPORT PIFFT +{ +public: + PIFFT(); + + PIVector * calcFFT(const PIVector &val); + PIVector * calcFFT(const PIVector &val); + PIVector * calcFFTinverse(const PIVector &val); + PIVector * calcHilbert(const PIVector &val); + PIVector getAmplitude(); + +private: + PIVector result; + bool prepared; + typedef ptrdiff_t ae_int_t; + void calc_coefs(uint cnt2); + void calc_indexes(uint cnt2, uint deep2); + complexd coef(uint n, uint k); + + struct ftplan { + PIVector plan; + PIVector precomputed; + PIVector tmpbuf; + PIVector stackbuf; + }; + + ftplan curplan; + + void fftc1d(const PIVector &a, uint n); + void fftc1r(const PIVector &a, uint n); + void fftc1dinv(const PIVector &a, uint n); + + void createPlan(uint n); + void ftbasegeneratecomplexfftplan(uint n, ftplan *plan); + void ftbase_ftbasegenerateplanrec(int n, int tasktype, ftplan *plan, int *plansize, int *precomputedsize, int *planarraysize, int *tmpmemsize, int *stackmemsize, ae_int_t stackptr, int debugi=0); + void ftbase_ftbaseprecomputeplanrec(ftplan *plan, int entryoffset, ae_int_t stackptr); + void ftbasefactorize(int n, int *n1, int *n2); + void ftbase_ftbasefindsmoothrec(int n, int seed, int leastfactor, int *best); + int ftbasefindsmooth(int n); + void ftbaseexecuteplan(PIVector *a, int aoffset, int n, ftplan *plan); + void ftbaseexecuteplanrec(PIVector *a, int aoffset, ftplan *plan, int entryoffset, ae_int_t stackptr); + void ftbase_internalcomplexlintranspose(PIVector *a, int m, int n, int astart, PIVector *buf); + void ftbase_ffticltrec(PIVector *a, int astart, int astride, PIVector *b, int bstart, int bstride, int m, int n); + void ftbase_internalreallintranspose(PIVector *a, int m, int n, int astart, PIVector *buf); + void ftbase_fftirltrec(PIVector *a, int astart, int astride, PIVector *b, int bstart, int bstride, int m, int n); + void ftbase_ffttwcalc(PIVector *a, int aoffset, int n1, int n2); + +}; + +#endif // PIFFT_H diff --git a/src/math/pimath.h b/src/math/pimath.h new file mode 100644 index 00000000..b9283cf3 --- /dev/null +++ b/src/math/pimath.h @@ -0,0 +1,30 @@ +/*! \file pimath.h + * \brief Many mathematical functions and classes +*/ +/* + PIP - Platform Independent Primitives + Many mathematical functions and classes + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIMATH_H +#define PIMATH_H + +#include "pimathsolver.h" +#include "pistatistic.h" +#include "pifft.h" + +#endif // PIMATH_H diff --git a/src/math/pimathbase.cpp b/src/math/pimathbase.cpp new file mode 100644 index 00000000..36602de0 --- /dev/null +++ b/src/math/pimathbase.cpp @@ -0,0 +1,468 @@ +/* + PIP - Platform Independent Primitives + Basic mathematical functions and defines + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pimathbase.h" + + +double piJ0(const double & v) { +#ifndef PIP_MATH_J0 + double x = v; + double xsq; + double nn; + double pzero; + double qzero; + double p1; + double q1; + double result; + if (x < 0) x = -x; + if (x > 8.) { + double xsq_; + double p2; + double q2; + double p3; + double q3; + xsq_ = 64. / (x * x); + p2 = 0.0; + p2 = 2485.271928957404011288128951 + xsq_ * p2; + p2 = 153982.6532623911470917825993 + xsq_ * p2; + p2 = 2016135.283049983642487182349 + xsq_ * p2; + p2 = 8413041.456550439208464315611 + xsq_ * p2; + p2 = 12332384.76817638145232406055 + xsq_ * p2; + p2 = 5393485.083869438325262122897 + xsq_ * p2; + q2 = 1.0; + q2 = 2615.700736920839685159081813 + xsq_ * q2; + q2 = 156001.7276940030940592769933 + xsq_ * q2; + q2 = 2025066.801570134013891035236 + xsq_ * q2; + q2 = 8426449.050629797331554404810 + xsq_ * q2; + q2 = 12338310.22786324960844856182 + xsq_ * q2; + q2 = 5393485.083869438325560444960 + xsq_ * q2; + p3 = -0.0; + p3 = -4.887199395841261531199129300 +xsq_ * p3; + p3 = -226.2630641933704113967255053 +xsq_ * p3; + p3 = -2365.956170779108192723612816 +xsq_ * p3; + p3 = -8239.066313485606568803548860 +xsq_ * p3; + p3 = -10381.41698748464093880530341 +xsq_ * p3; + p3 = -3984.617357595222463506790588 +xsq_ * p3; + q3 = 1.0; + q3 = 408.7714673983499223402830260 + xsq_ * q3; + q3 = 15704.89191515395519392882766 + xsq_ * q3; + q3 = 156021.3206679291652539287109 + xsq_ * q3; + q3 = 533291.3634216897168722255057 + xsq_ * q3; + q3 = 666745.4239319826986004038103 + xsq_ * q3; + q3 = 255015.5108860942382983170882 + xsq_ * q3; + pzero = p2 / q2; + qzero = 8. * p3 / q3 / x; + nn = x- M_PI / 4.; + result = sqrt(2. / M_PI / x) * (pzero * cos(nn) - qzero * sin(nn)); + return result; + } + xsq = x * x; + p1 = 26857.86856980014981415848441; + p1 = -40504123.71833132706360663322 + xsq * p1; + p1 = 25071582855.36881945555156435 + xsq * p1; + p1 = -8085222034853.793871199468171 + xsq * p1; + p1 = 1434354939140344.111664316553 + xsq * p1; + p1 = -136762035308817138.6865416609 + xsq * p1; + p1 = 6382059341072356562.289432465 + xsq * p1; + p1 = -117915762910761053603.8440800 + xsq * p1; + p1 = 493378725179413356181.6813446 + xsq * p1; + q1 = 1.; + q1 = 1363.063652328970604442810507 + xsq * q1; + q1 = 1114636.098462985378182402543 + xsq * q1; + q1 = 669998767.2982239671814028660 + xsq * q1; + q1 = 312304311494.1213172572469442 + xsq * q1; + q1 = 112775673967979.8507056031594 + xsq * q1; + q1 = 30246356167094626.98627330784 + xsq * q1; + q1 = 5428918384092285160.200195092 + xsq * q1; + q1 = 493378725179413356211.3278438 + xsq * q1; + return p1 / q1; +#else + return j0(v); +#endif +} + + +double piJ1(const double & v) { +#ifndef PIP_MATH_J1 + double x = v; + double s; + double xsq; + double nn; + double pzero; + double qzero; + double p1; + double q1; + double result; + s = sign(x); + if (x < 0) + x = -x; + if (x > 8.) { + double xsq_; + double p2; + double q2; + double p3; + double q3; + xsq_ = 64.0 / (x * x); + p2 = -1611.616644324610116477412898; + p2 = -109824.0554345934672737413139 + xsq_ * p2; + p2 = -1523529.351181137383255105722 + xsq_ * p2; + p2 = -6603373.248364939109255245434 + xsq_ * p2; + p2 = -9942246.505077641195658377899 + xsq_ * p2; + p2 = -4435757.816794127857114720794 + xsq_ * p2; + q2 = 1.0; + q2 = -1455.009440190496182453565068 + xsq_ * q2; + q2 = -107263.8599110382011903063867 + xsq_ * q2; + q2 = -1511809.506634160881644546358 + xsq_ * q2; + q2 = -6585339.479723087072826915069 + xsq_ * q2; + q2 = -9934124.389934585658967556309 + xsq_ * q2; + q2 = -4435757.816794127856828016962 + xsq_ * q2; + p3 = 35.26513384663603218592175580; + p3 = 1706.375429020768002061283546 + xsq_ * p3; + p3 = 18494.26287322386679652009819 + xsq_ * p3; + p3 = 66178.83658127083517939992166 + xsq_ * p3; + p3 = 85145.16067533570196555001171 + xsq_ * p3; + p3 = 33220.91340985722351859704442 + xsq_ * p3; + q3 = 1.0; + q3 = 863.8367769604990967475517183 + xsq_ * q3; + q3 = 37890.22974577220264142952256 + xsq_ * q3; + q3 = 400294.4358226697511708610813 + xsq_ * q3; + q3 = 1419460.669603720892855755253 + xsq_ * q3; + q3 = 1819458.042243997298924553839 + xsq_ * q3; + q3 = 708712.8194102874357377502472 + xsq_ * q3; + pzero = p2 / q2; + qzero = 8 * p3 / q3 / x; + nn = x - 3 * M_PI / 4; + result = sqrt(2 / M_PI / x) * (pzero * cos(nn) - qzero * sin(nn)); + if (s < 0) + result = -result; + return result; + } + xsq = sqr(x); + p1 = 2701.122710892323414856790990; + p1 = -4695753.530642995859767162166 + xsq * p1; + p1 = 3413234182.301700539091292655 + xsq * p1; + p1 = -1322983480332.126453125473247 + xsq * p1; + p1 = 290879526383477.5409737601689 + xsq * p1; + p1 = -35888175699101060.50743641413 + xsq * p1; + p1 = 2316433580634002297.931815435 + xsq * p1; + p1 = -66721065689249162980.20941484 + xsq * p1; + p1 = 581199354001606143928.050809 + xsq * p1; + q1 = 1.0; + q1 = 1606.931573481487801970916749 + xsq * q1; + q1 = 1501793.594998585505921097578 + xsq * q1; + q1 = 1013863514.358673989967045588 + xsq * q1; + q1 = 524371026216.7649715406728642 + xsq * q1; + q1 = 208166122130760.7351240184229 + xsq * q1; + q1 = 60920613989175217.46105196863 + xsq * q1; + q1 = 11857707121903209998.37113348 + xsq * q1; + q1 = 1162398708003212287858.529400 + xsq * q1; + result = s * x * p1 / q1; + return result; +#else + return j1(v); +#endif +} + + +double piJn(int n, const double & v) { +#ifndef PIP_MATH_JN + double x = v; + double pkm2; + double pkm1; + double pk; + double xk; + double r; + double ans; + int k; + int sg; + double result; + if (n < 0) { + n = -n; + if (n % 2 == 0) + sg = 1; + else + sg = -1; + } else + sg = 1; + if (x < 0) { + if (n % 2 != 0) + sg = -sg; + x = -x; + } + if (n == 0) { + result = sg * piJ0(x); + return result; + } + if (n == 1) { + result = sg * piJ1(x); + return result; + } + if (n == 2) { + if (x == 0) + result = 0; + else + result = sg * (2.0 * piJ1(x) / x - piJ0(x)); + return result; + } + if (x < 1E-16) { + result = 0; + return result; + } + k = 53; + pk = 2 * (n + k); + ans = pk; + xk = x * x; + do { + pk = pk - 2.0; + ans = pk - xk / ans; + k = k - 1; + } while (k != 0); + ans = x / ans; + pk = 1.0; + pkm1 = 1.0 / ans; + k = n - 1; + r = 2 * k; + do { + pkm2 = (pkm1 * r - pk * x) / x; + pk = pkm1; + pkm1 = pkm2; + r = r - 2.0; + k = k - 1; + } while (k != 0); + if (fabs(pk) > fabs(pkm1)) + ans = piJ1(x) / pk; + else + ans = piJ0(x) / pkm1; + result = sg * ans; + return result; +#else + return jn(n, v); +#endif +} + + +double piY0(const double & v) { +#ifndef PIP_MATH_Y0 + double x = v; + double nn; + double xsq; + double pzero; + double qzero; + double p4; + double q4; + double result; + if (x > 8.) { + double xsq_; + double p2; + double q2; + double p3; + double q3; + xsq_ = 64.0 / (x * x); + p2 = 0.0; + p2 = 2485.271928957404011288128951 + xsq_ * p2; + p2 = 153982.6532623911470917825993 + xsq_ * p2; + p2 = 2016135.283049983642487182349 + xsq_ * p2; + p2 = 8413041.456550439208464315611 + xsq_ * p2; + p2 = 12332384.76817638145232406055 + xsq_ * p2; + p2 = 5393485.083869438325262122897 + xsq_ * p2; + q2 = 1.0; + q2 = 2615.700736920839685159081813 + xsq_ * q2; + q2 = 156001.7276940030940592769933 + xsq_ * q2; + q2 = 2025066.801570134013891035236 + xsq_ * q2; + q2 = 8426449.050629797331554404810 + xsq_ * q2; + q2 = 12338310.22786324960844856182 + xsq_ * q2; + q2 = 5393485.083869438325560444960 + xsq_ * q2; + p3 = -0.0; + p3 = -4.887199395841261531199129300 + xsq_ * p3; + p3 = -226.2630641933704113967255053 + xsq_ * p3; + p3 = -2365.956170779108192723612816 + xsq_ * p3; + p3 = -8239.066313485606568803548860 + xsq_ * p3; + p3 = -10381.41698748464093880530341 + xsq_ * p3; + p3 = -3984.617357595222463506790588 + xsq_ * p3; + q3 = 1.0; + q3 = 408.7714673983499223402830260 + xsq_ * q3; + q3 = 15704.89191515395519392882766 + xsq_ * q3; + q3 = 156021.3206679291652539287109 + xsq_ * q3; + q3 = 533291.3634216897168722255057 + xsq_ * q3; + q3 = 666745.4239319826986004038103 + xsq_ * q3; + q3 = 255015.5108860942382983170882 + xsq_ * q3; + pzero = p2 / q2; + qzero = 8 * p3 / q3 / x; + nn = x - M_PI / 4; + result = sqrt(2 / M_PI / x) * (pzero * sin(nn) + qzero * cos(nn)); + return result; + } + xsq = sqr(x); + p4 = -41370.35497933148554125235152; + p4 = 59152134.65686889654273830069 + xsq * p4; + p4 = -34363712229.79040378171030138 + xsq * p4; + p4 = 10255208596863.94284509167421 + xsq * p4; + p4 = -1648605817185729.473122082537 + xsq * p4; + p4 = 137562431639934407.8571335453 + xsq * p4; + p4 = -5247065581112764941.297350814 + xsq * p4; + p4 = 65874732757195549259.99402049 + xsq * p4; + p4 = -27502866786291095837.01933175 + xsq * p4; + q4 = 1.0; + q4 = 1282.452772478993804176329391 + xsq * q4; + q4 = 1001702.641288906265666651753 + xsq * q4; + q4 = 579512264.0700729537480087915 + xsq * q4; + q4 = 261306575504.1081249568482092 + xsq * q4; + q4 = 91620380340751.85262489147968 + xsq * q4; + q4 = 23928830434997818.57439356652 + xsq * q4; + q4 = 4192417043410839973.904769661 + xsq * q4; + q4 = 372645883898616588198.9980 + xsq * q4; + result = p4 / q4 + 2 / M_PI * piJ0(x) * log(x); + return result; +#else + return y0(v); +#endif +} + + +double piY1(const double & v) { +#ifndef PIP_MATH_Y1 + double x = v; + double nn; + double xsq; + double pzero; + double qzero; + double p4; + double q4; + double result; + if (x > 8.) { + double xsq_; + double p2; + double q2; + double p3; + double q3; + xsq_ = 64.0 / (x * x); + p2 = -1611.616644324610116477412898; + p2 = -109824.0554345934672737413139 + xsq_ * p2; + p2 = -1523529.351181137383255105722 + xsq_ * p2; + p2 = -6603373.248364939109255245434 + xsq_ * p2; + p2 = -9942246.505077641195658377899 + xsq_ * p2; + p2 = -4435757.816794127857114720794 + xsq_ * p2; + q2 = 1.0; + q2 = -1455.009440190496182453565068 + xsq_ * q2; + q2 = -107263.8599110382011903063867 + xsq_ * q2; + q2 = -1511809.506634160881644546358 + xsq_ * q2; + q2 = -6585339.479723087072826915069 + xsq_ * q2; + q2 = -9934124.389934585658967556309 + xsq_ * q2; + q2 = -4435757.816794127856828016962 + xsq_ * q2; + p3 = 35.26513384663603218592175580; + p3 = 1706.375429020768002061283546 + xsq_ * p3; + p3 = 18494.26287322386679652009819 + xsq_ * p3; + p3 = 66178.83658127083517939992166 + xsq_ * p3; + p3 = 85145.16067533570196555001171 + xsq_ * p3; + p3 = 33220.91340985722351859704442 + xsq_ * p3; + q3 = 1.0; + q3 = 863.8367769604990967475517183 + xsq_ * q3; + q3 = 37890.22974577220264142952256 + xsq_ * q3; + q3 = 400294.4358226697511708610813 + xsq_ * q3; + q3 = 1419460.669603720892855755253 + xsq_ * q3; + q3 = 1819458.042243997298924553839 + xsq_ * q3; + q3 = 708712.8194102874357377502472 + xsq_ * q3; + pzero = p2 / q2; + qzero = 8 * p3 / q3 / x; + nn = x - 3 * M_PI / 4; + result = sqrt(2 / M_PI / x) * (pzero * sin(nn) + qzero * cos(nn)); + return result; + } + xsq = sqr(x); + p4 = -2108847.540133123652824139923; + p4 = 3639488548.124002058278999428 + xsq * p4; + p4 = -2580681702194.450950541426399 + xsq * p4; + p4 = 956993023992168.3481121552788 + xsq * p4; + p4 = -196588746272214065.8820322248 + xsq * p4; + p4 = 21931073399177975921.11427556 + xsq * p4; + p4 = -1212297555414509577913.561535 + xsq * p4; + p4 = 26554738314348543268942.48968 + xsq * p4; + p4 = -99637534243069222259967.44354 + xsq * p4; + q4 = 1.0; + q4 = 1612.361029677000859332072312 + xsq * q4; + q4 = 1563282.754899580604737366452 + xsq * q4; + q4 = 1128686837.169442121732366891 + xsq * q4; + q4 = 646534088126.5275571961681500 + xsq * q4; + q4 = 297663212564727.6729292742282 + xsq * q4; + q4 = 108225825940881955.2553850180 + xsq * q4; + q4 = 29549879358971486742.90758119 + xsq * q4; + q4 = 5435310377188854170800.653097 + xsq * q4; + q4 = 508206736694124324531442.4152 + xsq * q4; + result = x * p4 / q4 + 2 / M_PI * (piJ1(x) * log(x) - 1 / x); + return result; +#else + return y1(v); +#endif +} + + +double piYn(int n, const double & v) { +#ifndef PIP_MATH_YN + int i; + double x = v; + double a; + double b; + double tmp; + double s; + double result; + s = 1; + if (n < 0) { + n = -n; + if (n % 2 != 0) + s = -1; + } + if (n == 0) { + result = piY0(x); + return result; + } + if (n == 1) { + result = s * piY1(x); + return result; + } + a = piY0(x); + b = piY1(x); + for (i = 1; i <= n - 1; i++) { + tmp = b; + b = 2 * i / x * b - a; + a = tmp; + } + result = s * b; + return result; +#else + return yn(n, v); +#endif +} + + +double randomn(double dv, double sv) { + static bool agen = false; + double s = 2., v0 = 0., v1 = 0.; + if (agen) { + agen = false; + v1 = v1 * sqrt(-2 * log(s) / s); + return v1 * sv + dv; + } + while (s > 1. || s == 0.) { + v0 = randomd(); + v1 = randomd(); + s = v0*v0 + v1*v1; + } + v0 = v0 * sqrt(-2 * log(s) / s); + return v0 * sv + dv; +} diff --git a/src/math/pimathbase.h b/src/math/pimathbase.h new file mode 100644 index 00000000..963a3bbe --- /dev/null +++ b/src/math/pimathbase.h @@ -0,0 +1,189 @@ +/*! \file pimathbase.h + * \brief Basic mathematical functions and defines +*/ +/* + PIP - Platform Independent Primitives + Basic mathematical functions and defines + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIMATHBASE_H +#define PIMATHBASE_H + +#include "piinit.h" +#include "pibytearray.h" +#ifdef QNX +# undef PIP_MATH_J0 +# undef PIP_MATH_J1 +# undef PIP_MATH_JN +# undef PIP_MATH_Y0 +# undef PIP_MATH_Y1 +# undef PIP_MATH_YN +#endif + +#ifndef M_LN2 +# define M_LN2 0.69314718055994530942 +#endif +#ifndef M_LN10 +# define M_LN10 2.30258509299404568402 +#endif +#ifndef M_SQRT2 +# define M_SQRT2 1.41421356237309514547 +#endif +#ifndef M_SQRT3 +# define M_SQRT3 1.73205080756887719318 +#endif +#ifndef M_1_SQRT2 +# define M_1_SQRT2 0.70710678118654746172 +#endif +#ifndef M_1_SQRT3 +# define M_1_SQRT3 0.57735026918962584208 +#endif +#ifndef M_PI +# define M_PI 3.14159265358979323846 +#endif +#ifndef M_2PI +# define M_2PI 6.28318530717958647692 +#endif +#ifndef M_PI_3 +# define M_PI_3 1.04719755119659774615 +#endif +#ifndef M_2PI_3 +# define M_2PI_3 2.0943951023931954923 +#endif +#ifndef M_180_PI +# define M_180_PI 57.2957795130823208768 +#endif +#ifndef M_PI_180 +# define M_PI_180 1.74532925199432957692e-2 +#endif +#ifndef M_E +# define M_E 2.7182818284590452353602874713527 +#endif +#ifndef M_LIGHT_SPEED +# define M_LIGHT_SPEED 2.99792458e+8 +#endif + +const double deg2rad = M_PI_180; +const double rad2deg = M_180_PI; + +inline int sign(const float & x) {return (x < 0.) ? -1 : (x > 0. ? 1 : 0);} +inline int sign(const double & x) {return (x < 0.) ? -1 : (x > 0. ? 1 : 0);} +inline complexd sign(const complexd & x) {return complexd(sign(x.real()), sign(x.imag()));} +inline int pow2(const int p) {return 1 << p;} +inline double sqr(const int v) {return v * v;} +inline double sqr(const float & v) {return v * v;} +inline double sqr(const double & v) {return v * v;} +inline double sinc(const double & v) {if (v == 0.) return 1.; double t = M_PI * v; return sin(t) / t;} +inline complexd round(const complexd & c) {return complexd(piRound(c.real()), piRound(c.imag()));} +inline complexd floor(const complexd & c) {return complexd(floor(c.real()), floor(c.imag()));} +inline complexd ceil(const complexd & c) {return complexd(ceil(c.real()), ceil(c.imag()));} +inline complexd atanc(const complexd & c) {return -complexd(-0.5, 1.) * log((complexd_1 + complexd_i * c) / (complexd_1 - complexd_i * c));} +inline complexd asinc(const complexd & c) {return -complexd_i * log(complexd_i * c + sqrt(complexd_1 - c * c));} +inline complexd acosc(const complexd & c) {return -complexd_i * log(c + complexd_i * sqrt(complexd_1 - c * c));} +#ifdef CC_GCC +# if CC_GCC_VERSION <= 0x025F +inline complexd tan(const complexd & c) {return sin(c) / cos(c);} +inline complexd tanh(const complexd & c) {return sinh(c) / cosh(c);} +inline complexd log2(const complexd & c) {return log(c) / M_LN2;} +inline complexd log10(const complexd & c) {return log(c) / M_LN10;} +# endif +#endif +double piJ0(const double & v); +double piJ1(const double & v); +double piJn(int n, const double & v); +double piY0(const double & v); +double piY1(const double & v); +double piYn(int n, const double & v); +inline double toDb(double val) {return 10. * log10(val);} +inline double fromDb(double val) {return pow(10., val / 10.);} +inline double toRad(double deg) {return deg * M_PI_180;} +inline double toDeg(double rad) {return rad * M_180_PI;} + +template +inline PICout operator <<(PICout s, const complex & v) {s.space(); s.setControl(0, true); s << "(" << v.real() << "; " << v.imag() << ")"; s.restoreControl(); return s;} + +// [-1 ; 1] +inline double randomd() {return (double)random() / RAND_MAX * 2. - 1.;} +// [-1 ; 1] normal +double randomn(double dv = 0., double sv = 1.); + +inline PIVector abs(const PIVector & v) { + PIVector result; + result.resize(v.size()); + for (uint i = 0; i < v.size(); i++) + result[i] = abs(v[i]); + return result; +} +inline PIVector abs(const PIVector & v) { + PIVector result; + result.resize(v.size()); + for (uint i = 0; i < v.size(); i++) + result[i] = abs(v[i]); + return result; +} + + +template +bool OLS_Linear(const PIVector > & input, T * out_a, T * out_b) { + if (input.size_s() < 2) + return false; + int n = input.size_s(); + T a_t0 = T(), a_t1 = T(), a_t2 = T(), a_t3 = T(), a_t4 = T(), a = T(), b = T(); + for (int i = 0; i < n; ++i) { + const PIPair & cv(input[i]); + a_t0 += cv.first * cv.second; + a_t1 += cv.first; + a_t2 += cv.second; + a_t3 += cv.first * cv.first; + } + a_t4 = n * a_t3 - a_t1 * a_t1; + if (a_t4 != T()) + a = (n * a_t0 - a_t1 * a_t2) / a_t4; + b = (a_t2 - a * a_t1) / n; + if (out_a != 0) *out_a = a; + if (out_b != 0) *out_b = b; + return true; +} + + +template +bool WLS_Linear(const PIVector > & input, const PIVector & weights, T * out_a, T * out_b) { + if (input.size_s() < 2) + return false; + if (input.size_s() != weights.size_s()) + return false; + int n = input.size_s(); + T a_t0 = T(), a_t1 = T(), a_t2 = T(), a_t3 = T(), a_t4 = T(), a_n = T(), a = T(), b = T(); + for (int i = 0; i < n; ++i) { + T cp = weights[i]; + const PIPair & cv(input[i]); + a_t0 += cv.first * cv.second * cp; + a_t1 += cv.first * cp; + a_t2 += cv.second * cp; + a_t3 += cv.first * cv.first * cp; + a_n += cp; + } + a_t4 = a_n * a_t3 - a_t1 * a_t1; + if (a_t4 != T()) + a = (a_n * a_t0 - a_t1 * a_t2) / a_t4; + b = (a_t2 - a * a_t1) / a_n; + if (out_a != 0) *out_a = a; + if (out_b != 0) *out_b = b; + return true; +} + +#endif // PIMATHBASE_H diff --git a/src/math/pimathmatrix.h b/src/math/pimathmatrix.h new file mode 100644 index 00000000..9156e608 --- /dev/null +++ b/src/math/pimathmatrix.h @@ -0,0 +1,504 @@ +/*! \file pimathmatrix.h + * \brief PIMathMatrix +*/ +/* + PIP - Platform Independent Primitives + PIMathMatrix + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIMATHMATRIX_H +#define PIMATHMATRIX_H + +#include "pimathvector.h" + +/// Matrix templated + +#define PIMM_FOR(r, c) for (uint c = 0; c < Cols; ++c) { for (uint r = 0; r < Rows; ++r) { +#define PIMM_FOR_WB(r, c) for (uint c = 0; c < Cols; ++c) for (uint r = 0; r < Rows; ++r) // without brakes +#define PIMM_FOR_I(r, c) for (uint r = 0; r < Rows; ++r) { for (uint c = 0; c < Cols; ++c) { +#define PIMM_FOR_I_WB(r, c) for (uint r = 0; r < Rows; ++r) for (uint c = 0; c < Cols; ++c) // without brakes +#define PIMM_FOR_C(v) for (uint v = 0; v < Cols; ++v) +#define PIMM_FOR_R(v) for (uint v = 0; v < Rows; ++v) + +#pragma pack(push, 1) +template +class PIP_EXPORT PIMathMatrixT { + typedef PIMathMatrixT _CMatrix; + typedef PIMathMatrixT _CMatrixI; + typedef PIMathVectorT _CMCol; + typedef PIMathVectorT _CMRow; +public: + PIMathMatrixT() {resize(Rows, Cols);} + PIMathMatrixT(Type fval, ...) {resize(Rows, Cols); va_list vl; va_start(vl, fval); PIMM_FOR_I_WB(r, c) m[r][c] = (r + c == 0 ? fval : va_arg(vl, Type)); va_end(vl);} + PIMathMatrixT(const PIVector & val) {resize(Rows, Cols); int i = 0; PIMM_FOR_I_WB(r, c) m[r][c] = val[i++];} + //PIMathMatrixT(const _CMatrix & o) {resize(Rows, Cols); int i = 0; PIMM_FOR_I_WB(r, c) m[r][c] = val[i++];} + + static _CMatrix identity() {_CMatrix tm = _CMatrix(); PIMM_FOR_WB(r, c) tm.m[r][c] = (c == r ? Type(1) : Type(0)); return tm;} + static _CMatrix rotation(double angle) {return _CMatrix();} + static _CMatrix rotationX(double angle) {return _CMatrix();} + static _CMatrix rotationY(double angle) {return _CMatrix();} + static _CMatrix rotationZ(double angle) {return _CMatrix();} + static _CMatrix scaleX(double factor) {return _CMatrix();} + static _CMatrix scaleY(double factor) {return _CMatrix();} + static _CMatrix scaleZ(double factor) {return _CMatrix();} + + uint cols() const {return Cols;} + uint rows() const {return Rows;} + _CMCol col(uint index) {_CMCol tv; PIMM_FOR_R(i) tv[i] = m[i][index]; return tv;} + _CMRow row(uint index) {_CMRow tv; PIMM_FOR_C(i) tv[i] = m[index][i]; return tv;} + _CMatrix & setCol(uint index, const _CMCol & v) {PIMM_FOR_R(i) m[i][index] = v[i]; return *this;} + _CMatrix & setRow(uint index, const _CMRow & v) {PIMM_FOR_C(i) m[index][i] = v[i]; return *this;} + _CMatrix & swapRows(uint r0, uint r1) {Type t; PIMM_FOR_C(i) {t = m[r0][i]; m[r0][i] = m[r1][i]; m[r1][i] = t;} return *this;} + _CMatrix & swapCols(uint c0, uint c1) {Type t; PIMM_FOR_R(i) {t = m[i][c0]; m[i][c0] = m[i][c1]; m[i][c1] = t;} return *this;} + _CMatrix & fill(const Type & v) {PIMM_FOR_WB(r, c) m[r][c] = v; return *this;} + //inline _CMatrix & set(Type fval, ...) {m[0] = fval; va_list vl; va_start(vl, fval); PIMV_FOR(i, 1) m[i] = va_arg(vl, Type); va_end(vl); return *this;} + //inline void normalize() {Type tv = length(); if (tv == Type(1)) return; PIMV_FOR(i, 0) m[i] /= tv;} + bool isSquare() const {return cols() == rows();} + bool isIdentity() const {PIMM_FOR_WB(r, c) if ((c == r) ? m[r][c] != Type(1) : m[r][c] != Type(0)) return false; return true;} + bool isNull() const {PIMM_FOR_WB(r, c) if (m[r][c] != Type(0)) return false; return true;} + + Type & at(uint row, uint col) {return m[row][col];} + Type at(uint row, uint col) const {return m[row][col];} + Type * operator [](uint row) {return m[row];} + const Type * operator [](uint row) const {return m[row];} + void operator =(const _CMatrix & sm) {memcpy(m, sm.m, sizeof(Type) * Cols * Rows);} + bool operator ==(const _CMatrix & sm) const {PIMM_FOR_WB(r, c) if (m[r][c] != sm.m[r][c]) return false; return true;} + bool operator !=(const _CMatrix & sm) const {return !(*this == sm);} + void operator +=(const _CMatrix & sm) {PIMM_FOR_WB(r, c) m[r][c] += sm.m[r][c];} + void operator -=(const _CMatrix & sm) {PIMM_FOR_WB(r, c) m[r][c] -= sm.m[r][c];} + void operator *=(const Type & v) {PIMM_FOR_WB(r, c) m[r][c] *= v;} + void operator /=(const Type & v) {PIMM_FOR_WB(r, c) m[r][c] /= v;} + _CMatrix operator -() {_CMatrix tm; PIMM_FOR_WB(r, c) tm.m[r][c] = -m[r][c]; return tm;} + _CMatrix operator +(const _CMatrix & sm) {_CMatrix tm = _CMatrix(*this); PIMM_FOR_WB(r, c) tm.m[r][c] += sm.m[r][c]; return tm;} + _CMatrix operator -(const _CMatrix & sm) {_CMatrix tm = _CMatrix(*this); PIMM_FOR_WB(r, c) tm.m[r][c] -= sm.m[r][c]; return tm;} + _CMatrix operator *(const Type & v) {_CMatrix tm = _CMatrix(*this); PIMM_FOR_WB(r, c) tm.m[r][c] *= v; return tm;} + _CMatrix operator /(const Type & v) {_CMatrix tm = _CMatrix(*this); PIMM_FOR_WB(r, c) tm.m[r][c] /= v; return tm;} + + Type determinant(bool * ok = 0) const { + _CMatrix m(*this); + bool k; + Type ret = Type(0); + m.toUpperTriangular(&k); + if (ok) *ok = k; + if (!k) return ret; + ret = Type(1); + for (uint c = 0; c < Cols; ++c) + for (uint r = 0; r < Rows; ++r) + if (r == c) + ret *= m[r][c]; + return ret; + } + + _CMatrix & toUpperTriangular(bool * ok = 0) { + if (Cols != Rows) { + if (ok != 0) *ok = false; + return *this; + } + _CMatrix smat(*this); + bool ndet; + uint crow; + Type mul; + for (uint i = 0; i < Cols; ++i) { + ndet = true; + for (uint j = 0; j < Rows; ++j) if (smat.m[i][j] != 0) ndet = false; + if (ndet) { + if (ok != 0) *ok = false; + return *this; + } + for (uint j = 0; j < Cols; ++j) if (smat.m[j][i] != 0) ndet = false; + if (ndet) { + if (ok != 0) *ok = false; + return *this; + } + } + for (uint i = 0; i < Cols; ++i) { + crow = i; + while (smat.m[i][i] == Type(0)) + smat.swapRows(i, ++crow); + for (uint j = i + 1; j < Rows; ++j) { + mul = smat.m[i][j] / smat.m[i][i]; + for (uint k = i; k < Cols; ++k) smat.m[k][j] -= mul * smat.m[k][i]; + } + if (i < Cols - 1) { + if (fabs(smat.m[i+1][i+1]) < Type(1E-100)) { + if (ok != 0) *ok = false; + return *this; + } + } + } + if (ok != 0) *ok = true; + memcpy(m, smat.m, sizeof(Type) * Cols * Rows); + return *this; + } + + _CMatrix & invert(bool * ok = 0) { + if (Cols != Rows) { + if (ok != 0) *ok = false; + return *this; + } + _CMatrix mtmp = _CMatrix::identity(), smat(*this); + bool ndet; + uint crow; + Type mul, iddiv; + for (uint i = 0; i < Cols; ++i) { + ndet = true; + for (uint j = 0; j < Rows; ++j) if (smat.m[i][j] != 0) ndet = false; + if (ndet) { + if (ok != 0) *ok = false; + return *this; + } + for (uint j = 0; j < Cols; ++j) if (smat.m[j][i] != 0) ndet = false; + if (ndet) { + if (ok != 0) *ok = false; + return *this; + } + } + for (uint i = 0; i < Cols; ++i) { + crow = i; + while (smat.m[i][i] == Type(0)) { + ++crow; + smat.swapRows(i, crow); + mtmp.swapRows(i, crow); + } + for (uint j = i + 1; j < Rows; ++j) { + mul = smat.m[i][j] / smat.m[i][i]; + for (uint k = i; k < Cols; ++k) smat.m[k][j] -= mul * smat.m[k][i]; + for (uint k = 0; k < Cols; ++k) mtmp.m[k][j] -= mul * mtmp.m[k][i]; + } + //cout << i << endl << smat << endl; + if (i < Cols - 1) { + if (fabs(smat.m[i+1][i+1]) < Type(1E-100)) { + if (ok != 0) *ok = false; + return *this; + } + } + iddiv = smat.m[i][i]; + for (uint j = i; j < Cols; ++j) smat.m[j][i] /= iddiv; + for (uint j = 0; j < Cols; ++j) mtmp.m[j][i] /= iddiv; + } + for (uint i = Cols - 1; i > 0; --i) { + for (uint j = 0; j < i; ++j) { + mul = smat.m[i][j]; + smat.m[i][j] -= mul; + for (uint k = 0; k < Cols; ++k) mtmp.m[k][j] -= mtmp.m[k][i] * mul; + } + } + if (ok != 0) *ok = true; + memcpy(m, mtmp.m, sizeof(Type) * Cols * Rows); + return *this; + } + _CMatrix inverted(bool * ok = 0) const {_CMatrix tm(*this); tm.invert(ok); return tm;} + _CMatrixI transposed() const {_CMatrixI tm; PIMM_FOR_WB(r, c) tm[r][c] = m[r][c]; return tm;} + +private: + void resize(uint rows_, uint cols_, const Type & new_value = Type()) {r_ = rows_; c_ = cols_; PIMM_FOR_WB(r, c) m[r][c] = new_value;} + int c_, r_; + Type m[Rows][Cols]; + +}; +#pragma pack(pop) + + +template<> inline PIMathMatrixT<2u, 2u> PIMathMatrixT<2u, 2u>::rotation(double angle) {double c = cos(angle), s = sin(angle); PIMathMatrixT<2u, 2u> tm; tm[0][0] = tm[1][1] = c; tm[0][1] = -s; tm[1][0] = s; return tm;} +template<> inline PIMathMatrixT<2u, 2u> PIMathMatrixT<2u, 2u>::scaleX(double factor) {PIMathMatrixT<2u, 2u> tm; tm[0][0] = factor; tm[1][1] = 1.; return tm;} +template<> inline PIMathMatrixT<2u, 2u> PIMathMatrixT<2u, 2u>::scaleY(double factor) {PIMathMatrixT<2u, 2u> tm; tm[0][0] = 1.; tm[1][1] = factor; return tm;} + +template<> inline PIMathMatrixT<3u, 3u> PIMathMatrixT<3u, 3u>::rotationX(double angle) {double c = cos(angle), s = sin(angle); PIMathMatrixT<3u, 3u> tm; tm[0][0] = 1.; tm[1][1] = tm[2][2] = c; tm[2][1] = s; tm[1][2] = -s; return tm;} +template<> inline PIMathMatrixT<3u, 3u> PIMathMatrixT<3u, 3u>::rotationY(double angle) {double c = cos(angle), s = sin(angle); PIMathMatrixT<3u, 3u> tm; tm[1][1] = 1.; tm[0][0] = tm[2][2] = c; tm[2][0] = -s; tm[0][2] = s; return tm;} +template<> inline PIMathMatrixT<3u, 3u> PIMathMatrixT<3u, 3u>::rotationZ(double angle) {double c = cos(angle), s = sin(angle); PIMathMatrixT<3u, 3u> tm; tm[2][2] = 1.; tm[0][0] = tm[1][1] = c; tm[1][0] = s; tm[0][1] = -s; return tm;} +template<> inline PIMathMatrixT<3u, 3u> PIMathMatrixT<3u, 3u>::scaleX(double factor) {PIMathMatrixT<3u, 3u> tm; tm[1][1] = tm[2][2] = 1.; tm[0][0] = factor; return tm;} +template<> inline PIMathMatrixT<3u, 3u> PIMathMatrixT<3u, 3u>::scaleY(double factor) {PIMathMatrixT<3u, 3u> tm; tm[0][0] = tm[2][2] = 1.; tm[1][1] = factor; return tm;} +template<> inline PIMathMatrixT<3u, 3u> PIMathMatrixT<3u, 3u>::scaleZ(double factor) {PIMathMatrixT<3u, 3u> tm; tm[0][0] = tm[1][1] = 1.; tm[2][2] = factor; return tm;} + +template +inline std::ostream & operator <<(std::ostream & s, const PIMathMatrixT & m) {s << '{'; PIMM_FOR_I(r, c) s << m[r][c]; if (c < Cols - 1 || r < Rows - 1) s << ", ";} if (r < Rows - 1) s << endl << ' ';} s << '}'; return s;} +template +inline PICout operator <<(PICout s, const PIMathMatrixT & m) {s << '{'; PIMM_FOR_I(r, c) s << m[r][c]; if (c < Cols - 1 || r < Rows - 1) s << ", ";} if (r < Rows - 1) s << NewLine << ' ';} s << '}'; return s;} + +/// Multiply matrices {Rows0 x CR} on {CR x Cols1}, result is {Rows0 x Cols1} +template +inline PIMathMatrixT operator *(const PIMathMatrixT & fm, + const PIMathMatrixT & sm) { + PIMathMatrixT tm; + Type t; + for (uint j = 0; j < Rows0; ++j) { + for (uint i = 0; i < Cols1; ++i) { + t = Type(0); + for (uint k = 0; k < CR; ++k) + t += fm[j][k] * sm[k][i]; + tm[j][i] = t; + } + } + return tm; +} + +/// Multiply matrix {Rows x Cols} on vector {Rows}, result is vector {Cols} +template +inline PIMathVectorT operator *(const PIMathMatrixT & fm, + const PIMathVectorT & sv) { + PIMathVectorT tv; + Type t; + for (uint j = 0; j < Rows; ++j) { + t = Type(0); + for (uint i = 0; i < Cols; ++i) + t += fm[j][i] * sv[i]; + tv[j] = t; + } + return tv; +} + +typedef PIMathMatrixT<2u, 2u, int> PIMathMatrixT22i; +typedef PIMathMatrixT<3u, 3u, int> PIMathMatrixT33i; +typedef PIMathMatrixT<4u, 4u, int> PIMathMatrixT44i; +typedef PIMathMatrixT<2u, 2u, double> PIMathMatrixT22d; +typedef PIMathMatrixT<3u, 3u, double> PIMathMatrixT33d; +typedef PIMathMatrixT<4u, 4u, double> PIMathMatrixT44d; + + +template +class PIMathMatrix; + +#undef PIMV_FOR +#undef PIMM_FOR +#undef PIMM_FOR_WB +#undef PIMM_FOR_I +#undef PIMM_FOR_I_WB +#undef PIMM_FOR_C +#undef PIMM_FOR_R + + + + + +/// Matrix + +#define PIMM_FOR(c, r) for (uint c = 0; c < cols_; ++c) { for (uint r = 0; r < rows_; ++r) { +#define PIMM_FOR_WB(c, r) for (uint c = 0; c < cols_; ++c) for (uint r = 0; r < rows_; ++r) // without brakes +#define PIMM_FOR_I(c, r) for (uint r = 0; r < rows_; ++r) { for (uint c = 0; c < cols_; ++c) { +#define PIMM_FOR_I_WB(c, r) for (uint r = 0; r < rows_; ++r) for (uint c = 0; c < cols_; ++c) // without brakes +#define PIMM_FOR_C(v) for (uint v = 0; v < cols_; ++v) +#define PIMM_FOR_R(v) for (uint v = 0; v < rows_; ++v) + +template +class PIP_EXPORT PIMathMatrix { + typedef PIMathMatrix _CMatrix; + typedef PIMathVector _CMCol; + typedef PIMathVector _CMRow; +public: + PIMathMatrix(const uint cols = 3, const uint rows = 3) {resize(cols, rows);} + PIMathMatrix(const uint cols, const uint rows, Type fval, ...) {resize(cols, rows); va_list vl; va_start(vl, fval); PIMM_FOR_I_WB(c, r) m[c][r] = (r + c == 0 ? fval : va_arg(vl, Type)); va_end(vl);} + PIMathMatrix(const uint cols, const uint rows, const PIVector & val) {resize(cols, rows); int i = 0; PIMM_FOR_I_WB(c, r) m[c][r] = val[i++];} + + static _CMatrix identity(const uint cols_, const uint rows_) {_CMatrix tm(cols_, rows_); PIMM_FOR_WB(c, r) tm.m[c][r] = (c == r ? Type(1) : Type(0)); return tm;} + + uint cols() const {return cols_;} + uint rows() const {return rows_;} + _CMCol col(uint index) {_CMCol tv; PIMM_FOR_R(i) tv[i] = m[index][i]; return tv;} + _CMRow row(uint index) {_CMRow tv; PIMM_FOR_C(i) tv[i] = m[i][index]; return tv;} + _CMatrix & resize(const uint cols, const uint rows, const Type & new_value = Type()) {cols_ = cols; rows_ = rows; m.resize(cols); PIMM_FOR_C(i) m[i].resize(rows, new_value); return *this;} + _CMatrix & setCol(uint index, const _CMCol & v) {PIMM_FOR_R(i) m[index][i] = v[i]; return *this;} + _CMatrix & setRow(uint index, const _CMRow & v) {PIMM_FOR_C(i) m[i][index] = v[i]; return *this;} + _CMatrix & swapRows(uint r0, uint r1) {Type t; PIMM_FOR_C(i) {t = m[i][r0]; m[i][r0] = m[i][r1]; m[i][r1] = t;} return *this;} + _CMatrix & swapCols(uint c0, uint c1) {Type t; PIMM_FOR_R(i) {t = m[c0][i]; m[c0][i] = m[c1][i]; m[c1][i] = t;} return *this;} + _CMatrix & fill(const Type & v) {PIMM_FOR_WB(c, r) m[c][r] = v; return *this;} + //inline _CMatrix & set(Type fval, ...) {m[0] = fval; va_list vl; va_start(vl, fval); PIMV_FOR(i, 1) m[i] = va_arg(vl, Type); va_end(vl); return *this;} + //inline void normalize() {Type tv = length(); if (tv == Type(1)) return; PIMV_FOR(i, 0) m[i] /= tv;} + bool isSquare() const {return cols() == rows();} + bool isIdentity() const {PIMM_FOR_WB(c, r) if ((c == r) ? m[c][r] != Type(1) : m[c][r] != Type(0)) return false; return true;} + bool isNull() const {PIMM_FOR_WB(c, r) if (m[c][r] != Type(0)) return false; return true;} + + Type & at(uint col, uint row) {return m[col][row];} + Type at(uint col, uint row) const {return m[col][row];} + PIVector & operator [](uint col) {return m[col];} + PIVector operator [](uint col) const {return m[col];} + void operator =(const _CMatrix & sm) {m = sm.m;} + bool operator ==(const _CMatrix & sm) const {PIMM_FOR_WB(c, r) if (m[c][r] != sm.m[c][r]) return false; return true;} + bool operator !=(const _CMatrix & sm) const {return !(*this == sm);} + void operator +=(const _CMatrix & sm) {PIMM_FOR_WB(c, r) m[c][r] += sm.m[c][r];} + void operator -=(const _CMatrix & sm) {PIMM_FOR_WB(c, r) m[c][r] -= sm.m[c][r];} + void operator *=(const Type & v) {PIMM_FOR_WB(c, r) m[c][r] *= v;} + void operator /=(const Type & v) {PIMM_FOR_WB(c, r) m[c][r] /= v;} + _CMatrix operator -() {_CMatrix tm(*this); PIMM_FOR_WB(c, r) tm.m[c][r] = -m[c][r]; return tm;} + _CMatrix operator +(const _CMatrix & sm) {_CMatrix tm(*this); PIMM_FOR_WB(c, r) tm.m[c][r] += sm.m[c][r]; return tm;} + _CMatrix operator -(const _CMatrix & sm) {_CMatrix tm(*this); PIMM_FOR_WB(c, r) tm.m[c][r] -= sm.m[c][r]; return tm;} + _CMatrix operator *(const Type & v) {_CMatrix tm(*this); PIMM_FOR_WB(c, r) tm.m[c][r] *= v; return tm;} + _CMatrix operator /(const Type & v) {_CMatrix tm(*this); PIMM_FOR_WB(c, r) tm.m[c][r] /= v; return tm;} + + _CMatrix & toUpperTriangular(bool * ok = 0) { + if (cols_ != rows_) { + if (ok != 0) *ok = false; + return *this; + } + _CMatrix smat(*this); + bool ndet; + uint crow; + Type mul; + for (uint i = 0; i < cols_; ++i) { + ndet = true; + for (uint j = 0; j < rows_; ++j) if (smat.m[i][j] != 0) ndet = false; + if (ndet) { + if (ok != 0) *ok = false; + return *this; + } + for (uint j = 0; j < cols_; ++j) if (smat.m[j][i] != 0) ndet = false; + if (ndet) { + if (ok != 0) *ok = false; + return *this; + } + } + for (uint i = 0; i < cols_; ++i) { + crow = i; + while (smat.m[i][i] == Type(0)) + smat.swapRows(i, ++crow); + for (uint j = i + 1; j < rows_; ++j) { + mul = smat.m[i][j] / smat.m[i][i]; + for (uint k = i; k < cols_; ++k) smat.m[k][j] -= mul * smat.m[k][i]; + } + if (i < cols_ - 1) { + if (fabs(smat.m[i+1][i+1]) < Type(1E-100)) { + if (ok != 0) *ok = false; + return *this; + } + } + } + if (ok != 0) *ok = true; + m = smat.m; + return *this; + } + + _CMatrix & invert(bool * ok = 0, _CMCol * sv = 0) { + if (cols_ != rows_) { + if (ok != 0) *ok = false; + return *this; + } + _CMatrix mtmp = _CMatrix::identity(cols_, rows_), smat(*this); + bool ndet; + uint crow; + Type mul, iddiv; + for (uint i = 0; i < cols_; ++i) { + ndet = true; + for (uint j = 0; j < rows_; ++j) if (smat.m[i][j] != 0) ndet = false; + if (ndet) { + if (ok != 0) *ok = false; + return *this; + } + for (uint j = 0; j < cols_; ++j) if (smat.m[j][i] != 0) ndet = false; + if (ndet) { + if (ok != 0) *ok = false; + return *this; + } + } + for (uint i = 0; i < cols_; ++i) { + crow = i; + while (smat.m[i][i] == Type(0)) { + ++crow; + smat.swapRows(i, crow); + mtmp.swapRows(i, crow); + if (sv != 0) sv->swap(i, crow); + } + for (uint j = i + 1; j < rows_; ++j) { + mul = smat.m[i][j] / smat.m[i][i]; + for (uint k = i; k < cols_; ++k) smat.m[k][j] -= mul * smat.m[k][i]; + for (uint k = 0; k < cols_; ++k) mtmp.m[k][j] -= mul * mtmp.m[k][i]; + if (sv != 0) (*sv)[j] -= mul * (*sv)[i]; + } + //cout << i << endl << smat << endl; + if (i < cols_ - 1) { + if (fabs(smat.m[i+1][i+1]) < Type(1E-100)) { + if (ok != 0) *ok = false; + return *this; + } + } + iddiv = smat.m[i][i]; + for (uint j = i; j < cols_; ++j) smat.m[j][i] /= iddiv; + for (uint j = 0; j < cols_; ++j) mtmp.m[j][i] /= iddiv; + if (sv != 0) (*sv)[i] /= iddiv; + } + for (uint i = cols_ - 1; i > 0; --i) { + for (uint j = 0; j < i; ++j) { + mul = smat.m[i][j]; + smat.m[i][j] -= mul; + for (uint k = 0; k < cols_; ++k) mtmp.m[k][j] -= mtmp.m[k][i] * mul; + if (sv != 0) (*sv)[j] -= mul * (*sv)[i]; + } + } + if (ok != 0) *ok = true; + m = mtmp.m; + return *this; + } + _CMatrix inverted(bool * ok = 0) {_CMatrix tm(*this); tm.invert(ok); return tm;} + _CMatrix transposed() {_CMatrix tm(rows_, cols_); PIMM_FOR_WB(c, r) tm[r][c] = m[c][r]; return tm;} + +private: + uint cols_, rows_; + PIVector > m; + +}; + +template +inline std::ostream & operator <<(std::ostream & s, const PIMathMatrix & m) {s << '{'; for (uint r = 0; r < m.rows(); ++r) { for (uint c = 0; c < m.cols(); ++c) { s << m[c][r]; if (c < m.cols() - 1 || r < m.rows() - 1) s << ", ";} if (r < m.rows() - 1) s << endl << ' ';} s << '}'; return s;} +template +inline PICout operator <<(PICout s, const PIMathMatrix & m) {s << '{'; for (uint r = 0; r < m.rows(); ++r) { for (uint c = 0; c < m.cols(); ++c) { s << m[c][r]; if (c < m.cols() - 1 || r < m.rows() - 1) s << ", ";} if (r < m.rows() - 1) s << NewLine << ' ';} s << '}'; return s;} + +/// Multiply matrices {CR x Rows0} on {Cols1 x CR}, result is {Cols1 x Rows0} +template +inline PIMathMatrix operator *(const PIMathMatrix & fm, + const PIMathMatrix & sm) { + uint cr = fm.cols(), rows0 = fm.rows(), cols1 = sm.cols(); + PIMathMatrix tm(cols1, rows0); + if (fm.cols() != sm.rows()) return tm; + Type t; + for (uint j = 0; j < rows0; ++j) { + for (uint i = 0; i < cols1; ++i) { + t = Type(0); + for (uint k = 0; k < cr; ++k) + t += fm[k][j] * sm[i][k]; + tm[i][j] = t; + } + } + return tm; +} + +/// Multiply matrix {Cols x Rows} on vector {Cols}, result is vector {Rows} +template +inline PIMathVector operator *(const PIMathMatrix & fm, + const PIMathVector & sv) { + uint c = fm.cols(), r = fm.rows(); + PIMathVector tv(r); + if (c != sv.size()) return tv; + Type t; + for (uint i = 0; i < r; ++i) { + t = Type(0); + for (uint j = 0; j < c; ++j) + t += fm[j][i] * sv[j]; + tv[i] = t; + } + return tv; +} + +typedef PIMathMatrix PIMathMatrixi; +typedef PIMathMatrix PIMathMatrixd; + +#undef PIMV_FOR +#undef PIMM_FOR +#undef PIMM_FOR_WB +#undef PIMM_FOR_I +#undef PIMM_FOR_I_WB +#undef PIMM_FOR_C +#undef PIMM_FOR_R + +#endif // PIMATHMATRIX_H diff --git a/src/math/pimathsolver.cpp b/src/math/pimathsolver.cpp new file mode 100644 index 00000000..1218aad7 --- /dev/null +++ b/src/math/pimathsolver.cpp @@ -0,0 +1,248 @@ +/* + PIP - Platform Independent Primitives + PIMathSolver + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pimathsolver.h" + +const char PIMathSolver::methods_desc[] = "b{Methods:}\ +\n -1 - Global settings\ +\n 01 - Eyler 1\ +\n 02 - Eyler 2\ +\n 14 - Runge-Kutta 4\ +\n 23 - Adams-Bashfort-Moulton 3\ +\n 24 - Adams-Bashfort-Moulton 4\ +\n 32 - Polynomial Approximation 2\ +\n 33 - Polynomial Approximation 3\ +\n 34 - Polynomial Approximation 4\ +\n 35 - Polynomial Approximation 5"; + +PIMathSolver::Method PIMathSolver::method_global = PIMathSolver::Eyler_2; + + +void PIMathSolver::solve(double u, double h) { + switch (method) { + case Global: + switch (method_global) { + case Eyler_1: solveEyler1(u, h); break; + case Eyler_2: solveEyler2(u, h); break; + case RungeKutta_4: solveRK4(u, h); break; + case AdamsBashfortMoulton_2: solveABM2(u, h); break; + case AdamsBashfortMoulton_3: solveABM3(u, h); break; + case AdamsBashfortMoulton_4: default: solveABM4(u, h); break; + case PolynomialApproximation_2: solvePA2(u, h); break; + case PolynomialApproximation_3: solvePA3(u, h); break; + case PolynomialApproximation_4: solvePA4(u, h); break; + case PolynomialApproximation_5: solvePA5(u, h); break; + } + break; + case Eyler_1: solveEyler1(u, h); break; + case Eyler_2: solveEyler2(u, h); break; + case RungeKutta_4: solveRK4(u, h); break; + case AdamsBashfortMoulton_2: solveABM2(u, h); break; + case AdamsBashfortMoulton_3: solveABM3(u, h); break; + case AdamsBashfortMoulton_4: default: solveABM4(u, h); break; + case PolynomialApproximation_2: solvePA2(u, h); break; + case PolynomialApproximation_3: solvePA3(u, h); break; + case PolynomialApproximation_4: solvePA4(u, h); break; + case PolynomialApproximation_5: solvePA5(u, h); break; + } + step++; +} + + +void PIMathSolver::fromTF(const TransferFunction & TF) { + if (TF.vector_An.size() >= TF.vector_Bm.size()) + size = TF.vector_An.size()-1; + else { + piCout << "PIMathSolver error: {A} should be greater than {B}"; + return; + } + if (size == 0) return; + + step = 0; + times.fill(0.); + A.resize(size, size); + d.resize(size + 1); d.fill(0.); + a1.resize(size + 1); a1.fill(0.); + b1.resize(size + 1); b1.fill(0.); + X.resize(size); X.fill(0.); + F.resize(5); + for (uint i = 0; i < 5; ++i) + F[i].resize(size), F[i].fill(0.); + k1.resize(size); k1.fill(0.); + k2.resize(size); k2.fill(0.); + k3.resize(size); k3.fill(0.); + k4.resize(size); k4.fill(0.); + xx.resize(size); xx.fill(0.); + XX.resize(size); XX.fill(0.); + for (uint i = 0; i < size + 1; ++i) + a1[size - i] = TF.vector_An[i]; + for (uint i = 0; i < TF.vector_Bm.size(); ++i) + b1[size - i] = TF.vector_Bm[i]; + double a0 = a1[0]; + a1 /= a0; + b1 /= a0; + + d[0] = b1[0]; // Ðàññ÷èòûâàåì âåêòîð d + for (uint i = 1; i < size + 1; ++i) { + sum = 0.; + for (uint m = 0; m < i; ++m) + sum += a1[i - m] * d[m]; + d[i] = b1[i] - sum; + } + + for (uint i = 0; i < size - 1; ++i) // Çàïîëíÿåì ìàòðèöó À + for (uint j = 0; j < size; ++j) + A[j][i] = (j == i + 1); + for (uint i = 0; i < size; ++i) + A[i][size - 1] = -a1[size - i]; + for (uint i = 0; i < size; ++i) + d[i] = d[i + 1]; +} + + +void PIMathSolver::solveEyler1(double u, double h) { + /*for (uint i = 0; i < size; ++i) { + * sum = 0.; + * for (uint j = 0; j < size; ++j) + * sum += A[j][i] * X[j]; + * xx[i] = sum + d[i] * u; + }*/ + F[0] = A * X + d * u; + X += F[0] * h; + moveF(); +} + + +void PIMathSolver::solveEyler2(double u, double h) { + F[0] = A * X + d * u; + X += (F[0] + F[1]) * h / 2.; + moveF(); +} + + +void PIMathSolver::solveRK4(double u, double h) { + td = X[0] - F[0][0]; + k1 = A * X + d * u; xx = k1 * h / 2.; XX = X + xx; + k2 = A * (XX + k1 * h / 2.) + d * (u + td/3.); xx = k2 * h / 2.; XX += xx; + k3 = A * (XX + k2 * h / 2.) + d * (u + td*2./3.); xx = k3 * h; XX += xx; + k4 = A * (XX + k3 * h) + d * (u + td); + //cout << k1 << k2 << k3 << k4 << endl; + X += (k1 + k2 * 2. + k3 * 2. + k4) * h / 6.; + F[0] = X; +} + + +void PIMathSolver::solveABM2(double u, double h) { + F[0] = A * X + d * u; + XX = X + (F[0] * 3. - F[1]) * (h / 2.); + F[1] = A * XX + d * u; + X += (F[1] + F[0]) * (h / 2.); + moveF(); +} + + +void PIMathSolver::solveABM3(double u, double h) { + F[0] = A * X + d * u; + XX = X + (F[0] * 23. - F[1] * 16. + F[2] * 5.) * (h / 12.); + F[2] = A * XX + d * u; + X += (F[2] * 5. + F[0] * 8. - F[1]) * (h / 12.); + moveF(); +} + + +void PIMathSolver::solveABM4(double u, double h) { + F[0] = A * X + d * u; + XX = X + (F[0] * 55. - F[1] * 59. + F[2] * 37. - F[3] * 9.) * (h / 24.); + F[3] = A * XX + d * u; + X += (F[3] * 9. + F[0] * 19. - F[1] * 5. + F[2]) * (h / 24.); + moveF(); +} + + +void PIMathSolver::solvePA(double u, double h, uint deg) { + F[0] = A * X + d * u; + M.resize(deg, deg); + Y.resize(deg); + pY.resize(deg); + + for (uint k = 0; k < size; ++k) { + for (uint i = 0; i < deg; ++i) { + td = 1.; + ct = times[i]; + for (uint j = 0; j < deg; ++j) { + M[j][i] = td; + td *= ct; + } + } + for (uint i = 0; i < deg; ++i) + Y[i] = F[i][k]; + /// find polynom + //if (step == 1) cout << M << endl << Y << endl; + M.invert(&ok, &Y); + //if (step == 1) cout << Y << endl; + if (!ok) { + solveEyler2(u, h); + break; + } + /// calc last piece + x0 = 0.; + td = 1.; + t = times[0]; + for (uint i = 0; i < deg; ++i) { + x0 += Y[i] * td / (i + 1.); + td *= t; + } + x0 *= t; + + x1 = 0.; + td = 1.; + t = times[1]; + for (uint i = 0; i < deg; ++i) { + x1 += Y[i] * td / (i + 1.); + td *= t; + } + x1 *= t; + lp = x0 - x1; + + if (deg > 2) { + /// calc prev piece + x0 = 0.; + td = 1.; + dh = times[1] - times[2]; + if (dh != 0. && step > 1) { + t = times[2]; + for (uint i = 0; i < deg; ++i) { + x0 += Y[i] * td / (i + 1.); + td *= t; + } + x0 *= t; + ct = x1 - x0; + /// calc correction + ct -= pY[k]; + } + /// calc final + X[k] += lp - ct; + pY[k] = lp; + } else { + X[k] += lp; + pY[k] = lp; + } + } + moveF(); +} diff --git a/src/math/pimathsolver.h b/src/math/pimathsolver.h new file mode 100644 index 00000000..f9b4926d --- /dev/null +++ b/src/math/pimathsolver.h @@ -0,0 +1,94 @@ +/*! \file pimathsolver.h + * \brief PIMathSolver +*/ +/* + PIP - Platform Independent Primitives + PIMathSolver + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIMATHSOLVER_H +#define PIMATHSOLVER_H + +#include "pimathmatrix.h" + +/// Differential evaluations + +struct TransferFunction { // Äëÿ çàäàíèÿ ïåðåäàòî÷íîé ôóíêöèè + PIVector vector_Bm, vector_An; +}; + +// Êëàññ, ñëóæàùèé äëÿ ïåðåâîäà ïåðåäàòî÷íîé ôóíêöèè â ñèñòåìó ÎÄÓ ïåðâîãî ïîðÿäêà +// ðåàëèçîâàíû ñëåä. ìåòîäû ðåøåíèÿ äèôô. óð-íèé: +// Ýéëåðà +// Ðóíãå-Êóòòà 4-ãî ïîðÿäêà +// Àäàìñà-Áýøôîðòñà-Ìîóëòîíà 2, 3, 4 ïîðÿäêîâ +class PIP_EXPORT PIMathSolver +{ +public: + enum Method {Global = -1, + Eyler_1 = 01, + Eyler_2 = 02, + EylerKoshi = 03, + RungeKutta_4 = 14, + AdamsBashfortMoulton_2 = 22, + AdamsBashfortMoulton_3 = 23, + AdamsBashfortMoulton_4 = 24, + PolynomialApproximation_2 = 32, + PolynomialApproximation_3 = 33, + PolynomialApproximation_4 = 34, + PolynomialApproximation_5 = 35 + }; + + PIMathSolver() {times.resize(4); step = 0;} + + void solve(double u, double h); + void fromTF(const TransferFunction & TF); + void setMethod(Method m) {method = m;} + void setTime(double time) {times.pop_back(); times.push_front(time);} + + void solveEyler1(double u, double h); + void solveEyler2(double u, double h); + void solveRK4(double u, double h); + void solveABM2(double u, double h); + void solveABM3(double u, double h); + void solveABM4(double u, double h); + void solvePA(double u, double h, uint deg); + void solvePA2(double u, double h) {if (step > 0) solvePA(u, h, 2); else solveEyler1(u, h);} + void solvePA3(double u, double h) {if (step > 1) solvePA(u, h, 3); else solvePA2(u, h);} + void solvePA4(double u, double h) {if (step > 2) solvePA(u, h, 4); else solvePA3(u, h);} + void solvePA5(double u, double h) {if (step > 3) solvePA(u, h, 5); else solvePA4(u, h);} + + PIMathVectord X; + static Method method_global; + static const char methods_desc[]; + +private: + void moveF() {for (uint i = F.size() - 1; i > 0; --i) F[i] = F[i - 1];} + + PIMathMatrixd A, M; + PIMathVectord d, a1, b1; + PIMathVectord k1, k2, k3, k4, xx; + PIMathVectord XX, Y, pY; + PIVector F; + PIVector times; + uint size, step; + Method method; + double sum, td, ct, lp, dh, t, x1, x0; + bool ok; +}; + +#endif // PIMATHSOLVER_H diff --git a/src/math/pimathvector.h b/src/math/pimathvector.h new file mode 100644 index 00000000..760b81fb --- /dev/null +++ b/src/math/pimathvector.h @@ -0,0 +1,229 @@ +/*! \file pimathvector.h + * \brief PIMathVector +*/ +/* + PIP - Platform Independent Primitives + PIMathVector + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIMATHVECTOR_H +#define PIMATHVECTOR_H + +#include "pimathbase.h" + +template +class PIMathMatrixT; + + +/// Vector templated + +#define PIMV_FOR(v, s) for (uint v = s; v < Size; ++v) + +#pragma pack(push, 1) +template +class PIP_EXPORT PIMathVectorT { + typedef PIMathVectorT _CVector; +public: + PIMathVectorT() {resize(Size);} + //PIMathVectorT(Type val) {resize(Size); PIMV_FOR(i, 0) c[i] = val;} + PIMathVectorT(Type fval, ...) {resize(Size); c[0] = fval; va_list vl; va_start(vl, fval); PIMV_FOR(i, 1) c[i] = va_arg(vl, Type); va_end(vl);} + PIMathVectorT(const PIVector & val) {resize(Size); PIMV_FOR(i, 0) c[i] = val[i];} + PIMathVectorT(const _CVector & st, const _CVector & fn) {resize(Size); set(st, fn);} + + uint size() const {return Size;} + _CVector & fill(const Type & v) {PIMV_FOR(i, 0) c[i] = v; return *this;} + _CVector & set(Type fval, ...) {c[0] = fval; va_list vl; va_start(vl, fval); PIMV_FOR(i, 1) c[i] = va_arg(vl, Type); va_end(vl); return *this;} + _CVector & set(const _CVector & st, const _CVector & fn) {PIMV_FOR(i, 0) c[i] = fn[i] - st[i]; return *this;} + _CVector & move(const Type & v) {PIMV_FOR(i, 0) c[i] += v; return *this;} + _CVector & move(const _CVector & v) {PIMV_FOR(i, 0) c[i] += v[i]; return *this;} + _CVector & move(Type fval, ...) {c[0] += fval; va_list vl; va_start(vl, fval); PIMV_FOR(i, 1) c[i] += va_arg(vl, Type); va_end(vl); return *this;} + Type lengthSqr() const {Type tv(0); PIMV_FOR(i, 0) tv += (c[i] * c[i]); return tv;} + Type length() const {return sqrt(lengthSqr());} + Type manhattanLength() const {Type tv(0); PIMV_FOR(i, 0) tv += fabs(c[i]); return tv;} + Type angleCos(const _CVector & v) const {Type tv = v.length() * length(); return (tv == Type(0) ? Type(0) : ((*this) ^ v) / tv);} + Type angleSin(const _CVector & v) const {Type tv = angleCos(v); return sqrt(Type(1) - tv * tv);} + Type angleRad(const _CVector & v) const {return acos(angleCos(v));} + Type angleDeg(const _CVector & v) const {return toDeg(acos(angleCos(v)));} + _CVector projection(const _CVector & v) {Type tv = v.length(); return (tv == Type(0) ? _CVector() : v * (((*this) ^ v) / tv));} + _CVector & normalize() {Type tv = length(); if (tv == Type(1)) return *this; if (piAbs(tv) <= Type(1E-100)) {fill(Type(0)); return *this;} PIMV_FOR(i, 0) c[i] /= tv; return *this;} + _CVector normalized() {_CVector tv(*this); tv.normalize(); return tv;} + bool isNull() const {PIMV_FOR(i, 0) if (c[i] != Type(0)) return false; return true;} + bool isOrtho(const _CVector & v) const {return ((*this) ^ v) == Type(0);} + + Type & at(uint index) {return c[index];} + Type at(uint index) const {return c[index];} + Type & operator [](uint index) {return c[index];} + Type operator [](uint index) const {return c[index];} + _CVector & operator =(const _CVector & v) {memcpy(c, v.c, sizeof(Type) * Size); return *this;} + bool operator ==(const _CVector & v) const {PIMV_FOR(i, 0) if (c[i] != v[i]) return false; return true;} + bool operator !=(const _CVector & v) const {return !(*this == c);} + void operator +=(const _CVector & v) {PIMV_FOR(i, 0) c[i] += v[i];} + void operator -=(const _CVector & v) {PIMV_FOR(i, 0) c[i] -= v[i];} + void operator *=(const Type & v) {PIMV_FOR(i, 0) c[i] *= v;} + void operator *=(const _CVector & v) {PIMV_FOR(i, 0) c[i] *= v[i];} + void operator /=(const Type & v) {PIMV_FOR(i, 0) c[i] /= v;} + void operator /=(const _CVector & v) {PIMV_FOR(i, 0) c[i] /= v[i];} + _CVector operator -() const {_CVector tv; PIMV_FOR(i, 0) tv[i] = -c[i]; return tv;} + _CVector operator +(const _CVector & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] += v[i]; return tv;} + _CVector operator -(const _CVector & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] -= v[i]; return tv;} + _CVector operator *(const Type & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] *= v; return tv;} + _CVector operator /(const Type & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] /= v; return tv;} + _CVector operator /(const _CVector & v) const {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] /= v[i]; return tv;} + _CVector operator *(const _CVector & v) const {if (Size > 3) return _CVector(); _CVector tv; tv.fill(Type(1)); tv[0] = c[1]*v[2] - v[1]*c[2]; tv[1] = v[0]*c[2] - c[0]*v[2]; tv[2] = c[0]*v[1] - v[0]*c[1]; return tv;} + Type operator ^(const _CVector & v) const {Type tv(0); PIMV_FOR(i, 0) tv += c[i] * v[i]; return tv;} + + PIMathMatrixT<1, Size, Type> transposed() const { + PIMathMatrixT<1, Size, Type> ret; + PIMV_FOR(i, 0) ret[0][i] = c[i]; + return ret; + } + + operator PIMathMatrixT<1, Size, Type>() {return transposed();} + operator PIMathMatrixT() { + PIMathMatrixT ret; + PIMV_FOR(i, 0) ret[i][0] = c[i]; + return ret; + } + Type distToLine(const _CVector & lp0, const _CVector & lp1) { + _CVector a(lp0, lp1), b(lp0, *this), c(lp1, *this); + Type f = fabs(a[0]*b[1] - a[1]*b[0]) / a.length();//, s = b.length() + c.length() - a.length(); + return f;} + + template /// vector {Size, Type} to vector {Size1, Type1} + PIMathVectorT turnTo() {PIMathVectorT tv; uint sz = piMin(Size, Size1); for (uint i = 0; i < sz; ++i) tv[i] = c[i]; return tv;} + +private: + void resize(uint size, const Type & new_value = Type()) {s = size; for (int i = 0; i < s; ++i) c[i] = new_value;} + + int s; + Type c[Size]; + +}; +#pragma pack(pop) + +template +inline std::ostream & operator <<(std::ostream & s, const PIMathVectorT & v) {s << '{'; PIMV_FOR(i, 0) {s << v[i]; if (i < Size - 1) s << ", ";} s << '}'; return s;} +template +inline PICout operator <<(PICout s, const PIMathVectorT & v) {s << '{'; PIMV_FOR(i, 0) {s << v[i]; if (i < Size - 1) s << ", ";} s << '}'; return s;} +template +inline bool operator ||(const PIMathVectorT & f, const PIMathVectorT & s) {return (f * s).isNull();} +template +inline PIMathVectorT sqrt(const PIMathVectorT & v) {PIMathVectorT ret; PIMV_FOR(i, 0) {ret[i] = sqrt(v[i]);} return ret;} +template +inline PIMathVectorT sqr(const PIMathVectorT & v) {PIMathVectorT ret; PIMV_FOR(i, 0) {ret[i] = sqr(v[i]);} return ret;} + +template +inline PIByteArray & operator <<(PIByteArray & s, const PIMathVectorT & v) {for (uint i = 0; i < Size; ++i) s << v[i]; return s;} +template +inline PIByteArray & operator >>(PIByteArray & s, PIMathVectorT & v) {for (uint i = 0; i < Size; ++i) s >> v[i]; return s;} + +//template /// vector {Size0, Type0} to vector {Size1, Type1} +//inline operator PIMathVectorT(const PIMathVectorT & v) {PIMathVectorT tv; uint sz = piMin(Size0, Size1); for (uint i = 0; i < sz; ++i) tv[i] = v[i]; return tv;} + +typedef PIMathVectorT<2u, int> PIMathVectorT2i; +typedef PIMathVectorT<3u, int> PIMathVectorT3i; +typedef PIMathVectorT<4u, int> PIMathVectorT4i; +typedef PIMathVectorT<2u, double> PIMathVectorT2d; +typedef PIMathVectorT<3u, double> PIMathVectorT3d; +typedef PIMathVectorT<4u, double> PIMathVectorT4d; + +#undef PIMV_FOR + +/// Vector + +#define PIMV_FOR(v, s) for (uint v = s; v < size_; ++v) + +template +class PIP_EXPORT PIMathVector { + typedef PIMathVector _CVector; +public: + PIMathVector(const uint size = 3) {resize(size);} + PIMathVector(const uint size, Type fval, ...) {resize(size); c[0] = fval; va_list vl; va_start(vl, fval); PIMV_FOR(i, 1) c[i] = va_arg(vl, Type); va_end(vl);} + PIMathVector(const PIVector & val) {resize(val.size()); PIMV_FOR(i, 0) c[i] = val[i];} + PIMathVector(const _CVector & st, const _CVector & fn) {resize(st.size()); PIMV_FOR(i, 0) c[i] = fn[i] - st[i];} + + uint size() const {return size_;} + _CVector & resize(uint size, const Type & new_value = Type()) {size_ = size; c.resize(size, new_value); return *this;} + _CVector resized(uint size, const Type & new_value = Type()) {_CVector tv = _CVector(*this); tv.resize(size, new_value); return tv;} + _CVector & fill(const Type & v) {PIMV_FOR(i, 0) c[i] = v; return *this;} + _CVector & set(Type fval, ...) {c[0] = fval; va_list vl; va_start(vl, fval); PIMV_FOR(i, 1) c[i] = va_arg(vl, Type); va_end(vl); return *this;} + _CVector & move(const Type & v) {PIMV_FOR(i, 0) c[i] += v; return *this;} + _CVector & move(const _CVector & v) {PIMV_FOR(i, 0) c[i] += v[i]; return *this;} + _CVector & move(Type fval, ...) {c[0] += fval; va_list vl; va_start(vl, fval); PIMV_FOR(i, 1) c[i] += va_arg(vl, Type); va_end(vl); return *this;} + _CVector & swap(uint fe, uint se) {piSwap(c[fe], c[se]); return *this;} + Type lengthSqr() const {Type tv(0); PIMV_FOR(i, 0) tv += (c[i] * c[i]); return tv;} + Type length() const {return sqrt(lengthSqr());} + Type manhattanLength() const {Type tv(0); PIMV_FOR(i, 0) tv += fabs(c[i]); return tv;} + Type angleCos(const _CVector & v) const {Type tv = v.length() * length(); return (tv == Type(0) ? Type(0) : ((*this) ^ v) / tv);} + Type angleSin(const _CVector & v) const {Type tv = angleCos(v); return sqrt(Type(1) - tv * tv);} + Type angleRad(const _CVector & v) const {return acos(angleCos(v));} + Type angleDeg(const _CVector & v) const {return toDeg(acos(angleCos(v)));} + _CVector projection(const _CVector & v) {Type tv = v.length(); return (tv == Type(0) ? _CVector() : v * (((*this) ^ v) / tv));} + _CVector & normalize() {Type tv = length(); if (tv == Type(1)) return *this; if (piAbs(tv) <= Type(1E-100)) {fill(Type(0)); return *this;} PIMV_FOR(i, 0) c[i] /= tv; return *this;} + _CVector normalized() {_CVector tv(*this); tv.normalize(); return tv;} + bool isNull() const {PIMV_FOR(i, 0) if (c[i] != Type(0)) return false; return true;} + bool isOrtho(const _CVector & v) const {return ((*this) ^ v) == Type(0);} + + Type & at(uint index) {return c[index];} + Type at(uint index) const {return c[index];} + Type & operator [](uint index) {return c[index];} + Type operator [](uint index) const {return c[index];} + void operator =(const _CVector & v) {c = v.c;} + bool operator ==(const _CVector & v) const {PIMV_FOR(i, 0) if (c[i] != v[i]) return false; return true;} + bool operator !=(const _CVector & v) const {return !(*this == c);} + void operator +=(const _CVector & v) {PIMV_FOR(i, 0) c[i] += v[i];} + void operator -=(const _CVector & v) {PIMV_FOR(i, 0) c[i] -= v[i];} + void operator *=(const Type & v) {PIMV_FOR(i, 0) c[i] *= v;} + void operator *=(const _CVector & v) {PIMV_FOR(i, 0) c[i] *= v[i];} + void operator /=(const Type & v) {PIMV_FOR(i, 0) c[i] /= v;} + void operator /=(const _CVector & v) {PIMV_FOR(i, 0) c[i] /= v[i];} + _CVector operator -() {_CVector tv; PIMV_FOR(i, 0) tv[i] = -c[i]; return tv;} + _CVector operator +(const _CVector & v) {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] += v[i]; return tv;} + _CVector operator -(const _CVector & v) {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] -= v[i]; return tv;} + _CVector operator *(const Type & v) {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] *= v; return tv;} + _CVector operator /(const Type & v) {_CVector tv = _CVector(*this); PIMV_FOR(i, 0) tv[i] /= v; return tv;} + _CVector operator *(const _CVector & v) {if (size_ < 3) return _CVector(); _CVector tv; tv.fill(Type(1)); tv[0] = c[1]*v[2] - v[1]*c[2]; tv[1] = v[0]*c[2] - c[0]*v[2]; tv[2] = c[0]*v[1] - v[0]*c[1]; return tv;} + Type operator ^(const _CVector & v) const {Type tv(0); PIMV_FOR(i, 0) tv += c[i] * v[i]; return tv;} + + //inline operator PIMathMatrix<1, Size, Type>() {return PIMathMatrix<1, Size, Type>(c);} + Type distToLine(const _CVector & lp0, const _CVector & lp1) { + _CVector a(lp0, lp1), b(lp0, *this), c(lp1, *this); + Type f = fabs(a[0]*b[1] - a[1]*b[0]) / a.length();//, s = b.length() + c.length() - a.length(); + return f;} + + template + PIMathVector turnTo(uint size) {PIMathVector tv; uint sz = piMin(size_, size); for (uint i = 0; i < sz; ++i) tv[i] = c[i]; return tv;} + +private: + uint size_; + PIVector c; + +}; + +#undef PIMV_FOR + +template +inline std::ostream & operator <<(std::ostream & s, const PIMathVector & v) {s << '{'; for (uint i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << '}'; return s;} +template +inline PICout operator <<(PICout s, const PIMathVector & v) {s << '{'; for (uint i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << '}'; return s;} + +typedef PIMathVector PIMathVectori; +typedef PIMathVector PIMathVectord; + +//#include "pimathmatrix.h" + +#endif // PIMATHVECTOR_H diff --git a/src/math/pistatistic.h b/src/math/pistatistic.h new file mode 100644 index 00000000..3d8f1c07 --- /dev/null +++ b/src/math/pistatistic.h @@ -0,0 +1,89 @@ +/*! \file pistatistic.h + * \brief Class for calculating math statistic in values array +*/ +/* + PIP - Platform Independent Primitives + Class for calculacing math statistic in values array + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com, Andrey Bychkov work.a.b@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PISTATISTIC_H +#define PISTATISTIC_H + +#include "pimathbase.h" + +template +class PIP_EXPORT PIStatistic { +public: + PIStatistic() {mean = variance = skewness = kurtosis = T();} + + static T calculateMean(const PIVector & val) { + T ret = T(); + int n = val.size(); + if (n < 1) + return ret; + for (int i = 0; i < n; i++) + ret += val[i]; + return ret / n; + } + bool calculate(const PIVector & val, const T & given_mean) { + T v = T(), v1 = T(), v2 = T(), stddev = T(), var = T(); + int i, n = val.size(); + if (n < 2) + return false; + mean = given_mean; + variance = skewness = kurtosis = T(); + /* + * Variance (using corrected two-pass algorithm) + */ + for (i = 0; i < n; i++) + v1 += sqr(val[i] - mean); + for (i = 0; i < n; i++) + v2 += val[i] - mean; + v2 = sqr(v2) / n; + variance = v1 / n; + var = (v1 / n - v2) / (n - 1); + if (var < T()) + var = T(); + stddev = sqrt(var); + /* + * Skewness and kurtosis + */ + if (stddev != T()) { + for (i = 0; i < n; i++) { + v = (val[i] - mean) / stddev; + v2 = sqr(v); + skewness = skewness + v2 * v; + kurtosis = kurtosis + sqr(v2); + } + skewness /= n; + kurtosis = kurtosis / n - 3.; + } + return true; + } + bool calculate(const PIVector & val) {return calculate(val, calculateMean(val));} + + T mean; + T variance; + T skewness; + T kurtosis; +}; + +typedef PIStatistic PIStatistici; +typedef PIStatistic PIStatisticf; +typedef PIStatistic PIStatisticd; + +#endif // PISTATISTIC_H diff --git a/src/system/.piscreen.cpp.kate-swp b/src/system/.piscreen.cpp.kate-swp new file mode 100644 index 00000000..3b43720c Binary files /dev/null and b/src/system/.piscreen.cpp.kate-swp differ diff --git a/src/system/picodec.cpp b/src/system/picodec.cpp new file mode 100755 index 00000000..cecb3d32 --- /dev/null +++ b/src/system/picodec.cpp @@ -0,0 +1,41 @@ +/* + PIP - Platform Independent Primitives + Text codings coder, based on "iconv" + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "picodec.h" + + +PIStringList PICodec::availableCodecs() { + exec("/usr/bin/iconv", "-l"); + waitForFinish(); + PIString str(readOutput()); + str.cutLeft(str.find("\n ")); + str.replaceAll("\n", ""); + return str.split("//"); +} + + +PIByteArray PICodec::exec_iconv(const PIString & from, const PIString & to, const PIByteArray & str) { + tf.open(); + tf.clear(); + tf << str; + tf.close(); + exec("/usr/bin/iconv", ("-f=" + from), ("-t=" + to), tf.path()); + waitForFinish(); + return readOutput(); +} diff --git a/src/system/picodec.h b/src/system/picodec.h new file mode 100755 index 00000000..bcfa0f33 --- /dev/null +++ b/src/system/picodec.h @@ -0,0 +1,51 @@ +/* + PIP - Platform Independent Primitives + Text codings coder, based on "iconv" + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PICODEC_H +#define PICODEC_H + +#include "piprocess.h" + +class PIP_EXPORT PICodec: private PIProcess +{ + PIOBJECT(PICodec) +public: + PICodec(): PIProcess() {setGrabOutput(true); tf = PIFile::openTemporary(PIIODevice::ReadWrite); tf.open();} + PICodec(const PIString & from, const PIString & to): PIProcess() {setCodings(from, to); tf = PIFile::openTemporary(PIIODevice::ReadWrite);} + ~PICodec() {tf.remove();} + + void setFromCoding(const PIString & from) {c_from = from;} + void setToCoding(const PIString & to) {c_to = to;} + void setCodings(const PIString & from, const PIString & to) {c_from = from; c_to = to;} + + PIStringList availableCodecs(); + PIString encode(PIString & str) {return PIString(exec_iconv(c_from, c_to, str.toByteArray()));} + PIString encode(const PIByteArray & str) {return PIString(exec_iconv(c_from, c_to, str));} + PIString decode(PIString & str) {return PIString(exec_iconv(c_to, c_from, str.toByteArray()));} + PIString decode(const PIByteArray & str) {return PIString(exec_iconv(c_to, c_from, str));} + +private: + PIByteArray exec_iconv(const PIString & from, const PIString & to, const PIByteArray & str); + + PIString c_from, c_to; + PIFile tf; + +}; + +#endif // PICODEC_H diff --git a/src/system/piconsole.cpp b/src/system/piconsole.cpp new file mode 100755 index 00000000..ccf79ac7 --- /dev/null +++ b/src/system/piconsole.cpp @@ -0,0 +1,1064 @@ +/* + PIP - Platform Independent Primitives + Console output/input + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "piconsole.h" +#include "pipeer.h" + + +/** \class PIConsole + * \brief Console output class + * \details + * \section PIConsole_sec0 Synopsis + * This class provides output to console with automatic alignment and update. + * It supports tabs, keyboard listening, formats and colors. + * + * \section PIConsole_sec1 Layout + * %PIConsole works with variable pointers. You should add your variables with + * functions \a addVariable() which receives label name, pointer to variable + * and optional column and format. Columns count is dynamically increased if + * new column used. E.g. if you add variable to empty tab to column 3, columns + * count will be increased to 3, but two firsts columns will be empty. Each column + * filled from top to bottom, but you can add just string with function + * \a addString() or add empty line with function \a addEmptyLine(). Layout scheme: + * \image html piconsole_layout.png + * + * \section PIConsole_sec2 Keyboard usage + * %PIConsole should to be single in application. %PIConsole aggregate PIKbdListener + * which grab keyboard and automatic switch tabs by theirs bind keys. If there is no + * tab binded to pressed key external function "slot" will be called + * + **/ + + +extern PIMutex __PICout_mutex__; + + +PIConsole::PIConsole(bool startNow, KBFunc slot): PIThread() { + setName("console"); + setPriority(piLow); + needLockRun(true); + ret_func = slot; + num_format = systime_format = 0; + vid = 0; + cur_tab = width = height = pwidth = pheight = max_y = 0; + def_align = Nothing; + tabs.reserve(16); +#ifdef WINDOWS + ulcoord.X = 0; + hOut = GetStdHandle(STD_OUTPUT_HANDLE); + GetConsoleScreenBufferInfo(hOut, &sbi); + dattr = sbi.wAttributes; + width = sbi.srWindow.Right - sbi.srWindow.Left; + height = sbi.srWindow.Bottom - sbi.srWindow.Top; + ulcoord.Y = sbi.srWindow.Top; + GetConsoleMode(hOut, &smode); + GetConsoleCursorInfo(hOut, &curinfo); +#else + winsize ws; + ioctl(0, TIOCGWINSZ, &ws); + width = ws.ws_col; + height = ws.ws_row; +#endif + tabs.reserve(16); + addTab("main"); + listener = new PIKbdListener(key_event, this); + peer = 0; + server_mode = pause_ = false; + state = Disconnected; + peer_timer.addDelimiter(20); + peer_timer.setName("__S__PIConsole::peer_timer"); + CONNECT2(void, void * , int, &peer_timer, tickEvent, this, peerTimer); + if (startNow) start(); +} + + +PIConsole::~PIConsole() { + stopPeer(); + if (isRunning()) + stop(); + clearTabs(false); + delete listener; +#ifdef WINDOWS + SetConsoleMode(hOut, smode); + SetConsoleTextAttribute(hOut, dattr); +#endif +} + + +int PIConsole::addTab(const PIString & name, char bind_key) { + if (isRunning()) lock(); + tabs.push_back(Tab(name, bind_key)); + cur_tab = tabs.size() - 1; + if (isRunning()) unlock(); + return tabs.size(); +} + + +void PIConsole::removeTab(uint index) { + if (index >= tabs.size()) return; + if (isRunning()) lock(); + tabs.remove(index); + if (cur_tab >= tabs.size()) cur_tab = tabs.size() - 1; + if (isRunning()) unlock(); +} + + +void PIConsole::removeTab(const PIString & name) { + uint index = tabs.size() + 1; + for (uint i = 0; i < tabs.size(); ++i) { + if (tabs[i].name == name) { + index = i; + break; + } + } + removeTab(index); +} + + +void PIConsole::clearTab(uint index) { + if (index >= tabs.size()) return; + lock(); + tabs[index].columns.clear(); + if (cur_tab == index) { + clearScreen(); + fillLabels(); + } + if (cur_tab >= tabs.size()) cur_tab = tabs.size() - 1; + unlock(); +} + + +void PIConsole::clearTab(const PIString & name) { + uint index = tabs.size() + 1; + for (uint i = 0; i < tabs.size(); ++i) { + if (tabs[i].name == name) { + index = i; + break; + } + } + clearTab(index); +} + + +void PIConsole::update() { + lock(); + fillLabels(); + unlock(); +} + + +bool PIConsole::setTab(uint index) { + if (index >= tabs.size()) + return false; + if (!isRunning()) { + cur_tab = index; + return true; + } + lock(); + __PICout_mutex__.lock(); + cur_tab = index; + clearScreen(); + fillLabels(); + __PICout_mutex__.unlock(); + unlock(); + return true; +} + + +bool PIConsole::setTab(const PIString & name) { + uint index = tabs.size() + 1; + for (uint i = 0; i < tabs.size(); ++i) { + if (tabs[i].name == name) { + index = i; + break; + } + } + return setTab(index); +} + + +bool PIConsole::setTabBindKey(uint index, char bind_key) { + if (index >= tabs.size()) + return false; + tabs[index].key = bind_key; + return true; +} + + +bool PIConsole::setTabBindKey(const PIString & name, char bind_key) { + uint index =tabs.size() + 1; + for (uint i = 0; i < tabs.size(); ++i) { + if (tabs[i].name == name) { + index = i; + break; + } + } + return setTabBindKey(index, bind_key); +} + + +void PIConsole::key_event(char key, void * t) { + PIConsole * p = (PIConsole * )t; + int ct = p->cur_tab; + if (key == char(PIKbdListener::LeftArrow)) { + do { + ct--; + if (ct < 0) return; + } while (p->tabs[ct].key == 0); + p->setTab(ct); + return; + } + if (key == char(PIKbdListener::RightArrow)) { + do { + ct++; + if (ct >= p->tabs.size_s()) return; + } while (p->tabs[ct].key == 0); + p->setTab(ct); + return; + } + for (uint i = 0; i < p->tabsCount(); ++i) { + if (p->tabs[i].key == key) { + p->setTab(i); + return; + } + } + if (p->ret_func != 0) p->ret_func(key, t); + p->keyPressed(key, t); +} + + +void PIConsole::clearVariables(bool clearScreen) { + if (isRunning()) lock(); + if (clearScreen && isRunning()) { + toUpperLeft(); + clearScreenLower(); + } + columns().clear(); + if (isRunning()) unlock(); +} + + +void PIConsole::stop(bool clear) { + PIThread::stop(true); + if (clear) clearScreen(); + moveTo(0, max_y + 4); + showCursor(); + couts(fstr(Normal)); +#ifdef WINDOWS + SetConsoleMode(hOut, smode); + SetConsoleTextAttribute(hOut, dattr); +#endif + fflush(0); +} + + +PIString PIConsole::fstr(FormatFlags f) { + num_format = systime_format = 0; + if (f[PIConsole::Dec]) num_format = 0; + if (f[PIConsole::Hex]) num_format = 1; + if (f[PIConsole::Oct]) num_format = 2; + if (f[PIConsole::Bin]) num_format = 4; + if (f[PIConsole::Scientific]) num_format = 3; + if (f[PIConsole::SystemTimeSplit]) systime_format = 0; + if (f[PIConsole::SystemTimeSeconds]) systime_format = 1; + +#ifdef WINDOWS + WORD attr = 0; + + if (f[PIConsole::Inverse]) { + if (f[PIConsole::Red]) attr |= BACKGROUND_RED; + if (f[PIConsole::Green]) attr |= BACKGROUND_GREEN; + if (f[PIConsole::Blue]) attr |= BACKGROUND_BLUE; + if (f[PIConsole::Yellow]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN); + if (f[PIConsole::Magenta]) attr |= (BACKGROUND_RED | BACKGROUND_BLUE); + if (f[PIConsole::Cyan]) attr |= (BACKGROUND_GREEN | BACKGROUND_BLUE); + if (f[PIConsole::White]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); + if (f[PIConsole::BackRed]) attr |= FOREGROUND_RED; + if (f[PIConsole::BackGreen]) attr |= FOREGROUND_GREEN; + if (f[PIConsole::BackBlue]) attr |= FOREGROUND_BLUE; + if (f[PIConsole::BackYellow]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN); + if (f[PIConsole::BackMagenta]) attr |= (FOREGROUND_RED | FOREGROUND_BLUE); + if (f[PIConsole::BackCyan]) attr |= (FOREGROUND_GREEN | FOREGROUND_BLUE); + if (f[PIConsole::BackWhite]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + if ((attr & BACKGROUND_RED) + (attr & BACKGROUND_GREEN) + (attr & BACKGROUND_BLUE) == 0) + attr |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; + } else { + if (f[PIConsole::Red]) attr |= FOREGROUND_RED; + if (f[PIConsole::Green]) attr |= FOREGROUND_GREEN; + if (f[PIConsole::Blue]) attr |= FOREGROUND_BLUE; + if (f[PIConsole::Yellow]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN); + if (f[PIConsole::Magenta]) attr |= (FOREGROUND_RED | FOREGROUND_BLUE); + if (f[PIConsole::Cyan]) attr |= (FOREGROUND_GREEN | FOREGROUND_BLUE); + if (f[PIConsole::White]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + if (f[PIConsole::BackRed]) attr |= BACKGROUND_RED; + if (f[PIConsole::BackGreen]) attr |= BACKGROUND_GREEN; + if (f[PIConsole::BackBlue]) attr |= BACKGROUND_BLUE; + if (f[PIConsole::BackYellow]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN); + if (f[PIConsole::BackMagenta]) attr |= (BACKGROUND_RED | BACKGROUND_BLUE); + if (f[PIConsole::BackCyan]) attr |= (BACKGROUND_GREEN | BACKGROUND_BLUE); + if (f[PIConsole::BackWhite]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); + if ((attr & FOREGROUND_RED) + (attr & FOREGROUND_GREEN) + (attr & FOREGROUND_BLUE) == 0) + attr |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; + } + if (f[PIConsole::Bold]) attr |= FOREGROUND_INTENSITY; + if (f[PIConsole::Underline]) attr |= COMMON_LVB_UNDERSCORE; + + SetConsoleTextAttribute(hOut, attr); + return PIString(); +#else + PIString ts("\e[0"); + + if (f[PIConsole::Bold]) ts += ";1"; + if (f[PIConsole::Faint]) ts += ";2"; + if (f[PIConsole::Italic]) ts += ";3"; + if (f[PIConsole::Underline]) ts += ";4"; + if (f[PIConsole::Blink]) ts += ";5"; + if (f[PIConsole::Inverse]) ts += ";7"; + + if (f[PIConsole::Black]) ts += ";30"; + if (f[PIConsole::Red]) ts += ";31"; + if (f[PIConsole::Green]) ts += ";32"; + if (f[PIConsole::Yellow]) ts += ";33"; + if (f[PIConsole::Blue]) ts += ";34"; + if (f[PIConsole::Magenta]) ts += ";35"; + if (f[PIConsole::Cyan]) ts += ";36"; + if (f[PIConsole::White]) ts += ";37"; + + if (f[PIConsole::BackBlack]) ts += ";40"; + if (f[PIConsole::BackRed]) ts += ";41"; + if (f[PIConsole::BackGreen]) ts += ";42"; + if (f[PIConsole::BackYellow]) ts += ";43"; + if (f[PIConsole::BackBlue]) ts += ";44"; + if (f[PIConsole::BackMagenta]) ts += ";45"; + if (f[PIConsole::BackCyan]) ts += ";46"; + if (f[PIConsole::BackWhite]) ts += ";47"; + + return ts + "m"; +#endif +} + + +inline int PIConsole::couts(const bool v) {return (v ? printf("true") : printf("false"));} +inline int PIConsole::couts(const char v) {return printf("%c", v);} +inline int PIConsole::couts(const short v) { + switch (num_format) {case (1): return printf("0x%.4hX", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 2)); break; default: return printf("%hd", v); break;} +} +inline int PIConsole::couts(const int v) { + switch (num_format) {case (1): return printf("0x%.8X", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 4)); break; default: return printf("%d", v); break;} +} +inline int PIConsole::couts(const long v) { + switch (num_format) {case (1): return printf("0x%.16lX", v); break; case (2): return printf("%lo", v); break; case (4): return printf("%s", toBin(&v, sizeof(v))); break; default: return printf("%ld", v); break;} +} +inline int PIConsole::couts(const llong v) { + switch (num_format) {case (1): return printf("0x%.16llX", v); break; case (2): return printf("%llo", v); break; case (4): return printf("%s", toBin(&v, sizeof(v))); break; default: return printf("%lld", v); break;} +} +inline int PIConsole::couts(const uchar v) { + switch (num_format) {case (1): return printf("0x%.2X", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 1)); break; default: return printf("%u", v); break;} +} +inline int PIConsole::couts(const ushort v) { + switch (num_format) {case (1): return printf("0x%.4hX", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 2)); break; default: return printf("%hu", v); break;} +} +inline int PIConsole::couts(const uint v) { + switch (num_format) {case (1): return printf("0x%.8X", v); break; case (2): return printf("%o", v); break; case (4): return printf("%s", toBin(&v, 4)); break; default: return printf("%u", v); break;} +} +inline int PIConsole::couts(const ulong v) { + switch (num_format) {case (1): return printf("0x%.16lX", v); break; case (2): return printf("%lo", v); break; case (4): return printf("%s", toBin(&v, sizeof(v))); break; default: return printf("%lu", v); break;} +} +inline int PIConsole::couts(const ullong v) { + switch (num_format) {case (1): return printf("0x%.16llX", v); break; case (2): return printf("%llo", v); break; case (4): return printf("%s", toBin(&v, sizeof(v))); break; default: return printf("%llu", v); break;} +} +inline int PIConsole::couts(const float v) { + switch (num_format) {case (3): return printf("%e", v); break; default: return printf("%.5g", v); break;} +} +inline int PIConsole::couts(const double v) { + switch (num_format) {case (3): return printf("%le", v); break; default: return printf("%.5lg", v); break;} +} +inline int PIConsole::couts(const PISystemTime & v) { + switch (systime_format) {case (1): return printf("%.6lg", v.toSeconds()); break; + default: return couts(v.seconds) + printf(" s, ") + couts(v.nanoseconds) + printf(" ns"); break;} +} + + +void PIConsole::begin() { +#ifdef WINDOWS + SetConsoleMode(hOut, ENABLE_WRAP_AT_EOL_OUTPUT); +#endif + max_y = 0; + __PICout_mutex__.lock(); + clearScreen(); + hideCursor(); + fillLabels(); + __PICout_mutex__.unlock(); +} + + +void PIConsole::run() { + if (pause_) return; + uint cx, clen = 0; + int j; +#ifdef WINDOWS + GetConsoleScreenBufferInfo(hOut, &sbi); + width = sbi.srWindow.Right - sbi.srWindow.Left; + height = sbi.srWindow.Bottom - sbi.srWindow.Top; +#else + winsize ws; + ioctl(0, TIOCGWINSZ, &ws); + width = ws.ws_col; + height = ws.ws_row; +#endif + //fflush(0); return; + __PICout_mutex__.lock(); + if (pwidth != width || pheight != height) { + clearScreen(); + fillLabels(); + } + pwidth = width; + pheight = height; + col_cnt = columns().size(); + col_wid = (col_cnt > 0) ? width / col_cnt : width; + for (uint i = 0; i < col_cnt; ++i) { + PIVector & cvars(tabs[cur_tab].columns[i].variables); + cx = col_wid * i; + toUpperLeft(); + if (max_y < cvars.size()) max_y = cvars.size(); + j = 0; + piForeachC (Variable & tv, cvars) { + if (j > height - 3) continue; + j++; + moveRight(cx); + if (tv.type == 15) { + newLine(); + continue; + } + moveRight(tv.offset); + const void * ptr = 0; + if (tv.remote) { + if (tv.type == 0) { + rstr.clear(); + rba = tv.rdata; + rba >> rstr; + rstr.trim(); + ptr = &rstr; + } else + ptr = tv.rdata.data(); + } else + ptr = tv.ptr; + switch (tv.type) { + case 0: clen = printValue(ptr != 0 ? *(const PIString*)ptr : PIString(), tv.format); break; + case 1: clen = printValue(ptr != 0 ? *(const bool*)ptr : false, tv.format); break; + case 2: clen = printValue(ptr != 0 ? *(const int*)ptr : 0, tv.format); break; + case 3: clen = printValue(ptr != 0 ? *(const long*)ptr : 0l, tv.format); break; + case 4: clen = printValue(ptr != 0 ? *(const char*)ptr : char(0), tv.format); break; + case 5: clen = printValue(ptr != 0 ? *(const float*)ptr : 0.f, tv.format); break; + case 6: clen = printValue(ptr != 0 ? *(const double*)ptr : 0., tv.format); break; + case 7: clen = printValue(ptr != 0 ? *(const short*)ptr : short(0), tv.format); break; + case 8: clen = printValue(ptr != 0 ? *(const uint*)ptr : 0u, tv.format); break; + case 9: clen = printValue(ptr != 0 ? *(const ulong*)ptr : 0ul, tv.format); break; + case 10: clen = printValue(ptr != 0 ? *(const ushort*)ptr : ushort(0), tv.format); break; + case 11: clen = printValue(ptr != 0 ? *(const uchar*)ptr : uchar(0), tv.format); break; + case 12: clen = printValue(ptr != 0 ? *(const llong*)ptr : 0l, tv.format); break; + case 13: clen = printValue(ptr != 0 ? *(const ullong*)ptr: 0ull, tv.format); break; + case 20: clen = printValue(ptr != 0 ? *(const PISystemTime*)ptr: PISystemTime(), tv.format); break; + case 14: clen = printValue(bitsValue(ptr, tv.bitFrom, tv.bitCount), tv.format); break; + } + if (clen + tv.offset < (uint)col_wid) { + PIString ts = PIString( +#if defined(QNX) || defined(FREE_BSD) + col_wid - clen - tv.offset - 1, ' '); +#else + col_wid - clen - tv.offset, ' '); +#endif + printf("%s", ts.data()); + } + newLine(); + } + } +#ifdef WINDOWS + moveTo(0, max_y + 1); +#else + moveTo(0, max_y + 2); +#endif + fflush(0); + __PICout_mutex__.unlock(); +} + + +void PIConsole::fillLabels() { + if (!isRunning()) return; + uint cx, cy, mx = 0, dx; +#ifdef WINDOWS + GetConsoleScreenBufferInfo(hOut, &sbi); + width = sbi.srWindow.Right - sbi.srWindow.Left; + height = sbi.srWindow.Bottom - sbi.srWindow.Top; +#else + winsize ws; + ioctl(0, TIOCGWINSZ, &ws); + width = ws.ws_col; + height = ws.ws_row; +#endif + max_y = 0; + col_cnt = columns().size(); + col_wid = (col_cnt > 0) ? width / col_cnt : width; + for (uint i = 0; i < col_cnt; ++i) { + Column & ccol(tabs[cur_tab].columns[i]); + PIVector & cvars(ccol.variables); + if (ccol.alignment != Nothing) { + mx = 0; + piForeachC (Variable & j, cvars) + if (!j.isEmpty()) + if (mx < j.name.size()) + mx = j.name.size(); + mx += 2; + } + cx = col_wid * i; + cy = 1; + toUpperLeft(); + for (uint j = 0; j < cvars.size(); ++j) { + if (int(j) > height - 3) continue; + if (max_y < j) max_y = j; + moveRight(cx); + Variable & tv(cvars[j]); + cvars[j].nx = cx; + cvars[j].ny = cy; + if (tv.name.isEmpty()) { + cvars[j].offset = 0; + clearLine(); + newLine(); + cy++; + continue; + } + clearLine(); + //piCout << tv.name << tv.type << tv.ptr; + if (tv.type == 15) { + cvars[j].offset = cvars[j].name.length(); + cvars[j].nx += cvars[j].offset; + printLine(tv.name, cx, tv.format); + newLine(); + cy++; + continue; + } + if (!tv.isEmpty()) { + switch (ccol.alignment) { + case Nothing: + cvars[j].offset = (tv.name + ": ").length(); + cvars[j].nx += cvars[j].offset; + printValue(tv.name + ": ", tv.format); + break; + case Left: + cvars[j].offset = mx; + cvars[j].nx += cvars[j].offset; + printValue(tv.name + ": ", tv.format); + break; + case Right: + cvars[j].offset = mx; + cvars[j].nx += cvars[j].offset; + dx = mx - (tv.name + ": ").length(); + moveRight(dx); + printValue(tv.name + ": ", tv.format); + moveLeft(dx); + break; + } + } + newLine(); + cy++; + } + } +#ifdef WINDOWS + moveTo(0, max_y + 1); +#else + moveTo(0, max_y + 2); +#endif + if (!tabs[cur_tab].status.isEmpty()) { + printValue(tabs[cur_tab].status); + newLine(); + } + status(); + //couts(fstr(Normal)); + //fflush(0); +} + + +void PIConsole::status() { + Tab * ctab; + //clearLine(); + for (uint i = 0; i < tabsCount(); ++i) { + ctab = &tabs[i]; + if (ctab->key == 0) continue; + printValue(ctab->key, PIConsole::White | PIConsole::Bold); + if (i == cur_tab) + printValue(ctab->name + " ", PIConsole::BackYellow | PIConsole::Black); + else + printValue(ctab->name + " ", PIConsole::Cyan | PIConsole::Inverse); + printValue(" "); + } + newLine(); +} + + +int PIConsole::bitsValue(const void * src, int offset, int count) const { + int ret = 0, stbyte = offset / 8, cbit = offset - stbyte * 8; + char cbyte = reinterpret_cast(src)[stbyte]; + for (int i = 0; i < count; i++) { + ret |= ((cbyte >> cbit & 1) << i); + cbit++; + if (cbit == 8) { + cbit = 0; + stbyte++; + cbyte = reinterpret_cast(src)[stbyte]; + } + } + return ret; +} + + +const char * PIConsole::toBin(const void * d, int s) { + binstr.clear(); + uchar cc, b; + for (int i = 0; i < s; ++i) { + cc = ((const uchar *)d)[i]; + b = 1; + for (int j = 0; j < 8; ++j) { + binstr << (cc & b ? "1" : "0"); + b <<= 1; + } + if (i < s - 1) binstr << " "; + } + binstr.reverse(); + return binstr.data(); +} + + +#define ADD_VAR_BODY vid++; tv.id = vid; tv.name = name; tv.bitFrom = tv.bitCount = 0; tv.format = format; tv.remote = false; checkColumn(col); + +void PIConsole::addString(const PIString & name, int col, FormatFlags format) { + ADD_VAR_BODY tv.type = 15; tv.size = 0; tv.ptr = 0; column(col).push_back(tv);} +void PIConsole::addVariable(const PIString & name, const PIString * ptr, int col, FormatFlags format) { + ADD_VAR_BODY tv.type = 0; tv.size = 0; tv.ptr = ptr; column(col).push_back(tv);} +void PIConsole::addVariable(const PIString & name, const bool * ptr, int col, FormatFlags format) { + ADD_VAR_BODY tv.type = 1; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} +void PIConsole::addVariable(const PIString & name, const int * ptr, int col, FormatFlags format) { + ADD_VAR_BODY tv.type = 2; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} +void PIConsole::addVariable(const PIString & name, const long * ptr, int col, FormatFlags format) { + ADD_VAR_BODY tv.type = 3; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} +void PIConsole::addVariable(const PIString & name, const char * ptr, int col, FormatFlags format) { + ADD_VAR_BODY tv.type = 4; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} +void PIConsole::addVariable(const PIString & name, const float * ptr, int col, FormatFlags format) { + ADD_VAR_BODY tv.type = 5; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} +void PIConsole::addVariable(const PIString & name, const double * ptr, int col, FormatFlags format) { + ADD_VAR_BODY tv.type = 6; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} +void PIConsole::addVariable(const PIString & name, const short * ptr, int col, FormatFlags format) { + ADD_VAR_BODY tv.type = 7; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} +void PIConsole::addVariable(const PIString & name, const uint * ptr, int col, FormatFlags format) { + ADD_VAR_BODY tv.type = 8; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} +void PIConsole::addVariable(const PIString & name, const ulong * ptr, int col, FormatFlags format) { + ADD_VAR_BODY tv.type = 9; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} +void PIConsole::addVariable(const PIString & name, const ushort * ptr, int col, FormatFlags format) { + ADD_VAR_BODY tv.type = 10; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} +void PIConsole::addVariable(const PIString & name, const uchar * ptr, int col, FormatFlags format) { + ADD_VAR_BODY tv.type = 11; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} +void PIConsole::addVariable(const PIString & name, const llong * ptr, int col, FormatFlags format) { + ADD_VAR_BODY tv.type = 12; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} +void PIConsole::addVariable(const PIString & name, const ullong * ptr, int col, FormatFlags format) { + ADD_VAR_BODY tv.type = 13; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} +void PIConsole::addVariable(const PIString & name, const PISystemTime * ptr, int col, FormatFlags format) { + ADD_VAR_BODY tv.type = 20; tv.size = sizeof(*ptr); tv.ptr = ptr; column(col).push_back(tv);} +/** \brief Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" + * \details This function add to column "column" next lines: + * * "protocol " + * * "Rec - receiverDeviceName": \a PIProtocol::receiverDeviceState + * * "Send - senderDeviceName": \a PIProtocol::senderDeviceState + * * "Received count": \a PIProtocol::receiveCount + * * "Invalid count": \a PIProtocol::wrongCount + * * "Missed count": \a PIProtocol::missedCount + * * "Sended count": \a PIProtocol::sendCount + * * "Immediate Frequency, Hz": \a PIProtocol::immediateFrequency + * * "Integral Frequency, Hz": \a PIProtocol::integralFrequency + * * "Receive speed": \a PIProtocol::receiveSpeed + * * "Send speed": \a PIProtocol::sendSpeed + * * "Receiver history size": \a PIProtocol::receiverHistorySize + * * "Sender history size": \a PIProtocol::senderHistorySize + * * "Disconnect Timeout, s": \a PIProtocol::disconnectTimeout + * * "Quality": \a PIProtocol::quality + * */ +void PIConsole::addVariable(const PIString & name, const PIProtocol * ptr, int col, FormatFlags format) { + addString("protocol " + name, col, format | PIConsole::Bold); + addVariable("Rec - " + ptr->receiverDeviceName(), ptr->receiverDeviceState_ptr(), col, format); + addVariable("Send - " + ptr->senderDeviceName(), ptr->senderDeviceState_ptr(), col, format); + addVariable("Received count", ptr->receiveCount_ptr(), col, format); + addVariable("Invalid count", ptr->wrongCount_ptr(), col, format); + addVariable("Missed count", ptr->missedCount_ptr(), col, format); + addVariable("Sended count", ptr->sendCount_ptr(), col, format); + addVariable("Immediate Frequency, Hz", ptr->immediateFrequency_ptr(), col, format); + addVariable("Integral Frequency, Hz", ptr->integralFrequency_ptr(), col, format); + addVariable("Receive speed", ptr->receiveSpeed_ptr(), col, format); + addVariable("Send speed", ptr->sendSpeed_ptr(), col, format); + addVariable("Receiver history size", ptr->receiverHistorySize_ptr(), col, format); + addVariable("Sender history size", ptr->senderHistorySize_ptr(), col, format); + addVariable("Disconnect Timeout, s", ptr->disconnectTimeout_ptr(), col, format); + addVariable("Quality", ptr->quality_ptr(), col, format); +} +/** \brief Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" + * \details This function add to column "column" next lines: + * * " diagnostics" + * * "Received count": \a PIDiagnostics::receiveCount + * * "Invalid count": \a PIDiagnostics::wrongCount + * * "Sended count": \a PIDiagnostics::sendCount + * * "Immediate Frequency, Hz": \a PIDiagnostics::immediateFrequency + * * "Integral Frequency, Hz": \a PIDiagnostics::integralFrequency + * * "Receive speed": \a PIDiagnostics::receiveSpeed + * * "Send speed": \a PIDiagnostics::sendSpeed + * * "Quality": \a PIDiagnostics::quality + * */ +void PIConsole::addVariable(const PIString & name, const PIDiagnostics * ptr, int col, FormatFlags format) { + addString(name + " diagnostics", col, format | PIConsole::Bold); + addVariable("Received count", ptr->receiveCount_ptr(), col, format); + addVariable("Invalid count", ptr->wrongCount_ptr(), col, format); + addVariable("Sended count", ptr->sendCount_ptr(), col, format); + addVariable("Immediate Frequency, Hz", ptr->immediateFrequency_ptr(), col, format); + addVariable("Integral Frequency, Hz", ptr->integralFrequency_ptr(), col, format); + addVariable("Receive speed", ptr->receiveSpeed_ptr(), col, format); + addVariable("Send speed", ptr->sendSpeed_ptr(), col, format); + addVariable("Quality", ptr->quality_ptr(), col, format); +} +void PIConsole::addVariable(const PIString & name, const PISystemMonitor * ptr, int col, FormatFlags format) { + addString("monitor " + name, col, format | PIConsole::Bold); + addVariable("PID", &(ptr->statistic().ID), col, format); + //addVariable("state", &(ptr->statistic().state), col, format); + addVariable("threads", &(ptr->statistic().threads), col, format); + addVariable("priority", &(ptr->statistic().priority), col, format); + addVariable("memory physical", &(ptr->statistic().physical_memsize_readable), col, format); + addVariable("memory shared", &(ptr->statistic().share_memsize_readable), col, format); + addVariable("cpu load kernel", &(ptr->statistic().cpu_load_system), col, format); + addVariable("cpu load user", &(ptr->statistic().cpu_load_user), col, format); +} +void PIConsole::addBitVariable(const PIString & name, const void * ptr, int fromBit, int bitCount, int col, FormatFlags format) { + vid++; tv.id = vid; tv.size = sizeof(ullong); tv.name = name; tv.bitFrom = fromBit; tv.bitCount = bitCount; tv.type = 14; tv.ptr = ptr; tv.format = format; + checkColumn(col); column(col).push_back(tv);} +void PIConsole::addEmptyLine(int col, uint count) { + tv.id = 0; tv.size = 0; tv.name = ""; tv.type = 0; tv.ptr = 0; tv.format = Normal; + for (uint i = 0; i < count; ++i) { + checkColumn(col); + column(col).push_back(tv); + } +} + + +PIString PIConsole::getString(int x, int y) { + bool run = isRunning(); + if (run) PIThread::stop(true); + listener->setActive(false); + msleep(50); +#ifdef WINDOWS + moveTo(x - 1, y - 1); +#else + moveTo(x, y); +#endif + showCursor(); + PIByteArray ba(4096); +#ifdef CC_VC + int ret = scanf_s(" %s", ba.data()); +#else + int ret = scanf(" %s", ba.data()); +#endif + listener->setActive(true); + if (run) start(); + if (ret >= 1) return PIString(ba); + else return PIString(); +} + + +PIString PIConsole::getString(const PIString & name) { + piForeachC (Column & i, tabs[cur_tab].columns) + piForeachC (Variable & j, i.variables) + if (j.name == name) + return getString(j.nx + 1, j.ny); + return PIString(); +} + + +#define PRINT_VAR_BODY couts(fstr(format)); int ret = couts(value); couts(fstr(PIConsole::Dec)); return ret; + +inline void PIConsole::printLine(const PIString & value, int dx, FormatFlags format) { + int i = width - value.length() - dx; +#if defined(QNX) || defined(FREE_BSD) + --i; +#endif + PIString ts = fstr(format); + couts(ts); + if (i >= 0) ts = value + PIString(i, ' '); + else ts = value.left(value.size() + i); + couts(ts); + couts(fstr(Dec)); +} +inline int PIConsole::printValue(const PIString & value, FormatFlags format) { + couts(fstr(format)); + int ret = couts(value); + fstr(PIConsole::Dec); + return ret; +} +inline int PIConsole::printValue(const char * value, FormatFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const bool value, FormatFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const int value, FormatFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const long value, FormatFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const llong value, FormatFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const float value, FormatFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const double value, FormatFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const char value, FormatFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const short value, FormatFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const uchar value, FormatFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const ushort value, FormatFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const uint value, FormatFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const ulong value, FormatFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const ullong value, FormatFlags format) {PRINT_VAR_BODY} +inline int PIConsole::printValue(const PISystemTime & value, FormatFlags format) {PRINT_VAR_BODY} + + + +void PIConsole::startServer(const PIString & name) { + stopPeer(); + server_mode = true; + peer = new PIPeer("_rcs_:" + name); + CONNECT2(void, const PIString & , const PIByteArray &, peer, dataReceivedEvent, this, peerReceived); + CONNECT1(void, const PIString & , peer, peerDisconnectedEvent, this, peerDisconnectedEvent); + peer_timer.start(50.); + serverSendInfo(); +} + + +void PIConsole::stopPeer() { + remote_clients.clear(); + peer_timer.stop(); + if (peer != 0) delete peer; + peer = 0; + state = Disconnected; +} + + +PIStringList PIConsole::clients() const { + PIStringList sl; + if (peer == 0) return sl; + piForeachC (PIPeer::PeerInfo & i, peer->allPeers()) { + if (i.name.left(6) != "_rcc_:") continue; + sl << i.name.right(i.name.length() - 6); + } + return sl; +} + + +void PIConsole::listenServers() { + stopPeer(); + server_mode = false; + server_name.clear(); + srand(PISystemTime::current().nanoseconds); + peer = new PIPeer("_rcc_:" + PIDateTime::current().toString("hhmmssddMMyy_") + PIString::fromNumber(rand())); + CONNECT2(void, const PIString & , const PIByteArray &, peer, dataReceivedEvent, this, peerReceived); + peer_timer.start(100.); +} + + +PIStringList PIConsole::availableServers() const { + PIStringList sl; + if (peer == 0) return sl; + piForeachC (PIPeer::PeerInfo & i, peer->allPeers()) { + if (i.name.left(6) != "_rcs_:") continue; + sl << i.name.right(i.name.length() - 6); + } + return sl; +} + + +void PIConsole::connectToServer(const PIString & name) { + if (peer == 0) listenServers(); + server_name = name; +} + + +void PIConsole::disconnect() { + stopPeer(); +} + + +void PIConsole::serverSendInfo() { + if (peer == 0) return; + PIByteArray ba; + ba << int(0xAA); + peer->sendToAll(ba); +} + + +void PIConsole::serverSendData() { + if (peer == 0) return; + PIByteArray ba; + PIVector content; + piForeach (Tab & t, tabs) + piForeach (Column & c, t.columns) + piForeach (Variable & v, c.variables) + if (!v.isEmpty() && v.id > 0) { + VariableContent vc; + vc.id = v.id; + v.writeData(vc.rdata); + content << vc; + } + piForeach (RemoteClient & rc, remote_clients) { + ba.clear(); + switch (rc.state) { + case FetchingData: + ba << int(0xCC) << tabs; + //piCout << "server send const data" << rc.name << ba.size_s(); + break; + case Committing: + ba << int(0xDD); + break; + case Connected: + ba << int(0xEE) << content; + //piCout << "send data" << ba.size(); + break; + default: break; + } + if (!ba.isEmpty()) + peer->send(rc.name, ba); + } +} + + +PIConsole::RemoteClient & PIConsole::remoteClient(const PIString & fname) { + piForeach (RemoteClient & i, remote_clients) + if (i.name == fname) + return i; + remote_clients << RemoteClient(fname); + return remote_clients.back(); +} + + +void PIConsole::peerReceived(const PIString & from, const PIByteArray & data) { + int type; + PIByteArray ba(data); + ba >> type; + //piCout << "rec packet from" << from << "type" << PICoutManipulators::Hex << type; + if (server_mode) { + if (from.left(5) != "_rcc_") return; + //PIString rcn = from.right(from.length() - 6); + RemoteClient & rc(remoteClient(from)); + switch (type) { + case 0xBB: // fetch const data request + //piCout << "fetch data request from" << from << rc.state; + if (rc.state != Connected) + rc.state = FetchingData; + break; + case 0xCC: // const data commit + //piCout << "commit from" << from; + if (rc.state != Connected) + rc.state = Connected; + break; + default: break; + } + } else { + PIVector content; + PIMap vids; + if (from.left(5) != "_rcs_") return; + //PIString rcn = from.right(from.length() - 6); + switch (type) { + case 0xAA: // new server + //piCout << "new server" << rcn; + break; + case 0xCC: // const data + //piCout << "received const data"; + state = Committing; + ba >> tabs; + cur_tab = tabs.isEmpty() ? -1 : 0; + piForeach (Tab & t, tabs) + piForeach (Column & c, t.columns) + piForeach (Variable & v, c.variables) + v.remote = true; + break; + case 0xDD: // const data commit + //piCout << "received commit"; + state = Connected; + break; + case 0xEE: // dynamic data + //piCout << "received data" << ba.size_s(); + piForeach (Tab & t, tabs) + piForeach (Column & c, t.columns) + piForeach (Variable & v, c.variables) + if (!v.isEmpty() && v.id > 0) + vids[v.id] = &v; + ba >> content; + piForeach (VariableContent & vc, content) { + if (vc.id <= 0) continue; + Variable * v = vids.at(vc.id); + if (v == 0) continue; + //piCout << "read" << v->name << vc.rdata.size_s(); + v->rdata = vc.rdata; + } + break; + default: break; + } + } +} + + +void PIConsole::peerTimer(void * data, int delim) { + if (peer == 0) return; + //piCout << "timer" << delim; + if (server_mode) { + if (delim == 20) + serverSendInfo(); + else + serverSendData(); + } else { + if (delim != 1 || server_name.isEmpty()) return; + const PIPeer::PeerInfo * p = peer->getPeerByName("_rcs_:" + server_name); + if (p == 0) return; + PIByteArray ba; + switch (state) { + case Disconnected: + peer_tm.reset(); + ba << int(0xBB); + //piCout << "send to" << server_name << "fetch request disc"; + peer->send(p, ba); + state = FetchingData; + break; + case FetchingData: + if (peer_tm.elapsed_s() < 3.) + return; + peer_tm.reset(); + ba << int(0xBB); + //piCout << "send to" << server_name << "fetch request fd"; + peer->send(p, ba); + break; + case Committing: + peer_tm.reset(); + ba << int(0xCC); + //piCout << "send to" << server_name << "committing"; + state = Connected; + peer->send(p, ba); + break; + default: break; + }; + } +} + + +void PIConsole::peerDisconnectedEvent(const PIString & name) { + for (int i = 0; i < remote_clients.size_s(); ++i) + if (remote_clients[i].name == name) { + remote_clients.remove(i); + --i; + } +} diff --git a/src/system/piconsole.h b/src/system/piconsole.h new file mode 100755 index 00000000..fa9d2fbe --- /dev/null +++ b/src/system/piconsole.h @@ -0,0 +1,508 @@ +/*! \file piconsole.h + * \brief Console output class +*/ +/* + PIP - Platform Independent Primitives + Console output/input + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PICONSOLE_H +#define PICONSOLE_H + +#include "pikbdlistener.h" +#include "piprotocol.h" +#include "pidiagnostics.h" +#include "pisystemmonitor.h" +#ifndef WINDOWS +# include +# include +#else +# define COMMON_LVB_UNDERSCORE 0x8000 +#endif + +class PIPeer; + +class PIP_EXPORT PIConsole: public PIThread +{ + PIOBJECT_SUBCLASS(PIConsole, PIThread) +public: + + //! Constructs %PIConsole with key handler "slot" and if "startNow" start it + PIConsole(bool startNow = true, KBFunc slot = 0); + + ~PIConsole(); + + + //! Variables output format + enum Format { + Normal /** Default console format */ = 0x01, + Bold /** Bold text */ = 0x02, + Faint = 0x04, + Italic = 0x08, + Underline /** Underlined text */ = 0x10, + Blink /** Blinked text */ = 0x20, + Inverse /** Swap text and background colors */ = 0x40, + Black /** Black text */ = 0x100, + Red /** Red text */ = 0x200, + Green /** Green text */ = 0x400, + Yellow /** Yellow text */ = 0x800, + Blue /** Blue text */ = 0x1000, + Magenta /** Magenta text */ = 0x2000, + Cyan /** Cyan text */ = 0x4000, + White /** White text */ = 0x8000, + BackBlack /** Black background */ = 0x10000, + BackRed /** Red background */ = 0x20000, + BackGreen /** Green background */ = 0x40000, + BackYellow /** Yellow background */ = 0x80000, + BackBlue /** Blue background */ = 0x100000, + BackMagenta /** Magenta background */ = 0x200000, + BackCyan /** Cyan background */ = 0x400000, + BackWhite /** White background */ = 0x800000, + Dec /** Decimal base for integers */ = 0x1000000, + Hex /** Hexadecimal base for integers */ = 0x2000000, + Oct /** Octal base for integers */ = 0x4000000, + Bin /** Binary base for integers */ = 0x8000000, + Scientific /** Scientific representation of floats */ = 0x10000000, + SystemTimeSplit /** PISystemTime split representation (* s, * ns) */ = 0x20000000, + SystemTimeSeconds /** PISystemTime seconds representation (*.* s) */ = 0x40000000 + }; + + //! Column labels alignment + enum Alignment { + Nothing /** No alignment */ , + Left /** Labels align left and variables align left */ , + Right /** Labels align right and variables align left */ + }; + + typedef PIFlags FormatFlags; + + //! Add to current tab to column "column" string "name" with format "format" + void addString(const PIString & name, int column = 1, FormatFlags format = PIConsole::Normal); + + //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" + void addVariable(const PIString & name, const PIString * ptr, int column = 1, FormatFlags format = PIConsole::Normal); + + //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" + void addVariable(const PIString & name, const char * ptr, int column = 1, FormatFlags format = PIConsole::Normal); + + //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" + void addVariable(const PIString & name, const bool * ptr, int column = 1, FormatFlags format = PIConsole::Normal); + + //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" + void addVariable(const PIString & name, const short * ptr, int column = 1, FormatFlags format = PIConsole::Normal); + + //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" + void addVariable(const PIString & name, const int * ptr, int column = 1, FormatFlags format = PIConsole::Normal); + + //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" + void addVariable(const PIString & name, const long * ptr, int column = 1, FormatFlags format = PIConsole::Normal); + + //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" + void addVariable(const PIString & name, const llong * ptr, int column = 1, FormatFlags format = PIConsole::Normal); + + //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" + void addVariable(const PIString & name, const uchar * ptr, int column = 1, FormatFlags format = PIConsole::Normal); + + //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" + void addVariable(const PIString & name, const ushort * ptr, int column = 1, FormatFlags format = PIConsole::Normal); + + //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" + void addVariable(const PIString & name, const uint * ptr, int column = 1, FormatFlags format = PIConsole::Normal); + + //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" + void addVariable(const PIString & name, const ulong * ptr, int column = 1, FormatFlags format = PIConsole::Normal); + + //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" + void addVariable(const PIString & name, const ullong * ptr, int column = 1, FormatFlags format = PIConsole::Normal); + + //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" + void addVariable(const PIString & name, const float * ptr, int column = 1, FormatFlags format = PIConsole::Normal); + + //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" + void addVariable(const PIString & name, const double * ptr, int column = 1, FormatFlags format = PIConsole::Normal); + + //! Add to current tab to column "column" variable with label "name", pointer "ptr" and format "format" + void addVariable(const PIString & name, const PISystemTime * ptr, int column = 1, FormatFlags format = PIConsole::Normal); + + void addVariable(const PIString & name, const PIProtocol * ptr, int column = 1, FormatFlags format = PIConsole::Normal); + void addVariable(const PIString & name, const PIDiagnostics * ptr, int column = 1, FormatFlags format = PIConsole::Normal); + void addVariable(const PIString & name, const PISystemMonitor * ptr, int column = 1, FormatFlags format = PIConsole::Normal); + + //! Add to current tab to column "column" bits field with label "name", pointer "ptr" and format "format" + void addBitVariable(const PIString & name, const void * ptr, int fromBit, int bitsCount, int column = 1, FormatFlags format = PIConsole::Normal); + + //! Add to current tab to column "column" "count" empty lines + void addEmptyLine(int column = 1, uint count = 1); + + PIString getString(int x, int y); + short getShort(int x, int y) {return getString(x, y).toShort();} + int getInt(int x, int y) {return getString(x, y).toInt();} + float getFloat(int x, int y) {return getString(x, y).toFloat();} + double getDouble(int x, int y) {return getString(x, y).toDouble();} + PIString getString(const PIString & name); + short getShort(const PIString & name) {return getString(name).toShort();} + int getInt(const PIString & name) {return getString(name).toInt();} + float getFloat(const PIString & name) {return getString(name).toFloat();} + double getDouble(const PIString & name) {return getString(name).toDouble();} + + + //! Returns tabs count + uint tabsCount() const {return tabs.size();} + + //! Returns current tab name + PIString currentTab() const {return tabs[cur_tab].name;} + + //! Returns current tab index + int currentTabIndex() const {return cur_tab;} + + //! Add new tab with name "name", bind key "bind_key" and returns this tab index + int addTab(const PIString & name, char bind_key = 0); + + //! Remove tab with index "index" + void removeTab(uint index); + + //! Remove tab with name "name" + void removeTab(const PIString & name); + + //! Clear content of tab with index "index" + void clearTab(uint index); + + //! Clear content of tab with name "name" + void clearTab(const PIString & name); + + //! Set current tab to tab with index "index", returns if tab exists + bool setTab(uint index); + + //! Set current tab to tab with name "name", returns if tab exists + bool setTab(const PIString & name); + + //! Set tab with index "index" bind key to "bind_key", returns if tab exists + bool setTabBindKey(uint index, char bind_key); + + //! Set tab with name "name" bind key to "bind_key", returns if tab exists + bool setTabBindKey(const PIString & name, char bind_key); + + //! Remove all tabs and if "clearScreen" clear the screen + void clearTabs(bool clearScreen = true) {if (clearScreen && isRunning()) {toUpperLeft(); clearScreenLower();} tabs.clear();} + + + //! Set custom status text of current tab to "str" + void addCustomStatus(const PIString & str) {tabs[cur_tab].status = str;} + + //! Clear custom status text of current tab + void clearCustomStatus() {tabs[cur_tab].status.clear();} + + //! Returns default alignment + Alignment defaultAlignment() const {return def_align;} + + //! Set default alignment to "align" + void setDefaultAlignment(Alignment align) {def_align = align;} + + //! Set column "col" alignment to "align" + void setColumnAlignment(int col, Alignment align) {if (col < 0 || col >= columns().size_s()) return; column(col).alignment = align;} + + //! Set all columns of all tabs alignment to "align" + void setColumnAlignmentToAll(Alignment align) {piForeach (Tab & i, tabs) piForeach (Column & j, i.columns) j.alignment = align; fillLabels();} + + + //! Directly call function from \a PIKbdListener + void enableExitCapture(char key = 'Q') {listener->enableExitCapture(key);} + + //! Directly call function from \a PIKbdListener + void disableExitCapture() {listener->disableExitCapture();} + + //! Directly call function from \a PIKbdListener + bool exitCaptured() const {return listener->exitCaptured();} + + //! Directly call function from \a PIKbdListener + char exitKey() const {return listener->exitKey();} + + + int windowWidth() const {return width;} + int windowHeight() const {return height;} + + PIString fstr(FormatFlags f); + void update(); + void pause(bool yes) {pause_ = yes;} + + // Server functions + void startServer(const PIString & name); + void stopPeer(); + bool isServerStarted() const {return peer != 0;} + PIStringList clients() const; + + // Client functions + void listenServers(); + PIStringList availableServers() const; + PIString selectedServer() const {return server_name;} + void connectToServer(const PIString & name); + void disconnect(); + bool isConnected() const {return state == Connected;} + +#ifdef WINDOWS + void toUpperLeft() {SetConsoleCursorPosition(hOut, ulcoord);} + void moveRight(int n = 1) {SetConsoleCursorPosition(hOut, getWinCoord(n));} + void moveLeft(int n = 1) {SetConsoleCursorPosition(hOut, getWinCoord(-n));} + void moveTo(int x = 0, int y = 0) {ccoord.X = x; ccoord.Y = ulcoord.Y + y; SetConsoleCursorPosition(hOut, ccoord);} + void clearScreen() {couts(fstr(Normal)); toUpperLeft(); FillConsoleOutputAttribute(hOut, dattr, width * (height + 1), ulcoord, &written); + FillConsoleOutputCharacter(hOut, ' ', width * (height + 1), ulcoord, &written);} + void clearScreenLower() {couts(fstr(Normal)); getWinCurCoord(); FillConsoleOutputAttribute(hOut, dattr, width * height - width * ccoord.Y + ccoord.X, ccoord, &written); + FillConsoleOutputCharacter(hOut, ' ', width * height - width * ccoord.Y + ccoord.X, ccoord, &written);} + void clearLine() {getWinCurCoord(); FillConsoleOutputAttribute(hOut, dattr, width - ccoord.X, ccoord, &written); + FillConsoleOutputCharacter(hOut, ' ', width - ccoord.X, ccoord, &written);} + void newLine() {getWinCurCoord(); ccoord.X = 0; ccoord.Y++; SetConsoleCursorPosition(hOut, ccoord);} + void hideCursor() {curinfo.bVisible = false; SetConsoleCursorInfo(hOut, &curinfo);} + void showCursor() {curinfo.bVisible = true; SetConsoleCursorInfo(hOut, &curinfo);} +#else + void toUpperLeft() {printf("\e[H");} + void moveRight(int n = 1) {if (n > 0) printf("\e[%dC", n);} + void moveLeft(int n = 1) {if (n > 0) printf("\e[%dD", n);} + void moveTo(int x = 0, int y = 0) {printf("\e[%d;%dH", y, x);} + void clearScreen() {couts(fstr(Normal)); printf("\e[H\e[J");} + void clearScreenLower() {couts(fstr(Normal)); printf("\e[J");} + void clearLine() {printf("\e[K");} + void newLine() {printf("\eE");} + void hideCursor() {printf("\e[?25l");} + void showCursor() {printf("\e[?25h");} +#endif + + EVENT_HANDLER0(void, clearVariables) {clearVariables(true);} + EVENT_HANDLER1(void, clearVariables, bool, clearScreen); + + EVENT_HANDLER0(void, waitForFinish) {WAIT_FOR_EXIT} + EVENT_HANDLER0(void, start) {start(false);} + EVENT_HANDLER1(void, start, bool, wait) {PIThread::start(40); if (wait) waitForFinish();} + EVENT_HANDLER0(void, stop) {stop(false);} + EVENT_HANDLER1(void, stop, bool, clear); + + EVENT2(keyPressed, char, key, void * , data) + +//! \handlers +//! \{ + + //! \fn void waitForFinish() + //! \brief block until finished (exit key will be pressed) + + //! \fn void clearVariables(bool clearScreen = true) + //! \brief Remove all columns at current tab and if "clearScreen" clear the screen + + //! \fn void start(bool wait = false) + //! \brief Start console output and if "wait" block until finished (exit key will be pressed) + + //! \fn void stop(bool clear = false) + //! \brief Stop console output and if "clear" clear the screen + +//! \} +//! \events +//! \{ + + //! \fn void keyPressed(char key, void * data) + //! \brief Raise on key "key" pressed, "data" is pointer to %PIConsole object + +//! \} + +private: +#ifdef WINDOWS + void getWinCurCoord() {GetConsoleScreenBufferInfo(hOut, &csbi); ccoord = csbi.dwCursorPosition;} + COORD & getWinCoord(int dx = 0, int dy = 0) {getWinCurCoord(); ccoord.X += dx; ccoord.Y += dy; return ccoord;} +#endif + + void begin(); + void run(); + void fillLabels(); + void status(); + void checkColumn(uint col) {while (columns().size() < col) columns().push_back(Column(def_align));} + int bitsValue(const void * src, int offset, int count) const; + const char * toBin(const void * d, int s); + inline void printLine(const PIString & str, int dx = 0, FormatFlags format = PIConsole::Normal); + inline int printValue(const PIString & str, FormatFlags format = PIConsole::Normal); + inline int printValue(const char * str, FormatFlags format = PIConsole::Normal); + inline int printValue(const bool value, FormatFlags format = PIConsole::Normal); + inline int printValue(const int value, FormatFlags format = PIConsole::Normal); + inline int printValue(const long value, FormatFlags format = PIConsole::Normal); + inline int printValue(const llong value, FormatFlags format = PIConsole::Normal); + inline int printValue(const float value, FormatFlags format = PIConsole::Normal); + inline int printValue(const double value, FormatFlags format = PIConsole::Normal); + inline int printValue(const char value, FormatFlags format = PIConsole::Normal); + inline int printValue(const short value, FormatFlags format = PIConsole::Normal); + inline int printValue(const uchar value, FormatFlags format = PIConsole::Normal); + inline int printValue(const ushort value, FormatFlags format = PIConsole::Normal); + inline int printValue(const uint value, FormatFlags format = PIConsole::Normal); + inline int printValue(const ulong value, FormatFlags format = PIConsole::Normal); + inline int printValue(const ullong value, FormatFlags format = PIConsole::Normal); + inline int printValue(const PISystemTime & value, FormatFlags format = PIConsole::Normal); + static void key_event(char key, void * t); + + struct Variable { + Variable() {nx = ny = type = offset = bitFrom = bitCount = size = 0; format = Normal; remote = false; ptr = 0; id = 1;} + bool isEmpty() const {return (remote ? false : ptr == 0);} + const void * data() {return (remote ? rdata.data() : ptr);} + void writeData(PIByteArray & ba) { + if (remote) ba << rdata; + else { + if (type == 0) ba << (*(PIString * )ptr); + else ba << PIByteArray::RawData(ptr, size); + } + } + PIString name; + FormatFlags format; + int nx; + int ny; + int type; + int offset; + int bitFrom; + int bitCount; + int size; + int id; + bool remote; + const void * ptr; + PIByteArray rdata; + void operator =(const Variable & src) {remote = src.remote; name = src.name; format = src.format; type = src.type; offset = src.offset; size = src.size; + bitFrom = src.bitFrom; bitCount = src.bitCount; ptr = src.ptr; nx = src.nx; ny = src.ny; rdata = src.rdata; id = src.id;} + }; + + struct VariableContent { + int id; + PIByteArray rdata; + }; + + struct Column { + Column(Alignment align = PIConsole::Right) {variables.reserve(32); alignment = align;} + PIVector variables; + Alignment alignment; + uint size() const {return variables.size();} + Variable & operator [](int index) {return variables[index];} + const Variable & operator [](int index) const {return variables[index];} + void push_back(const Variable & v) {variables.push_back(v);} + void operator =(const Column & src) {variables = src.variables; alignment = src.alignment;} + }; + + struct Tab { + Tab(PIString n = "", char k = 0) {columns.reserve(8); name = n; key = k;} + PIVector columns; + PIString name; + PIString status; + char key; + }; + + enum ConnectedState {Disconnected, FetchingData, Committing, Connected}; + + friend PIByteArray & operator <<(PIByteArray & ba, const PIConsole::VariableContent & v); + friend PIByteArray & operator >>(PIByteArray & ba, PIConsole::VariableContent & v); + + friend PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Variable & v); + friend PIByteArray & operator >>(PIByteArray & ba, PIConsole::Variable & v); + + friend PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Column & v); + friend PIByteArray & operator >>(PIByteArray & ba, PIConsole::Column & v); + + friend PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Tab & v); + friend PIByteArray & operator >>(PIByteArray & ba, PIConsole::Tab & v); + + PIVector & columns() {return tabs[cur_tab].columns;} + Column & column(int index) {return tabs[cur_tab].columns[index - 1];} + inline int couts(const PIString & v) {return printf("%s", v.data());} + inline int couts(const char * v) {return printf("%s", v);} + inline int couts(const bool v); + inline int couts(const char v); + inline int couts(const short v); + inline int couts(const int v); + inline int couts(const long v); + inline int couts(const llong v); + inline int couts(const uchar v); + inline int couts(const ushort v); + inline int couts(const uint v); + inline int couts(const ulong v); + inline int couts(const ullong v); + inline int couts(const float v); + inline int couts(const double v); + inline int couts(const PISystemTime & v); + + struct RemoteClient; + + void serverSendInfo(); + void serverSendData(); + RemoteClient & remoteClient(const PIString & fname); + EVENT_HANDLER2(void, peerReceived, const PIString &, from, const PIByteArray &, data); + EVENT_HANDLER2(void, peerTimer, void * , data, int, delim); + EVENT_HANDLER1(void, peerDisconnectedEvent, const PIString &, name); + +#ifdef WINDOWS + void * hOut; + CONSOLE_SCREEN_BUFFER_INFO sbi, csbi; + CONSOLE_CURSOR_INFO curinfo; + COORD ccoord, ulcoord; + WORD dattr; + DWORD smode, written; +#else + struct termios sterm, vterm; +#endif + PIVector tabs; + PIString binstr, rstr; + PIByteArray rba; + Variable tv; + PIKbdListener * listener; + Alignment def_align; + KBFunc ret_func; + int width, height, pwidth, pheight, ret, col_wid, num_format, systime_format; + uint max_y; + int vid; + uint cur_tab, col_cnt; + + PIPeer * peer; + PITimer peer_timer; + PITimeMeasurer peer_tm; + PIString server_name; + bool server_mode, pause_; + ConnectedState state; + + /*struct RemoteData { + RemoteData() {msg_count = msg_rec = msg_send = 0;} + void clear() {msg_count = msg_rec = msg_send = 0; data.clear();} + bool isEmpty() const {return msg_count == 0;} + bool isReadyRec() const {return msg_count == msg_rec;} + bool isReadySend() const {return msg_count == msg_send;} + void setData(const PIByteArray & ba) {data = ba; msg_rec = msg_send = 0; msg_count = (data.size_s() - 1) / 4096 + 1;} + PIByteArray data; + int msg_count; + int msg_rec; + int msg_send; + };*/ + + struct RemoteClient { + RemoteClient(const PIString & n = "") {name = n; state = Disconnected;} + PIString name; + ConnectedState state; + }; + + PIVector remote_clients; + +}; + +inline PIByteArray & operator <<(PIByteArray & ba, const PIConsole::VariableContent & v) {ba << v.id << v.rdata; return ba;} +inline PIByteArray & operator >>(PIByteArray & ba, PIConsole::VariableContent & v) {ba >> v.id; ba >> v.rdata; return ba;} + +inline PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Variable & v) {ba << v.name << v.id << (int)v.format << v.type << v.size << v.bitFrom << v.bitCount; return ba;} +inline PIByteArray & operator >>(PIByteArray & ba, PIConsole::Variable & v) {ba >> v.name >> v.id >> (int & )v.format >> v.type >> v.size >> v.bitFrom >> v.bitCount; return ba;} + +inline PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Column & v) {ba << (int)v.alignment << v.variables; return ba;} +inline PIByteArray & operator >>(PIByteArray & ba, PIConsole::Column & v) {ba >> (int & )v.alignment >> v.variables; return ba;} + +inline PIByteArray & operator <<(PIByteArray & ba, const PIConsole::Tab & v) {ba << v.name << v.status << (uchar)v.key << v.columns; return ba;} +inline PIByteArray & operator >>(PIByteArray & ba, PIConsole::Tab & v) {ba >> v.name >> v.status >> (uchar&)v.key >> v.columns; return ba;} + +#endif // PICONSOLE_H diff --git a/src/system/pikbdlistener.cpp b/src/system/pikbdlistener.cpp new file mode 100755 index 00000000..1f7d674b --- /dev/null +++ b/src/system/pikbdlistener.cpp @@ -0,0 +1,176 @@ +/* + PIP - Platform Independent Primitives + Keyboard grabber for console + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pikbdlistener.h" + + +/** \class PIKbdListener + * \brief Keyboard console input listener + * \details This class provide listening of console keyboard input. + * There is two ways to receive pressed key: + * * external static function with format "void func(char key, void * data_)" + * * event \a keyPressed() + * + * Also there is static variable \a exiting which by default is set to + * \b false. If \a enableExitCapture() was called and listener was started + * with function \a start(), this variable will be set to \b true if exit + * key will be pressed. By default exit key is 'Q' = shift + 'q'. + * To wait for this variable changes to \b true there is WAIT_FOR_EXIT macro + * \snippet pikbdlistener.cpp main + * */ + + +bool PIKbdListener::exiting; + +PIKbdListener::PIKbdListener(KBFunc slot, void * _data): PIThread() { + setName("keyboard_listener"); +#ifdef WINDOWS + hIn = GetStdHandle(STD_INPUT_HANDLE); + GetConsoleMode(hIn, &smode); +#else + struct termios term; + tcgetattr(0, &term); + sterm = term; +#endif + is_active = true; + ret_func = slot; + data_ = _data; + PIKbdListener::exiting = exit_enabled = false; + start(); +} + + +void PIKbdListener::begin() { +#ifdef WINDOWS + GetConsoleMode(hIn, &tmode); + SetConsoleMode(hIn, ENABLE_PROCESSED_INPUT); +#else + struct termios term; + tcgetattr(0, &term); + term.c_lflag &= ~(ECHO | ICANON) | NOFLSH; + tterm = term; + tcsetattr(0, TCSANOW, &term); +#endif +} + + +void PIKbdListener::run() { + rc = 0; + char lc = 0; +#ifdef WINDOWS + INPUT_RECORD ir; + ReadConsoleInput(hIn, &ir, 1, &ret); + if (ir.EventType == KEY_EVENT) { + KEY_EVENT_RECORD ker = ir.Event.KeyEvent; + if (ker.bKeyDown) { + bool ctrl = ((ker.dwControlKeyState & LEFT_CTRL_PRESSED) || (ker.dwControlKeyState & RIGHT_CTRL_PRESSED)); + bool shift = (ker.dwControlKeyState & SHIFT_PRESSED); + if (ker.dwControlKeyState & CAPSLOCK_ON) shift = !shift; + //cout << "key " << int(ker.wVirtualKeyCode) << endl; + switch (ker.wVirtualKeyCode) { + case 37: ret = 1; lc = (ctrl ? CtrlLeftArrow : LeftArrow); break; + case 38: ret = 1; lc = (ctrl ? CtrlUpArrow : UpArrow); break; + case 39: ret = 1; lc = (ctrl ? CtrlRightArrow : RightArrow); break; + case 40: ret = 1; lc = (ctrl ? CtrlDownArrow : DownArrow); break; + default: ret = 1; lc = (shift ? char(toupper(ker.uChar.AsciiChar)) : ker.uChar.AsciiChar); break; + } + if (lc == 0) {piMSleep(10); return;} + } else {piMSleep(10); return;} + } else {piMSleep(10); return;} + /*if (lc == 0) { + ReadConsole(hIn, &rc, 1, &ret, 0); + //cout << "read console" << endl; + lc = char(rc); + }*/ + /*if (ret < 0 || ret > 3) return; + lc = char(((uchar * )&rc)[ret - 1]); + for (int i = 0; i < ret; ++i) + cout << std::hex << int(((uchar * )&rc)[i]) << ' '; + cout << endl << std::hex << rc << endl;*/ +#else + tcsetattr(0, TCSANOW, &tterm); + ret = read(0, &rc, 4); + if (rc == 0) {piMSleep(10); return;} + if (ret < 0 || ret > 3) {piMSleep(10); return;} + lc = char(((uchar * )&rc)[ret - 1]); + /*for (int i = 0; i < ret; ++i) + cout << std::hex << int(((uchar * )&rc)[i]) << ' '; + cout << endl << std::hex << rc << endl;*/ + if (((char * )&rc)[0] == '\e' && ret == 3) { + if (((char * )&rc)[1] == '[') { + switch (((char * )&rc)[2]) { + case 'A': lc = UpArrow; break; // up + case 'B': lc = DownArrow; break; // down + case 'C': lc = RightArrow; break; // right + case 'D': lc = LeftArrow; break; // left + case 'H': lc = Home; break; + case 'F': lc = End; break; + } + } + } + if (((char * )&rc)[0] == '5' && ret == 2) { + switch (((char * )&rc)[1]) { + case 'A': lc = CtrlUpArrow; break; // up + case 'B': lc = CtrlDownArrow; break; // down + case 'C': lc = CtrlRightArrow; break; // right + case 'D': lc = CtrlLeftArrow; break; // left + case 'H': lc = CtrlHome; break; + case 'F': lc = CtrlEnd; break; + } + } +#endif + if ((((char * )&rc)[0] == '\n' || ((char * )&rc)[0] == '\r') && ret == 1) + lc = Return; + if (exit_enabled && ret == 1 && lc == exit_key) { + PIKbdListener::exiting = true; + return; + } + if (ret > 0) { + keyPressed(lc, data_); + if (ret_func != 0) ret_func(lc, data_); + } +} + + +void PIKbdListener::end() { + //cout << "list end" << endl; +#ifdef WINDOWS + SetConsoleMode(hIn, smode); +#else + tcsetattr(0, TCSANOW, &sterm); +#endif +} + + +void PIKbdListener::setActive(bool yes) { + is_active = yes; + if (is_active) { +#ifdef WINDOWS + SetConsoleMode(hIn, tmode); +#else + tcsetattr(0, TCSANOW, &tterm); +#endif + } else { +#ifdef WINDOWS + SetConsoleMode(hIn, smode); +#else + tcsetattr(0, TCSANOW, &sterm); +#endif + } +} diff --git a/src/system/pikbdlistener.h b/src/system/pikbdlistener.h new file mode 100755 index 00000000..a6b908e3 --- /dev/null +++ b/src/system/pikbdlistener.h @@ -0,0 +1,139 @@ +/*! \file pikbdlistener.h + * \brief Keyboard console input listener +*/ +/* + PIP - Platform Independent Primitives + Keyboard grabber for console + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIKBDLISTENER_H +#define PIKBDLISTENER_H + +#include "pithread.h" +#ifndef WINDOWS +# include +#endif + +#define WAIT_FOR_EXIT while (!PIKbdListener::exiting) msleep(5); + +typedef void (*KBFunc)(char, void * ); + +class PIP_EXPORT PIKbdListener: public PIThread +{ + PIOBJECT(PIKbdListener) + PIOBJECT_PARENT(PIThread) + friend class PIConsole; +public: + + //! Special keyboard keys + enum SpecialSymbol { + UpArrow /** Up arrow key */ = -1, + DownArrow /** Down arrow key */ = -2, + RightArrow /** Right arrow key */ = -3, + LeftArrow /** Left arrow key */ = -4, + Home /** Home key */ = -9, + End /** End key */ = -10, + CtrlUpArrow /** Ctrl + Up arrow key */ = -5, + CtrlDownArrow /** Ctrl + Down arrow key */ = -6, + CtrlRightArrow /** Ctrl + Right arrow key */ = -7, + CtrlLeftArrow /** Ctrl + Left arrow key */ = -8, + CtrlHome /** Ctrl + Home key */ = -11, + CtrlEnd /** Ctrl + End key */ = -12, + Return /** Enter key */ = 0x0a, + Esc /** Escape key */ = 0x1b, + Space /** Space key */ = 0x20, + Backspace /** Backspace key */ = 0x7f + }; + + //! Constructs keyboard listener with external function "slot" and custom data "data" + PIKbdListener(KBFunc slot = 0, void * data = 0); + + ~PIKbdListener() {terminate(); end();} + + + //! Returns custom data + void * data() {return data_;} + + //! Set custom data to "_data" + void setData(void * _data) {data_ = _data;} + + //! Set external function to "slot" + void setSlot(KBFunc slot) {ret_func = slot;} + + //! Returns if exit key if awaiting + bool exitCaptured() const {return exit_enabled;} + + //! Returns exit key, default 'Q' + char exitKey() const {return exit_key;} + + + //! Returns if keyboard listening is active (not running!) + bool isActive() {return is_active;} + + EVENT_HANDLER( void, enableExitCapture) {enableExitCapture('Q');} + EVENT_HANDLER1(void, enableExitCapture, char, key) {exit_enabled = true; exit_key = key;} + EVENT_HANDLER(void, disableExitCapture) {exit_enabled = false;} + EVENT_HANDLER(void, setActive) {setActive(true);} + EVENT_HANDLER1(void, setActive, bool, yes); + + EVENT2(keyPressed, char, key, void * , data) + +//! \handlers +//! \{ + + //! \fn void enableExitCapture(char key = 'Q') + //! \brief Enable exit key "key" awaiting + + //! \fn void disableExitCapture() + //! \brief Disable exit key awaiting + + //! \fn void setActive(bool yes = true) + //! \brief Set keyboard listening is active or not + +//! \} +//! \events +//! \{ + + //! \fn void keyPressed(char key, void * data) + //! \brief Raise on key "key" pressed, "data" is custom data + +//! \} + + static bool exiting; + +private: + void begin(); + void run(); + void end(); + + KBFunc ret_func; + char exit_key; + bool exit_enabled, is_active; + void * data_; +#ifdef WINDOWS + DWORD ret, rc; + void * hIn; + DWORD smode, tmode; +#else + int rc; + int ret; + struct termios sterm, tterm; +#endif + +}; + +#endif // PIKBDLISTENER_H diff --git a/src/system/pimonitor.cpp b/src/system/pimonitor.cpp new file mode 100755 index 00000000..73ea3f1a --- /dev/null +++ b/src/system/pimonitor.cpp @@ -0,0 +1,26 @@ +/* + PIP - Platform Independent Primitives + Counter of some PIP types + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pimonitor.h" + +PIMonitor piMonitor; + +PIMonitor::PIMonitor() { + containers = strings = threads = timers = serials = ethernets = files = objects = 0; +} diff --git a/src/system/pimonitor.h b/src/system/pimonitor.h new file mode 100755 index 00000000..288e9634 --- /dev/null +++ b/src/system/pimonitor.h @@ -0,0 +1,39 @@ +/* + PIP - Platform Independent Primitives + Counter of some PIP types + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIMONITOR_H +#define PIMONITOR_H + +#include "pip_export.h" + +#if defined(DOXYGEN) || defined(__GNUC__) +# undef PIP_EXPORT +# define PIP_EXPORT +#endif + +class PIP_EXPORT PIMonitor +{ +public: + PIMonitor(); + + int containers, strings, threads, timers, serials, ethernets, files, objects; + +}; + +#endif // PIMONITOR_H diff --git a/src/system/piprocess.cpp b/src/system/piprocess.cpp new file mode 100755 index 00000000..3f237575 --- /dev/null +++ b/src/system/piprocess.cpp @@ -0,0 +1,199 @@ +/* + PIP - Platform Independent Primitives + Process + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "piprocess.h" + + +PIProcess::PIProcess(): PIThread() { + exit_code = -1; +#ifdef WINDOWS + pi.dwProcessId = 0; +#else + pid = 0; +#endif + is_exec = false; + g_in = g_out = g_err = false; + t_in = t_out = t_err = false; + env = PIProcess::currentEnvironment(); +} + + +PIProcess::~PIProcess() { + if (t_in) f_in.remove(); + if (t_out) f_out.remove(); + if (t_err) f_err.remove(); +} + + +void PIProcess::exec_() { + is_exec = false; + startOnce(); + //cout << "exec wait" << endl; + while (!is_exec) + msleep(1); + //cout << "exec end" << endl; +} + + +void PIProcess::run() { + //cout << "run" << endl; + string str; + /// arguments convertion + as = 0; +#ifdef WINDOWS + //args.pop_front(); + piForeachC (PIString & i, args) + as += i.lengthAscii() + 1; + char * a = new char[as]; + memset(a, ' ', as - 1); + as = 0; + for (int i = 0; i < args.size_s(); ++i) { + str = args[i].stdString(); + memcpy(&a[as], str.c_str(), str.size()); + as += str.length() + 1; + } + a[as - 1] = 0; +#else + char * a[args.size_s() + 1]; + for (int i = 0; i < args.size_s(); ++i) { + str = args[i].stdString(); + a[i] = new char[str.size() + 1]; + memcpy(a[i], str.c_str(), str.size()); + a[i][str.size()] = 0; + //cout << a[i] << endl; + } + a[args.size_s()] = 0; +#endif + /// environment convertion + char ** e = new char*[env.size_s() + 1]; + for (int i = 0; i < env.size_s(); ++i) { + str = env[i].stdString(); + e[i] = new char[str.size() + 1]; + memcpy(e[i], str.c_str(), str.size()); + e[i][str.size()] = 0; + //cout << e[i] << endl; + } + e[env.size_s()] = 0; + /// files for stdin/out/err + t_in = t_out = t_err = false; + if (f_in.path().isEmpty()) { + f_in = PIFile::openTemporary(PIIODevice::ReadWrite); + t_in = true; + } + //f_in.open(PIIODevice::ReadWrite); f_in.close(); + if (f_out.path().isEmpty()) { + f_out = PIFile::openTemporary(PIIODevice::ReadWrite); + t_out = true; + } + //f_out.open(PIIODevice::WriteOnly); f_out.close(); + if (f_err.path().isEmpty()) { + f_err = PIFile::openTemporary(PIIODevice::ReadWrite); + t_err = true; + } + //f_err.open(PIIODevice::WriteOnly); f_err.close(); + + str = args.front().stdString(); + is_exec = true; + execStarted(PIString(str)); +#ifndef WINDOWS + pid = fork(); + if (pid == 0) { +#endif + tf_in = tf_out = tf_err = 0; + //cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl; + //cout << f_out.path() << endl; + if (g_in) tf_in = freopen(f_in.path().data(), "r", stdin); + if (g_out) tf_out = freopen(f_out.path().data(), "w", stdout); + if (g_err) tf_err = freopen(f_err.path().data(), "w", stderr); +#ifndef WINDOWS + if (!wd.isEmpty()) as = chdir(wd.data()); +#endif +#ifdef WINDOWS + GetStartupInfoA(&si); + memset(&pi, 0, sizeof(pi)); + if(CreateProcessA(0, // No module name (use command line) + a, // Command line + 0, // Process handle not inheritable + 0, // Thread handle not inheritable + false, // Set handle inheritance to FALSE + 0, // No creation flags + 0,//e, // Use environment + wd.isEmpty() ? 0 : wd.data(), // Use working directory + &si, // Pointer to STARTUPINFO structure + &pi)) // Pointer to PROCESS_INFORMATION structure + { + WaitForSingleObject(pi.hProcess, INFINITE); + CloseHandle(pi.hProcess); + } else + piCoutObj << "\"CreateProcess\" error, " << errorString(); +#else + + //cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl; + if (execve(str.c_str(), a, e) < 0) + piCoutObj << "\"execve\" error, " << errorString(); + } else { + msleep(1); + //cout << "wait" << endl; + wait(&exit_code); + /*if (tf_in != 0) fclose(tf_in); + if (tf_out != 0) fclose(tf_out); + if (tf_err != 0) fclose(tf_err);*/ + pid = 0; + //cout << "wait done" << endl; + } +#endif + execFinished(PIString(str), exit_code); + is_exec = false; + for (int i = 0; i < env.size_s(); ++i) + delete e[i]; + delete e; +#ifdef WINDOWS + delete a; +#else + for (int i = 0; i < args.size_s(); ++i) + delete a[i]; +#endif + //cout << "end " << tf_in << ", " << tf_out << ", " << tf_err << endl; +} + + +void PIProcess::removeEnvironmentVariable(const PIString & variable) { + PIString s; + for (int i = 0; i < env.size_s(); ++i) { + s = env[i]; + if (s.left(s.find("=")).trimmed() == variable) { + env.remove(i); + --i; + } + } +} + + +void PIProcess::setEnvironmentVariable(const PIString & variable, const PIString & value) { + PIString s, v; + for (int i = 0; i < env.size_s(); ++i) { + s = env[i]; + v = s.left(s.find("=")).trimmed(); + if (v == variable) { + env[i] = v + "=" + value; + return; + } + } + env << variable + "=" + value; +} diff --git a/src/system/piprocess.h b/src/system/piprocess.h new file mode 100755 index 00000000..4feed9b0 --- /dev/null +++ b/src/system/piprocess.h @@ -0,0 +1,130 @@ +/*! \file piprocess.h + * \brief Process +*/ +/* + PIP - Platform Independent Primitives + Process + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIPROCESS_H +#define PIPROCESS_H + +#include "pithread.h" +#include "pifile.h" +#ifdef WINDOWS +//# include <.h> +#else +# include +#endif + +/// events: +/// execStarted(PIString program) +/// execFinished(PIString program, int exit_code) +/// +/// handlers: +/// bool exec(const PIString & program) +/// bool exec(const PIString & program, const PIString & arg1) +/// bool exec(const PIString & program, const PIString & arg1, const PIString & arg2) +/// bool exec(const PIString & program, const PIString & arg1, const PIString & arg2, const PIString & arg3) +/// bool exec(const PIString & program, const PIStringList & args) +/// void terminate() +/// bool waitForFinish(int timeout_msecs = 60000) +class PIP_EXPORT PIProcess: private PIThread +{ + PIOBJECT_SUBCLASS(PIProcess, PIThread) +public: + PIProcess(); + virtual ~PIProcess(); + + int exitCode() const {return exit_code;} + int pID() const { +#ifdef WINDOWS + return pi.dwProcessId; +#else + return pid; +#endif + } + + void setGrabInput(bool yes) {g_in = yes;} + void setGrabOutput(bool yes) {g_out = yes;} + void setGrabError(bool yes) {g_err = yes;} + void setInputFile(const PIString & path) {f_in.setPath(path);} + void setOutputFile(const PIString & path) {f_out.setPath(path);} + void setErrorFile(const PIString & path) {f_err.setPath(path);} + void unsetInputFile() {f_in.setPath("");} + void unsetOutputFile() {f_out.setPath("");} + void unsetErrorFile() {f_err.setPath("");} + PIString workingDirectory() const {return wd;} + void setWorkingDirectory(const PIString & path) {wd = path;} + void resetWorkingDirectory() {wd.clear();} + PIByteArray readOutput() {f_out.open(PIIODevice::ReadOnly); return f_out.readAll();} + PIByteArray readError() {f_err.open(PIIODevice::ReadOnly); return f_err.readAll();} + + PIStringList environment() {return env;} + void clearEnvironment() {env.clear();} + void removeEnvironmentVariable(const PIString & variable); + void setEnvironmentVariable(const PIString & variable, const PIString & value); + + EVENT_HANDLER1(void, exec, const PIString & , program) {args.clear(); args << program; exec_();} + EVENT_HANDLER2(void, exec, const PIString & , program, const PIString & , arg) {args.clear(); args << program << arg; exec_();} + EVENT_HANDLER3(void, exec, const PIString & , program, const PIString & , arg1, const PIString & , arg2) {args.clear(); args << program << arg1 << arg2; exec_();} + EVENT_HANDLER4(void, exec, const PIString & , program, const PIString & , arg1, const PIString & , arg2, const PIString & , arg3) {args.clear(); args << program << arg1 << arg2 << arg3; exec_();} + EVENT_HANDLER2(void, exec, const PIString & , program, const PIStringList & , args_) {args << program << args_; exec_();} + EVENT_HANDLER(void, terminate) { +#ifdef WINDOWS + if (is_exec) if (!TerminateProcess(pi.hProcess, 0)) return; pi.dwProcessId = 0; +#else + if (is_exec) kill(pid, SIGKILL); pid = 0; +#endif + } + EVENT_HANDLER(bool, waitForFinish) {return waitForFinish(60000);} + EVENT_HANDLER1(bool, waitForFinish, int, timeout_msecs) {return PIThread::waitForFinish(timeout_msecs);} + + EVENT1(execStarted, PIString, program) + EVENT2(execFinished, PIString, program, int, exit_code) + + static PIStringList currentEnvironment() {PIStringList l; int i = 0; while (environ[i] != 0) {l << environ[i]; ++i;} return l;} + static int currentPID() { +#ifdef WINDOWS + return GetCurrentProcessId(); +#else + return getpid(); +#endif + } + +private: + virtual void run(); + void exec_(); + + PIStringList args, env; + PIString wd; + PIByteArray out; + PIFile f_in, f_out, f_err; + bool g_in, g_out, g_err, t_in, t_out, t_err; +#ifdef WINDOWS + STARTUPINFOA si; + PROCESS_INFORMATION pi; +#else + pid_t pid; +#endif + FILE * tf_in, * tf_out, * tf_err; + int exit_code, sz, as; + bool is_exec; + +}; + +#endif // PIPROCESS_H diff --git a/src/system/piscreen.cpp b/src/system/piscreen.cpp new file mode 100644 index 00000000..e8ede7ea --- /dev/null +++ b/src/system/piscreen.cpp @@ -0,0 +1,208 @@ +/* + PIP - Platform Independent Primitives + Console output/input + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "piscreen.h" + + +/** \class PIScreen + * \brief Console output class + * \details + * \section PIScreen_sec0 Synopsis + * This class provides output to console with automatic alignment and update. + * It supports tabs, keyboard listening, formats and colors. + * + * \section PIScreen_sec1 Layout + * %PIScreen works with variable pointers. You should add your variables with + * functions \a addVariable() which receives label name, pointer to variable + * and optional column and format. Columns count is dynamically increased if + * new column used. E.g. if you add variable to empty tab to column 3, columns + * count will be increased to 3, but two firsts columns will be empty. Each column + * filled from top to bottom, but you can add just string with function + * \a addString() or add empty line with function \a addEmptyLine(). Layout scheme: + * \image html piconsole_layout.png + * + * \section PIScreen_sec2 Keyboard usage + * %PIScreen should to be single in application. %PIScreen aggregate PIKbdListener + * which grab keyboard and automatic switch tabs by theirs bind keys. If there is no + * tab binded to pressed key external function "slot" will be called + * + **/ + + +extern PIMutex __PICout_mutex__; + + +PIScreen::SystemConsole::SystemConsole() { + width = height = pwidth = pheight = 0; + int w, h; +#ifdef WINDOWS + ulcoord.X = 0; + hOut = GetStdHandle(STD_OUTPUT_HANDLE); + GetConsoleScreenBufferInfo(hOut, &sbi); + dattr = sbi.wAttributes; + w = sbi.srWindow.Right - sbi.srWindow.Left; + h = sbi.srWindow.Bottom - sbi.srWindow.Top; + ulcoord.Y = sbi.srWindow.Top; + GetConsoleMode(hOut, &smode); + GetConsoleCursorInfo(hOut, &curinfo); +#else + winsize ws; + ioctl(0, TIOCGWINSZ, &ws); + w = ws.ws_col; + h = ws.ws_row; +#endif + resize(w, h); +} + + +PIScreen::SystemConsole::~SystemConsole() { +#ifdef WINDOWS + SetConsoleMode(hOut, smode); + SetConsoleTextAttribute(hOut, dattr); +#endif +} + + +void PIScreen::SystemConsole::begin() { +#ifdef WINDOWS + SetConsoleMode(hOut, ENABLE_WRAP_AT_EOL_OUTPUT); + GetConsoleScreenBufferInfo(hOut, &sbi); + bc.X = 0; + bc.Y = 0; +#endif + clearScreen(); + hideCursor(); +} + + +void PIScreen::SystemConsole::end() { + showCursor(); +} + + +void PIScreen::SystemConsole::prepare() { + int w, h; +#ifdef WINDOWS + GetConsoleScreenBufferInfo(hOut, &sbi); + w = sbi.srWindow.Right - sbi.srWindow.Left + 1; + h = sbi.srWindow.Bottom - sbi.srWindow.Top + 1; +#else + winsize ws; + ioctl(0, TIOCGWINSZ, &ws); + w = ws.ws_col; + h = ws.ws_row; +#endif + resize(w, h); +} + + +void PIScreen::SystemConsole::resize(int w, int h) { + if (w == pwidth && h == pheight) return; + width = piMax(w, 0); + height = piMax(h, 0); + pwidth = width; + pheight = height; + cells.resize(height); + pcells.resize(height); + for (int i = 0; i < height; ++i) { + cells[i].resize(width); + pcells[i].resize(width, Cell(0)); + } +#ifdef WINDOWS + bs.X = width; + bs.Y = height; + chars.resize(width * height); +#endif +} + + +void PIScreen::SystemConsole::print() { +#ifdef WINDOWS + static int cnt = 0; + for (int i = 0; i < width; ++i) + for (int j = 0; j < height; ++j) { + int k = j * width + i; + chars[k].Char.UnicodeChar = 0; + chars[k].Char.AsciiChar = ((cnt + i + j / 3)%11 + '0'); + chars[k].Attributes = sbi.wAttributes; + if (i % 3 == 0) chars[k].Attributes |= BACKGROUND_RED; + //if (j % 3 == 1) chars[k].Attributes |= BACKGROUND_GREEN; + //if (j % 3 == 2) chars[k].Attributes |= BACKGROUND_BLUE; + /*if (i % 3 == 2) chars[k].Attributes |= FOREGROUND_INTENSITY; + if (i % 3 == 2) { + chars[k].Attributes |= FOREGROUND_INTENSITY; + chars[k].Attributes &= ~(FOREGROUND_RED | FOREGROUND_BLUE); + }*/ + } + srect = sbi.srWindow; + WriteConsoleOutput(hOut, chars.data(), bs, bc, &srect); +#else + for (int i = 0; i < height; ++i) + pcells[i] = cells[i]; +#endif +} + + + + +PIScreen::PIScreen(bool startNow, KBFunc slot): PIThread() { + setName("screen"); + setPriority(piLow); + needLockRun(true); + ret_func = slot; + listener = new PIKbdListener(key_event, this); + if (startNow) start(); +} + + +PIScreen::~PIScreen() { + if (isRunning()) + stop(); + delete listener; +} + + +void PIScreen::key_event(char key, void * t) { + PIScreen * p = (PIScreen * )t; + if (p->ret_func != 0) p->ret_func(key, t); + p->keyPressed(key, t); +} + + +void PIScreen::stop(bool clear) { + PIThread::stop(true); + if (clear) console.clearScreen(); + fflush(0); +} + + +void PIScreen::begin() { + console.begin(); +} + + +void PIScreen::run() { + console.prepare(); + console.print(); +} + + +void PIScreen::end() { + console.end(); +} diff --git a/src/system/piscreen.h b/src/system/piscreen.h new file mode 100644 index 00000000..d0576662 --- /dev/null +++ b/src/system/piscreen.h @@ -0,0 +1,194 @@ +/*! \file piscreen.h + * \brief Console output class +*/ +/* + PIP - Platform Independent Primitives + Console output/input + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PSCREEN_H +#define PSCREEN_H + +#include "pikbdlistener.h" +#include "piprotocol.h" +#include "pidiagnostics.h" +#include "pisystemmonitor.h" +#ifndef WINDOWS +# include +# include +#endif + + +class PIP_EXPORT PIScreen: public PIThread +{ + PIOBJECT_SUBCLASS(PIScreen, PIThread) +public: + + //! Constructs %PIScreen with key handler "slot" and if "startNow" start it + PIScreen(bool startNow = true, KBFunc slot = 0); + + ~PIScreen(); + + //! Color for chars or background + enum Color { + Default /** Default */, + Black /** Black */, + Red /** Red */, + Green /** Green */, + Yellow /** Yellow */, + Blue /** Blue */, + Magenta /** Magenta */, + Cyan /** Cyan */, + White /** White */ + }; + + //! Flags for chars + enum CharFlag { + Bold /** Bold flag */ = 0x1, + Blink /** Blink flag */ = 0x2, + }; + + //! Variables output format + enum __Format { + Dec /** Decimal base for integers */ = 0x1000000, + Hex /** Hexadecimal base for integers */ = 0x2000000, + Oct /** Octal base for integers */ = 0x4000000, + Bin /** Binary base for integers */ = 0x8000000, + Scientific /** Scientific representation of floats */ = 0x10000000, + SystemTimeSplit /** PISystemTime split representation (* s, * ns) */ = 0x20000000, + SystemTimeSeconds /** PISystemTime seconds representation (*.* s) */ = 0x40000000 + }; + + //! Column labels alignment + enum Alignment { + Nothing /** No alignment */ , + Left /** Labels align left and variables align left */ , + Right /** Labels align right and variables align left */, + Center /** */ + }; + + typedef PIFlags CharFlags; + + + //! Directly call function from \a PIKbdListener + void enableExitCapture(char key = 'Q') {listener->enableExitCapture(key);} + + //! Directly call function from \a PIKbdListener + void disableExitCapture() {listener->disableExitCapture();} + + //! Directly call function from \a PIKbdListener + bool exitCaptured() const {return listener->exitCaptured();} + + //! Directly call function from \a PIKbdListener + char exitKey() const {return listener->exitKey();} + + + EVENT_HANDLER0(void, waitForFinish) {WAIT_FOR_EXIT} + EVENT_HANDLER0(void, start) {start(false);} + EVENT_HANDLER1(void, start, bool, wait) {PIThread::start(40); if (wait) waitForFinish();} + EVENT_HANDLER0(void, stop) {stop(false);} + EVENT_HANDLER1(void, stop, bool, clear); + + EVENT2(keyPressed, char, key, void * , data) + +//! \handlers +//! \{ + + //! \fn void waitForFinish() + //! \brief block until finished (exit key will be pressed) + + //! \fn void clearVariables(bool clearScreen = true) + //! \brief Remove all columns at current tab and if "clearScreen" clear the screen + + //! \fn void start(bool wait = false) + //! \brief Start console output and if "wait" block until finished (exit key will be pressed) + + //! \fn void stop(bool clear = false) + //! \brief Stop console output and if "clear" clear the screen + +//! \} +//! \events +//! \{ + + //! \fn void keyPressed(char key, void * data) + //! \brief Raise on key "key" pressed, "data" is pointer to %PIConsole object + +//! \} + +private: + class SystemConsole { + public: + SystemConsole(); + ~SystemConsole(); + struct Cell { + Cell(char c = ' ') {color_back = color_char = flags = 0; symbol = c;} + uchar color_char; + uchar color_back; + ushort flags; + PIChar symbol; + }; + void begin(); + void end(); + void prepare(); + void print(); + void resize(int w, int h); +#ifdef WINDOWS + void getWinCurCoord() {GetConsoleScreenBufferInfo(hOut, &csbi); ccoord = csbi.dwCursorPosition;} + COORD & getWinCoord(int dx = 0, int dy = 0) {getWinCurCoord(); ccoord.X += dx; ccoord.Y += dy; return ccoord;} + void toUpperLeft() {SetConsoleCursorPosition(hOut, ulcoord);} + void moveTo(int x = 0, int y = 0) {ccoord.X = x; ccoord.Y = ulcoord.Y + y; SetConsoleCursorPosition(hOut, ccoord);} + void hideCursor() {curinfo.bVisible = false; SetConsoleCursorInfo(hOut, &curinfo);} + void showCursor() {curinfo.bVisible = true; SetConsoleCursorInfo(hOut, &curinfo);} + void clearScreen() {toUpperLeft(); FillConsoleOutputAttribute(hOut, dattr, width * (height + 1), ulcoord, &written); + FillConsoleOutputCharacter(hOut, ' ', width * (height + 1), ulcoord, &written);} + void clearScreenLower() {getWinCurCoord(); FillConsoleOutputAttribute(hOut, dattr, width * height - width * ccoord.Y + ccoord.X, ccoord, &written); + FillConsoleOutputCharacter(hOut, ' ', width * height - width * ccoord.Y + ccoord.X, ccoord, &written);} +#else + void toUpperLeft() {printf("\e[H");} + void moveTo(int x = 0, int y = 0) {printf("\e[%d;%dH", y, x);} + void hideCursor() {printf("\e[?25l");} + void showCursor() {printf("\e[?25h");} + void clearScreen() {printf("\e[0m\e[H\e[J");} + void clearScreenLower() {printf("\e[0m\e[J");} +#endif +#ifdef WINDOWS + void * hOut; + CONSOLE_SCREEN_BUFFER_INFO sbi, csbi; + CONSOLE_CURSOR_INFO curinfo; + COORD ccoord, ulcoord, bs, bc; + SMALL_RECT srect; + WORD dattr; + DWORD smode, written; + PIVector chars; +#endif + int width, height, pwidth, pheight; + PIVector > cells, pcells, dcells; + }; + + void begin(); + void run(); + void end(); + static void key_event(char key, void * t); + + SystemConsole console; + PIKbdListener * listener; + KBFunc ret_func; + + +}; + +#endif // PSCREEN_H diff --git a/src/system/pisignals.cpp b/src/system/pisignals.cpp new file mode 100755 index 00000000..a06f58da --- /dev/null +++ b/src/system/pisignals.cpp @@ -0,0 +1,111 @@ +/* + PIP - Platform Independent Primitives + Signals + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pisignals.h" + +PISignals::SignalEvent PISignals::ret_func; + + +void PISignals::grabSignals(PIFlags signals_) { + if (signals_[PISignals::Interrupt]) signal(signalCode(PISignals::Interrupt), PISignals::signal_event); + if (signals_[PISignals::Illegal]) signal(signalCode(PISignals::Illegal), PISignals::signal_event); + if (signals_[PISignals::Abort]) signal(signalCode(PISignals::Abort), PISignals::signal_event); + if (signals_[PISignals::FPE]) signal(signalCode(PISignals::FPE), PISignals::signal_event); + if (signals_[PISignals::SegFault]) signal(signalCode(PISignals::SegFault), PISignals::signal_event); + if (signals_[PISignals::Termination]) signal(signalCode(PISignals::Termination), PISignals::signal_event); + if (signals_[PISignals::UserDefined1]) signal(signalCode(PISignals::UserDefined1), PISignals::signal_event); + if (signals_[PISignals::UserDefined2]) signal(signalCode(PISignals::UserDefined2), PISignals::signal_event); +#ifndef WINDOWS + if (signals_[PISignals::Hangup]) signal(signalCode(PISignals::Hangup), PISignals::signal_event); + if (signals_[PISignals::Quit]) signal(signalCode(PISignals::Quit), PISignals::signal_event); + if (signals_[PISignals::Kill]) signal(signalCode(PISignals::Kill), PISignals::signal_event); + if (signals_[PISignals::BrokenPipe]) signal(signalCode(PISignals::BrokenPipe), PISignals::signal_event); + if (signals_[PISignals::Timer]) signal(signalCode(PISignals::Timer), PISignals::signal_event); + if (signals_[PISignals::ChildStopped]) signal(signalCode(PISignals::ChildStopped), PISignals::signal_event); + if (signals_[PISignals::Continue]) signal(signalCode(PISignals::Continue), PISignals::signal_event); + if (signals_[PISignals::StopProcess]) signal(signalCode(PISignals::StopProcess), PISignals::signal_event); + if (signals_[PISignals::StopTTY]) signal(signalCode(PISignals::StopTTY), PISignals::signal_event); + if (signals_[PISignals::StopTTYInput]) signal(signalCode(PISignals::StopTTYInput), PISignals::signal_event); + if (signals_[PISignals::StopTTYOutput]) signal(signalCode(PISignals::StopTTYOutput), PISignals::signal_event); +#endif +} + + +int PISignals::signalCode(PISignals::Signal signal) { + switch (signal) { + case PISignals::Interrupt: return SIGINT; + case PISignals::Illegal: return SIGILL; + case PISignals::Abort: return SIGABRT; + case PISignals::FPE: return SIGFPE; + case PISignals::SegFault: return SIGSEGV; + case PISignals::Termination: return SIGTERM; + case PISignals::UserDefined1: return SIGUSR1; + case PISignals::UserDefined2: return SIGUSR2; +#ifndef WINDOWS + case PISignals::Hangup: return SIGHUP; + case PISignals::Quit: return SIGQUIT; + case PISignals::Kill: return SIGKILL; + case PISignals::BrokenPipe: return SIGPIPE; + case PISignals::Timer: return SIGALRM; + case PISignals::ChildStopped: return SIGCHLD; + case PISignals::Continue: return SIGCONT; + case PISignals::StopProcess: return SIGSTOP; + case PISignals::StopTTY: return SIGTSTP; + case PISignals::StopTTYInput: return SIGTTIN; + case PISignals::StopTTYOutput:return SIGTTOU; +#endif + default:; + } + return 0; +} + + +PISignals::Signal PISignals::signalFromCode(int signal) { + switch (signal) { + case SIGINT: return PISignals::Interrupt; + case SIGILL: return PISignals::Illegal; + case SIGABRT: return PISignals::Abort; + case SIGFPE: return PISignals::FPE; + case SIGSEGV: return PISignals::SegFault; + case SIGTERM: return PISignals::Termination; + case SIGUSR1: return PISignals::UserDefined1; + case SIGUSR2: return PISignals::UserDefined2; +#ifndef WINDOWS + case SIGHUP: return PISignals::Hangup; + case SIGQUIT: return PISignals::Quit; + case SIGKILL: return PISignals::Kill; + case SIGPIPE: return PISignals::BrokenPipe; + case SIGALRM: return PISignals::Timer; + case SIGCHLD: return PISignals::ChildStopped; + case SIGCONT: return PISignals::Continue; + case SIGSTOP: return PISignals::StopProcess; + case SIGTSTP: return PISignals::StopTTY; + case SIGTTIN: return PISignals::StopTTYInput; + case SIGTTOU: return PISignals::StopTTYOutput; +#endif + default:; + } + return PISignals::Termination; +} + + +void PISignals::signal_event(int signal) { + if (PISignals::ret_func == 0) return; + PISignals::ret_func(PISignals::signalFromCode(signal)); +} diff --git a/src/system/pisignals.h b/src/system/pisignals.h new file mode 100755 index 00000000..8ffce889 --- /dev/null +++ b/src/system/pisignals.h @@ -0,0 +1,78 @@ +/*! \file pisignals.h + * \brief System signals +*/ +/* + PIP - Platform Independent Primitives + Signals + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PISIGNALS_H +#define PISIGNALS_H + +#include "picontainers.h" +#include +#ifdef WINDOWS +# define SIGUSR1 10 +# define SIGUSR2 12 +#endif + +class PIP_EXPORT PISignals +{ +public: + enum Signal { + Interrupt /** Interrupt from keyboard */ = 0x01, // Term Interrupt from keyboard + Illegal /** Illegal Instruction */ = 0x02, // Core Illegal Instruction + Abort /** Abort signal */ = 0x04, // Core Abort signal from abort + FPE /** Floating point exception */ = 0x08, // Core Floating point exception + SegFault /** Invalid memory reference */ = 0x10, // Core Invalid memory reference + Termination /** Termination signal */ = 0x20, // Term Termination signal + Hangup = 0x40, // Term Hangup detected on controlling terminal or death of controlling process + Quit = 0x80, // Core Quit from keyboard + Kill = 0x100, // Term Kill signal + BrokenPipe = 0x200, // Term Broken pipe: write to pipe with no readers + Timer = 0x400, // Term Timer signal from alarm + UserDefined1 = 0x800, // Term User-defined signal 1 + UserDefined2 = 0x1000, // Term User-defined signal 2 + ChildStopped = 0x2000, // Ign Child stopped or terminated + Continue = 0x4000, // Cont Continue if stopped + StopProcess = 0x8000, // Stop Stop process + StopTTY = 0x10000, // Stop Stop typed at tty + StopTTYInput = 0x20000, // Stop tty input for background process + StopTTYOutput = 0x40000, // Stop tty output for background process + All = 0xFFFFF + }; + + typedef void (*SignalEvent)(PISignals::Signal); + // slot is any function format "void (PISignals::Signal)" + static void setSlot(SignalEvent slot) {ret_func = slot;} + static void grabSignals(PIFlags signals_); + static void raiseSignal(PISignals::Signal signal) {raise(signalCode(signal));} + +private: + PISignals() {ret_func = 0;} + ~PISignals() {} + + static int signalCode(PISignals::Signal signal); + static PISignals::Signal signalFromCode(int signal); + static void signal_event(int signal); + + static SignalEvent ret_func; + +}; + + +#endif // PISIGNALS_H diff --git a/src/system/pisysteminfo.cpp b/src/system/pisysteminfo.cpp new file mode 100644 index 00000000..966b38b0 --- /dev/null +++ b/src/system/pisysteminfo.cpp @@ -0,0 +1,189 @@ +/* + PIP - Platform Independent Primitives + System information + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pisysteminfo.h" +#include "pidir.h" +#include "pitime.h" +#include "piprocess.h" +#include "pisysteminfo.h" +#include "pitime.h" + + +PISystemInfo::PISystemInfo() { + processorsCount = 1; +} + + +PISystemInfo * PISystemInfo::instance() { + static PISystemInfo ret; + return &ret; +} + + +PIStringList PISystemInfo::mountRoots() { + PIStringList ret; +#ifdef WINDOWS + char letters[1024]; + DWORD ll = GetLogicalDriveStrings(1023, letters); + PIString clet; + for (int i = 0; i < ll; ++i) { + if (letters[i] == '\0') { + if (clet.size_s() > 2) ret << clet.cutRight(1); + clet.clear(); + } else + clet += PIChar(letters[i]); + } +#else +# ifdef LINUX + PIString s_df, s_m; + char in[1024]; + memset(in, 0, 1024); + FILE * fp = popen("mount -l", "r"); + PIStringList tl; + if (fp) { + while (fgets(in, 1024, fp)) { + tl = PIString(in).trim().replaceAll(" ", " ").split(" "); + if (tl.size_s() < 2) continue; + for (int i = 0; i < tl.size_s() - 1; ++i) + if (tl[i] == "on") {if (!ret.contains(tl[i + 1])) ret << tl[i + 1]; break;} + } + pclose(fp); + } +# else +# endif +#endif + return ret; +} + + +struct String3 {PIString mp, type, label;}; + +PIVector PISystemInfo::mountInfo() { + static PIVector cache; + static PITimeMeasurer tm; + static bool first = true; + if (tm.elapsed_m() < piMountInfoRefreshIntervalMs && !first) + return cache; + first = false; + tm.reset(); + cache.clear(); + + PIVector ret; + MountInfo m; +#ifdef WINDOWS + char letters[1024], volname[1024], volfs[1024]; + DWORD ll = GetLogicalDriveStrings(1023, letters); + PIString clet; + for (int i = 0; i < ll; ++i) { + if (letters[i] == '\0') { + if (GetVolumeInformation(clet.data(), volname, 1023, 0, 0, 0, volfs, 1023)) { + m.mount_point = clet; + m.filesystem = volfs; + m.label = volname; + DWORD spc, bps, free_cl, all_cl; + if (GetDiskFreeSpace(clet.data(), &spc, &bps, &free_cl, &all_cl)) { + ullong bpc = ullong(spc) * ullong(bps); + m.space_all = bpc * ullong(all_cl); + m.space_free = bpc * ullong(free_cl); + m.space_used = m.space_all - m.space_free; + } else + m.space_all = m.space_free = m.space_used = 0U; + clet.cutRight(1); + int qdd = QueryDosDevice(clet.data(), volfs, 1023); + if (qdd > 0) + m.device = volfs; + else + m.device.clear(); + ret << m; + } + clet.clear(); + } else + clet += PIChar(letters[i]); + } + + /*HANDLE hVolume = FindFirstVolumeA(volGUID, 1024); + if (hVolume) { + do { + piCout << "Volume" << PIString(volGUID); + } while (FindNextVolumeA(hVolume, volGUID, 1024)) + FindVolumeClose(hVolume); + }*/ +#else +# ifdef LINUX + PIString s_df, s_m; + char in[1024]; + memset(in, 0, 1024); + //piCout << "mountInfo 0"; + FILE * fp = popen("df -B1", "r"); + PIStringList l_df; + PIMap fs; + if (fp) { + while (fgets(in, 1024, fp)) + l_df << PIString(in).trim(); + pclose(fp); + fp = 0; + } + //piCout << "mountInfo 1"; + memset(in, 0, 1024); + fp = popen("mount -l", "r"); + PIStringList tl; + if (fp) { + while (fgets(in, 1024, fp)) { + tl = PIString(in).trim().replaceAll(" ", " ").split(" "); + if (tl.size_s() < 2) continue; + String3 me; + PIString dev; + dev = tl.front(); + for (int i = 0; i < tl.size_s() - 1; ++i) { + if (tl[i] == "on") {me.mp = tl[i + 1]; ++i; continue;} + if (tl[i] == "type") {me.type = tl[i + 1]; ++i; continue;} + } + if (tl.back().startsWith("[")) { + me.label = tl.back(); + me.label.cutLeft(1).cutRight(1); + } + fs[dev] = me; + //piCout << fsmp << fstl; + } + pclose(fp); + fp = 0; + } + if (l_df.size_s() < 2) return ret; + l_df.pop_front(); + piForeachC (PIString & s, l_df) { + PIStringList ml(s.replaceAll(" ", " ").split(" ")); + if (ml.size_s() < 2) continue; + if (ml.front() == "none") continue; + m.space_all = ml[1].toULLong(); + m.space_used = ml[2].toULLong(); + m.space_free = m.space_all - m.space_used; + String3 s3 = fs.value(ml.front()); + m.device = ml.front(); + m.filesystem = s3.type; + m.mount_point = s3.mp; + m.label = s3.label; + ret << m; + //piCout << ml; + } +# else +# endif +#endif + cache = ret; + return ret; +} diff --git a/src/system/pisysteminfo.h b/src/system/pisysteminfo.h new file mode 100644 index 00000000..8ed2e15a --- /dev/null +++ b/src/system/pisysteminfo.h @@ -0,0 +1,61 @@ +/* + PIP - Platform Independent Primitives + System information + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PISYSTEMINFO_H +#define PISYSTEMINFO_H + +#include "pitime.h" + +class PIP_EXPORT PISystemInfo { +public: + PISystemInfo(); + + struct MountInfo { + MountInfo() {space_all = space_used = space_free = 0;} + PIString mount_point; + PIString device; + PIString filesystem; + PIString label; + ullong space_all; + ullong space_used; + ullong space_free; + }; + + PIString ifconfigPath, execCommand, hostname, user, OS_name, OS_version, architecture; + PIDateTime execDateTime; + int processorsCount; + + static PIStringList mountRoots(); + static PIVector mountInfo(); + + static PISystemInfo * instance(); + +}; + +inline PICout operator <<(PICout s, const PISystemInfo::MountInfo & v) { + s.setControl(0, true); + s << "MountInfo(" << v.device << " mounted on \"" << v.mount_point << "\", type " << v.filesystem + << ", label \"" << v.label << "\", all " << PIString::readableSize(v.space_all) + << ", used " << PIString::readableSize(v.space_used) + << ", free " << PIString::readableSize(v.space_free) << ")"; + s.restoreControl(); + return s; +} + +#endif // PISYSTEMINFO_H diff --git a/src/system/pisystemmonitor.cpp b/src/system/pisystemmonitor.cpp new file mode 100755 index 00000000..a764b8d5 --- /dev/null +++ b/src/system/pisystemmonitor.cpp @@ -0,0 +1,203 @@ +/* + PIP - Platform Independent Primitives + Process resource monitor + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pisystemmonitor.h" +#include "pisysteminfo.h" +#ifdef WINDOWS +# include "TlHelp32.h" +#endif + + +PISystemMonitor::PISystemMonitor(): PIThread() { + pID_ = cycle = 0; + cpu_count = PISystemInfo::instance()->processorsCount; +#ifndef WINDOWS +# ifdef QNX + page_size = 4096; +# else + page_size = getpagesize(); +# endif +#else + hProc = 0; + mem_cnt.cb = sizeof(mem_cnt); +#endif + setName("system_monitor"); +} + + +PISystemMonitor::~PISystemMonitor() { + stop(); +} + + +PISystemMonitor::ProcessStats::ProcessStats() { + ID = parent_ID = group_ID = session_ID = priority = threads = 0; + physical_memsize = resident_memsize = share_memsize = virtual_memsize = data_memsize = 0; + cpu_load_user = cpu_load_system = 0.f; +} + + +bool PISystemMonitor::startOnProcess(int pID) { + stop(); + pID_ = pID; +#ifndef WINDOWS + file.open("/proc/" + PIString::fromNumber(pID_) + "/stat", PIIODevice::ReadOnly); + filem.open("/proc/" + PIString::fromNumber(pID_) + "/statm", PIIODevice::ReadOnly); + if (!file.isOpened()) { + piCoutObj << "Can`t find process with ID = " << pID_ << "!"; + return false; + } + cycle = -1; +#else + hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pID_); + if (hProc == 0) { + piCoutObj << "Can`t open process with ID = " << pID_ << "," << errorString(); + return false; + } + tm.reset(); +#endif + return start(1000); +} + + +void PISystemMonitor::stop() { + PIThread::stop(); +#ifdef WINDOWS + if (hProc != 0) { + CloseHandle(hProc); + hProc = 0; + } +#endif + +} + + +void PISystemMonitor::run() { +#ifndef WINDOWS + file.seekToBegin(); + PIString str(file.readAll(true)); + int si = str.find('(') + 1, fi = 0, cc = 1; + for (int i = si; i < str.size_s(); ++i) { + if (str[i] == '(') cc++; + if (str[i] == ')') cc--; + if (cc <= 0) { + fi = i; + break; + } + } + stat.exec_name = str.mid(si, fi - si); + str.cutMid(si - 1, fi - si + 3); + PIStringList sl = str.split(" "); + if (sl.size_s() < 19) return; + stat.ID = sl[0].toInt(); + stat.state = sl[1]; + stat.parent_ID = sl[2].toInt(); + stat.group_ID = sl[3].toInt(); + stat.session_ID = sl[4].toInt(); + if (cycle < 0) { + cpu_u_prev = cpu_u_cur = sl[12].toLLong(); + cpu_s_prev = cpu_s_cur = sl[13].toLLong(); + } + cycle++; + //if (cycle >= 4) { + cpu_u_prev = cpu_u_cur; + cpu_s_prev = cpu_s_cur; + cpu_u_cur = sl[12].toLLong(); + cpu_s_cur = sl[13].toLLong(); + stat.cpu_load_system = cpu_s_cur - cpu_s_prev; + stat.cpu_load_user = cpu_u_cur - cpu_u_prev; + stat.cpu_load_system /= cpu_count; + stat.cpu_load_user /= cpu_count; + cycle = 0; + //} + stat.priority = sl[16].toInt(); + stat.threads = sl[18].toInt(); + + filem.seekToBegin(); + str = filem.readAll(true); + sl = str.split(" "); + if (sl.size_s() < 6) return; + stat.virtual_memsize = sl[0].toLong() * page_size; + stat.resident_memsize = sl[1].toLong() * page_size; + stat.share_memsize = sl[2].toLong() * page_size; + stat.data_memsize = sl[5].toLong() * page_size; + stat.physical_memsize = stat.resident_memsize - stat.share_memsize; +#else + stat.ID = pID_; + HMODULE hMod; + DWORD cbNeeded; + if (GetProcessMemoryInfo(hProc, &mem_cnt, sizeof(mem_cnt)) != 0) { + stat.physical_memsize = mem_cnt.WorkingSetSize; + } + stat.priority = GetPriorityClass(hProc); + HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, pID_); + int thcnt = 0; + if (snap != 0) { + THREADENTRY32 thread; + thread.dwSize = sizeof(THREADENTRY32); + if (Thread32First(snap, &thread) == TRUE) { + if (thread.th32OwnerProcessID == pID_) + ++thcnt; + while (Thread32Next(snap, &thread) == TRUE) { + if (thread.th32OwnerProcessID == pID_) + ++thcnt; + } + } + stat.threads = thcnt; + CloseHandle(snap); + } + FILETIME ft0, ft1, ft_kernel, ft_user; + double el_s = tm.elapsed_s() * cpu_count / 100.; + if (GetProcessTimes(hProc, &ft0, &ft1, &ft_kernel, &ft_user) != 0) { + PISystemTime tm_kernel_c(ft_kernel), tm_user_c(ft_user); + if (cycle < 0) { + tm_kernel = tm_kernel_c; + tm_user = tm_user_c; + } + //cycle++; + cycle = 0; + if (el_s <= 0.) { + stat.cpu_load_system = 0.f; + stat.cpu_load_user = 0.f; + } else { + stat.cpu_load_system = (tm_kernel_c - tm_kernel).toSeconds() / el_s; + stat.cpu_load_user = (tm_user_c - tm_user).toSeconds() / el_s; + } + tm_kernel = tm_kernel_c; + tm_user = tm_user_c; + } else { + stat.cpu_load_system = 0.f; + stat.cpu_load_user = 0.f; + } + tm.reset(); +#endif + + stat.cpu_load_system = piClampf(stat.cpu_load_system, 0.f, 100.f); + stat.cpu_load_user = piClampf(stat.cpu_load_user, 0.f, 100.f); + makeStrings(); +} + + +void PISystemMonitor::makeStrings() { + stat.physical_memsize_readable.setReadableSize(stat.physical_memsize); + stat.resident_memsize_readable.setReadableSize(stat.resident_memsize); + stat.share_memsize_readable.setReadableSize(stat.share_memsize); + stat.virtual_memsize_readable.setReadableSize(stat.virtual_memsize); + stat.data_memsize_readable.setReadableSize(stat.data_memsize); +} diff --git a/src/system/pisystemmonitor.h b/src/system/pisystemmonitor.h new file mode 100755 index 00000000..0e3c0cdd --- /dev/null +++ b/src/system/pisystemmonitor.h @@ -0,0 +1,82 @@ +/* + PIP - Platform Independent Primitives + Process resource monitor + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PISYSTEMMONITOR_H +#define PISYSTEMMONITOR_H + +#include "pithread.h" +#include "piprocess.h" + +class PIP_EXPORT PISystemMonitor: public PIThread +{ + PIOBJECT_SUBCLASS(PISystemMonitor, PIThread) +public: + PISystemMonitor(); + ~PISystemMonitor(); + + struct ProcessStats { + ProcessStats(); + PIString exec_name; + PIString state; + int ID; + int parent_ID; + int group_ID; + int session_ID; + int priority; + int threads; + ulong physical_memsize; + ulong resident_memsize; + ulong share_memsize; + ulong virtual_memsize; + ulong data_memsize; + PIString physical_memsize_readable; + PIString resident_memsize_readable; + PIString share_memsize_readable; + PIString virtual_memsize_readable; + PIString data_memsize_readable; + float cpu_load_system; + float cpu_load_user; + }; + + bool startOnProcess(int pID); + bool startOnSelf() {return startOnProcess(PIProcess::currentPID());} + + const ProcessStats & statistic() const {return stat;} + void setStatistic(const ProcessStats & s) {stat = s; makeStrings();} + +private: + void stop(); + void run(); + void makeStrings(); + + PIFile file, filem; + ProcessStats stat; + int pID_, page_size, cpu_count, cycle; +#ifndef WINDOWS + llong cpu_u_cur, cpu_u_prev, cpu_s_cur, cpu_s_prev; +#else + HANDLE hProc; + PROCESS_MEMORY_COUNTERS mem_cnt; + PISystemTime tm_kernel, tm_user; + PITimeMeasurer tm; +#endif + +}; + +#endif // PISYSTEMMONITOR_H diff --git a/src/system/pisystemtests.cpp b/src/system/pisystemtests.cpp new file mode 100755 index 00000000..cdb072fb --- /dev/null +++ b/src/system/pisystemtests.cpp @@ -0,0 +1,41 @@ +/* + PIP - Platform Independent Primitives + System tests results (see system_test folder) + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pisystemtests.h" + + +namespace PISystemTests { + long time_resolution_ns = 1; + long time_elapsed_ns = 0; + long usleep_offset_us = 60; + + PISystemTestReader pisystestreader; + +}; + + +PISystemTests::PISystemTestReader::PISystemTestReader() { +#ifndef WINDOWS + PIConfig conf("/etc/pip.conf", PIIODevice::ReadOnly); + //conf.setReopenEnabled(false); + time_resolution_ns = conf.getValue("time_resolution_ns", 1); + time_elapsed_ns = conf.getValue("time_elapsed_ns", 0); + usleep_offset_us = conf.getValue("usleep_offset_us", 60); +#endif +} diff --git a/src/system/pisystemtests.h b/src/system/pisystemtests.h new file mode 100755 index 00000000..ddf602d9 --- /dev/null +++ b/src/system/pisystemtests.h @@ -0,0 +1,39 @@ +/* + PIP - Platform Independent Primitives + System tests results (see system_test folder) + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PISYSTEMTESTS_H +#define PISYSTEMTESTS_H + +#include "piconfig.h" + +namespace PISystemTests { + PIP_EXPORT extern long time_resolution_ns; + PIP_EXPORT extern long time_elapsed_ns; + PIP_EXPORT extern long usleep_offset_us; + + class PISystemTestReader { + public: + PISystemTestReader(); + }; + + extern PISystemTestReader pisystestreader; + +}; + +#endif // PISYSTEMTESTS_H diff --git a/src/thread/pimutex.cpp b/src/thread/pimutex.cpp new file mode 100755 index 00000000..37f19baf --- /dev/null +++ b/src/thread/pimutex.cpp @@ -0,0 +1,59 @@ +/* + PIP - Platform Independent Primitives + Mutex + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pimutex.h" + + +/** \class PIMutex + * \brief Mutex + * \details + * \section PIMutex_sec0 Synopsis + * %PIMutex provides synchronization blocks between several threads. + * Using mutex guarantees execution of some code only one of threads. + * Mutex contains logic state and functions to change it: \a lock(), + * \a unlock() and \a tryLock(). + * + * \section PIMutex_sec1 Usage + * Block of code that should to be executed only one thread simultaniously + * should to be started with \a lock() and ended with \a unlock(). + * \snippet pimutex.cpp main + * "mutex" in this example is one for all threads. + * + * */ + + +PIMutex::PIMutex() { +#ifdef WINDOWS + mutex = CreateMutex(0, false, 0); +#else + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutex_init(&mutex, &attr); + pthread_mutexattr_destroy(&attr); +#endif +} + + +PIMutex::~PIMutex() { +#ifdef WINDOWS + if (mutex != 0) CloseHandle(mutex); +#else + pthread_mutex_destroy(&mutex); +#endif +} diff --git a/src/thread/pimutex.h b/src/thread/pimutex.h new file mode 100755 index 00000000..0228869f --- /dev/null +++ b/src/thread/pimutex.h @@ -0,0 +1,93 @@ +/*! \file pimutex.h + * \brief Mutex +*/ +/* + PIP - Platform Independent Primitives + Mutex + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIMUTEX_H +#define PIMUTEX_H + +#include "piinit.h" + +class PIP_EXPORT PIMutex +{ +public: + + //! Constructs unlocked mutex + PIMutex(); + + ~PIMutex(); + + + //! \brief Lock mutex + //! \details If mutex is unlocked it set to locked state and returns immediate. + //! If mutex is already locked function blocks until mutex will be unlocked + void lock() { +#ifdef WINDOWS + WaitForSingleObject(mutex, INFINITE); +#else + pthread_mutex_lock(&mutex); +#endif + } + + + //! \brief Unlock mutex + //! \details In any case this function returns immediate + void unlock() { +#ifdef WINDOWS + ReleaseMutex(mutex); +#else + pthread_mutex_unlock(&mutex); +#endif + } + + + //! \brief Try to lock mutex + //! \details If mutex is unlocked it set to locked state and returns "true" immediate. + //! If mutex is already locked function returns immediate an returns "false" + bool tryLock() { +#ifdef WINDOWS + return (WaitForSingleObject(mutex, 0) == WAIT_OBJECT_0); +#else + return (pthread_mutex_trylock(&mutex) == 0); +#endif + } + +private: +#ifdef WINDOWS + void * +#else + pthread_mutex_t +#endif + mutex; + +}; + + +class PIP_EXPORT PIMutexLocker +{ +public: + PIMutexLocker(PIMutex * m): mutex(m) {mutex->lock();} + PIMutexLocker(PIMutex & m): mutex(&m) {mutex->lock();} + ~PIMutexLocker() {mutex->unlock();} +private: + PIMutex * mutex; +}; + +#endif // PIMUTEX_H diff --git a/src/thread/pithread.cpp b/src/thread/pithread.cpp new file mode 100755 index 00000000..532caaa7 --- /dev/null +++ b/src/thread/pithread.cpp @@ -0,0 +1,339 @@ +/* + PIP - Platform Independent Primitives + Thread + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pithread.h" +#include "pisystemtests.h" + + +/*! \class PIThread + * \brief Thread class + * \details This class allow you exec your code in separate thread. + * + * \section PIThread_sec0 Synopsis + * Multithreading allow you to write program which will be executed + * in several threads simultaneously. This trend allow you to use all + * cores of modern processors, but there are many dangers. + * + * This class provide virtual functions \a begin(), \a run() and \a end(), + * which describes start, execution and finish work of some process. + * These functions executes in \b separate thread. When you execute + * \a start(), %PIThread create separate system thread and sequentially + * executes function \a begin(), \a run() and \a end(). You can + * reimplement each function and write your own code to execute. + * Scheme of functions executing: +\code{.cpp} +begin(); +event started(); +while (isRunning()) { + run(); + ThreadFunc(); + msleep(timer_delay); +} +event stopped(); +end(); +\endcode + * Unlike from directly using "pthread" or some similar you doesn`t need + * to write your own main thread cycle and sleep at every cycle end. + * %PIThread make it for you, and your job is to set sleep value from + * contructor or when starting thread, and reimplement \a begin(), \a run() + * and \a end() functions. + * + * \section PIThread_sec1 Using without subclassing + * You can use %PIThread without subclassing by using "ThreadFunc" pointer + * that can be set from constructor or by overloaded function \a start(ThreadFunc func, int timer_delay). + * If "func" if not null this function will be executed as \a run(). ThreadFunc is any static + * function with format void func(void * data). "Data" is custom data set from constructor or + * with function \a setData(). \n Also you can connect to event \a started(), but + * in this case you should to white your thread main cycle, because this event raised only one time. + * + * \section PIThread_sec2 Locking + * %PIThread has inrternal mutex that can be locked and unlocked every \a run() if you set this flag + * with function \a needLockRun(bool). Also you can access to this mutex by functions \a lock(), \a unlock() + * and \a mutex(). Using this functions together with needLockRun(true) can guarantee one-thread access to + * some data. + * + */ + + +PIThread::PIThread(void * data, ThreadFunc func, bool startNow, int timer_delay): PIObject() { + piMonitor.threads++; + thread = 0; + data_ = data; + ret_func = func; + terminating = running_ = lockRun = false; + priority_ = piNormal; + delay_ = timer_delay; + if (startNow) start(timer_delay); +} + + +PIThread::PIThread(bool startNow, int timer_delay): PIObject() { + piMonitor.threads++; + thread = 0; + ret_func = 0; + terminating = running_ = lockRun = false; + priority_ = piNormal; + delay_ = timer_delay; + if (startNow) start(timer_delay); +} + + +PIThread::~PIThread() { + piMonitor.threads--; + if (!running_ || thread == 0) return; +#ifndef WINDOWS +# ifdef ANDROID + pthread_kill(thread, SIGSTOP); +# else + pthread_cancel(thread); +# endif +#else + TerminateThread(thread, 0); + CloseHandle(thread); +#endif + terminating = running_ = false; +} + + +bool PIThread::start(int timer_delay) { + if (running_) return false; + terminating = running_ = false; + delay_ = timer_delay; +#ifndef WINDOWS + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setschedparam(&attr, &sparam); + if (pthread_create(&thread, &attr, thread_function, this) == 0) { + setPriority(priority_); + running_ = true; + return true; +#else + thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)thread_function, this, 0, 0); + if (thread != 0) { + setPriority(priority_); + running_ = true; + return true; +#endif + } else { + thread = 0; + piCoutObj << "Error: Can`t start new thread:" << errorString(); + } + return false; +} + + +bool PIThread::startOnce() { + if (running_) return false; + terminating = running_ = false; +#ifndef WINDOWS + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setschedparam(&attr, &sparam); + if (pthread_create(&thread, &attr, thread_function_once, this) == 0) { + setPriority(priority_); + running_ = true; + return true; +#else + thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)thread_function_once, this, 0, 0); + if (thread != 0) { + setPriority(priority_); + running_ = true; + return false; +#endif + } else { + thread = 0; + piCoutObj << "Error: Can`t start new thread:" << errorString(); + } + return false; +} + + +void PIThread::terminate() { + if (thread == 0) return; + terminating = running_ = false; +#ifndef WINDOWS +# ifdef ANDROID + pthread_kill(thread, SIGKILL); +# else + //pthread_kill(thread, SIGKILL); + pthread_cancel(thread); +# endif +#else + TerminateThread(thread, 0); + CloseHandle(thread); +#endif + thread = 0; + end(); +} + + +void * PIThread::thread_function(void * t) { +#ifndef WINDOWS +# ifndef ANDROID + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0); + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0); +# endif +#else + __PISetTimerResolution(); +#endif + PIThread & ct = *((PIThread * )t); + ct.running_ = true; + if (ct.lockRun) ct.mutex_.lock(); + ct.begin(); + if (ct.lockRun) ct.mutex_.unlock(); + ct.started(); + while (!ct.terminating) { + if (ct.lockRun) ct.mutex_.lock(); + ct.run(); + if (ct.ret_func != 0) ct.ret_func(ct.data_); + if (ct.lockRun) ct.mutex_.unlock(); + if (ct.delay_ > 0) { + ct.tmr_.reset(); + double sl(0.); + while (1) { + sl = piMind(ct.delay_ - ct.tmr_.elapsed_m(), 2.); + if (sl <= 0.) break; + piMSleep(sl); + if (ct.terminating) + break; + } + } + } + ct.stopped(); + if (ct.lockRun) ct.mutex_.lock(); + ct.end(); + if (ct.lockRun) ct.mutex_.unlock(); + ct.terminating = ct.running_ = false; + //cout << "thread " << t << " exiting ... " << endl; +#ifndef WINDOWS + pthread_exit(0); +#else + ExitThread(0); +#endif + ct.thread = 0; + return 0; +} + + +void * PIThread::thread_function_once(void * t) { +#ifndef WINDOWS +# ifndef ANDROID + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0); + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0); +# endif +#else + __PISetTimerResolution(); +#endif + PIThread & ct = *((PIThread * )t); + ct.running_ = true; + ct.begin(); + ct.started(); + if (ct.lockRun) ct.mutex_.lock(); + ct.run(); + if (ct.ret_func != 0) ct.ret_func(ct.data_); + if (ct.lockRun) ct.mutex_.unlock(); + ct.stopped(); + ct.end(); + ct.terminating = ct.running_ = false; + //cout << "thread " << t << " exiting ... " << endl; +#ifndef WINDOWS + pthread_exit(0); +#else + ExitThread(0); +#endif + ct.thread = 0; + return 0; +} + + +int PIThread::priority2System(PIThread::Priority p) { + switch (p) { +# ifdef QNX + case piLowerst: return 8; + case piLow: return 9; + case piNormal: return 10; + case piHigh: return 11; + case piHighest: return 12; +# else +# ifdef WINDOWS + case piLowerst: return -2; + case piLow: return -1; + case piNormal: return 0; + case piHigh: return 1; + case piHighest: return 2; +# else + case piLowerst: return 2; + case piLow: return 1; + case piNormal: return 0; + case piHigh: return -1; + case piHighest: return -2; +# endif +# endif + default: return 0; + } + return 0; +} + + +void PIThread::setPriority(PIThread::Priority prior) { + priority_ = prior; +#ifndef WINDOWS + if (!running_ && thread != 0) return; + pthread_getschedparam(thread, &policy_, &sparam); + sparam. +# ifndef LINUX + sched_priority +# else + __sched_priority +# endif + = priority2System(priority_); + pthread_setschedparam(thread, policy_, &sparam); +#else + if (!running_ && thread != 0) return; + SetThreadPriority(thread, priority2System(priority_)); +#endif +} + + +bool PIThread::waitForFinish(int timeout_msecs) { + if (!running_) return true; + if (timeout_msecs < 0) { + while (running_) + msleep(1); + return true; + } + tmf_.reset(); + while (running_ && tmf_.elapsed_m() < timeout_msecs) + msleep(1); + return tmf_.elapsed_m() < timeout_msecs; +} + + +bool PIThread::waitForStart(int timeout_msecs) { + if (running_) return true; + if (timeout_msecs < 0) { + while (!running_) + msleep(1); + return true; + } + tms_.reset(); + while (!running_ && tms_.elapsed_m() < timeout_msecs) + msleep(1); + return tms_.elapsed_m() < timeout_msecs; +} diff --git a/src/thread/pithread.h b/src/thread/pithread.h new file mode 100755 index 00000000..1bbd0b5e --- /dev/null +++ b/src/thread/pithread.h @@ -0,0 +1,208 @@ +/*! \file pithread.h + * \brief Thread + * + * This file declare thread class and some wait functions +*/ +/* + PIP - Platform Independent Primitives + Thread + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PITHREAD_H +#define PITHREAD_H + +#include +#include "piinit.h" +#include "pimutex.h" +#include "piobject.h" + +typedef void (*ThreadFunc)(void * ); + +class PIP_EXPORT PIThread: public PIObject +{ + PIOBJECT(PIThread) +public: + + //! Contructs thread with custom data "data", external function "func" and main loop delay "loop_delay". + PIThread(void * data, ThreadFunc func, bool startNow = false, int loop_delay = -1); + + //! Contructs thread with main loop delay "loop_delay". + PIThread(bool startNow = false, int loop_delay = -1); + + virtual ~PIThread(); + + //! Priority of thread + enum Priority { + piLowerst /** Lowest */, + piLow /** Low */, + piNormal /** Normal, this is default priority of threads and timers */, + piHigh /** High */, + piHighest /** Highest */ + }; + + EVENT_HANDLER0(bool, start) {return start(-1);} + EVENT_HANDLER1(bool, start, int, timer_delay); + EVENT_HANDLER1(bool, start, ThreadFunc, func) {ret_func = func; return start(-1);} + EVENT_HANDLER2(bool, start, ThreadFunc, func, int, timer_delay) {ret_func = func; return start(timer_delay);} + EVENT_HANDLER0(bool, startOnce); + EVENT_HANDLER1(bool, startOnce, ThreadFunc, func) {ret_func = func; return startOnce();} + EVENT_HANDLER0(void, stop) {stop(false);} + EVENT_HANDLER1(void, stop, bool, wait) {terminating = true; if (wait) waitForFinish();} + EVENT_HANDLER0(void, terminate); + + //! \brief Set common data passed to external function + void setData(void * d) {data_ = d;} + + //! \brief Set external function that will be executed after every \a run() + void setSlot(ThreadFunc func) {ret_func = func;} + + //! \brief Set priority of thread + void setPriority(PIThread::Priority prior); + + //! \brief Returns common data passed to external function + void * data() const {return data_;} + + //! \brief Return priority of thread + PIThread::Priority priority() const {return priority_;} + + //! \brief Return \c true if thread is running + bool isRunning() const {return running_;} + + bool isStopping() const {return running_ && terminating;} + + EVENT_HANDLER0(bool, waitForStart) {return waitForStart(-1);} + EVENT_HANDLER1(bool, waitForStart, int, timeout_msecs); + EVENT_HANDLER0(bool, waitForFinish) {return waitForFinish(-1);} + EVENT_HANDLER1(bool, waitForFinish, int, timeout_msecs); + + //! \brief Set necessity of lock every \a run with internal mutex + void needLockRun(bool need) {lockRun = need;} + EVENT_HANDLER0(void, lock) {mutex_.lock();} + EVENT_HANDLER0(void, unlock) {mutex_.unlock();} + + //! \brief Return internal mutex + PIMutex & mutex() {return mutex_;} + + EVENT(started) + EVENT(stopped) + +//! \handlers +//! \{ + + /** \fn bool start(int timer_delay = -1) + * \brief Start thread + * \details Start execution of \a run() in internal loop with + * "timer_delay" delay in milliseconds. If "timer_delay" <= 0 + * there is no delay in loop. Thread also exec external function + * set by \a setSlot() if it`s not null + * + * \return \c false if thread already started or can`t start thread */ + + /** \fn bool start(ThreadFunc func, int timer_delay = -1) + * \brief Start thread + * \details Overloaded function. Set external function "func" before start + * + * \return \c false if thread already started or can`t start thread */ + + /** \fn bool startOnce() + * \brief Start thread without internal loop + * \details Start execution of \a run() once. Thread also exec + * external function set by \a setSlot() if it`s not null + * + * \return \c false if thread already started or can`t start thread */ + + /** \fn bool startOnce(ThreadFunc func) + * \brief Start thread without internal loop + * \details Overloaded function. Set external function "func" before start + * + * \return \c false if thread already started or can`t start thread */ + + /** \fn void stop(bool wait = false) + * \brief Stop thread + * \details Stop execution of thread and wait for it finish + * if "wait" is \c true. This function can block for infinite + * time if "wait" is \c true and any of thread function is + * busy forever */ + + /** \fn void terminate() + * \brief Strongly stop thread + * \details Stop execution of thread immediately */ + + /** \fn bool waitForStart(int timeout_msecs = -1) + * \brief Wait for thread start + * \details This function block until thread finish for "timeout_msecs" + * or forever if "timeout_msecs" < 0 + * + * \return \c false if timeout is exceeded */ + + /** \fn bool waitForFinish(int timeout_msecs = -1) + * \brief Wait for thread finish + * \details This function block until thread start for "timeout_msecs" + * or forever if "timeout_msecs" < 0 + * + * \return \c false if timeout is exceeded */ + + //! \fn void lock() + //! \brief Lock internal mutex + + //! \fn void unlock() + //! \brief Unlock internal mutex + +//! \} +//! \events +//! \{ + + //! \fn void started() + //! \brief Raise on thread start + + //! \fn void stopped() + //! \brief Raise on thread stop + +//! \} + +protected: + static void * thread_function(void * t); + static void * thread_function_once(void * t); + static int priority2System(PIThread::Priority p); + + + //! Function executed once at the start of thread. + virtual void begin() {;} + + //! Function executed at every "timer_delay" msecs until thread was stopped. + virtual void run() {;} + + //! Function executed once at the end of thread. + virtual void end() {;} + + volatile bool terminating, running_, lockRun; + int delay_, policy_; + void * data_; + PIMutex mutex_; + PITimeMeasurer tmf_, tms_, tmr_; + PIThread::Priority priority_; + ThreadFunc ret_func; +#ifndef WINDOWS + pthread_t thread; + sched_param sparam; +#else + void * thread; +#endif + +}; + +#endif // PITHREAD_H diff --git a/src/thread/pitimer.cpp b/src/thread/pitimer.cpp new file mode 100755 index 00000000..c3f72986 --- /dev/null +++ b/src/thread/pitimer.cpp @@ -0,0 +1,428 @@ +/* + PIP - Platform Independent Primitives + Timer + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pitimer.h" + + +/*! \class PITimer + * \brief Timer + * + * \section PITimer_sec0 Synopsis + * This class implements timer function. PIP timers supports 3 way to tick notify, + * frequency delimiters and time measurements. + * \section PITimer_sec1 Notify variants + * Notify variants: + * * "slot" - static function with format void func(void * data, int delimiter); + * * event - \a tickEvent(); + * * virtual function - \a tick(). + * + * All these variants are equivalent, use most applicable. + * \section PITimer_sec2 Frequency delimiters + * Frequency delimiter is an integer number and "slot" function. If "slot" function is null + * timer main "slot" will be used. Each delimiter numbers tick timer will be execute + * delimiters or timer main "slot" function with \b delimiter value = delimiter number. + * Example: \snippet pitimer.cpp delimiter + * \section PITimer_sec3 Time measurements + * PITimer can be used as time measurer. Function \a reset() set time mark to current + * system time, then functions double elapsed_*() returns time elapsed from this mark. + * These functions can returns nano-, micro-, milli- and seconds with suffixes "n", "u", "m" + * and "s" + * Example: \snippet pitimer.cpp elapsed +*/ + + +_PITimerBase::_PITimerBase() { + interval_ = deferred_delay = 0.; + running_ = deferred_ = deferred_mode = false; +} + + +void _PITimerBase::setInterval(double i) { + interval_ = i; + if (isRunning()) { + stop(); + start(); + } +} + + +bool _PITimerBase::start(double interval_ms) { + if (isRunning()) stop(); + deferred_ = false; + setInterval(interval_ms); + running_ = startTimer(interval_ms); + return running_; +} + + +void _PITimerBase::startDeferred(double interval_ms, PIDateTime start_datetime) { + if (isRunning()) stop(); + deferred_ = true; + deferred_mode = true; + deferred_datetime = start_datetime; + setInterval(interval_ms); + running_ = startTimer(interval_ms); +} + + +void _PITimerBase::startDeferred(double interval_ms, double delay_ms) { + if (isRunning()) stop(); + deferred_ = true; + deferred_mode = false; + deferred_delay = delay_ms; + setInterval(interval_ms); + running_ = startTimer(interval_ms); +} + + +bool _PITimerBase::stop() { + if (!isRunning()) return true; + running_ = !stopTimer(); + return !running_; +} + + + + +_PITimerImp_Thread::_PITimerImp_Thread() { + thread_.setName("__S__PITimerImp_Thread::thread"); + wait_dt = 100; + wait_dd = 200; + wait_tick = 10; + //piCout << "new _PITimerImp_Thread"; +} + + +_PITimerImp_Thread::~_PITimerImp_Thread() { + stop(); +} + + +void _PITimerImp_Thread::prepareStart(double interval_ms) { + st_inc = PISystemTime::fromMilliseconds(interval_ms); + st_odt = st_inc * 5; + if (st_odt.toSeconds() < 1.) st_odt = PISystemTime::fromSeconds(1.); + if (deferred_) { + if (!deferred_mode) + st_time = PISystemTime::current(true) + PISystemTime::fromMilliseconds(deferred_delay); + st_time -= st_inc; + } else + st_time = PISystemTime::current(true) + st_inc; +} + + +bool _PITimerImp_Thread::startTimer(double interval_ms) { + prepareStart(interval_ms); + thread_.setData(this); + return thread_.start(threadFuncS); +} + + +bool _PITimerImp_Thread::stopTimer() { + thread_.stop(); + if (!thread_.waitForFinish(10)) + if (thread_.isRunning()) + thread_.terminate(); + return true; +} + + +bool _PITimerImp_Thread::threadFunc() { + if (!running_) return false; + if (deferred_) { + PISystemTime dwt; + int wth(wait_dt); + if (deferred_mode) { + dwt = deferred_datetime.toSystemTime() - PISystemTime::current(); + wth = wait_dd; + } else + dwt = st_time - PISystemTime::current(true); + if (wth > 0) { + if (dwt.toMilliseconds() > wth + 1.) { + piMSleep(wth); + return false; + } else { + dwt.sleep(); + deferred_ = false; + st_time = PISystemTime::current(true); + } + } else { + if (dwt.toMilliseconds() > 0.1) + return false; + } + } + st_wait = st_time - PISystemTime::current(true); + //piCout << "wait" << this << st_wait; + if (st_wait.abs() > st_odt || st_wait.seconds <= -5) { + adjustTimes(); + return true; + } + if (wait_tick > 0) { + if (st_wait.toMilliseconds() > wait_tick + 1.) { + piMSleep(wait_tick); + return false; + } else { + st_wait.sleep(); + } + } else { + if (st_wait.toMilliseconds() > 0.1) + return false; + } + st_time += st_inc; + tfunc(parent); + return true; +} + + +void _PITimerImp_Thread::adjustTimes() { + PISystemTime cst = PISystemTime::current(true); + if (st_time < cst) { + while (st_time < cst) + st_time += st_inc; + } else { + cst += st_inc; + while (st_time > cst) + st_time -= st_inc; + } +} + + + + +#ifdef PIP_TIMER_RT + +_PITimerImp_RT::_PITimerImp_RT() { + //piCout << "new _PITimerImp_RT"; + ti = -1; + tt = 0; + memset(&se, 0, sizeof(se)); + se.sigev_notify = SIGEV_THREAD; + se.sigev_value.sival_ptr = this; + se.sigev_notify_function = threadFuncS; + se.sigev_notify_attributes = 0; +} + + +bool _PITimerImp_RT::startTimer(double interval_ms) { + int flags(0); + spec.it_interval.tv_nsec = ((int)(interval_ms * 1000) % 1000000) * 1000; + spec.it_interval.tv_sec = (time_t)(interval_ms / 1000); + if (deferred_) { + if (deferred_mode) { + PISystemTime dtm = deferred_datetime.toSystemTime(); + spec.it_value.tv_nsec = dtm.nanoseconds; + spec.it_value.tv_sec = dtm.seconds; + flags = TIMER_ABSTIME; + } else { + spec.it_value.tv_nsec = ((int)(deferred_delay * 1000) % 1000000) * 1000; + spec.it_value.tv_sec = (time_t)(deferred_delay / 1000); + } + } else { + spec.it_value = spec.it_interval; + } + ti = timer_create(CLOCK_REALTIME, &se, &tt); + //cout << "***create timer " << msecs << " msecs\n"; + if (ti == -1) { + piCout << "Can`t create RT timer for " << interval_ms << " msecs: " << errorString(); + return false; + } + timer_settime(tt, flags, &spec, 0); + return true; +} + + +bool _PITimerImp_RT::stopTimer() { + if (ti < 0) return true; + timer_delete(tt); + ti = -1; + tt = 0; + return true; +} + +#endif + + + + +_PITimerImp_Pool::_PITimerImp_Pool(): _PITimerImp_Thread() { + wait_dt = wait_dd = wait_tick = 0; + //piCout << "new _PITimerImp_Pool"; +} + + +_PITimerImp_Pool::Pool::Pool(): PIThread() { + setName("__S__PITimerImp_Pool::Pool"); + needLockRun(true); + timers.reserve(64); + start(2); +} + + +_PITimerImp_Pool::Pool::~Pool() { + stop(); + if (!waitForFinish(100)) + terminate(); + timers.clear(); +} + + +_PITimerImp_Pool::Pool * _PITimerImp_Pool::Pool::instance() { + static Pool pool; + return &pool; +} + + +void _PITimerImp_Pool::Pool::add(_PITimerImp_Pool * t) { + //piCout << "add ..."; + lock(); + if (!timers.contains(t)) + timers << t; + unlock(); + //piCout << "add done"; +} + + +void _PITimerImp_Pool::Pool::remove(_PITimerImp_Pool * t) { + //piCout << "remove ..."; + lock(); + timers.removeOne(t); + unlock(); + //piCout << "remove done"; +} + + +void _PITimerImp_Pool::Pool::run() { + piForeach (_PITimerImp_Pool * t, timers) + t->threadFunc(); + //while (t->threadFunc()); +} + + +bool _PITimerImp_Pool::startTimer(double interval_ms) { + prepareStart(interval_ms); + Pool::instance()->add(this); + return true; +} + + +bool _PITimerImp_Pool::stopTimer() { + Pool::instance()->remove(this); + return true; +} + + + + + +PITimer::PITimer(): PIObject() { + piMonitor.timers++; + imp_mode = PITimer::Thread; + initFirst(); +} + + +PITimer::PITimer(PITimer::TimerImplementation ti): PIObject() { + piMonitor.timers++; + imp_mode = ti; + initFirst(); +} + + +PITimer::PITimer(TimerEvent slot, void * data, PITimer::TimerImplementation ti): PIObject() { + piMonitor.timers++; + imp_mode = ti; + initFirst(); + data_t = data; + ret_func = slot; +} + + +PITimer::~PITimer() { + piMonitor.timers--; + destroy(); +} + + +void PITimer::initFirst() { + setProperty("interval", 0.); + lockRun = false; + data_t = 0; + ret_func = 0; + imp = 0; + init(); +} + + +void PITimer::init() { + destroy(); + switch (imp_mode) { + case PITimer::Pool: imp = new _PITimerImp_Pool(); break; + case PITimer::ThreadRT: +#ifdef PIP_TIMER_RT + imp = new _PITimerImp_RT(); + break; +#else + piCoutObj << "Warning: \"ThreadRT\" is not available at this system! Using \"Thread\"."; +#endif + case PITimer::Thread: imp = new _PITimerImp_Thread(); break; + default: piCout << "Fatal: invalid implementation() of" << this << "!"; abort(); + } + if (imp == 0) return; + imp->tfunc = tickImpS; + imp->parent = this; +} + + +void PITimer::destroy() { + //piCout << "destroy" << this << imp; + if (imp == 0) return; + delete imp; + imp = 0; +} + + +void PITimer::tickImp() { + if (!isRunning()) return; + if (lockRun) lock(); + if (ret_func != 0) ret_func(data_t, 1); + tick(data_t, 1); + tickEvent(data_t, 1); + piForeach (Delimiter & i, delims) { + if (i.delim > ++(i.tick)) continue; + i.tick = 0; + if (i.slot != 0) i.slot(data_t, i.delim); + else if (ret_func != 0) ret_func(data_t, i.delim); + tick(data_t, i.delim); + tickEvent(data_t, i.delim); + } + if (lockRun) unlock(); +} + + +bool PITimer::waitForFinish(int timeout_msecs) { + if (timeout_msecs < 0) { + while (isRunning()) + msleep(1); + return true; + } + PITimeMeasurer tm; + while (isRunning() && tm.elapsed_m() < timeout_msecs) + msleep(1); + return tm.elapsed_m() < timeout_msecs; +} diff --git a/src/thread/pitimer.h b/src/thread/pitimer.h new file mode 100755 index 00000000..452d9793 --- /dev/null +++ b/src/thread/pitimer.h @@ -0,0 +1,309 @@ +/*! \file pitimer.h + * \brief Timer +*/ +/* + PIP - Platform Independent Primitives + Timer + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PITIMER_H +#define PITIMER_H + +#include "pithread.h" +#include "pitime.h" + + +typedef void (*TimerEvent)(void * , int ); + +class PITimer; + +class _PITimerBase { + friend class PITimer; +public: + _PITimerBase(); + virtual ~_PITimerBase() {stop();} + + double interval() const {return interval_;} + void setInterval(double i); + + // ! \brief Return \c true if thread is running + bool isRunning() const {return running_;} + + bool isStopped() const {return !running_;} + + bool start() {return start(interval_);} + bool start(double interval_ms); + void startDeferred(double delay_ms) {startDeferred(interval_, delay_ms);} + void startDeferred(double interval_ms, double delay_ms); + void startDeferred(PIDateTime start_datetime) {startDeferred(interval_, start_datetime);} + void startDeferred(double interval_ms, PIDateTime start_datetime); + + bool stop(); + +protected: + typedef void(*TickFunc)(PITimer*); + + virtual bool startTimer(double interval_ms) = 0; + virtual bool stopTimer() = 0; + + double interval_, deferred_delay; + bool deferred_, deferred_mode; // mode: true - date, false - delay + volatile bool running_; + PIDateTime deferred_datetime; + PITimer * parent; + TickFunc tfunc; +}; + + + +class _PITimerImp_Thread: public _PITimerBase { +public: + _PITimerImp_Thread(); + virtual ~_PITimerImp_Thread(); +protected: + void prepareStart(double interval_ms); + bool threadFunc(); // returns true if repeat is needed + int wait_dt, wait_dd, wait_tick; +private: + virtual bool startTimer(double interval_ms); + virtual bool stopTimer(); + static void threadFuncS(void * d) {((_PITimerImp_Thread*)d)->threadFunc();} + void adjustTimes(); + + PIThread thread_; + PISystemTime st_time, st_inc, st_wait, st_odt; +}; + + +#ifdef PIP_TIMER_RT +class _PITimerImp_RT: public _PITimerBase { +public: + _PITimerImp_RT(); + virtual ~_PITimerImp_RT() {stop();} +protected: +private: + virtual bool startTimer(double interval_ms); + virtual bool stopTimer(); + static void threadFuncS(sigval sv) {((_PITimerImp_RT * )sv.sival_ptr)->tfunc(((_PITimerImp_RT * )sv.sival_ptr)->parent);} + + int ti; + itimerspec spec; + timer_t tt; + sigevent se; +}; +#endif + + +class _PITimerImp_Pool: public _PITimerImp_Thread { +public: + _PITimerImp_Pool(); + virtual ~_PITimerImp_Pool() {stop();} +private: + class Pool: public PIThread { + public: + Pool(); + ~Pool(); + static Pool * instance(); + void add(_PITimerImp_Pool * t); + void remove(_PITimerImp_Pool * t); + void run(); + PIVector<_PITimerImp_Pool * > timers; + }; + virtual bool startTimer(double interval_ms); + virtual bool stopTimer(); +}; + + + + +class PITimer: public PIObject { + PIOBJECT(PITimer) +public: + + //! \brief Constructs timer with PITimer::Thread implementation + explicit PITimer(); + + //! \brief Timer implementations + enum TimerImplementation { + Thread /*! Timer works in his own thread. Intervals are measured by the system time */ = 0x01, + ThreadRT /*! Using POSIX timer with SIGEV_THREAD notification. \attention Doesn`t support on Windows and Mac OS! */ = 0x02, + // SignalRT /*! */ = 0x03, + Pool /*! Using single TimerPool for all timers with this implementation. TimerPool works as Thread implementation and + * sequentially executes all timers. \attention Use this implementation with care! */ = 0x04 + }; + + //! \brief Constructs timer with "ti" implementation + explicit PITimer(TimerImplementation ti); + + //! \brief Constructs timer with "slot" slot, "data" data and "ti" implementation + explicit PITimer(TimerEvent slot, void * data = 0, TimerImplementation ti = Thread); + + virtual ~PITimer(); + + + //! \brief Returns timer implementation + PITimer::TimerImplementation implementation() const {return imp_mode;} + + //! \brief Returns timer loop delay in milliseconds + double interval() const {return imp->interval_;} + + //! \brief Set timer loop delay in milliseconds + EVENT_HANDLER1(void, setInterval, double, ms) {setProperty("interval", ms); imp->setInterval(ms);} + + //! \brief Returns if timer is started + bool isRunning() const {return imp->running_;} + + //! \brief Returns if timer is not started + bool isStopped() const {return !imp->running_;} + + EVENT_HANDLER0(bool, start) {return imp->start();} + EVENT_HANDLER1(bool, start, int, interval_ms_i) {setInterval(double(interval_ms_i)); return imp->start(double(interval_ms_i));} + EVENT_HANDLER1(bool, start, double, interval_ms_d) {setInterval(interval_ms_d); return imp->start(interval_ms_d);} + EVENT_HANDLER0(bool, restart) {imp->stop(); return imp->start();} + EVENT_HANDLER1(void, startDeferred, double, delay_ms) {imp->startDeferred(delay_ms);} + EVENT_HANDLER2(void, startDeferred, double, interval_ms, double, delay_ms) {imp->startDeferred(interval_ms, delay_ms);} + EVENT_HANDLER1(void, startDeferred, PIDateTime, start_datetime) {startDeferred(imp->interval_, start_datetime);} + EVENT_HANDLER2(void, startDeferred, double, interval_ms, PIDateTime, start_datetime) {imp->startDeferred(interval_ms, start_datetime);} + + EVENT_HANDLER0(bool, stop) {return imp->stop();} + bool waitForFinish() {return waitForFinish(-1);} + bool waitForFinish(int timeout_msecs); + + //! \brief Set custom data + void setData(void * data_) {data_t = data_;} + + //! \brief Set timer tick function + void setSlot(TimerEvent slot) {ret_func = slot;} + + //! \brief Returns common data passed to tick functions + void * data() const {return data_t;} + + void needLockRun(bool need) {lockRun = need;} + EVENT_HANDLER0(void, lock) {mutex_.lock();} + EVENT_HANDLER0(void, unlock) {mutex_.unlock();} + + //! \brief Add frequency delimiter \b delim with optional delimiter slot \b slot. + void addDelimiter(int delim, TimerEvent slot = 0) {delims << Delimiter(slot, delim);} + + //! \brief Remove all frequency delimiters \b delim. + void removeDelimiter(int delim) {for (int i = 0; i < delims.size_s(); ++i) if (delims[i].delim == delim) {delims.remove(i); i--;}} + + //! \brief Remove all frequency delimiters with slot \b slot. + void removeDelimiter(TimerEvent slot) {for (int i = 0; i < delims.size_s(); ++i) if (delims[i].slot == slot) {delims.remove(i); i--;}} + + //! \brief Remove all frequency delimiters \b delim with slot \b slot. + void removeDelimiter(int delim, TimerEvent slot) {for (int i = 0; i < delims.size_s(); ++i) if (delims[i].slot == slot && delims[i].delim == delim) {delims.remove(i); i--;}} + + void setDelimiterValue(int delim, int value) {for (int i = 0; i < delims.size_s(); ++i) if (delims[i].delim == delim) delims[i].tick = value;} + void setDelimiterValue(TimerEvent slot, int value) {for (int i = 0; i < delims.size_s(); ++i) if (delims[i].slot == slot) delims[i].tick = value;} + void setDelimiterValue(int delim, TimerEvent slot, int value) {for (int i = 0; i < delims.size_s(); ++i) if (delims[i].slot == slot && delims[i].delim == delim) delims[i].tick = value;} + int delimiterValue(int delim) {for (int i = 0; i < delims.size_s(); ++i) if (delims[i].delim == delim) return delims[i].tick; return -1;} + int delimiterValue(int delim, TimerEvent slot) {for (int i = 0; i < delims.size_s(); ++i) if (delims[i].slot == slot && delims[i].delim == delim) return delims[i].tick; return -1;} + EVENT_HANDLER0(void, clearDelimiters) {delims.clear();} + + EVENT2(tickEvent, void * , data_, int, delimiter) + +//! \handlers +//! \{ + + /** \fn bool start() + * \brief Start timer with \a interval() loop delay + * \details Start execution of timer functions with frequency = 1 / msecs Hz. */ + + /** \fn bool start(int msecs) + * \brief Start timer with \b msecs loop delay + * \details Start execution of timer functions with frequency = 1 / msecs Hz. */ + + /** \fn bool start(double msecs) + * \brief Start timer with \b msecs loop delay + * \details Start execution of timer functions with frequency = 1. / msecs Hz. + * Instead of \a start(int msecs) function this variant allow start timer + * with frequencies more than 1 kHz */ + + //! \fn bool restart() + //! \brief Stop and start timer with \a interval() loop delay + + //! \fn bool stop() + //! \brief Stop timer + + /** \fn void deferredStart(double delay_msecs) + * \brief Start timer with \b interval() loop delay after \b delay_msecs delay. + * \details Timer wait \b delay_msecs milliseconds and then normally starts with + * \b interval() loop delay. */ + + /** \fn void deferredStart(const PIDateTime & start_datetime) + * \brief Start timer with \b interval() loop delay after \b start_datetime date and time. + * \details Timer wait until \b start_datetime and then normally starts with + * \b interval() loop delay. */ + + /** \fn void deferredStart(double interval_msecs, double delay_msecs) + * \brief Start timer with \b interval_msecs loop delay after \b delay_msecs delay. + * \details Timer wait \b delay_msecs milliseconds and then normally starts with + * \b interval_msecs loop delay. */ + + /** \fn void deferredStart(double interval_msecs, const PIDateTime & start_datetime) + * \brief Start timer with \b interval_msecs loop delay after \b start_datetime date and time. + * \details Timer wait until \b start_datetime and then normally starts with + * \b interval_msecs loop delay. */ + + //! \fn void clearDelimiters() + //! \brief Remove all frequency delimiters + +//! \} +//! \events +//! \{ + + /** \fn void tickEvent(void * data, int delimiter) + * \brief Raise on timer tick + * \details \b Data can be set with function \a setData(void * data) or from constructor. + * \b Delimiter if frequency delimiter, 1 for main loop. */ + + +//! \} + +protected: + struct Delimiter { + Delimiter(TimerEvent slot_ = 0, int delim_ = 1) {slot = slot_; delim = delim_; tick = 0;} + TimerEvent slot; + int delim; + int tick; + }; + + void initFirst(); + void init(); + void destroy(); + + static void tickImpS(PITimer * t) {t->tickImp();} + void tickImp(); + + //! Virtual timer execution function, similar to "slot" or event \a void timeout(void * data, int delimiter). + //! By default is empty. + virtual void tick(void * data_, int delimiter) {} + + void * data_t; + volatile bool lockRun; + PIMutex mutex_; + TimerEvent ret_func; + TimerImplementation imp_mode; + PIVector delims; + + _PITimerBase * imp; + +}; + + +#endif // PITIMER_H diff --git a/utils/code_model_generator/CMakeLists.txt b/utils/code_model_generator/CMakeLists.txt new file mode 100755 index 00000000..16a4e75f --- /dev/null +++ b/utils/code_model_generator/CMakeLists.txt @@ -0,0 +1,5 @@ +add_executable(pip_cmg "main.cpp") +target_link_libraries(pip_cmg pip) +if (DEFINED LIB) + install(TARGETS pip_cmg DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +endif () diff --git a/utils/code_model_generator/Makefile b/utils/code_model_generator/Makefile new file mode 100644 index 00000000..383b9f2a --- /dev/null +++ b/utils/code_model_generator/Makefile @@ -0,0 +1,209 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 2.8 + +# Default target executed when no arguments are given to make. +default_target: all +.PHONY : default_target + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/andrey/linux_build/libs + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/andrey/linux_build/libs + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running interactive CMake command-line interface..." + /usr/bin/cmake -i . +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache +.PHONY : edit_cache/fast + +# Special rule for the target install +install: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." + /usr/bin/cmake -P cmake_install.cmake +.PHONY : install + +# Special rule for the target install +install/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." + /usr/bin/cmake -P cmake_install.cmake +.PHONY : install/fast + +# Special rule for the target install/local +install/local: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." + /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake +.PHONY : install/local + +# Special rule for the target install/local +install/local/fast: install/local +.PHONY : install/local/fast + +# Special rule for the target install/strip +install/strip: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..." + /usr/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake +.PHONY : install/strip + +# Special rule for the target install/strip +install/strip/fast: install/strip +.PHONY : install/strip/fast + +# Special rule for the target list_install_components +list_install_components: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\"" +.PHONY : list_install_components + +# Special rule for the target list_install_components +list_install_components/fast: list_install_components +.PHONY : list_install_components/fast + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." + /usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache +.PHONY : rebuild_cache/fast + +# The main all target +all: cmake_check_build_system + cd /home/andrey/linux_build/libs && $(CMAKE_COMMAND) -E cmake_progress_start /home/andrey/linux_build/libs/CMakeFiles /home/andrey/linux_build/libs/pip/utils/code_model_generator/CMakeFiles/progress.marks + cd /home/andrey/linux_build/libs && $(MAKE) -f CMakeFiles/Makefile2 pip/utils/code_model_generator/all + $(CMAKE_COMMAND) -E cmake_progress_start /home/andrey/linux_build/libs/CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + cd /home/andrey/linux_build/libs && $(MAKE) -f CMakeFiles/Makefile2 pip/utils/code_model_generator/clean +.PHONY : clean + +# The main clean target +clean/fast: clean +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + cd /home/andrey/linux_build/libs && $(MAKE) -f CMakeFiles/Makefile2 pip/utils/code_model_generator/preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + cd /home/andrey/linux_build/libs && $(MAKE) -f CMakeFiles/Makefile2 pip/utils/code_model_generator/preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + cd /home/andrey/linux_build/libs && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +# Convenience name for target. +pip/utils/code_model_generator/CMakeFiles/pip_cmg.dir/rule: + cd /home/andrey/linux_build/libs && $(MAKE) -f CMakeFiles/Makefile2 pip/utils/code_model_generator/CMakeFiles/pip_cmg.dir/rule +.PHONY : pip/utils/code_model_generator/CMakeFiles/pip_cmg.dir/rule + +# Convenience name for target. +pip_cmg: pip/utils/code_model_generator/CMakeFiles/pip_cmg.dir/rule +.PHONY : pip_cmg + +# fast build rule for target. +pip_cmg/fast: + cd /home/andrey/linux_build/libs && $(MAKE) -f pip/utils/code_model_generator/CMakeFiles/pip_cmg.dir/build.make pip/utils/code_model_generator/CMakeFiles/pip_cmg.dir/build +.PHONY : pip_cmg/fast + +main.o: main.cpp.o +.PHONY : main.o + +# target to build an object file +main.cpp.o: + cd /home/andrey/linux_build/libs && $(MAKE) -f pip/utils/code_model_generator/CMakeFiles/pip_cmg.dir/build.make pip/utils/code_model_generator/CMakeFiles/pip_cmg.dir/main.cpp.o +.PHONY : main.cpp.o + +main.i: main.cpp.i +.PHONY : main.i + +# target to preprocess a source file +main.cpp.i: + cd /home/andrey/linux_build/libs && $(MAKE) -f pip/utils/code_model_generator/CMakeFiles/pip_cmg.dir/build.make pip/utils/code_model_generator/CMakeFiles/pip_cmg.dir/main.cpp.i +.PHONY : main.cpp.i + +main.s: main.cpp.s +.PHONY : main.s + +# target to generate assembly for a file +main.cpp.s: + cd /home/andrey/linux_build/libs && $(MAKE) -f pip/utils/code_model_generator/CMakeFiles/pip_cmg.dir/build.make pip/utils/code_model_generator/CMakeFiles/pip_cmg.dir/main.cpp.s +.PHONY : main.cpp.s + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... edit_cache" + @echo "... install" + @echo "... install/local" + @echo "... install/strip" + @echo "... list_install_components" + @echo "... pip_cmg" + @echo "... rebuild_cache" + @echo "... main.o" + @echo "... main.i" + @echo "... main.s" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + cd /home/andrey/linux_build/libs && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/utils/code_model_generator/cmake_install.cmake b/utils/code_model_generator/cmake_install.cmake new file mode 100644 index 00000000..73365251 --- /dev/null +++ b/utils/code_model_generator/cmake_install.cmake @@ -0,0 +1,60 @@ +# Install script for directory: /home/andrey/linux_build/libs/pip/utils/code_model_generator + +# Set the install prefix +IF(NOT DEFINED CMAKE_INSTALL_PREFIX) + SET(CMAKE_INSTALL_PREFIX "/usr") +ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) +STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + IF(BUILD_TYPE) + STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + ELSE(BUILD_TYPE) + SET(CMAKE_INSTALL_CONFIG_NAME "Release") + ENDIF(BUILD_TYPE) + MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + +# Set the component getting installed. +IF(NOT CMAKE_INSTALL_COMPONENT) + IF(COMPONENT) + MESSAGE(STATUS "Install component: \"${COMPONENT}\"") + SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + ELSE(COMPONENT) + SET(CMAKE_INSTALL_COMPONENT) + ENDIF(COMPONENT) +ENDIF(NOT CMAKE_INSTALL_COMPONENT) + +# Install shared libraries without execute permission? +IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + SET(CMAKE_INSTALL_SO_NO_EXE "1") +ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + +IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") + IF(EXISTS "$ENV{DESTDIR}/usr/bin/pip_cmg" AND + NOT IS_SYMLINK "$ENV{DESTDIR}/usr/bin/pip_cmg") + FILE(RPATH_CHECK + FILE "$ENV{DESTDIR}/usr/bin/pip_cmg" + RPATH "") + ENDIF() + list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES + "/usr/bin/pip_cmg") + IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) + message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) + IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) + message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) +FILE(INSTALL DESTINATION "/usr/bin" TYPE EXECUTABLE FILES "/home/andrey/linux_build/libs/pip/utils/code_model_generator/pip_cmg") + IF(EXISTS "$ENV{DESTDIR}/usr/bin/pip_cmg" AND + NOT IS_SYMLINK "$ENV{DESTDIR}/usr/bin/pip_cmg") + FILE(RPATH_REMOVE + FILE "$ENV{DESTDIR}/usr/bin/pip_cmg") + IF(CMAKE_INSTALL_DO_STRIP) + EXECUTE_PROCESS(COMMAND "/usr/bin/strip" "$ENV{DESTDIR}/usr/bin/pip_cmg") + ENDIF(CMAKE_INSTALL_DO_STRIP) + ENDIF() +ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") + diff --git a/utils/code_model_generator/main.cpp b/utils/code_model_generator/main.cpp new file mode 100755 index 00000000..292ca1f4 --- /dev/null +++ b/utils/code_model_generator/main.cpp @@ -0,0 +1,263 @@ +/* + PIP - Platform Independent Primitives + Code model generator + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "picli.h" +#include "picodeparser.h" + + +void usage() { + piCout << Bold << "PIP Code model generator"; + piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine; + piCout << Green << Bold << "Usage:" << Default << "\"pip_cmg [-hqPpEs] -o [-I] [-I] [...] [-D] [-D] [...] [] [] [...]\"" << NewLine; + piCout << Green << Bold << "Details:"; + piCout << "-h " << Green << "- display this message and exit"; + piCout << "-q " << Green << "- quiet, no debug output to console"; + piCout << "-P " << Green << "- print list of all parsed files to console before exit"; + piCout << "-p " << Green << "- print list of all parsed files without file with \"main\" function to console before exit"; + piCout << "-E " << Green << "- write only enums"; + piCout << "-s " << Green << "- single file (don`t follow includes)"; + piCout << "-o " << Green << "- output file for code model without extension (e.g. \"ccm\" - files \"ccm.h\" and \"ccm.cpp\" will be created)"; + piCout << "-I " << Green << "- add include dir (e.g. -I.. -I../some_dir -I/usr/include)"; + piCout << "-D " << Green << "- add define to preprocessor, define PICODE is always defined (e.g. -DMY_DEFINE will add MY_DEFINE define)"; + piCout << " " << Green << "- add file to code model, all includes of this file will be proceed (e.g. \"main.cpp\")"; +} + + +void makeClassInfo(PIFile & f, const PICodeParser::Entity * e) { + f << "\n\tci = new ClassInfo();\n"; + f << "\t(*classesInfo)[\"" << e->name << "\"] = ci;\n"; + f << "\tci->name = \"" << e->name << "\";\n"; + piForeachC (PICodeParser::Entity * p, e->parents) + f << "\tci->parents << \"" << p->name << "\";\n"; + piForeachC (PICodeParser::Member & m, e->members) { + f << "\tci->variables << TypeInfo(\"" << m.name << "\", \"" << m.type << "\""; + if (m.attributes != 0) { + bool fir = true; + f << ", "; + if (m.attributes[PICodeParser::Const]) {if (fir) fir = false; else f << " | "; f << "Const";} + if (m.attributes[PICodeParser::Static]) {if (fir) fir = false; else f << " | "; f << "Static";} + if (m.attributes[PICodeParser::Mutable]) {if (fir) fir = false; else f << " | "; f << "Mutable";} + if (m.attributes[PICodeParser::Volatile]) {if (fir) fir = false; else f << " | "; f << "Volatile";} + if (m.attributes[PICodeParser::Inline]) {if (fir) fir = false; else f << " | "; f << "Inline";} + if (m.attributes[PICodeParser::Virtual]) {if (fir) fir = false; else f << " | "; f << "Virtual";} + } + f << ");\n"; + } + PIString arg; + piForeachC (PICodeParser::Member & m, e->functions) { + if (e->name.findCWord(m.name) >= 0) continue; + f << "\tci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back());\n"; + f << "\tfi->name = \"" << m.name << "\";"; + f << " fi->return_type = TypeInfo(\"\", \"" << m.type << "\""; + if (m.attributes[PICodeParser::Const] || m.attributes[PICodeParser::Static]) { + bool fir = true; + f << ", "; + if (m.attributes[PICodeParser::Const]) {if (fir) fir = false; else f << " | "; f << "Const";} + if (m.attributes[PICodeParser::Static]) {if (fir) fir = false; else f << " | "; f << "Static";} + } + f << ");\n"; + //piCout << "write func" << m.name; + piForeachC (PIString & a, m.arguments_full) { + //piCout << "write arg" << a; + f << "\tfi->arguments << TypeInfo("; + arg = a; + bool con = false; + arg.prepend(" "); + if (arg.find(" const ") >= 0) { + arg.replaceAll(" const ", " "); + con = true; + } + arg.trim(); + int ts = 0; + for (ts = arg.size_s() - 1; ts > 0; --ts) + if (!_isCChar(arg[ts]) && !(arg[ts].isDigit())) break; + f << "\"" << arg.takeRight(arg.size_s() - ts - 1).trim() << "\", "; + f << "\"" << arg.trim() << "\""; + if (con) f << ", Const"; + f << ");\n"; + } + } +} + + +void makeEnumInfo(PIFile & f, const PICodeParser::Enum * e) { + if (e->name.isEmpty()) { + f << "\n\tei = (*enumsInfo)[\"\"];\n"; + } else { + f << "\n\tei = new EnumInfo();\n"; + f << "\t(*enumsInfo)[\"" << e->name << "\"] = ei;\n"; + f << "\tei->name = \"" << e->name << "\";\n"; + } + piForeachC (PICodeParser::Enumerator & m, e->members) + f << "\tei->members << PICodeInfo::EnumeratorInfo(\"" << m.first << "\", " << m.second << ");\n"; +} + + +void writeModel(PICodeParser & parser, const PIString out, bool only_enums) { + PIVector ventities; + PIString defname = out.replaceAll(".", "_").replaceAll("/", "_").toUpperCase() + "_H"; + + PISet inc_files; + piForeachC (PICodeParser::Entity * e, parser.entities) + if (e->name.find("::") < 0 && !e->name.startsWith("_PI")) + inc_files << e->file; + + PIFile f(out + ".cpp"); + f.clear(); + f.open(PIIODevice::WriteOnly); + f << "// Generated by \"PIP Code model generator\" " << PIDateTime::current().toString("dd.MM.yyyy hh:mm:ss\n\n"); + f << "#include \n#include \"" << out << ".h\"\n\nusing namespace PICodeInfo;\n\n"; + if (!only_enums) { + PIVector incf = inc_files.toVector(); + piForeachC (PIString & i, incf) { + if (i != parser.mainFile()) + f << "#include \"" << i << "\"\n"; + } + f << "\n"; + PIString entry, argtype, rettype, args; + piForeachC (PICodeParser::Entity * e, parser.entities) { + if (e->name.find("::") >= 0 || e->name.startsWith("_PI")) continue; + entry.clear(); + entry << "\nPIVariant execFunction(" << e->name << " * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) {\n"; + const PIVector & fl(e->functions); + bool efunc = true; + piForeachC (PICodeParser::Member & m, fl) { + if (m.name.startsWith("__stat") || m.attributes[PICodeParser::Static]) continue; + //piCout << e->name << m.name << m.visibility; + args.clear(); + rettype = m.type; + if (rettype.startsWith("const") && rettype.endsWith("&")) + rettype.cutLeft(5).cutRight(1).trim(); + if (rettype.endsWith("&")) continue; + bool aok = true, ret = (m.type != "void"); + if (m.arguments_full.size() > 4 || m.visibility != PICodeParser::Public) continue; + for (int i = 0; i < m.arguments_full.size_s(); ++i) { + if (i > 0) args << ", "; + argtype = m.arguments_type[i]; + if (argtype.startsWith("const") && argtype.endsWith("&")) + argtype.cutLeft(5).cutRight(1).trim(); + if (argtype.endsWith("&")) { + aok = false; + continue; + } + //entry << "(" << m.arguments_type[i] << ")"; + //if (parser.isEnum(m.arguments_type[i])) entry << "(int)"; + args << "arg" << i << ".toValue<" << argtype << " >()"; + } + if (!aok) continue; + efunc = false; + entry << "\tif (strcmp(function, \"" << m.name << "\") == 0) {"; + if (ret) entry << "return PIVariant::fromValue<" << rettype << " >("; + entry << "object->" << m.name << "(" << args << ")"; + if (ret) entry << ");"; + else entry << "; return PIVariant();"; + entry << "}\n"; + } + if (efunc) continue; + f << entry << "\tPICout(AddNewLine) << \"Can`t find function \\\"\" << function << \"\\\" in " + << e->type << " \\\"" << e->name << "\\\"!\";\n\treturn PIVariant();\n}\n"; + ventities << e; + } + } + + f << "\n\n__ClassInfo_" << defname << "_Initializer__::__ClassInfo_" << defname << "_Initializer__() {\n"; + f << "\tif (_inited_) return;\n\t_inited_ = true;\n\n"; + if (!only_enums) + f << "\tClassInfo * ci;\n\tTypeInfo * ni;\n\tFunctionInfo * fi;\n"; + f << "\tEnumInfo * ei;\n"; + f << "\t(*enumsInfo)[\"\"] = new EnumInfo();\n"; + if (!only_enums) { + f << "\n\n// Classes\n"; + piForeachC (PICodeParser::Entity * e, parser.entities) { + if (e->name.startsWith("_PI")) continue; + makeClassInfo(f, e); + } + } + f << "\n// Enums\n"; + piForeachC (PICodeParser::Enum & e, parser.enums) + makeEnumInfo(f, &e); + f << "}\n"; + f << "\n\nbool __ClassInfo_" << defname << "_Initializer__::_inited_ = false;\n"; + f.close(); + + + f.setPath(out + ".h"); + f.clear(); + f.open(PIIODevice::WriteOnly); + f << "// Generated by \"PIP Code model generator\" " << PIDateTime::current().toString("dd.MM.yyyy hh:mm:ss\n\n"); + f << "#ifndef " << defname << "\n#define " << defname << "\n\n"; + f << "#include \"pivariant.h\"\n#include \"picodeinfo.h\""; + if (!only_enums) { + f << "\n\n"; + piForeachC (PICodeParser::Entity * e, ventities) + f << e->type << " " << e->name << ";\n"; + f << "\n"; + piForeachC (PICodeParser::Entity * e, ventities) { + f << "\nPIVariant execFunction(" << e->name << " * object, const char * function, const PIVariant & arg0 = PIVariant(), \ +const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());"; + } + } + f << "\n\n\nclass __ClassInfo_" << defname << "_Initializer__ {\n"; + f << "public:\n\t__ClassInfo_" << defname << "_Initializer__();\n\tstatic bool _inited_;\n};\n"; + f << "\nstatic __ClassInfo_" << defname << "_Initializer__ __classinfo_" << defname.toLowerCase() << "_initializer__;\n"; + f << "\n\n#endif // " << defname << "\n"; + f.close(); +} + + +int main(int argc, char * argv[]) { + PICLI cli(argc, argv); + cli.setOptionalArgumentsCount(-1); + cli.addArgument("output", true); + cli.addArgument("help"); + cli.addArgument("quiet"); + cli.addArgument("Enum"); + cli.addArgument("print"); + cli.addArgument("Print"); + cli.addArgument("single"); + if (cli.hasArgument("help") || cli.argumentValue("output").isEmpty() || cli.optionalArguments().isEmpty()) { + usage(); + return 0; + } + piDebug = !cli.hasArgument("quiet"); + PICodeParser parser; + piForeachC (PIString & a, cli.rawArguments()) { + if (a.startsWith("-I")) parser.includeDirectory(a.mid(2)); + if (a.startsWith("-D")) parser.addDefine(a.mid(2), PIString()); + } + PIStringList files; + piForeachC (PIString & a, cli.optionalArguments()) + if (!a.startsWith("-")) files << a; + piCout << Cyan << Bold << "Parse files" << files << "..."; + parser.parseFiles(files, !cli.hasArgument("single")); + piCout << Cyan << Bold << "Parsing done"; + piCout << Cyan << Bold << "Writing code model ..."; + writeModel(parser, cli.argumentValue("output"), cli.hasArgument("Enum")); + piCout << Cyan << Bold << "Writing done"; + if (cli.hasArgument("print") || cli.hasArgument("Print")) { + bool womain = cli.hasArgument("print"); + piDebug = true; + PIStringList pf(parser.parsedFiles()); + piForeachC (PIString & f, pf) { + if ((womain && (f != parser.mainFile())) || !womain) + piCout << f; + } + } + return 0; +}; diff --git a/utils/code_model_generator/main_test.cpp b/utils/code_model_generator/main_test.cpp new file mode 100755 index 00000000..103aeb4f --- /dev/null +++ b/utils/code_model_generator/main_test.cpp @@ -0,0 +1,48 @@ +/* + PIP - Platform Independent Primitives + Code model generator + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pitimer.h" +#include "test.h" + +void event(void * , int d) { + piCout << "tick" << d; +} + +PITimer tm; + +int main(int argc, char * argv[]) { + //tm.setSlot(event); + //tm.start(200); + /*execFunction(&tm, "setSlot", PIVariant::fromValue(event)); + execFunction(&tm, "start", 200); + piMSleep(1000); + execFunction(&tm, "addDelimiter", 2); + piMSleep(1000); + execFunction(&tm, "stop"); + execFunction(&tm, "stop_"); + piMSleep(1000);*/ + typedef PIMap::value_type mpair; + piForeachC (mpair & i, *(PICodeInfo::classesInfo)) + piCout << *i.second; + piCout << "\n\n"; + typedef PIMap::value_type epair; + piForeachC (epair & i, *(PICodeInfo::enumsInfo)) + piCout << *i.second; + return 0; +}; diff --git a/utils/code_model_generator/pip_cmg b/utils/code_model_generator/pip_cmg new file mode 100755 index 00000000..b89cb562 Binary files /dev/null and b/utils/code_model_generator/pip_cmg differ diff --git a/utils/code_model_generator/pip_cmg.exe b/utils/code_model_generator/pip_cmg.exe new file mode 100644 index 00000000..1361e1b3 Binary files /dev/null and b/utils/code_model_generator/pip_cmg.exe differ diff --git a/utils/code_model_generator/test.cpp b/utils/code_model_generator/test.cpp new file mode 100755 index 00000000..c3242a40 --- /dev/null +++ b/utils/code_model_generator/test.cpp @@ -0,0 +1,7084 @@ +// Generated by "PIP Code model generator" 29.04.2014 18:03:05 + +#include +#include "test.h" + +using namespace PICodeInfo; + +#include "piusb.h" +#include "picli.h" +#include "pitime.h" +#include "pipeer.h" +#include "pimath.h" +#include "pifile.h" +#include "pichar.h" +#include "pitimer.h" +#include "pimutex.h" +#include "picodec.h" +#include "pithread.h" +#include "pistring.h" +#include "piserial.h" +#include "piobject.h" +#include "piconfig.h" +#include "pivariant.h" +#include "pisignals.h" +#include "piprocess.h" +#include "pimonitor.h" +#include "piconsole.h" +#include "piprotocol.h" +#include "piiodevice.h" +#include "piincludes.h" +#include "piethernet.h" +#include "pibitarray.h" +#include "pievaluator.h" +#include "pibytearray.h" +#include "pibinarylog.h" +#include "picollection.h" +#include "pikbdlistener.h" +#include "pidiagnostics.h" +#include "pisystemmonitor.h" +#include "pimultiprotocol.h" +#include "pipacketextractor.h" + + +PIVariant execFunction(PIMutex * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "lock") == 0) {object->lock(); return PIVariant();} + if (strcmp(function, "unlock") == 0) {object->unlock(); return PIVariant();} + if (strcmp(function, "tryLock") == 0) {return PIVariant::fromValue(object->tryLock());} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIMutex\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIBitArray * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "bitSize") == 0) {return PIVariant::fromValue(object->bitSize());} + if (strcmp(function, "byteSize") == 0) {return PIVariant::fromValue(object->byteSize());} + if (strcmp(function, "data") == 0) {return PIVariant::fromValue(object->data());} + if (strcmp(function, "toUChar") == 0) {return PIVariant::fromValue(object->toUChar());} + if (strcmp(function, "toUShort") == 0) {return PIVariant::fromValue(object->toUShort());} + if (strcmp(function, "toUInt") == 0) {return PIVariant::fromValue(object->toUInt());} + if (strcmp(function, "toULong") == 0) {return PIVariant::fromValue(object->toULong());} + if (strcmp(function, "toULLong") == 0) {return PIVariant::fromValue(object->toULLong());} + if (strcmp(function, "at") == 0) {return PIVariant::fromValue(object->at(arg0.toValue()));} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIBitArray\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIHuffman * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "compress") == 0) {return PIVariant::fromValue >(object->compress(arg0.toValue >()));} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIHuffman\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIByteArray * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "resized") == 0) {return PIVariant::fromValue(object->resized(arg0.toValue()));} + if (strcmp(function, "toBase64") == 0) {return PIVariant::fromValue(object->toBase64());} + if (strcmp(function, "fromBase64") == 0) {return PIVariant::fromValue(object->fromBase64());} + if (strcmp(function, "compressedRLE") == 0) {return PIVariant::fromValue(object->compressedRLE(arg0.toValue()));} + if (strcmp(function, "decompressedRLE") == 0) {return PIVariant::fromValue(object->decompressedRLE(arg0.toValue()));} + if (strcmp(function, "checksumPlain8") == 0) {return PIVariant::fromValue(object->checksumPlain8());} + if (strcmp(function, "checksumPlain32") == 0) {return PIVariant::fromValue(object->checksumPlain32());} + if (strcmp(function, "checksumCRC8") == 0) {return PIVariant::fromValue(object->checksumCRC8());} + if (strcmp(function, "checksumCRC16") == 0) {return PIVariant::fromValue(object->checksumCRC16());} + if (strcmp(function, "checksumCRC32") == 0) {return PIVariant::fromValue(object->checksumCRC32());} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIByteArray\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIChar * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "isDigit") == 0) {return PIVariant::fromValue(object->isDigit());} + if (strcmp(function, "isHex") == 0) {return PIVariant::fromValue(object->isHex());} + if (strcmp(function, "isGraphical") == 0) {return PIVariant::fromValue(object->isGraphical());} + if (strcmp(function, "isControl") == 0) {return PIVariant::fromValue(object->isControl());} + if (strcmp(function, "isLower") == 0) {return PIVariant::fromValue(object->isLower());} + if (strcmp(function, "isUpper") == 0) {return PIVariant::fromValue(object->isUpper());} + if (strcmp(function, "isPrint") == 0) {return PIVariant::fromValue(object->isPrint());} + if (strcmp(function, "isSpace") == 0) {return PIVariant::fromValue(object->isSpace());} + if (strcmp(function, "isAlpha") == 0) {return PIVariant::fromValue(object->isAlpha());} + if (strcmp(function, "isAscii") == 0) {return PIVariant::fromValue(object->isAscii());} + if (strcmp(function, "toInt") == 0) {return PIVariant::fromValue(object->toInt());} + if (strcmp(function, "toWCharPtr") == 0) {return PIVariant::fromValue(object->toWCharPtr());} + if (strcmp(function, "toCharPtr") == 0) {return PIVariant::fromValue(object->toCharPtr());} + if (strcmp(function, "toWChar") == 0) {return PIVariant::fromValue(object->toWChar());} + if (strcmp(function, "toAscii") == 0) {return PIVariant::fromValue(object->toAscii());} + if (strcmp(function, "unicode16Code") == 0) {return PIVariant::fromValue(object->unicode16Code());} + if (strcmp(function, "toUpper") == 0) {return PIVariant::fromValue(object->toUpper());} + if (strcmp(function, "toLower") == 0) {return PIVariant::fromValue(object->toLower());} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIChar\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIString * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "mid") == 0) {return PIVariant::fromValue(object->mid(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "left") == 0) {return PIVariant::fromValue(object->left(arg0.toValue()));} + if (strcmp(function, "right") == 0) {return PIVariant::fromValue(object->right(arg0.toValue()));} + if (strcmp(function, "trimmed") == 0) {return PIVariant::fromValue(object->trimmed());} + if (strcmp(function, "replaced") == 0) {return PIVariant::fromValue(object->replaced(arg0.toValue(), arg1.toValue(), arg2.toValue()));} + if (strcmp(function, "replaced") == 0) {return PIVariant::fromValue(object->replaced(arg0.toValue(), arg1.toValue(), arg2.toValue()));} + if (strcmp(function, "replaceAll") == 0) {return PIVariant::fromValue(object->replaceAll(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "reversed") == 0) {return PIVariant::fromValue(object->reversed());} + if (strcmp(function, "takeMid") == 0) {return PIVariant::fromValue(object->takeMid(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "takeLeft") == 0) {return PIVariant::fromValue(object->takeLeft(arg0.toValue()));} + if (strcmp(function, "takeRight") == 0) {return PIVariant::fromValue(object->takeRight(arg0.toValue()));} + if (strcmp(function, "takeSymbol") == 0) {return PIVariant::fromValue(object->takeSymbol());} + if (strcmp(function, "takeWord") == 0) {return PIVariant::fromValue(object->takeWord());} + if (strcmp(function, "takeCWord") == 0) {return PIVariant::fromValue(object->takeCWord());} + if (strcmp(function, "takeLine") == 0) {return PIVariant::fromValue(object->takeLine());} + if (strcmp(function, "takeNumber") == 0) {return PIVariant::fromValue(object->takeNumber());} + if (strcmp(function, "takeRange") == 0) {return PIVariant::fromValue(object->takeRange(arg0.toValue(), arg1.toValue(), arg2.toValue()));} + if (strcmp(function, "lengthAscii") == 0) {return PIVariant::fromValue(object->lengthAscii());} + if (strcmp(function, "data") == 0) {return PIVariant::fromValue(object->data());} + if (strcmp(function, "stdString") == 0) {return PIVariant::fromValue(object->stdString());} + if (strcmp(function, "toByteArray") == 0) {return PIVariant::fromValue(object->toByteArray());} + if (strcmp(function, "split") == 0) {return PIVariant::fromValue(object->split(arg0.toValue()));} + if (strcmp(function, "toUpperCase") == 0) {return PIVariant::fromValue(object->toUpperCase());} + if (strcmp(function, "toLowerCase") == 0) {return PIVariant::fromValue(object->toLowerCase());} + if (strcmp(function, "toNativeDecimalPoints") == 0) {return PIVariant::fromValue(object->toNativeDecimalPoints());} + if (strcmp(function, "find") == 0) {return PIVariant::fromValue(object->find(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "find") == 0) {return PIVariant::fromValue(object->find(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "find") == 0) {return PIVariant::fromValue(object->find(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "find") == 0) {return PIVariant::fromValue(object->find(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "findLast") == 0) {return PIVariant::fromValue(object->findLast(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "findLast") == 0) {return PIVariant::fromValue(object->findLast(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "findLast") == 0) {return PIVariant::fromValue(object->findLast(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "findLast") == 0) {return PIVariant::fromValue(object->findLast(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "findWord") == 0) {return PIVariant::fromValue(object->findWord(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "findCWord") == 0) {return PIVariant::fromValue(object->findCWord(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "startsWith") == 0) {return PIVariant::fromValue(object->startsWith(arg0.toValue()));} + if (strcmp(function, "endsWith") == 0) {return PIVariant::fromValue(object->endsWith(arg0.toValue()));} + if (strcmp(function, "length") == 0) {return PIVariant::fromValue(object->length());} + if (strcmp(function, "isEmpty") == 0) {return PIVariant::fromValue(object->isEmpty());} + if (strcmp(function, "toBool") == 0) {return PIVariant::fromValue(object->toBool());} + if (strcmp(function, "toChar") == 0) {return PIVariant::fromValue(object->toChar());} + if (strcmp(function, "toShort") == 0) {return PIVariant::fromValue(object->toShort(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "toUShort") == 0) {return PIVariant::fromValue(object->toUShort(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "toInt") == 0) {return PIVariant::fromValue(object->toInt(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "toUInt") == 0) {return PIVariant::fromValue(object->toUInt(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "toLong") == 0) {return PIVariant::fromValue(object->toLong(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "toULong") == 0) {return PIVariant::fromValue(object->toULong(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "toLLong") == 0) {return PIVariant::fromValue(object->toLLong(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "toULLong") == 0) {return PIVariant::fromValue(object->toULLong(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "toFloat") == 0) {return PIVariant::fromValue(object->toFloat());} + if (strcmp(function, "toDouble") == 0) {return PIVariant::fromValue(object->toDouble());} + if (strcmp(function, "toLDouble") == 0) {return PIVariant::fromValue(object->toLDouble());} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIString\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIStringList * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "join") == 0) {return PIVariant::fromValue(object->join(arg0.toValue()));} + if (strcmp(function, "contentSize") == 0) {return PIVariant::fromValue(object->contentSize());} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIStringList\"!"; + return PIVariant(); +} + +PIVariant execFunction(PISystemTime * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "toSeconds") == 0) {return PIVariant::fromValue(object->toSeconds());} + if (strcmp(function, "toMilliseconds") == 0) {return PIVariant::fromValue(object->toMilliseconds());} + if (strcmp(function, "toMicroseconds") == 0) {return PIVariant::fromValue(object->toMicroseconds());} + if (strcmp(function, "toNanoseconds") == 0) {return PIVariant::fromValue(object->toNanoseconds());} + if (strcmp(function, "sleep") == 0) {object->sleep(); return PIVariant();} + if (strcmp(function, "abs") == 0) {return PIVariant::fromValue(object->abs());} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PISystemTime\"!"; + return PIVariant(); +} + +PIVariant execFunction(PITime * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "toString") == 0) {return PIVariant::fromValue(object->toString(arg0.toValue()));} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in struct \"PITime\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIDate * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "toString") == 0) {return PIVariant::fromValue(object->toString(arg0.toValue()));} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in struct \"PIDate\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIDateTime * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "normalized") == 0) {return PIVariant::fromValue(object->normalized());} + if (strcmp(function, "normalize") == 0) {object->normalize(); return PIVariant();} + if (strcmp(function, "toString") == 0) {return PIVariant::fromValue(object->toString(arg0.toValue()));} + if (strcmp(function, "toSecondSinceEpoch") == 0) {return PIVariant::fromValue(object->toSecondSinceEpoch());} + if (strcmp(function, "toSystemTime") == 0) {return PIVariant::fromValue(object->toSystemTime());} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in struct \"PIDateTime\"!"; + return PIVariant(); +} + +PIVariant execFunction(Solver * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "solve") == 0) {object->solve(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "fromTF") == 0) {object->fromTF(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setMethod") == 0) {object->setMethod(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setTime") == 0) {object->setTime(arg0.toValue()); return PIVariant();} + if (strcmp(function, "solveEyler1") == 0) {object->solveEyler1(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "solveEyler2") == 0) {object->solveEyler2(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "solveRK4") == 0) {object->solveRK4(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "solveABM2") == 0) {object->solveABM2(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "solveABM3") == 0) {object->solveABM3(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "solveABM4") == 0) {object->solveABM4(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "solvePA") == 0) {object->solvePA(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "solvePA2") == 0) {object->solvePA2(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "solvePA3") == 0) {object->solvePA3(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "solvePA4") == 0) {object->solvePA4(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "solvePA5") == 0) {object->solvePA5(arg0.toValue(), arg1.toValue()); return PIVariant();} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"Solver\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIFFT * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "calcFFT") == 0) {return PIVariant::fromValue * >(object->calcFFT(arg0.toValue >()));} + if (strcmp(function, "calcFFT") == 0) {return PIVariant::fromValue * >(object->calcFFT(arg0.toValue >()));} + if (strcmp(function, "calcFFTinverse") == 0) {return PIVariant::fromValue * >(object->calcFFTinverse(arg0.toValue >()));} + if (strcmp(function, "calcHilbert") == 0) {return PIVariant::fromValue * >(object->calcHilbert(arg0.toValue >()));} + if (strcmp(function, "getAmplitude") == 0) {return PIVariant::fromValue >(object->getAmplitude());} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIFFT\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIVariant * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue()); return PIVariant();} + if (strcmp(function, "toBool") == 0) {return PIVariant::fromValue(object->toBool());} + if (strcmp(function, "toInt") == 0) {return PIVariant::fromValue(object->toInt());} + if (strcmp(function, "toLLong") == 0) {return PIVariant::fromValue(object->toLLong());} + if (strcmp(function, "toFloat") == 0) {return PIVariant::fromValue(object->toFloat());} + if (strcmp(function, "toDouble") == 0) {return PIVariant::fromValue(object->toDouble());} + if (strcmp(function, "toLDouble") == 0) {return PIVariant::fromValue(object->toLDouble());} + if (strcmp(function, "toComplexd") == 0) {return PIVariant::fromValue(object->toComplexd());} + if (strcmp(function, "toComplexld") == 0) {return PIVariant::fromValue(object->toComplexld());} + if (strcmp(function, "toTime") == 0) {return PIVariant::fromValue(object->toTime());} + if (strcmp(function, "toDate") == 0) {return PIVariant::fromValue(object->toDate());} + if (strcmp(function, "toDateTime") == 0) {return PIVariant::fromValue(object->toDateTime());} + if (strcmp(function, "toSystemTime") == 0) {return PIVariant::fromValue(object->toSystemTime());} + if (strcmp(function, "toString") == 0) {return PIVariant::fromValue(object->toString());} + if (strcmp(function, "toStringList") == 0) {return PIVariant::fromValue(object->toStringList());} + if (strcmp(function, "toBitArray") == 0) {return PIVariant::fromValue(object->toBitArray());} + if (strcmp(function, "toByteArray") == 0) {return PIVariant::fromValue(object->toByteArray());} + if (strcmp(function, "type") == 0) {return PIVariant::fromValue(object->type());} + if (strcmp(function, "typeName") == 0) {return PIVariant::fromValue(object->typeName());} + if (strcmp(function, "isValid") == 0) {return PIVariant::fromValue(object->isValid());} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIVariant\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIObject * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "name") == 0) {return PIVariant::fromValue(object->name());} + if (strcmp(function, "className") == 0) {return PIVariant::fromValue(object->className());} + if (strcmp(function, "debug") == 0) {return PIVariant::fromValue(object->debug());} + if (strcmp(function, "setName") == 0) {object->setName(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setDebug") == 0) {object->setDebug(arg0.toValue()); return PIVariant();} + if (strcmp(function, "properties") == 0) {return PIVariant::fromValue >(object->properties());} + if (strcmp(function, "propertiesCount") == 0) {return PIVariant::fromValue(object->propertiesCount());} + if (strcmp(function, "property") == 0) {return PIVariant::fromValue(object->property(arg0.toValue()));} + if (strcmp(function, "setProperty") == 0) {object->setProperty(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "isPropertyExists") == 0) {return PIVariant::fromValue(object->isPropertyExists(arg0.toValue()));} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIObject\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIThread * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "className") == 0) {return PIVariant::fromValue(object->className());} + if (strcmp(function, "start") == 0) {return PIVariant::fromValue(object->start());} + if (strcmp(function, "start") == 0) {return PIVariant::fromValue(object->start(arg0.toValue()));} + if (strcmp(function, "start") == 0) {return PIVariant::fromValue(object->start(arg0.toValue()));} + if (strcmp(function, "start") == 0) {return PIVariant::fromValue(object->start(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "startOnce") == 0) {return PIVariant::fromValue(object->startOnce());} + if (strcmp(function, "startOnce") == 0) {return PIVariant::fromValue(object->startOnce(arg0.toValue()));} + if (strcmp(function, "stop") == 0) {object->stop(); return PIVariant();} + if (strcmp(function, "stop") == 0) {object->stop(arg0.toValue()); return PIVariant();} + if (strcmp(function, "terminate") == 0) {object->terminate(); return PIVariant();} + if (strcmp(function, "setData") == 0) {object->setData(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setSlot") == 0) {object->setSlot(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setPriority") == 0) {object->setPriority(arg0.toValue()); return PIVariant();} + if (strcmp(function, "priority") == 0) {return PIVariant::fromValue(object->priority());} + if (strcmp(function, "isRunning") == 0) {return PIVariant::fromValue(object->isRunning());} + if (strcmp(function, "isStopping") == 0) {return PIVariant::fromValue(object->isStopping());} + if (strcmp(function, "waitForStart") == 0) {return PIVariant::fromValue(object->waitForStart());} + if (strcmp(function, "waitForStart") == 0) {return PIVariant::fromValue(object->waitForStart(arg0.toValue()));} + if (strcmp(function, "waitForFinish") == 0) {return PIVariant::fromValue(object->waitForFinish());} + if (strcmp(function, "waitForFinish") == 0) {return PIVariant::fromValue(object->waitForFinish(arg0.toValue()));} + if (strcmp(function, "needLockRun") == 0) {object->needLockRun(arg0.toValue()); return PIVariant();} + if (strcmp(function, "lock") == 0) {object->lock(); return PIVariant();} + if (strcmp(function, "unlock") == 0) {object->unlock(); return PIVariant();} + if (strcmp(function, "started") == 0) {object->started(); return PIVariant();} + if (strcmp(function, "stopped") == 0) {object->stopped(); return PIVariant();} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIThread\"!"; + return PIVariant(); +} + +PIVariant execFunction(PITimer * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "className") == 0) {return PIVariant::fromValue(object->className());} + if (strcmp(function, "setData") == 0) {object->setData(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setSlot") == 0) {object->setSlot(arg0.toValue()); return PIVariant();} + if (strcmp(function, "interval") == 0) {return PIVariant::fromValue(object->interval());} + if (strcmp(function, "reset") == 0) {object->reset(); return PIVariant();} + if (strcmp(function, "start") == 0) {object->start(arg0.toValue()); return PIVariant();} + if (strcmp(function, "start") == 0) {object->start(arg0.toValue()); return PIVariant();} + if (strcmp(function, "deferredStart") == 0) {object->deferredStart(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "deferredStart") == 0) {object->deferredStart(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "stop") == 0) {object->stop(); return PIVariant();} + if (strcmp(function, "addDelimiter") == 0) {object->addDelimiter(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "removeDelimiter") == 0) {object->removeDelimiter(arg0.toValue()); return PIVariant();} + if (strcmp(function, "removeDelimiter") == 0) {object->removeDelimiter(arg0.toValue()); return PIVariant();} + if (strcmp(function, "removeDelimiter") == 0) {object->removeDelimiter(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "setDelimiterValue") == 0) {object->setDelimiterValue(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "setDelimiterValue") == 0) {object->setDelimiterValue(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "setDelimiterValue") == 0) {object->setDelimiterValue(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "delimiterValue") == 0) {return PIVariant::fromValue(object->delimiterValue(arg0.toValue()));} + if (strcmp(function, "delimiterValue") == 0) {return PIVariant::fromValue(object->delimiterValue(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "clearDelimiters") == 0) {object->clearDelimiters(); return PIVariant();} + if (strcmp(function, "elapsed_n") == 0) {return PIVariant::fromValue(object->elapsed_n());} + if (strcmp(function, "elapsed_u") == 0) {return PIVariant::fromValue(object->elapsed_u());} + if (strcmp(function, "elapsed_m") == 0) {return PIVariant::fromValue(object->elapsed_m());} + if (strcmp(function, "elapsed_s") == 0) {return PIVariant::fromValue(object->elapsed_s());} + if (strcmp(function, "reset_time_n") == 0) {return PIVariant::fromValue(object->reset_time_n());} + if (strcmp(function, "reset_time_u") == 0) {return PIVariant::fromValue(object->reset_time_u());} + if (strcmp(function, "reset_time_m") == 0) {return PIVariant::fromValue(object->reset_time_m());} + if (strcmp(function, "reset_time_s") == 0) {return PIVariant::fromValue(object->reset_time_s());} + if (strcmp(function, "reset_time") == 0) {return PIVariant::fromValue(object->reset_time());} + if (strcmp(function, "timeout") == 0) {object->timeout(arg0.toValue(), arg1.toValue()); return PIVariant();} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PITimer\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIKbdListener * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "className") == 0) {return PIVariant::fromValue(object->className());} + if (strcmp(function, "data") == 0) {return PIVariant::fromValue(object->data());} + if (strcmp(function, "setData") == 0) {object->setData(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setSlot") == 0) {object->setSlot(arg0.toValue()); return PIVariant();} + if (strcmp(function, "exitCaptured") == 0) {return PIVariant::fromValue(object->exitCaptured());} + if (strcmp(function, "exitKey") == 0) {return PIVariant::fromValue(object->exitKey());} + if (strcmp(function, "isActive") == 0) {return PIVariant::fromValue(object->isActive());} + if (strcmp(function, "enableExitCapture") == 0) {object->enableExitCapture(); return PIVariant();} + if (strcmp(function, "enableExitCapture") == 0) {object->enableExitCapture(arg0.toValue()); return PIVariant();} + if (strcmp(function, "disableExitCapture") == 0) {object->disableExitCapture(); return PIVariant();} + if (strcmp(function, "setActive") == 0) {object->setActive(); return PIVariant();} + if (strcmp(function, "setActive") == 0) {object->setActive(arg0.toValue()); return PIVariant();} + if (strcmp(function, "keyPressed") == 0) {object->keyPressed(arg0.toValue(), arg1.toValue()); return PIVariant();} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIKbdListener\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIIODevice * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "className") == 0) {return PIVariant::fromValue(object->className());} + if (strcmp(function, "mode") == 0) {return PIVariant::fromValue(object->mode());} + if (strcmp(function, "path") == 0) {return PIVariant::fromValue(object->path());} + if (strcmp(function, "setPath") == 0) {object->setPath(arg0.toValue()); return PIVariant();} + if (strcmp(function, "isReadable") == 0) {return PIVariant::fromValue(object->isReadable());} + if (strcmp(function, "isWriteable") == 0) {return PIVariant::fromValue(object->isWriteable());} + if (strcmp(function, "isInitialized") == 0) {return PIVariant::fromValue(object->isInitialized());} + if (strcmp(function, "isOpened") == 0) {return PIVariant::fromValue(object->isOpened());} + if (strcmp(function, "isClosed") == 0) {return PIVariant::fromValue(object->isClosed());} + if (strcmp(function, "canRead") == 0) {return PIVariant::fromValue(object->canRead());} + if (strcmp(function, "canWrite") == 0) {return PIVariant::fromValue(object->canWrite());} + if (strcmp(function, "setReopenEnabled") == 0) {object->setReopenEnabled(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setReopenTimeout") == 0) {object->setReopenTimeout(arg0.toValue()); return PIVariant();} + if (strcmp(function, "isReopenEnabled") == 0) {return PIVariant::fromValue(object->isReopenEnabled());} + if (strcmp(function, "reopenTimeout") == 0) {return PIVariant::fromValue(object->reopenTimeout());} + if (strcmp(function, "setThreadedReadSlot") == 0) {object->setThreadedReadSlot(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setThreadedReadData") == 0) {object->setThreadedReadData(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setThreadedReadBufferSize") == 0) {object->setThreadedReadBufferSize(arg0.toValue()); return PIVariant();} + if (strcmp(function, "threadedReadBufferSize") == 0) {return PIVariant::fromValue(object->threadedReadBufferSize());} + if (strcmp(function, "threadedReadBuffer") == 0) {return PIVariant::fromValue(object->threadedReadBuffer());} + if (strcmp(function, "isThreadedRead") == 0) {return PIVariant::fromValue(object->isThreadedRead());} + if (strcmp(function, "startThreadedRead") == 0) {object->startThreadedRead(); return PIVariant();} + if (strcmp(function, "startThreadedRead") == 0) {object->startThreadedRead(arg0.toValue()); return PIVariant();} + if (strcmp(function, "stopThreadedRead") == 0) {object->stopThreadedRead(); return PIVariant();} + if (strcmp(function, "isThreadedWrite") == 0) {return PIVariant::fromValue(object->isThreadedWrite());} + if (strcmp(function, "startThreadedWrite") == 0) {object->startThreadedWrite(); return PIVariant();} + if (strcmp(function, "stopThreadedWrite") == 0) {object->stopThreadedWrite(); return PIVariant();} + if (strcmp(function, "clearThreadedWriteQueue") == 0) {object->clearThreadedWriteQueue(); return PIVariant();} + if (strcmp(function, "start") == 0) {object->start(); return PIVariant();} + if (strcmp(function, "stop") == 0) {object->stop(arg0.toValue()); return PIVariant();} + if (strcmp(function, "read") == 0) {return PIVariant::fromValue(object->read(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "write") == 0) {return PIVariant::fromValue(object->write(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "read") == 0) {return PIVariant::fromValue(object->read(arg0.toValue()));} + if (strcmp(function, "readForTime") == 0) {return PIVariant::fromValue(object->readForTime(arg0.toValue()));} + if (strcmp(function, "write") == 0) {return PIVariant::fromValue(object->write(arg0.toValue()));} + if (strcmp(function, "writeThreaded") == 0) {return PIVariant::fromValue(object->writeThreaded(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "writeThreaded") == 0) {return PIVariant::fromValue(object->writeThreaded(arg0.toValue()));} + if (strcmp(function, "configure") == 0) {return PIVariant::fromValue(object->configure(arg0.toValue(), arg1.toValue(), arg2.toValue()));} + if (strcmp(function, "open") == 0) {return PIVariant::fromValue(object->open());} + if (strcmp(function, "open") == 0) {return PIVariant::fromValue(object->open(arg0.toValue()));} + if (strcmp(function, "open") == 0) {return PIVariant::fromValue(object->open(arg0.toValue()));} + if (strcmp(function, "open") == 0) {return PIVariant::fromValue(object->open(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "close") == 0) {return PIVariant::fromValue(object->close());} + if (strcmp(function, "initialize") == 0) {return PIVariant::fromValue(object->initialize());} + if (strcmp(function, "flush") == 0) {object->flush(); return PIVariant();} + if (strcmp(function, "opened") == 0) {object->opened(); return PIVariant();} + if (strcmp(function, "closed") == 0) {object->closed(); return PIVariant();} + if (strcmp(function, "threadedReadEvent") == 0) {object->threadedReadEvent(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "threadedWriteEvent") == 0) {object->threadedWriteEvent(arg0.toValue(), arg1.toValue()); return PIVariant();} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIIODevice\"!"; + return PIVariant(); +} + +PIVariant execFunction(PISerial * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "className") == 0) {return PIVariant::fromValue(object->className());} + if (strcmp(function, "setSpeed") == 0) {object->setSpeed(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setOutSpeed") == 0) {object->setOutSpeed(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setInSpeed") == 0) {object->setInSpeed(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setDevice") == 0) {object->setDevice(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setParameters") == 0) {object->setParameters(arg0.toValue >()); return PIVariant();} + if (strcmp(function, "setParameter") == 0) {object->setParameter(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "isParameterSet") == 0) {return PIVariant::fromValue(object->isParameterSet(arg0.toValue()));} + if (strcmp(function, "parameters") == 0) {return PIVariant::fromValue >(object->parameters());} + if (strcmp(function, "setDataBitsCount") == 0) {object->setDataBitsCount(arg0.toValue()); return PIVariant();} + if (strcmp(function, "dataBitsCount") == 0) {return PIVariant::fromValue(object->dataBitsCount());} + if (strcmp(function, "setPin") == 0) {return PIVariant::fromValue(object->setPin(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "isPin") == 0) {return PIVariant::fromValue(object->isPin(arg0.toValue()));} + if (strcmp(function, "setLE") == 0) {return PIVariant::fromValue(object->setLE(arg0.toValue()));} + if (strcmp(function, "setDTR") == 0) {return PIVariant::fromValue(object->setDTR(arg0.toValue()));} + if (strcmp(function, "setRTS") == 0) {return PIVariant::fromValue(object->setRTS(arg0.toValue()));} + if (strcmp(function, "setCTS") == 0) {return PIVariant::fromValue(object->setCTS(arg0.toValue()));} + if (strcmp(function, "setST") == 0) {return PIVariant::fromValue(object->setST(arg0.toValue()));} + if (strcmp(function, "setSR") == 0) {return PIVariant::fromValue(object->setSR(arg0.toValue()));} + if (strcmp(function, "setCAR") == 0) {return PIVariant::fromValue(object->setCAR(arg0.toValue()));} + if (strcmp(function, "setRNG") == 0) {return PIVariant::fromValue(object->setRNG(arg0.toValue()));} + if (strcmp(function, "setDSR") == 0) {return PIVariant::fromValue(object->setDSR(arg0.toValue()));} + if (strcmp(function, "isLE") == 0) {return PIVariant::fromValue(object->isLE());} + if (strcmp(function, "isDTR") == 0) {return PIVariant::fromValue(object->isDTR());} + if (strcmp(function, "isRTS") == 0) {return PIVariant::fromValue(object->isRTS());} + if (strcmp(function, "isCTS") == 0) {return PIVariant::fromValue(object->isCTS());} + if (strcmp(function, "isST") == 0) {return PIVariant::fromValue(object->isST());} + if (strcmp(function, "isSR") == 0) {return PIVariant::fromValue(object->isSR());} + if (strcmp(function, "isCAR") == 0) {return PIVariant::fromValue(object->isCAR());} + if (strcmp(function, "isRNG") == 0) {return PIVariant::fromValue(object->isRNG());} + if (strcmp(function, "isDSR") == 0) {return PIVariant::fromValue(object->isDSR());} + if (strcmp(function, "setVTime") == 0) {object->setVTime(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setReadIsBlocking") == 0) {object->setReadIsBlocking(arg0.toValue()); return PIVariant();} + if (strcmp(function, "device") == 0) {return PIVariant::fromValue(object->device());} + if (strcmp(function, "outSpeed") == 0) {return PIVariant::fromValue(object->outSpeed());} + if (strcmp(function, "inSpeed") == 0) {return PIVariant::fromValue(object->inSpeed());} + if (strcmp(function, "VTime") == 0) {return PIVariant::fromValue(object->VTime());} + if (strcmp(function, "flush") == 0) {object->flush(); return PIVariant();} + if (strcmp(function, "read") == 0) {return PIVariant::fromValue(object->read(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "read") == 0) {return PIVariant::fromValue(object->read(arg0.toValue(), arg1.toValue(), arg2.toValue()));} + if (strcmp(function, "read") == 0) {return PIVariant::fromValue(object->read(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "readData") == 0) {return PIVariant::fromValue(object->readData(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "write") == 0) {return PIVariant::fromValue(object->write(arg0.toValue(), arg1.toValue(), arg2.toValue()));} + if (strcmp(function, "send") == 0) {return PIVariant::fromValue(object->send(arg0.toValue(), arg1.toValue(), arg2.toValue()));} + if (strcmp(function, "send") == 0) {return PIVariant::fromValue(object->send(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "send") == 0) {return PIVariant::fromValue(object->send(arg0.toValue(), arg1.toValue()));} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PISerial\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIFile * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "className") == 0) {return PIVariant::fromValue(object->className());} + if (strcmp(function, "flush") == 0) {object->flush(); return PIVariant();} + if (strcmp(function, "seek") == 0) {object->seek(arg0.toValue()); return PIVariant();} + if (strcmp(function, "seekToBegin") == 0) {object->seekToBegin(); return PIVariant();} + if (strcmp(function, "seekToEnd") == 0) {object->seekToEnd(); return PIVariant();} + if (strcmp(function, "seekToLine") == 0) {object->seekToLine(arg0.toValue()); return PIVariant();} + if (strcmp(function, "readChar") == 0) {return PIVariant::fromValue(object->readChar());} + if (strcmp(function, "readLine") == 0) {return PIVariant::fromValue(object->readLine());} + if (strcmp(function, "readAll") == 0) {return PIVariant::fromValue(object->readAll(arg0.toValue()));} + if (strcmp(function, "readAll") == 0) {return PIVariant::fromValue(object->readAll(arg0.toValue()));} + if (strcmp(function, "setPath") == 0) {object->setPath(arg0.toValue()); return PIVariant();} + if (strcmp(function, "size") == 0) {return PIVariant::fromValue(object->size());} + if (strcmp(function, "pos") == 0) {return PIVariant::fromValue(object->pos());} + if (strcmp(function, "isEnd") == 0) {return PIVariant::fromValue(object->isEnd());} + if (strcmp(function, "isEmpty") == 0) {return PIVariant::fromValue(object->isEmpty());} + if (strcmp(function, "precision") == 0) {return PIVariant::fromValue(object->precision());} + if (strcmp(function, "setPrecision") == 0) {object->setPrecision(arg0.toValue()); return PIVariant();} + if (strcmp(function, "read") == 0) {return PIVariant::fromValue(object->read(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "write") == 0) {return PIVariant::fromValue(object->write(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "clear") == 0) {object->clear(); return PIVariant();} + if (strcmp(function, "remove") == 0) {object->remove(); return PIVariant();} + if (strcmp(function, "resize") == 0) {object->resize(arg0.toValue()); return PIVariant();} + if (strcmp(function, "resize") == 0) {object->resize(arg0.toValue(), arg1.toValue()); return PIVariant();} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIFile\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIProcess * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "className") == 0) {return PIVariant::fromValue(object->className());} + if (strcmp(function, "exitCode") == 0) {return PIVariant::fromValue(object->exitCode());} + if (strcmp(function, "pID") == 0) {return PIVariant::fromValue(object->pID());} + if (strcmp(function, "setGrabInput") == 0) {object->setGrabInput(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setGrabOutput") == 0) {object->setGrabOutput(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setGrabError") == 0) {object->setGrabError(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setInputFile") == 0) {object->setInputFile(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setOutputFile") == 0) {object->setOutputFile(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setErrorFile") == 0) {object->setErrorFile(arg0.toValue()); return PIVariant();} + if (strcmp(function, "unsetInputFile") == 0) {object->unsetInputFile(); return PIVariant();} + if (strcmp(function, "unsetOutputFile") == 0) {object->unsetOutputFile(); return PIVariant();} + if (strcmp(function, "unsetErrorFile") == 0) {object->unsetErrorFile(); return PIVariant();} + if (strcmp(function, "workingDirectory") == 0) {return PIVariant::fromValue(object->workingDirectory());} + if (strcmp(function, "setWorkingDirectory") == 0) {object->setWorkingDirectory(arg0.toValue()); return PIVariant();} + if (strcmp(function, "resetWorkingDirectory") == 0) {object->resetWorkingDirectory(); return PIVariant();} + if (strcmp(function, "readOutput") == 0) {return PIVariant::fromValue(object->readOutput());} + if (strcmp(function, "readError") == 0) {return PIVariant::fromValue(object->readError());} + if (strcmp(function, "environment") == 0) {return PIVariant::fromValue(object->environment());} + if (strcmp(function, "clearEnvironment") == 0) {object->clearEnvironment(); return PIVariant();} + if (strcmp(function, "removeEnvironmentVariable") == 0) {object->removeEnvironmentVariable(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setEnvironmentVariable") == 0) {object->setEnvironmentVariable(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "exec") == 0) {object->exec(arg0.toValue()); return PIVariant();} + if (strcmp(function, "exec") == 0) {object->exec(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "exec") == 0) {object->exec(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "exec") == 0) {object->exec(arg0.toValue(), arg1.toValue(), arg2.toValue(), arg3.toValue()); return PIVariant();} + if (strcmp(function, "exec") == 0) {object->exec(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "terminate") == 0) {object->terminate(); return PIVariant();} + if (strcmp(function, "waitForFinish") == 0) {return PIVariant::fromValue(object->waitForFinish());} + if (strcmp(function, "waitForFinish") == 0) {return PIVariant::fromValue(object->waitForFinish(arg0.toValue()));} + if (strcmp(function, "execStarted") == 0) {object->execStarted(arg0.toValue()); return PIVariant();} + if (strcmp(function, "execFinished") == 0) {object->execFinished(arg0.toValue(), arg1.toValue()); return PIVariant();} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIProcess\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIEthernet * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "className") == 0) {return PIVariant::fromValue(object->className());} + if (strcmp(function, "setReadAddress") == 0) {object->setReadAddress(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "setReadAddress") == 0) {object->setReadAddress(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setReadIP") == 0) {object->setReadIP(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setReadPort") == 0) {object->setReadPort(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setSendAddress") == 0) {object->setSendAddress(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "setSendAddress") == 0) {object->setSendAddress(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setSendIP") == 0) {object->setSendIP(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setSendPort") == 0) {object->setSendPort(arg0.toValue()); return PIVariant();} + if (strcmp(function, "readAddress") == 0) {return PIVariant::fromValue(object->readAddress());} + if (strcmp(function, "readIP") == 0) {return PIVariant::fromValue(object->readIP());} + if (strcmp(function, "readPort") == 0) {return PIVariant::fromValue(object->readPort());} + if (strcmp(function, "sendAddress") == 0) {return PIVariant::fromValue(object->sendAddress());} + if (strcmp(function, "sendIP") == 0) {return PIVariant::fromValue(object->sendIP());} + if (strcmp(function, "sendPort") == 0) {return PIVariant::fromValue(object->sendPort());} + if (strcmp(function, "setParameters") == 0) {object->setParameters(arg0.toValue >()); return PIVariant();} + if (strcmp(function, "setParameter") == 0) {object->setParameter(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "isParameterSet") == 0) {return PIVariant::fromValue(object->isParameterSet(arg0.toValue()));} + if (strcmp(function, "parameters") == 0) {return PIVariant::fromValue >(object->parameters());} + if (strcmp(function, "type") == 0) {return PIVariant::fromValue(object->type());} + if (strcmp(function, "joinMulticastGroup") == 0) {return PIVariant::fromValue(object->joinMulticastGroup(arg0.toValue()));} + if (strcmp(function, "leaveMulticastGroup") == 0) {return PIVariant::fromValue(object->leaveMulticastGroup(arg0.toValue()));} + if (strcmp(function, "multicastGroups") == 0) {return PIVariant::fromValue(object->multicastGroups());} + if (strcmp(function, "connect") == 0) {return PIVariant::fromValue(object->connect());} + if (strcmp(function, "connect") == 0) {return PIVariant::fromValue(object->connect(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "connect") == 0) {return PIVariant::fromValue(object->connect(arg0.toValue()));} + if (strcmp(function, "isConnected") == 0) {return PIVariant::fromValue(object->isConnected());} + if (strcmp(function, "listen") == 0) {return PIVariant::fromValue(object->listen());} + if (strcmp(function, "listen") == 0) {return PIVariant::fromValue(object->listen(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "listen") == 0) {return PIVariant::fromValue(object->listen(arg0.toValue()));} + if (strcmp(function, "client") == 0) {return PIVariant::fromValue(object->client(arg0.toValue()));} + if (strcmp(function, "clientsCount") == 0) {return PIVariant::fromValue(object->clientsCount());} + if (strcmp(function, "clients") == 0) {return PIVariant::fromValue >(object->clients());} + if (strcmp(function, "send") == 0) {return PIVariant::fromValue(object->send(arg0.toValue(), arg1.toValue(), arg2.toValue(), arg3.toValue()));} + if (strcmp(function, "send") == 0) {return PIVariant::fromValue(object->send(arg0.toValue(), arg1.toValue(), arg2.toValue()));} + if (strcmp(function, "send") == 0) {return PIVariant::fromValue(object->send(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "read") == 0) {return PIVariant::fromValue(object->read(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "write") == 0) {return PIVariant::fromValue(object->write(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "write") == 0) {return PIVariant::fromValue(object->write(arg0.toValue()));} + if (strcmp(function, "newConnection") == 0) {object->newConnection(arg0.toValue()); return PIVariant();} + if (strcmp(function, "connected") == 0) {object->connected(); return PIVariant();} + if (strcmp(function, "disconnected") == 0) {object->disconnected(arg0.toValue()); return PIVariant();} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIEthernet\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIPacketExtractor * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "className") == 0) {return PIVariant::fromValue(object->className());} + if (strcmp(function, "device") == 0) {return PIVariant::fromValue(object->device());} + if (strcmp(function, "setDevice") == 0) {object->setDevice(arg0.toValue()); return PIVariant();} + if (strcmp(function, "bufferSize") == 0) {return PIVariant::fromValue(object->bufferSize());} + if (strcmp(function, "setBufferSize") == 0) {object->setBufferSize(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setHeaderCheckSlot") == 0) {object->setHeaderCheckSlot(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setPacketData") == 0) {object->setPacketData(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "missedBytes") == 0) {return PIVariant::fromValue(object->missedBytes());} + if (strcmp(function, "missedPackets") == 0) {return PIVariant::fromValue(object->missedPackets());} + if (strcmp(function, "missedBytes_ptr") == 0) {return PIVariant::fromValue(object->missedBytes_ptr());} + if (strcmp(function, "missedPackets_ptr") == 0) {return PIVariant::fromValue(object->missedPackets_ptr());} + if (strcmp(function, "lastHeader") == 0) {return PIVariant::fromValue(object->lastHeader());} + if (strcmp(function, "read") == 0) {return PIVariant::fromValue(object->read(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "write") == 0) {return PIVariant::fromValue(object->write(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "packetReceived") == 0) {object->packetReceived(arg0.toValue(), arg1.toValue()); return PIVariant();} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIPacketExtractor\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIConfig * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "getValues") == 0) {return PIVariant::fromValue(object->getValues(arg0.toValue()));} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue(), arg1.toValue(), arg2.toValue(), arg3.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "entriesCount") == 0) {return PIVariant::fromValue(object->entriesCount());} + if (strcmp(function, "isEntryExists") == 0) {return PIVariant::fromValue(object->isEntryExists(arg0.toValue()));} + if (strcmp(function, "allTree") == 0) {return PIVariant::fromValue(object->allTree());} + if (strcmp(function, "allLeaves") == 0) {return PIVariant::fromValue(object->allLeaves());} + if (strcmp(function, "entryIndex") == 0) {return PIVariant::fromValue(object->entryIndex(arg0.toValue()));} + if (strcmp(function, "getName") == 0) {return PIVariant::fromValue(object->getName(arg0.toValue()));} + if (strcmp(function, "getValue") == 0) {return PIVariant::fromValue(object->getValue(arg0.toValue()));} + if (strcmp(function, "getType") == 0) {return PIVariant::fromValue(object->getType(arg0.toValue()));} + if (strcmp(function, "getComment") == 0) {return PIVariant::fromValue(object->getComment(arg0.toValue()));} + if (strcmp(function, "addEntry") == 0) {object->addEntry(arg0.toValue(), arg1.toValue(), arg2.toValue(), arg3.toValue()); return PIVariant();} + if (strcmp(function, "setName") == 0) {object->setName(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "setValue") == 0) {object->setValue(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "setType") == 0) {object->setType(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "setComment") == 0) {object->setComment(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "removeEntry") == 0) {object->removeEntry(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "removeEntry") == 0) {object->removeEntry(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "clear") == 0) {object->clear(); return PIVariant();} + if (strcmp(function, "readAll") == 0) {object->readAll(); return PIVariant();} + if (strcmp(function, "writeAll") == 0) {object->writeAll(); return PIVariant();} + if (strcmp(function, "delimiter") == 0) {return PIVariant::fromValue(object->delimiter());} + if (strcmp(function, "setDelimiter") == 0) {object->setDelimiter(arg0.toValue()); return PIVariant();} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIConfig\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIMultiProtocolBase * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "className") == 0) {return PIVariant::fromValue(object->className());} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIMultiProtocolBase\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIProtocol * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "className") == 0) {return PIVariant::fromValue(object->className());} + if (strcmp(function, "startReceive") == 0) {object->startReceive(); return PIVariant();} + if (strcmp(function, "startReceive") == 0) {object->startReceive(arg0.toValue()); return PIVariant();} + if (strcmp(function, "stopReceive") == 0) {object->stopReceive(); return PIVariant();} + if (strcmp(function, "setExpectedFrequency") == 0) {object->setExpectedFrequency(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setReceiverDevice") == 0) {object->setReceiverDevice(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "setReceiverData") == 0) {object->setReceiverData(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "setReceiverDataHeader") == 0) {object->setReceiverDataHeader(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "setReceiverAddress") == 0) {object->setReceiverAddress(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "setReceiverParameters") == 0) {object->setReceiverParameters(arg0.toValue >()); return PIVariant();} + if (strcmp(function, "setReceiveSlot") == 0) {object->setReceiveSlot(arg0.toValue()); return PIVariant();} + if (strcmp(function, "expectedFrequency") == 0) {return PIVariant::fromValue(object->expectedFrequency());} + if (strcmp(function, "startSend") == 0) {object->startSend(); return PIVariant();} + if (strcmp(function, "startSend") == 0) {object->startSend(arg0.toValue()); return PIVariant();} + if (strcmp(function, "stopSend") == 0) {object->stopSend(); return PIVariant();} + if (strcmp(function, "setSenderFrequency") == 0) {object->setSenderFrequency(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setSenderDevice") == 0) {object->setSenderDevice(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "setSenderData") == 0) {object->setSenderData(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "setSenderAddress") == 0) {object->setSenderAddress(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "setSenderIP") == 0) {object->setSenderIP(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "setSenderPort") == 0) {object->setSenderPort(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "setSenderParameters") == 0) {object->setSenderParameters(arg0.toValue >()); return PIVariant();} + if (strcmp(function, "senderFrequency") == 0) {return PIVariant::fromValue(object->senderFrequency());} + if (strcmp(function, "start") == 0) {object->start(); return PIVariant();} + if (strcmp(function, "stop") == 0) {object->stop(); return PIVariant();} + if (strcmp(function, "send") == 0) {object->send(); return PIVariant();} + if (strcmp(function, "send") == 0) {object->send(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "send") == 0) {object->send(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "setName") == 0) {object->setName(arg0.toValue()); return PIVariant();} + if (strcmp(function, "name") == 0) {return PIVariant::fromValue(object->name());} + if (strcmp(function, "setDisconnectTimeout") == 0) {object->setDisconnectTimeout(arg0.toValue()); return PIVariant();} + if (strcmp(function, "disconnectTimeout") == 0) {return PIVariant::fromValue(object->disconnectTimeout());} + if (strcmp(function, "disconnectTimeout_ptr") == 0) {return PIVariant::fromValue(object->disconnectTimeout_ptr());} + if (strcmp(function, "immediateFrequency") == 0) {return PIVariant::fromValue(object->immediateFrequency());} + if (strcmp(function, "integralFrequency") == 0) {return PIVariant::fromValue(object->integralFrequency());} + if (strcmp(function, "immediateFrequency_ptr") == 0) {return PIVariant::fromValue(object->immediateFrequency_ptr());} + if (strcmp(function, "integralFrequency_ptr") == 0) {return PIVariant::fromValue(object->integralFrequency_ptr());} + if (strcmp(function, "receiveCountPerSec") == 0) {return PIVariant::fromValue(object->receiveCountPerSec());} + if (strcmp(function, "receiveCountPerSec_ptr") == 0) {return PIVariant::fromValue(object->receiveCountPerSec_ptr());} + if (strcmp(function, "sendCountPerSec") == 0) {return PIVariant::fromValue(object->sendCountPerSec());} + if (strcmp(function, "sendCountPerSec_ptr") == 0) {return PIVariant::fromValue(object->sendCountPerSec_ptr());} + if (strcmp(function, "receiveBytesPerSec") == 0) {return PIVariant::fromValue(object->receiveBytesPerSec());} + if (strcmp(function, "receiveBytesPerSec_ptr") == 0) {return PIVariant::fromValue(object->receiveBytesPerSec_ptr());} + if (strcmp(function, "sendBytesPerSec") == 0) {return PIVariant::fromValue(object->sendBytesPerSec());} + if (strcmp(function, "sendBytesPerSec_ptr") == 0) {return PIVariant::fromValue(object->sendBytesPerSec_ptr());} + if (strcmp(function, "receiveCount") == 0) {return PIVariant::fromValue(object->receiveCount());} + if (strcmp(function, "receiveCount_ptr") == 0) {return PIVariant::fromValue(object->receiveCount_ptr());} + if (strcmp(function, "wrongCount") == 0) {return PIVariant::fromValue(object->wrongCount());} + if (strcmp(function, "wrongCount_ptr") == 0) {return PIVariant::fromValue(object->wrongCount_ptr());} + if (strcmp(function, "sendCount") == 0) {return PIVariant::fromValue(object->sendCount());} + if (strcmp(function, "sendCount_ptr") == 0) {return PIVariant::fromValue(object->sendCount_ptr());} + if (strcmp(function, "missedCount") == 0) {return PIVariant::fromValue(object->missedCount());} + if (strcmp(function, "missedCount_ptr") == 0) {return PIVariant::fromValue(object->missedCount_ptr());} + if (strcmp(function, "quality") == 0) {return PIVariant::fromValue(object->quality());} + if (strcmp(function, "quality_ptr") == 0) {return PIVariant::fromValue(object->quality_ptr());} + if (strcmp(function, "receiverDeviceName") == 0) {return PIVariant::fromValue(object->receiverDeviceName());} + if (strcmp(function, "senderDeviceName") == 0) {return PIVariant::fromValue(object->senderDeviceName());} + if (strcmp(function, "receiverDeviceState") == 0) {return PIVariant::fromValue(object->receiverDeviceState());} + if (strcmp(function, "receiverDeviceState_ptr") == 0) {return PIVariant::fromValue(object->receiverDeviceState_ptr());} + if (strcmp(function, "senderDeviceState") == 0) {return PIVariant::fromValue(object->senderDeviceState());} + if (strcmp(function, "senderDeviceState_ptr") == 0) {return PIVariant::fromValue(object->senderDeviceState_ptr());} + if (strcmp(function, "receiveSpeed") == 0) {return PIVariant::fromValue(object->receiveSpeed());} + if (strcmp(function, "receiveSpeed_ptr") == 0) {return PIVariant::fromValue(object->receiveSpeed_ptr());} + if (strcmp(function, "sendSpeed") == 0) {return PIVariant::fromValue(object->sendSpeed());} + if (strcmp(function, "sendSpeed_ptr") == 0) {return PIVariant::fromValue(object->sendSpeed_ptr());} + if (strcmp(function, "receiverHistorySize") == 0) {return PIVariant::fromValue(object->receiverHistorySize());} + if (strcmp(function, "receiverHistorySize_ptr") == 0) {return PIVariant::fromValue(object->receiverHistorySize_ptr());} + if (strcmp(function, "senderHistorySize") == 0) {return PIVariant::fromValue(object->senderHistorySize());} + if (strcmp(function, "senderHistorySize_ptr") == 0) {return PIVariant::fromValue(object->senderHistorySize_ptr());} + if (strcmp(function, "writeReceiverHistory") == 0) {return PIVariant::fromValue(object->writeReceiverHistory());} + if (strcmp(function, "writeReceiverHistory_ptr") == 0) {return PIVariant::fromValue(object->writeReceiverHistory_ptr());} + if (strcmp(function, "writeSenderHistory") == 0) {return PIVariant::fromValue(object->writeSenderHistory());} + if (strcmp(function, "writeSenderHistory_ptr") == 0) {return PIVariant::fromValue(object->writeSenderHistory_ptr());} + if (strcmp(function, "receiveData") == 0) {return PIVariant::fromValue(object->receiveData());} + if (strcmp(function, "sendData") == 0) {return PIVariant::fromValue(object->sendData());} + if (strcmp(function, "packetExtractor") == 0) {return PIVariant::fromValue(object->packetExtractor());} + if (strcmp(function, "lastHeader") == 0) {return PIVariant::fromValue(object->lastHeader());} + if (strcmp(function, "receiverStarted") == 0) {object->receiverStarted(); return PIVariant();} + if (strcmp(function, "receiverStopped") == 0) {object->receiverStopped(); return PIVariant();} + if (strcmp(function, "senderStarted") == 0) {object->senderStarted(); return PIVariant();} + if (strcmp(function, "senderStopped") == 0) {object->senderStopped(); return PIVariant();} + if (strcmp(function, "received") == 0) {object->received(arg0.toValue()); return PIVariant();} + if (strcmp(function, "qualityChanged") == 0) {object->qualityChanged(arg0.toValue(), arg1.toValue()); return PIVariant();} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIProtocol\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIDiagnostics * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "className") == 0) {return PIVariant::fromValue(object->className());} + if (strcmp(function, "immediateFrequency") == 0) {return PIVariant::fromValue(object->immediateFrequency());} + if (strcmp(function, "integralFrequency") == 0) {return PIVariant::fromValue(object->integralFrequency());} + if (strcmp(function, "receiveCountPerSec") == 0) {return PIVariant::fromValue(object->receiveCountPerSec());} + if (strcmp(function, "sendCountPerSec") == 0) {return PIVariant::fromValue(object->sendCountPerSec());} + if (strcmp(function, "receiveBytesPerSec") == 0) {return PIVariant::fromValue(object->receiveBytesPerSec());} + if (strcmp(function, "sendBytesPerSec") == 0) {return PIVariant::fromValue(object->sendBytesPerSec());} + if (strcmp(function, "receiveCount") == 0) {return PIVariant::fromValue(object->receiveCount());} + if (strcmp(function, "wrongCount") == 0) {return PIVariant::fromValue(object->wrongCount());} + if (strcmp(function, "sendCount") == 0) {return PIVariant::fromValue(object->sendCount());} + if (strcmp(function, "quality") == 0) {return PIVariant::fromValue(object->quality());} + if (strcmp(function, "receiveSpeed") == 0) {return PIVariant::fromValue(object->receiveSpeed());} + if (strcmp(function, "sendSpeed") == 0) {return PIVariant::fromValue(object->sendSpeed());} + if (strcmp(function, "immediateFrequency_ptr") == 0) {return PIVariant::fromValue(object->immediateFrequency_ptr());} + if (strcmp(function, "integralFrequency_ptr") == 0) {return PIVariant::fromValue(object->integralFrequency_ptr());} + if (strcmp(function, "receiveCountPerSec_ptr") == 0) {return PIVariant::fromValue(object->receiveCountPerSec_ptr());} + if (strcmp(function, "sendCountPerSec_ptr") == 0) {return PIVariant::fromValue(object->sendCountPerSec_ptr());} + if (strcmp(function, "receiveBytesPerSec_ptr") == 0) {return PIVariant::fromValue(object->receiveBytesPerSec_ptr());} + if (strcmp(function, "sendBytesPerSec_ptr") == 0) {return PIVariant::fromValue(object->sendBytesPerSec_ptr());} + if (strcmp(function, "receiveCount_ptr") == 0) {return PIVariant::fromValue(object->receiveCount_ptr());} + if (strcmp(function, "wrongCount_ptr") == 0) {return PIVariant::fromValue(object->wrongCount_ptr());} + if (strcmp(function, "sendCount_ptr") == 0) {return PIVariant::fromValue(object->sendCount_ptr());} + if (strcmp(function, "quality_ptr") == 0) {return PIVariant::fromValue(object->quality_ptr());} + if (strcmp(function, "receiveSpeed_ptr") == 0) {return PIVariant::fromValue(object->receiveSpeed_ptr());} + if (strcmp(function, "sendSpeed_ptr") == 0) {return PIVariant::fromValue(object->sendSpeed_ptr());} + if (strcmp(function, "start") == 0) {object->start(); return PIVariant();} + if (strcmp(function, "start") == 0) {object->start(arg0.toValue()); return PIVariant();} + if (strcmp(function, "reset") == 0) {object->reset(); return PIVariant();} + if (strcmp(function, "received") == 0) {object->received(arg0.toValue()); return PIVariant();} + if (strcmp(function, "received") == 0) {object->received(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "sended") == 0) {object->sended(arg0.toValue()); return PIVariant();} + if (strcmp(function, "qualityChanged") == 0) {object->qualityChanged(arg0.toValue(), arg1.toValue()); return PIVariant();} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIDiagnostics\"!"; + return PIVariant(); +} + +PIVariant execFunction(PISystemMonitor * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "startOnProcess") == 0) {return PIVariant::fromValue(object->startOnProcess(arg0.toValue()));} + if (strcmp(function, "startOnSelf") == 0) {return PIVariant::fromValue(object->startOnSelf());} + if (strcmp(function, "statistic") == 0) {return PIVariant::fromValue(object->statistic());} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PISystemMonitor\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIConsole * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "className") == 0) {return PIVariant::fromValue(object->className());} + if (strcmp(function, "addString") == 0) {object->addString(arg0.toValue(), arg1.toValue(), arg2.toValue >()); return PIVariant();} + if (strcmp(function, "addVariable") == 0) {object->addVariable(arg0.toValue(), arg1.toValue(), arg2.toValue(), arg3.toValue >()); return PIVariant();} + if (strcmp(function, "addVariable") == 0) {object->addVariable(arg0.toValue(), arg1.toValue(), arg2.toValue(), arg3.toValue >()); return PIVariant();} + if (strcmp(function, "addVariable") == 0) {object->addVariable(arg0.toValue(), arg1.toValue(), arg2.toValue(), arg3.toValue >()); return PIVariant();} + if (strcmp(function, "addVariable") == 0) {object->addVariable(arg0.toValue(), arg1.toValue(), arg2.toValue(), arg3.toValue >()); return PIVariant();} + if (strcmp(function, "addVariable") == 0) {object->addVariable(arg0.toValue(), arg1.toValue(), arg2.toValue(), arg3.toValue >()); return PIVariant();} + if (strcmp(function, "addVariable") == 0) {object->addVariable(arg0.toValue(), arg1.toValue(), arg2.toValue(), arg3.toValue >()); return PIVariant();} + if (strcmp(function, "addVariable") == 0) {object->addVariable(arg0.toValue(), arg1.toValue(), arg2.toValue(), arg3.toValue >()); return PIVariant();} + if (strcmp(function, "addVariable") == 0) {object->addVariable(arg0.toValue(), arg1.toValue(), arg2.toValue(), arg3.toValue >()); return PIVariant();} + if (strcmp(function, "addVariable") == 0) {object->addVariable(arg0.toValue(), arg1.toValue(), arg2.toValue(), arg3.toValue >()); return PIVariant();} + if (strcmp(function, "addVariable") == 0) {object->addVariable(arg0.toValue(), arg1.toValue(), arg2.toValue(), arg3.toValue >()); return PIVariant();} + if (strcmp(function, "addVariable") == 0) {object->addVariable(arg0.toValue(), arg1.toValue(), arg2.toValue(), arg3.toValue >()); return PIVariant();} + if (strcmp(function, "addVariable") == 0) {object->addVariable(arg0.toValue(), arg1.toValue(), arg2.toValue(), arg3.toValue >()); return PIVariant();} + if (strcmp(function, "addVariable") == 0) {object->addVariable(arg0.toValue(), arg1.toValue(), arg2.toValue(), arg3.toValue >()); return PIVariant();} + if (strcmp(function, "addVariable") == 0) {object->addVariable(arg0.toValue(), arg1.toValue(), arg2.toValue(), arg3.toValue >()); return PIVariant();} + if (strcmp(function, "addVariable") == 0) {object->addVariable(arg0.toValue(), arg1.toValue(), arg2.toValue(), arg3.toValue >()); return PIVariant();} + if (strcmp(function, "addVariable") == 0) {object->addVariable(arg0.toValue(), arg1.toValue(), arg2.toValue(), arg3.toValue >()); return PIVariant();} + if (strcmp(function, "addVariable") == 0) {object->addVariable(arg0.toValue(), arg1.toValue(), arg2.toValue(), arg3.toValue >()); return PIVariant();} + if (strcmp(function, "addVariable") == 0) {object->addVariable(arg0.toValue(), arg1.toValue(), arg2.toValue(), arg3.toValue >()); return PIVariant();} + if (strcmp(function, "addEmptyLine") == 0) {object->addEmptyLine(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "getString") == 0) {return PIVariant::fromValue(object->getString(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "getShort") == 0) {return PIVariant::fromValue(object->getShort(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "getInt") == 0) {return PIVariant::fromValue(object->getInt(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "getFloat") == 0) {return PIVariant::fromValue(object->getFloat(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "getDouble") == 0) {return PIVariant::fromValue(object->getDouble(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "getString") == 0) {return PIVariant::fromValue(object->getString(arg0.toValue()));} + if (strcmp(function, "getShort") == 0) {return PIVariant::fromValue(object->getShort(arg0.toValue()));} + if (strcmp(function, "getInt") == 0) {return PIVariant::fromValue(object->getInt(arg0.toValue()));} + if (strcmp(function, "getFloat") == 0) {return PIVariant::fromValue(object->getFloat(arg0.toValue()));} + if (strcmp(function, "getDouble") == 0) {return PIVariant::fromValue(object->getDouble(arg0.toValue()));} + if (strcmp(function, "tabsCount") == 0) {return PIVariant::fromValue(object->tabsCount());} + if (strcmp(function, "currentTab") == 0) {return PIVariant::fromValue(object->currentTab());} + if (strcmp(function, "addTab") == 0) {return PIVariant::fromValue(object->addTab(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "removeTab") == 0) {object->removeTab(arg0.toValue()); return PIVariant();} + if (strcmp(function, "removeTab") == 0) {object->removeTab(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setTab") == 0) {return PIVariant::fromValue(object->setTab(arg0.toValue()));} + if (strcmp(function, "setTab") == 0) {return PIVariant::fromValue(object->setTab(arg0.toValue()));} + if (strcmp(function, "setTabBindKey") == 0) {return PIVariant::fromValue(object->setTabBindKey(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "setTabBindKey") == 0) {return PIVariant::fromValue(object->setTabBindKey(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "clearTabs") == 0) {object->clearTabs(arg0.toValue()); return PIVariant();} + if (strcmp(function, "addCustomStatus") == 0) {object->addCustomStatus(arg0.toValue()); return PIVariant();} + if (strcmp(function, "clearCustomStatus") == 0) {object->clearCustomStatus(); return PIVariant();} + if (strcmp(function, "defaultAlignment") == 0) {return PIVariant::fromValue(object->defaultAlignment());} + if (strcmp(function, "setDefaultAlignment") == 0) {object->setDefaultAlignment(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setColumnAlignment") == 0) {object->setColumnAlignment(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "setColumnAlignmentToAll") == 0) {object->setColumnAlignmentToAll(arg0.toValue()); return PIVariant();} + if (strcmp(function, "fstr") == 0) {return PIVariant::fromValue(object->fstr(arg0.toValue >()));} + if (strcmp(function, "enableExitCapture") == 0) {object->enableExitCapture(arg0.toValue()); return PIVariant();} + if (strcmp(function, "disableExitCapture") == 0) {object->disableExitCapture(); return PIVariant();} + if (strcmp(function, "exitCaptured") == 0) {return PIVariant::fromValue(object->exitCaptured());} + if (strcmp(function, "exitKey") == 0) {return PIVariant::fromValue(object->exitKey());} + if (strcmp(function, "startServer") == 0) {object->startServer(arg0.toValue()); return PIVariant();} + if (strcmp(function, "stopPeer") == 0) {object->stopPeer(); return PIVariant();} + if (strcmp(function, "isServerStarted") == 0) {return PIVariant::fromValue(object->isServerStarted());} + if (strcmp(function, "clients") == 0) {return PIVariant::fromValue(object->clients());} + if (strcmp(function, "listenServers") == 0) {object->listenServers(); return PIVariant();} + if (strcmp(function, "availableServers") == 0) {return PIVariant::fromValue(object->availableServers());} + if (strcmp(function, "selectedServer") == 0) {return PIVariant::fromValue(object->selectedServer());} + if (strcmp(function, "connectToServer") == 0) {object->connectToServer(arg0.toValue()); return PIVariant();} + if (strcmp(function, "disconnect") == 0) {object->disconnect(); return PIVariant();} + if (strcmp(function, "isConnected") == 0) {return PIVariant::fromValue(object->isConnected());} + if (strcmp(function, "toUpperLeft") == 0) {object->toUpperLeft(); return PIVariant();} + if (strcmp(function, "moveRight") == 0) {object->moveRight(arg0.toValue()); return PIVariant();} + if (strcmp(function, "moveLeft") == 0) {object->moveLeft(arg0.toValue()); return PIVariant();} + if (strcmp(function, "moveTo") == 0) {object->moveTo(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "clearScreen") == 0) {object->clearScreen(); return PIVariant();} + if (strcmp(function, "clearScreenLower") == 0) {object->clearScreenLower(); return PIVariant();} + if (strcmp(function, "clearLine") == 0) {object->clearLine(); return PIVariant();} + if (strcmp(function, "newLine") == 0) {object->newLine(); return PIVariant();} + if (strcmp(function, "hideCursor") == 0) {object->hideCursor(); return PIVariant();} + if (strcmp(function, "showCursor") == 0) {object->showCursor(); return PIVariant();} + if (strcmp(function, "clearVariables") == 0) {object->clearVariables(); return PIVariant();} + if (strcmp(function, "clearVariables") == 0) {object->clearVariables(arg0.toValue()); return PIVariant();} + if (strcmp(function, "waitForFinish") == 0) {object->waitForFinish(); return PIVariant();} + if (strcmp(function, "start") == 0) {object->start(); return PIVariant();} + if (strcmp(function, "start") == 0) {object->start(arg0.toValue()); return PIVariant();} + if (strcmp(function, "stop") == 0) {object->stop(); return PIVariant();} + if (strcmp(function, "stop") == 0) {object->stop(arg0.toValue()); return PIVariant();} + if (strcmp(function, "keyPressed") == 0) {object->keyPressed(arg0.toValue(), arg1.toValue()); return PIVariant();} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIConsole\"!"; + return PIVariant(); +} + +PIVariant execFunction(PICLI * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "className") == 0) {return PIVariant::fromValue(object->className());} + if (strcmp(function, "addArgument") == 0) {object->addArgument(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "addArgument") == 0) {object->addArgument(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "addArgument") == 0) {object->addArgument(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "addArgument") == 0) {object->addArgument(arg0.toValue(), arg1.toValue(), arg2.toValue(), arg3.toValue()); return PIVariant();} + if (strcmp(function, "addArgument") == 0) {object->addArgument(arg0.toValue(), arg1.toValue(), arg2.toValue(), arg3.toValue()); return PIVariant();} + if (strcmp(function, "rawArgument") == 0) {return PIVariant::fromValue(object->rawArgument(arg0.toValue()));} + if (strcmp(function, "mandatoryArgument") == 0) {return PIVariant::fromValue(object->mandatoryArgument(arg0.toValue()));} + if (strcmp(function, "optionalArgument") == 0) {return PIVariant::fromValue(object->optionalArgument(arg0.toValue()));} + if (strcmp(function, "rawArguments") == 0) {return PIVariant::fromValue(object->rawArguments());} + if (strcmp(function, "mandatoryArguments") == 0) {return PIVariant::fromValue(object->mandatoryArguments());} + if (strcmp(function, "optionalArguments") == 0) {return PIVariant::fromValue(object->optionalArguments());} + if (strcmp(function, "programCommand") == 0) {return PIVariant::fromValue(object->programCommand());} + if (strcmp(function, "hasArgument") == 0) {return PIVariant::fromValue(object->hasArgument(arg0.toValue()));} + if (strcmp(function, "argumentValue") == 0) {return PIVariant::fromValue(object->argumentValue(arg0.toValue()));} + if (strcmp(function, "argumentShortKey") == 0) {return PIVariant::fromValue(object->argumentShortKey(arg0.toValue()));} + if (strcmp(function, "argumentFullKey") == 0) {return PIVariant::fromValue(object->argumentFullKey(arg0.toValue()));} + if (strcmp(function, "shortKeyPrefix") == 0) {return PIVariant::fromValue(object->shortKeyPrefix());} + if (strcmp(function, "fullKeyPrefix") == 0) {return PIVariant::fromValue(object->fullKeyPrefix());} + if (strcmp(function, "mandatoryArgumentsCount") == 0) {return PIVariant::fromValue(object->mandatoryArgumentsCount());} + if (strcmp(function, "optionalArgumentsCount") == 0) {return PIVariant::fromValue(object->optionalArgumentsCount());} + if (strcmp(function, "setShortKeyPrefix") == 0) {object->setShortKeyPrefix(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setFullKeyPrefix") == 0) {object->setFullKeyPrefix(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setMandatoryArgumentsCount") == 0) {object->setMandatoryArgumentsCount(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setOptionalArgumentsCount") == 0) {object->setOptionalArgumentsCount(arg0.toValue()); return PIVariant();} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PICLI\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIEvaluatorContent * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "addFunction") == 0) {object->addFunction(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "addVariable") == 0) {object->addVariable(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "addCustomFunction") == 0) {object->addCustomFunction(arg0.toValue(), arg1.toValue(), arg2.toValue()); return PIVariant();} + if (strcmp(function, "functionsCount") == 0) {return PIVariant::fromValue(object->functionsCount());} + if (strcmp(function, "variablesCount") == 0) {return PIVariant::fromValue(object->variablesCount());} + if (strcmp(function, "customVariablesCount") == 0) {return PIVariant::fromValue(object->customVariablesCount());} + if (strcmp(function, "findFunction") == 0) {return PIVariant::fromValue(object->findFunction(arg0.toValue()));} + if (strcmp(function, "findVariable") == 0) {return PIVariant::fromValue(object->findVariable(arg0.toValue()));} + if (strcmp(function, "function") == 0) {return PIVariant::fromValue(object->function(arg0.toValue()));} + if (strcmp(function, "variable") == 0) {return PIVariant::fromValue(object->variable(arg0.toValue()));} + if (strcmp(function, "function") == 0) {return PIVariant::fromValue(object->function(arg0.toValue()));} + if (strcmp(function, "variable") == 0) {return PIVariant::fromValue(object->variable(arg0.toValue()));} + if (strcmp(function, "customVariable") == 0) {return PIVariant::fromValue(object->customVariable(arg0.toValue()));} + if (strcmp(function, "setVariableValue") == 0) {return PIVariant::fromValue(object->setVariableValue(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "setVariableName") == 0) {return PIVariant::fromValue(object->setVariableName(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "setVariableValue") == 0) {return PIVariant::fromValue(object->setVariableValue(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "setVariableName") == 0) {return PIVariant::fromValue(object->setVariableName(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "removeVariable") == 0) {object->removeVariable(arg0.toValue()); return PIVariant();} + if (strcmp(function, "removeVariable") == 0) {object->removeVariable(arg0.toValue()); return PIVariant();} + if (strcmp(function, "clearCustomVariables") == 0) {object->clearCustomVariables(); return PIVariant();} + if (strcmp(function, "sortVariables") == 0) {object->sortVariables(); return PIVariant();} + if (strcmp(function, "getBaseFunction") == 0) {return PIVariant::fromValue(object->getBaseFunction(arg0.toValue()));} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIEvaluatorContent\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIEvaluator * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "data") == 0) {return PIVariant::fromValue(object->data());} + if (strcmp(function, "setData") == 0) {object->setData(arg0.toValue()); return PIVariant();} + if (strcmp(function, "check") == 0) {return PIVariant::fromValue(object->check(arg0.toValue()));} + if (strcmp(function, "isCorrect") == 0) {return PIVariant::fromValue(object->isCorrect());} + if (strcmp(function, "setVariable") == 0) {return PIVariant::fromValue(object->setVariable(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "setVariable") == 0) {object->setVariable(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "setCustomVariableValue") == 0) {object->setCustomVariableValue(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "evaluate") == 0) {return PIVariant::fromValue(object->evaluate());} + if (strcmp(function, "removeVariable") == 0) {object->removeVariable(arg0.toValue()); return PIVariant();} + if (strcmp(function, "clearCustomVariables") == 0) {object->clearCustomVariables(); return PIVariant();} + if (strcmp(function, "variableIndex") == 0) {return PIVariant::fromValue(object->variableIndex(arg0.toValue()));} + if (strcmp(function, "unknownVariables") == 0) {return PIVariant::fromValue(object->unknownVariables());} + if (strcmp(function, "expression") == 0) {return PIVariant::fromValue(object->expression());} + if (strcmp(function, "error") == 0) {return PIVariant::fromValue(object->error());} + if (strcmp(function, "lastResult") == 0) {return PIVariant::fromValue(object->lastResult());} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIEvaluator\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIMultiProtocol * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "addProtocol") == 0) {object->addProtocol(arg0.toValue()); return PIVariant();} + if (strcmp(function, "protocol") == 0) {return PIVariant::fromValue(object->protocol(arg0.toValue()));} + if (strcmp(function, "protocol") == 0) {return PIVariant::fromValue(object->protocol(arg0.toValue()));} + if (strcmp(function, "startSend") == 0) {object->startSend(); return PIVariant();} + if (strcmp(function, "startReceive") == 0) {object->startReceive(); return PIVariant();} + if (strcmp(function, "start") == 0) {object->start(); return PIVariant();} + if (strcmp(function, "stopSend") == 0) {object->stopSend(); return PIVariant();} + if (strcmp(function, "stopReceive") == 0) {object->stopReceive(); return PIVariant();} + if (strcmp(function, "stop") == 0) {object->stop(); return PIVariant();} + if (strcmp(function, "worseQuality") == 0) {return PIVariant::fromValue(object->worseQuality());} + if (strcmp(function, "bestQuality") == 0) {return PIVariant::fromValue(object->bestQuality());} + if (strcmp(function, "count") == 0) {return PIVariant::fromValue(object->count());} + if (strcmp(function, "clear") == 0) {object->clear(); return PIVariant();} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIMultiProtocol\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIRepeater * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "firstChannelName") == 0) {return PIVariant::fromValue(object->firstChannelName());} + if (strcmp(function, "secondChannelName") == 0) {return PIVariant::fromValue(object->secondChannelName());} + if (strcmp(function, "receiveCount") == 0) {return PIVariant::fromValue(object->receiveCount());} + if (strcmp(function, "receiveCount_ptr") == 0) {return PIVariant::fromValue(object->receiveCount_ptr());} + if (strcmp(function, "sendCount") == 0) {return PIVariant::fromValue(object->sendCount());} + if (strcmp(function, "sendCount_ptr") == 0) {return PIVariant::fromValue(object->sendCount_ptr());} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIRepeater\"!"; + return PIVariant(); +} + +PIVariant execFunction(PICodec * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "setFromCoding") == 0) {object->setFromCoding(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setToCoding") == 0) {object->setToCoding(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setCodings") == 0) {object->setCodings(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "availableCodecs") == 0) {return PIVariant::fromValue(object->availableCodecs());} + if (strcmp(function, "encode") == 0) {return PIVariant::fromValue(object->encode(arg0.toValue()));} + if (strcmp(function, "decode") == 0) {return PIVariant::fromValue(object->decode(arg0.toValue()));} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PICodec\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIPeer * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "className") == 0) {return PIVariant::fromValue(object->className());} + if (strcmp(function, "send") == 0) {return PIVariant::fromValue(object->send(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "send") == 0) {return PIVariant::fromValue(object->send(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "send") == 0) {return PIVariant::fromValue(object->send(arg0.toValue(), arg1.toValue(), arg2.toValue()));} + if (strcmp(function, "send") == 0) {return PIVariant::fromValue(object->send(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "send") == 0) {return PIVariant::fromValue(object->send(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "send") == 0) {return PIVariant::fromValue(object->send(arg0.toValue(), arg1.toValue(), arg2.toValue()));} + if (strcmp(function, "send") == 0) {return PIVariant::fromValue(object->send(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "send") == 0) {return PIVariant::fromValue(object->send(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "send") == 0) {return PIVariant::fromValue(object->send(arg0.toValue(), arg1.toValue(), arg2.toValue()));} + if (strcmp(function, "sendToAll") == 0) {object->sendToAll(arg0.toValue()); return PIVariant();} + if (strcmp(function, "sendToAll") == 0) {object->sendToAll(arg0.toValue()); return PIVariant();} + if (strcmp(function, "sendToAll") == 0) {object->sendToAll(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "isMulticastReceive") == 0) {return PIVariant::fromValue(object->isMulticastReceive());} + if (strcmp(function, "isBroadcastReceive") == 0) {return PIVariant::fromValue(object->isBroadcastReceive());} + if (strcmp(function, "allPeers") == 0) {return PIVariant::fromValue >(object->allPeers());} + if (strcmp(function, "isPeerExists") == 0) {return PIVariant::fromValue(object->isPeerExists(arg0.toValue()));} + if (strcmp(function, "getPeerByName") == 0) {return PIVariant::fromValue(object->getPeerByName(arg0.toValue()));} + if (strcmp(function, "lock") == 0) {object->lock(); return PIVariant();} + if (strcmp(function, "unlock") == 0) {object->unlock(); return PIVariant();} + if (strcmp(function, "dataReceivedEvent") == 0) {object->dataReceivedEvent(arg0.toValue(), arg1.toValue()); return PIVariant();} + if (strcmp(function, "peerConnectedEvent") == 0) {object->peerConnectedEvent(arg0.toValue()); return PIVariant();} + if (strcmp(function, "peerDisconnectedEvent") == 0) {object->peerDisconnectedEvent(arg0.toValue()); return PIVariant();} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIPeer\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIBinaryLog * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "className") == 0) {return PIVariant::fromValue(object->className());} + if (strcmp(function, "playMode") == 0) {return PIVariant::fromValue(object->playMode());} + if (strcmp(function, "logDir") == 0) {return PIVariant::fromValue(object->logDir());} + if (strcmp(function, "filePrefix") == 0) {return PIVariant::fromValue(object->filePrefix());} + if (strcmp(function, "defaultID") == 0) {return PIVariant::fromValue(object->defaultID());} + if (strcmp(function, "playSpeed") == 0) {return PIVariant::fromValue(object->playSpeed());} + if (strcmp(function, "rapidStart") == 0) {return PIVariant::fromValue(object->rapidStart());} + if (strcmp(function, "setPlayMode") == 0) {object->setPlayMode(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setLogDir") == 0) {object->setLogDir(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setFilePrefix") == 0) {object->setFilePrefix(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setDefaultID") == 0) {object->setDefaultID(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setRapidStart") == 0) {object->setRapidStart(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setPlaySpeed") == 0) {object->setPlaySpeed(arg0.toValue()); return PIVariant();} + if (strcmp(function, "writeBinLog") == 0) {return PIVariant::fromValue(object->writeBinLog(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "writeBinLog") == 0) {return PIVariant::fromValue(object->writeBinLog(arg0.toValue(), arg1.toValue(), arg2.toValue()));} + if (strcmp(function, "readBinLog") == 0) {return PIVariant::fromValue(object->readBinLog(arg0.toValue()));} + if (strcmp(function, "readBinLog") == 0) {return PIVariant::fromValue(object->readBinLog(arg0.toValue(), arg1.toValue(), arg2.toValue()));} + if (strcmp(function, "isEnd") == 0) {return PIVariant::fromValue(object->isEnd());} + if (strcmp(function, "isEmpty") == 0) {return PIVariant::fromValue(object->isEmpty());} + if (strcmp(function, "lastReadedID") == 0) {return PIVariant::fromValue(object->lastReadedID());} + if (strcmp(function, "read") == 0) {return PIVariant::fromValue(object->read(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "write") == 0) {return PIVariant::fromValue(object->write(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "restart") == 0) {object->restart(); return PIVariant();} + if (strcmp(function, "createNewFile") == 0) {return PIVariant::fromValue(object->createNewFile());} + if (strcmp(function, "fileEnd") == 0) {object->fileEnd(); return PIVariant();} + if (strcmp(function, "fileError") == 0) {object->fileError(); return PIVariant();} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIBinaryLog\"!"; + return PIVariant(); +} + +PIVariant execFunction(PIUSB * object, const char * function, const PIVariant & arg0, const PIVariant & arg1, const PIVariant & arg2, const PIVariant & arg3) { + if (strcmp(function, "className") == 0) {return PIVariant::fromValue(object->className());} + if (strcmp(function, "currentDescriptor") == 0) {return PIVariant::fromValue(object->currentDescriptor());} + if (strcmp(function, "currentConfiguration") == 0) {return PIVariant::fromValue(object->currentConfiguration());} + if (strcmp(function, "currentInterface") == 0) {return PIVariant::fromValue(object->currentInterface());} + if (strcmp(function, "vendorID") == 0) {return PIVariant::fromValue(object->vendorID());} + if (strcmp(function, "productID") == 0) {return PIVariant::fromValue(object->productID());} + if (strcmp(function, "deviceNumber") == 0) {return PIVariant::fromValue(object->deviceNumber());} + if (strcmp(function, "timeoutRead") == 0) {return PIVariant::fromValue(object->timeoutRead());} + if (strcmp(function, "timeoutWrite") == 0) {return PIVariant::fromValue(object->timeoutWrite());} + if (strcmp(function, "endpointRead") == 0) {return PIVariant::fromValue(object->endpointRead());} + if (strcmp(function, "endpointWrite") == 0) {return PIVariant::fromValue(object->endpointWrite());} + if (strcmp(function, "endpoints") == 0) {return PIVariant::fromValue >(object->endpoints());} + if (strcmp(function, "endpointsRead") == 0) {return PIVariant::fromValue >(object->endpointsRead());} + if (strcmp(function, "endpointsWrite") == 0) {return PIVariant::fromValue >(object->endpointsWrite());} + if (strcmp(function, "getEndpointByAddress") == 0) {return PIVariant::fromValue(object->getEndpointByAddress(arg0.toValue()));} + if (strcmp(function, "setVendorID") == 0) {object->setVendorID(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setProductID") == 0) {object->setProductID(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setConfiguration") == 0) {return PIVariant::fromValue(object->setConfiguration(arg0.toValue()));} + if (strcmp(function, "setInterface") == 0) {return PIVariant::fromValue(object->setInterface(arg0.toValue()));} + if (strcmp(function, "setEndpointRead") == 0) {object->setEndpointRead(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setEndpointWrite") == 0) {object->setEndpointWrite(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setDeviceNumber") == 0) {object->setDeviceNumber(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setTimeoutRead") == 0) {object->setTimeoutRead(arg0.toValue()); return PIVariant();} + if (strcmp(function, "setTimeoutWrite") == 0) {object->setTimeoutWrite(arg0.toValue()); return PIVariant();} + if (strcmp(function, "read") == 0) {return PIVariant::fromValue(object->read(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "write") == 0) {return PIVariant::fromValue(object->write(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "controlWrite") == 0) {return PIVariant::fromValue(object->controlWrite(arg0.toValue(), arg1.toValue()));} + if (strcmp(function, "flush") == 0) {object->flush(); return PIVariant();} + PICout(AddNewLine) << "Can`t find function \"" << function << "\" in class \"PIUSB\"!"; + return PIVariant(); +} + + +__ClassInfo_TEST_H_Initializer__::__ClassInfo_TEST_H_Initializer__() { + if (_inited_) return; + _inited_ = true; + + ClassInfo * ci; + TypeInfo * ni; + FunctionInfo * fi; + EnumInfo * ei; + +// Classes + + ci = new ClassInfo(); + (*classesInfo)["PIMonitor"] = ci; + ci->name = "PIMonitor"; + ci->variables << TypeInfo("containers", "int"); + ci->variables << TypeInfo("strings", "int"); + ci->variables << TypeInfo("threads", "int"); + ci->variables << TypeInfo("timers", "int"); + ci->variables << TypeInfo("serials", "int"); + ci->variables << TypeInfo("ethernets", "int"); + ci->variables << TypeInfo("files", "int"); + ci->variables << TypeInfo("objects", "int"); + + ci = new ClassInfo(); + (*classesInfo)["PIInit"] = ci; + ci->name = "PIInit"; + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fileExists"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("p", "string &", Const); + + ci = new ClassInfo(); + (*classesInfo)["PICout"] = ci; + ci->name = "PICout"; + ci->variables << TypeInfo("fo_", "bool"); + ci->variables << TypeInfo("cc_", "bool"); + ci->variables << TypeInfo("fc_", "bool"); + ci->variables << TypeInfo("cnb_", "int"); + ci->variables << TypeInfo("attr_", "int"); + ci->variables << TypeInfo("co_", "PICoutControls"); + ci->variables << TypeInfo("cos_", "std::stack"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setControl"; fi->return_type = TypeInfo("", "PICout &"); + fi->arguments << TypeInfo("c", "PICoutControl"); + fi->arguments << TypeInfo("on", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setControl"; fi->return_type = TypeInfo("", "PICout &"); + fi->arguments << TypeInfo("c", "PICoutControls"); + fi->arguments << TypeInfo("save", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "saveControl"; fi->return_type = TypeInfo("", "PICout &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "restoreControl"; fi->return_type = TypeInfo("", "PICout &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "space"; fi->return_type = TypeInfo("", "PICout &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "quote"; fi->return_type = TypeInfo("", "PICout &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "newLine"; fi->return_type = TypeInfo("", "PICout &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "applyFormat"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("f", "PICoutFormat"); + + ci = new ClassInfo(); + (*classesInfo)["PIMutex"] = ci; + ci->name = "PIMutex"; + ci->variables << TypeInfo("mutex", "pthread_mutex_t"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "lock"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "unlock"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "tryLock"; fi->return_type = TypeInfo("", "bool"); + + ci = new ClassInfo(); + (*classesInfo)["PIMutexLocker"] = ci; + ci->name = "PIMutexLocker"; + ci->variables << TypeInfo("mutex", "PIMutex*"); + + ci = new ClassInfo(); + (*classesInfo)["PIBitArray"] = ci; + ci->name = "PIBitArray"; + ci->variables << TypeInfo("data_", "PIVector"); + ci->variables << TypeInfo("size_", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "bitSize"; fi->return_type = TypeInfo("", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "byteSize"; fi->return_type = TypeInfo("", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "resize"; fi->return_type = TypeInfo("", "PIBitArray &"); + fi->arguments << TypeInfo("size", "uint &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "clearBit"; fi->return_type = TypeInfo("", "PIBitArray &"); + fi->arguments << TypeInfo("index", "uint &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setBit"; fi->return_type = TypeInfo("", "PIBitArray &"); + fi->arguments << TypeInfo("index", "uint &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeBit"; fi->return_type = TypeInfo("", "PIBitArray &"); + fi->arguments << TypeInfo("index", "uint &", Const); + fi->arguments << TypeInfo("value", "bool &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeBit"; fi->return_type = TypeInfo("", "PIBitArray &"); + fi->arguments << TypeInfo("index", "uint &", Const); + fi->arguments << TypeInfo("value", "uchar &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "push_back"; fi->return_type = TypeInfo("", "PIBitArray &"); + fi->arguments << TypeInfo("value", "bool &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "push_back"; fi->return_type = TypeInfo("", "PIBitArray &"); + fi->arguments << TypeInfo("value", "uchar &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "insert"; fi->return_type = TypeInfo("", "PIBitArray &"); + fi->arguments << TypeInfo("index", "uint &", Const); + fi->arguments << TypeInfo("value", "bool &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "insert"; fi->return_type = TypeInfo("", "PIBitArray &"); + fi->arguments << TypeInfo("index", "uint &", Const); + fi->arguments << TypeInfo("value", "uchar &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "push_front"; fi->return_type = TypeInfo("", "PIBitArray &"); + fi->arguments << TypeInfo("value", "bool &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "push_front"; fi->return_type = TypeInfo("", "PIBitArray &"); + fi->arguments << TypeInfo("value", "uchar &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "pop_back"; fi->return_type = TypeInfo("", "PIBitArray &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "pop_front"; fi->return_type = TypeInfo("", "PIBitArray &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "append"; fi->return_type = TypeInfo("", "PIBitArray &"); + fi->arguments << TypeInfo("ba", "PIBitArray &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "data"; fi->return_type = TypeInfo("", "uchar *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toUChar"; fi->return_type = TypeInfo("", "uchar"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toUShort"; fi->return_type = TypeInfo("", "ushort"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toUInt"; fi->return_type = TypeInfo("", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toULong"; fi->return_type = TypeInfo("", "ulong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toULLong"; fi->return_type = TypeInfo("", "ullong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "at"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("index", "uint &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "bytesInBits"; fi->return_type = TypeInfo("", "uint"); + fi->arguments << TypeInfo("bits", "uint &", Const); + + ci = new ClassInfo(); + (*classesInfo)["PIHuffman"] = ci; + ci->name = "PIHuffman"; + ci->variables << TypeInfo("nodes", "PIVector"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "compress"; fi->return_type = TypeInfo("", "PIVector"); + fi->arguments << TypeInfo("src", "PIVector &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "nodeCompare"; fi->return_type = TypeInfo("", "int", Static); + fi->arguments << TypeInfo("f", "void *", Const); + fi->arguments << TypeInfo("s", "void *", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "calcFrequencies"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("src", "PIVector &", Const); + + ci = new ClassInfo(); + (*classesInfo)["PIHuffman::node"] = ci; + ci->name = "PIHuffman::node"; + ci->variables << TypeInfo("freq", "int"); + ci->variables << TypeInfo("word", "PIVector"); + ci->variables << TypeInfo("path", "PIBitArray"); + ci->variables << TypeInfo("parent", "node*"); + ci->variables << TypeInfo("right", "node*"); + ci->variables << TypeInfo("left", "node*"); + + ci = new ClassInfo(); + (*classesInfo)["PIByteArray"] = ci; + ci->name = "PIByteArray"; + ci->variables << TypeInfo("base64HelpStruct", "union"); + ci->variables << TypeInfo("base64Table", "char[64]", Const | Static); + ci->variables << TypeInfo("base64InvTable", "char[256]", Const | Static); + ci->variables << TypeInfo("huffman", "PIHuffman", Static); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "resized"; fi->return_type = TypeInfo("", "PIByteArray"); + fi->arguments << TypeInfo("new_size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "convertToBase64"; fi->return_type = TypeInfo("", "PIByteArray &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "convertFromBase64"; fi->return_type = TypeInfo("", "PIByteArray &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toBase64"; fi->return_type = TypeInfo("", "PIByteArray"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fromBase64"; fi->return_type = TypeInfo("", "PIByteArray"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "compressRLE"; fi->return_type = TypeInfo("", "PIByteArray &"); + fi->arguments << TypeInfo("threshold", "uchar"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "decompressRLE"; fi->return_type = TypeInfo("", "PIByteArray &"); + fi->arguments << TypeInfo("threshold", "uchar"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "compressedRLE"; fi->return_type = TypeInfo("", "PIByteArray"); + fi->arguments << TypeInfo("threshold", "uchar"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "decompressedRLE"; fi->return_type = TypeInfo("", "PIByteArray"); + fi->arguments << TypeInfo("threshold", "uchar"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "compressHuffman"; fi->return_type = TypeInfo("", "PIByteArray &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "append"; fi->return_type = TypeInfo("", "PIByteArray &"); + fi->arguments << TypeInfo("data_", "void *", Const); + fi->arguments << TypeInfo("size_", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "append"; fi->return_type = TypeInfo("", "PIByteArray &"); + fi->arguments << TypeInfo("data_", "PIByteArray &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "checksumPlain8"; fi->return_type = TypeInfo("", "uchar"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "checksumPlain32"; fi->return_type = TypeInfo("", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "checksumCRC8"; fi->return_type = TypeInfo("", "uchar"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "checksumCRC16"; fi->return_type = TypeInfo("", "ushort"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "checksumCRC32"; fi->return_type = TypeInfo("", "uint"); + + ci = new ClassInfo(); + (*classesInfo)["PIByteArray::RawData"] = ci; + ci->name = "PIByteArray::RawData"; + ci->variables << TypeInfo("d", "void*"); + ci->variables << TypeInfo("s", "int"); + + ci = new ClassInfo(); + (*classesInfo)["PIChar"] = ci; + ci->name = "PIChar"; + ci->variables << TypeInfo("ch", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isDigit"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isHex"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isGraphical"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isControl"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isLower"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isUpper"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isPrint"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isSpace"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isAlpha"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isAscii"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toInt"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toWCharPtr"; fi->return_type = TypeInfo("", "const wchar_t *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toCharPtr"; fi->return_type = TypeInfo("", "const char *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toWChar"; fi->return_type = TypeInfo("", "wchar_t"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toAscii"; fi->return_type = TypeInfo("", "char"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "unicode16Code"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toUpper"; fi->return_type = TypeInfo("", "PIChar"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toLower"; fi->return_type = TypeInfo("", "PIChar"); + + ci = new ClassInfo(); + (*classesInfo)["PIString"] = ci; + ci->name = "PIString"; + ci->variables << TypeInfo("toBaseN", "char[]", Const | Static); + ci->variables << TypeInfo("fromBaseN", "int[]", Const | Static); + ci->variables << TypeInfo("data_", "PIByteArray", Mutable); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "mid"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("start", "int", Const); + fi->arguments << TypeInfo("len", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "left"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("len", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "right"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("len", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "cutMid"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("start", "int", Const); + fi->arguments << TypeInfo("len", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "cutLeft"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("len", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "cutRight"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("len", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "trim"; fi->return_type = TypeInfo("", "PIString &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "trimmed"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "replace"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("from", "int", Const); + fi->arguments << TypeInfo("count", "int", Const); + fi->arguments << TypeInfo("with", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "replaced"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("from", "int", Const); + fi->arguments << TypeInfo("count", "int", Const); + fi->arguments << TypeInfo("with", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "replace"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("what", "PIString &", Const); + fi->arguments << TypeInfo("with", "PIString &", Const); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "replaced"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("what", "PIString &", Const); + fi->arguments << TypeInfo("with", "PIString &", Const); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "replaceAll"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("what", "PIString &", Const); + fi->arguments << TypeInfo("with", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "replaceAll"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("what", "PIString &", Const); + fi->arguments << TypeInfo("with", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "insert"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("index", "int", Const); + fi->arguments << TypeInfo("c", "PIChar &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "insert"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("index", "int", Const); + fi->arguments << TypeInfo("c", "char &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "insert"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("index", "int", Const); + fi->arguments << TypeInfo("str", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "insert"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("index", "int", Const); + fi->arguments << TypeInfo("c", "char *", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "expandRightTo"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("len", "int", Const); + fi->arguments << TypeInfo("c", "PIChar &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "expandLeftTo"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("len", "int", Const); + fi->arguments << TypeInfo("c", "PIChar &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "reverse"; fi->return_type = TypeInfo("", "PIString &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "reversed"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "takeMid"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("start", "int", Const); + fi->arguments << TypeInfo("len", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "takeLeft"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("len", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "takeRight"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("len", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "takeSymbol"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "takeWord"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "takeCWord"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "takeLine"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "takeNumber"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "takeRange"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("start", "PIChar &", Const); + fi->arguments << TypeInfo("end", "PIChar &", Const); + fi->arguments << TypeInfo("shield", "PIChar &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "lengthAscii"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "data"; fi->return_type = TypeInfo("", "const char *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "stdString"; fi->return_type = TypeInfo("", "std::string"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toByteArray"; fi->return_type = TypeInfo("", "PIByteArray"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "split"; fi->return_type = TypeInfo("", "PIStringList"); + fi->arguments << TypeInfo("delim", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toUpperCase"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toLowerCase"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toNativeDecimalPoints"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "find"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("str", "char", Const); + fi->arguments << TypeInfo("start", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "find"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("str", "PIString", Const); + fi->arguments << TypeInfo("start", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "find"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("str", "char *", Const); + fi->arguments << TypeInfo("start", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "find"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("str", "string", Const); + fi->arguments << TypeInfo("start", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "findLast"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("str", "char", Const); + fi->arguments << TypeInfo("start", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "findLast"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("str", "PIString", Const); + fi->arguments << TypeInfo("start", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "findLast"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("str", "char *", Const); + fi->arguments << TypeInfo("start", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "findLast"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("str", "string", Const); + fi->arguments << TypeInfo("start", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "findWord"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("word", "PIString &", Const); + fi->arguments << TypeInfo("start", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "findCWord"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("word", "PIString &", Const); + fi->arguments << TypeInfo("start", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "startsWith"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("str", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "endsWith"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("str", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "length"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isEmpty"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toBool"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toChar"; fi->return_type = TypeInfo("", "char"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toShort"; fi->return_type = TypeInfo("", "short"); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toUShort"; fi->return_type = TypeInfo("", "ushort"); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toInt"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toUInt"; fi->return_type = TypeInfo("", "uint"); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toLong"; fi->return_type = TypeInfo("", "long"); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toULong"; fi->return_type = TypeInfo("", "ulong"); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toLLong"; fi->return_type = TypeInfo("", "llong"); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toULLong"; fi->return_type = TypeInfo("", "ullong"); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toFloat"; fi->return_type = TypeInfo("", "float"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toDouble"; fi->return_type = TypeInfo("", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toLDouble"; fi->return_type = TypeInfo("", "ldouble"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setNumber"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("value", "short", Const); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setNumber"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("value", "ushort", Const); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setNumber"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("value", "int", Const); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setNumber"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("value", "uint", Const); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setNumber"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("value", "long", Const); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setNumber"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("value", "ulong", Const); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setNumber"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("value", "llong &", Const); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setNumber"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("value", "ullong &", Const); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setNumber"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("value", "float", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setNumber"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("value", "double &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setNumber"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("value", "ldouble &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setReadableSize"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("bytes", "llong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fromNumber"; fi->return_type = TypeInfo("", "PIString", Static); + fi->arguments << TypeInfo("value", "short", Const); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fromNumber"; fi->return_type = TypeInfo("", "PIString", Static); + fi->arguments << TypeInfo("value", "ushort", Const); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fromNumber"; fi->return_type = TypeInfo("", "PIString", Static); + fi->arguments << TypeInfo("value", "int", Const); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fromNumber"; fi->return_type = TypeInfo("", "PIString", Static); + fi->arguments << TypeInfo("value", "uint", Const); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fromNumber"; fi->return_type = TypeInfo("", "PIString", Static); + fi->arguments << TypeInfo("value", "long", Const); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fromNumber"; fi->return_type = TypeInfo("", "PIString", Static); + fi->arguments << TypeInfo("value", "ulong", Const); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fromNumber"; fi->return_type = TypeInfo("", "PIString", Static); + fi->arguments << TypeInfo("value", "llong &", Const); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fromNumber"; fi->return_type = TypeInfo("", "PIString", Static); + fi->arguments << TypeInfo("value", "ullong &", Const); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fromNumber"; fi->return_type = TypeInfo("", "PIString", Static); + fi->arguments << TypeInfo("value", "float", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fromNumber"; fi->return_type = TypeInfo("", "PIString", Static); + fi->arguments << TypeInfo("value", "double &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fromNumber"; fi->return_type = TypeInfo("", "PIString", Static); + fi->arguments << TypeInfo("value", "ldouble &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fromBool"; fi->return_type = TypeInfo("", "PIString", Static); + fi->arguments << TypeInfo("value", "bool", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "readableSize"; fi->return_type = TypeInfo("", "PIString", Static); + fi->arguments << TypeInfo("bytes", "llong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "removeAll"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("v", "char"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "removeAll"; fi->return_type = TypeInfo("", "PIString &"); + fi->arguments << TypeInfo("v", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fromNumberBaseS"; fi->return_type = TypeInfo("", "PIString", Static); + fi->arguments << TypeInfo("value", "llong", Const); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fromNumberBaseU"; fi->return_type = TypeInfo("", "PIString", Static); + fi->arguments << TypeInfo("value", "ullong", Const); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toNumberBase"; fi->return_type = TypeInfo("", "llong", Static); + fi->arguments << TypeInfo("value", "PIString &", Const); + fi->arguments << TypeInfo("base", "int"); + fi->arguments << TypeInfo("ok", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "appendFromChars"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("c", "char *", Const); + fi->arguments << TypeInfo("s", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "convertToStd"; fi->return_type = TypeInfo("", "string"); + + ci = new ClassInfo(); + (*classesInfo)["PIStringList"] = ci; + ci->name = "PIStringList"; + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "join"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("delim", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "removeStrings"; fi->return_type = TypeInfo("", "PIStringList &"); + fi->arguments << TypeInfo("value", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "remove"; fi->return_type = TypeInfo("", "PIStringList &"); + fi->arguments << TypeInfo("num", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "remove"; fi->return_type = TypeInfo("", "PIStringList &"); + fi->arguments << TypeInfo("num", "uint"); + fi->arguments << TypeInfo("count", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "removeDuplicates"; fi->return_type = TypeInfo("", "PIStringList &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "trim"; fi->return_type = TypeInfo("", "PIStringList &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "contentSize"; fi->return_type = TypeInfo("", "uint"); + + ci = new ClassInfo(); + (*classesInfo)["PISystemTime"] = ci; + ci->name = "PISystemTime"; + ci->variables << TypeInfo("seconds", "long"); + ci->variables << TypeInfo("nanoseconds", "long"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toSeconds"; fi->return_type = TypeInfo("", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toMilliseconds"; fi->return_type = TypeInfo("", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toMicroseconds"; fi->return_type = TypeInfo("", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toNanoseconds"; fi->return_type = TypeInfo("", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addSeconds"; fi->return_type = TypeInfo("", "PISystemTime &"); + fi->arguments << TypeInfo("v", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addMilliseconds"; fi->return_type = TypeInfo("", "PISystemTime &"); + fi->arguments << TypeInfo("v", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addMicroseconds"; fi->return_type = TypeInfo("", "PISystemTime &"); + fi->arguments << TypeInfo("v", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addNanoseconds"; fi->return_type = TypeInfo("", "PISystemTime &"); + fi->arguments << TypeInfo("v", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sleep"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "abs"; fi->return_type = TypeInfo("", "PISystemTime"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fromSeconds"; fi->return_type = TypeInfo("", "PISystemTime", Static); + fi->arguments << TypeInfo("v", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fromMilliseconds"; fi->return_type = TypeInfo("", "PISystemTime", Static); + fi->arguments << TypeInfo("v", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fromMicroseconds"; fi->return_type = TypeInfo("", "PISystemTime", Static); + fi->arguments << TypeInfo("v", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fromNanoseconds"; fi->return_type = TypeInfo("", "PISystemTime", Static); + fi->arguments << TypeInfo("v", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "checkOverflows"; fi->return_type = TypeInfo("", "void"); + + ci = new ClassInfo(); + (*classesInfo)["PITime"] = ci; + ci->name = "PITime"; + ci->variables << TypeInfo("milliseconds", "int"); + ci->variables << TypeInfo("seconds", "int"); + ci->variables << TypeInfo("minutes", "int"); + ci->variables << TypeInfo("hours", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toString"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("format", "PIString &", Const); + + ci = new ClassInfo(); + (*classesInfo)["PIDate"] = ci; + ci->name = "PIDate"; + ci->variables << TypeInfo("day", "int"); + ci->variables << TypeInfo("month", "int"); + ci->variables << TypeInfo("year", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toString"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("format", "PIString &", Const); + + ci = new ClassInfo(); + (*classesInfo)["PIDateTime"] = ci; + ci->name = "PIDateTime"; + ci->variables << TypeInfo("milliseconds", "int"); + ci->variables << TypeInfo("seconds", "int"); + ci->variables << TypeInfo("minutes", "int"); + ci->variables << TypeInfo("hours", "int"); + ci->variables << TypeInfo("day", "int"); + ci->variables << TypeInfo("month", "int"); + ci->variables << TypeInfo("year", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "normalized"; fi->return_type = TypeInfo("", "PIDateTime"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "normalize"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toString"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("format", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toSecondSinceEpoch"; fi->return_type = TypeInfo("", "time_t"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toSystemTime"; fi->return_type = TypeInfo("", "PISystemTime"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fromSecondSinceEpoch"; fi->return_type = TypeInfo("", "PIDateTime", Static); + fi->arguments << TypeInfo("sec", "time_t", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fromSystemTime"; fi->return_type = TypeInfo("", "PIDateTime", Static); + fi->arguments << TypeInfo("st", "PISystemTime &", Const); + + ci = new ClassInfo(); + (*classesInfo)["TransferFunction"] = ci; + ci->name = "TransferFunction"; + ci->variables << TypeInfo("vector_Bm", "PIVector"); + ci->variables << TypeInfo("vector_An", "PIVector"); + + ci = new ClassInfo(); + (*classesInfo)["Solver"] = ci; + ci->name = "Solver"; + ci->variables << TypeInfo("X", "PIMathVectord"); + ci->variables << TypeInfo("method_global", "Solver::Method", Static); + ci->variables << TypeInfo("methods_desc", "char[]", Const | Static); + ci->variables << TypeInfo("A", "PIMathMatrixd"); + ci->variables << TypeInfo("M", "PIMathMatrixd"); + ci->variables << TypeInfo("d", "PIMathVectord"); + ci->variables << TypeInfo("a1", "PIMathVectord"); + ci->variables << TypeInfo("b1", "PIMathVectord"); + ci->variables << TypeInfo("k1", "PIMathVectord"); + ci->variables << TypeInfo("k2", "PIMathVectord"); + ci->variables << TypeInfo("k3", "PIMathVectord"); + ci->variables << TypeInfo("k4", "PIMathVectord"); + ci->variables << TypeInfo("xx", "PIMathVectord"); + ci->variables << TypeInfo("XX", "PIMathVectord"); + ci->variables << TypeInfo("Y", "PIMathVectord"); + ci->variables << TypeInfo("pY", "PIMathVectord"); + ci->variables << TypeInfo("F", "PIVector"); + ci->variables << TypeInfo("times", "PIVector"); + ci->variables << TypeInfo("size", "uint"); + ci->variables << TypeInfo("step", "uint"); + ci->variables << TypeInfo("method", "Solver::Method"); + ci->variables << TypeInfo("sum", "double"); + ci->variables << TypeInfo("td", "double"); + ci->variables << TypeInfo("ct", "double"); + ci->variables << TypeInfo("lp", "double"); + ci->variables << TypeInfo("dh", "double"); + ci->variables << TypeInfo("t", "double"); + ci->variables << TypeInfo("x1", "double"); + ci->variables << TypeInfo("x0", "double"); + ci->variables << TypeInfo("ok", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "solve"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("u", "double"); + fi->arguments << TypeInfo("h", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fromTF"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("TF", "TransferFunction &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setMethod"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("m", "Method"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setTime"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("time", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "solveEyler1"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("u", "double"); + fi->arguments << TypeInfo("h", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "solveEyler2"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("u", "double"); + fi->arguments << TypeInfo("h", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "solveRK4"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("u", "double"); + fi->arguments << TypeInfo("h", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "solveABM2"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("u", "double"); + fi->arguments << TypeInfo("h", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "solveABM3"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("u", "double"); + fi->arguments << TypeInfo("h", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "solveABM4"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("u", "double"); + fi->arguments << TypeInfo("h", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "solvePA"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("u", "double"); + fi->arguments << TypeInfo("h", "double"); + fi->arguments << TypeInfo("deg", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "solvePA2"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("u", "double"); + fi->arguments << TypeInfo("h", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "solvePA3"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("u", "double"); + fi->arguments << TypeInfo("h", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "solvePA4"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("u", "double"); + fi->arguments << TypeInfo("h", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "solvePA5"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("u", "double"); + fi->arguments << TypeInfo("h", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "moveF"; fi->return_type = TypeInfo("", "void"); + + ci = new ClassInfo(); + (*classesInfo)["PIFFT"] = ci; + ci->name = "PIFFT"; + ci->variables << TypeInfo("result", "PIVector"); + ci->variables << TypeInfo("prepared", "bool"); + ci->variables << TypeInfo("curplan", "PIFFT::ftplan"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "calcFFT"; fi->return_type = TypeInfo("", "PIVector *"); + fi->arguments << TypeInfo("val", "PIVector &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "calcFFT"; fi->return_type = TypeInfo("", "PIVector *"); + fi->arguments << TypeInfo("val", "PIVector &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "calcFFTinverse"; fi->return_type = TypeInfo("", "PIVector *"); + fi->arguments << TypeInfo("val", "PIVector &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "calcHilbert"; fi->return_type = TypeInfo("", "PIVector *"); + fi->arguments << TypeInfo("val", "PIVector &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getAmplitude"; fi->return_type = TypeInfo("", "PIVector"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "calc_coefs"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("cnt2", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "calc_indexes"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("cnt2", "uint"); + fi->arguments << TypeInfo("deep2", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "coef"; fi->return_type = TypeInfo("", "complexd"); + fi->arguments << TypeInfo("n", "uint"); + fi->arguments << TypeInfo("k", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fftc1d"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("a", "PIVector &", Const); + fi->arguments << TypeInfo("n", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fftc1r"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("a", "PIVector &", Const); + fi->arguments << TypeInfo("n", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fftc1dinv"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("a", "PIVector &", Const); + fi->arguments << TypeInfo("n", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "createPlan"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("n", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "ftbasegeneratecomplexfftplan"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("n", "uint"); + fi->arguments << TypeInfo("plan", "ftplan *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "ftbase_ftbasegenerateplanrec"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("n", "int"); + fi->arguments << TypeInfo("tasktype", "int"); + fi->arguments << TypeInfo("plan", "ftplan *"); + fi->arguments << TypeInfo("plansize", "int *"); + fi->arguments << TypeInfo("precomputedsize", "int *"); + fi->arguments << TypeInfo("planarraysize", "int *"); + fi->arguments << TypeInfo("tmpmemsize", "int *"); + fi->arguments << TypeInfo("stackmemsize", "int *"); + fi->arguments << TypeInfo("stackptr", "ae_int_t"); + fi->arguments << TypeInfo("debugi", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "ftbase_ftbaseprecomputeplanrec"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("plan", "ftplan *"); + fi->arguments << TypeInfo("entryoffset", "int"); + fi->arguments << TypeInfo("stackptr", "ae_int_t"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "ftbasefactorize"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("n", "int"); + fi->arguments << TypeInfo("n1", "int *"); + fi->arguments << TypeInfo("n2", "int *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "ftbase_ftbasefindsmoothrec"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("n", "int"); + fi->arguments << TypeInfo("seed", "int"); + fi->arguments << TypeInfo("leastfactor", "int"); + fi->arguments << TypeInfo("best", "int *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "ftbasefindsmooth"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("n", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "ftbaseexecuteplan"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("a", "PIVector *"); + fi->arguments << TypeInfo("aoffset", "int"); + fi->arguments << TypeInfo("n", "int"); + fi->arguments << TypeInfo("plan", "ftplan *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "ftbaseexecuteplanrec"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("a", "PIVector *"); + fi->arguments << TypeInfo("aoffset", "int"); + fi->arguments << TypeInfo("plan", "ftplan *"); + fi->arguments << TypeInfo("entryoffset", "int"); + fi->arguments << TypeInfo("stackptr", "ae_int_t"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "ftbase_internalcomplexlintranspose"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("a", "PIVector *"); + fi->arguments << TypeInfo("m", "int"); + fi->arguments << TypeInfo("n", "int"); + fi->arguments << TypeInfo("astart", "int"); + fi->arguments << TypeInfo("buf", "PIVector *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "ftbase_ffticltrec"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("a", "PIVector *"); + fi->arguments << TypeInfo("astart", "int"); + fi->arguments << TypeInfo("astride", "int"); + fi->arguments << TypeInfo("b", "PIVector *"); + fi->arguments << TypeInfo("bstart", "int"); + fi->arguments << TypeInfo("bstride", "int"); + fi->arguments << TypeInfo("m", "int"); + fi->arguments << TypeInfo("n", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "ftbase_internalreallintranspose"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("a", "PIVector *"); + fi->arguments << TypeInfo("m", "int"); + fi->arguments << TypeInfo("n", "int"); + fi->arguments << TypeInfo("astart", "int"); + fi->arguments << TypeInfo("buf", "PIVector *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "ftbase_fftirltrec"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("a", "PIVector *"); + fi->arguments << TypeInfo("astart", "int"); + fi->arguments << TypeInfo("astride", "int"); + fi->arguments << TypeInfo("b", "PIVector *"); + fi->arguments << TypeInfo("bstart", "int"); + fi->arguments << TypeInfo("bstride", "int"); + fi->arguments << TypeInfo("m", "int"); + fi->arguments << TypeInfo("n", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "ftbase_ffttwcalc"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("a", "PIVector *"); + fi->arguments << TypeInfo("aoffset", "int"); + fi->arguments << TypeInfo("n1", "int"); + fi->arguments << TypeInfo("n2", "int"); + + ci = new ClassInfo(); + (*classesInfo)["PIFFT::ftplan"] = ci; + ci->name = "PIFFT::ftplan"; + ci->variables << TypeInfo("plan", "PIVector"); + ci->variables << TypeInfo("precomputed", "PIVector"); + ci->variables << TypeInfo("tmpbuf", "PIVector"); + ci->variables << TypeInfo("stackbuf", "PIVector"); + + ci = new ClassInfo(); + (*classesInfo)["PIVariant"] = ci; + ci->name = "PIVariant"; + ci->variables << TypeInfo("nion", "u"); + ci->variables << TypeInfo("_vbitarray", "PIBitArray"); + ci->variables << TypeInfo("_vbytearray", "PIByteArray"); + ci->variables << TypeInfo("_vstring", "PIString"); + ci->variables << TypeInfo("_vstringlist", "PIStringList"); + ci->variables << TypeInfo("_vcustom", "PIByteArray"); + ci->variables << TypeInfo("type_", "PIVariant::Type"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "char *", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "bool", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "char", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "uchar", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "short", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "ushort", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "int &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "uint &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "long &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "ulong &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "llong &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "ullong &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "float &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "double &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "ldouble &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "complexd &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "complexld &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "PIBitArray &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "PIByteArray &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "PIStringList &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "PITime &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "PIDate &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "PIDateTime &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "PISystemTime &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toBool"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toInt"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toLLong"; fi->return_type = TypeInfo("", "llong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toFloat"; fi->return_type = TypeInfo("", "float"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toDouble"; fi->return_type = TypeInfo("", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toLDouble"; fi->return_type = TypeInfo("", "ldouble"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toComplexd"; fi->return_type = TypeInfo("", "complexd"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toComplexld"; fi->return_type = TypeInfo("", "complexld"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toTime"; fi->return_type = TypeInfo("", "PITime"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toDate"; fi->return_type = TypeInfo("", "PIDate"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toDateTime"; fi->return_type = TypeInfo("", "PIDateTime"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toSystemTime"; fi->return_type = TypeInfo("", "PISystemTime"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toString"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toStringList"; fi->return_type = TypeInfo("", "PIStringList"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toBitArray"; fi->return_type = TypeInfo("", "PIBitArray"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toByteArray"; fi->return_type = TypeInfo("", "PIByteArray"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "type"; fi->return_type = TypeInfo("", "PIVariant::Type"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "typeName"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isValid"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "typeFromName"; fi->return_type = TypeInfo("", "PIVariant::Type", Static); + fi->arguments << TypeInfo("tname", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "typeName"; fi->return_type = TypeInfo("", "PIString", Static); + fi->arguments << TypeInfo("type", "PIVariant::Type"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "destroy"; fi->return_type = TypeInfo("", "void"); + + ci = new ClassInfo(); + (*classesInfo)["PIObject"] = ci; + ci->name = "PIObject"; + ci->variables << TypeInfo("connections", "PIVector"); + ci->variables << TypeInfo("properties_", "PIMap"); + ci->variables << TypeInfo("objects", "PIVector", Static); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "name"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "className"; fi->return_type = TypeInfo("", "const char *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "debug"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setName"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setDebug"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("debug", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "properties"; fi->return_type = TypeInfo("", "const PIMap &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "propertiesCount"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "property"; fi->return_type = TypeInfo("", "PIVariant"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setProperty"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("value", "PIVariant &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isPropertyExists"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "piConnect"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("src", "PIObject *"); + fi->arguments << TypeInfo("sig", "PIString &", Const); + fi->arguments << TypeInfo("dest", "void *"); + fi->arguments << TypeInfo("ev_h", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "piConnect"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("src", "PIObject *"); + fi->arguments << TypeInfo("sig", "PIString &", Const); + fi->arguments << TypeInfo("dest", "void *"); + fi->arguments << TypeInfo("ev_h", "void *"); + fi->arguments << TypeInfo("e_h", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "piConnect"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("src", "PIString &", Const); + fi->arguments << TypeInfo("sig", "PIString &", Const); + fi->arguments << TypeInfo("dest", "void *"); + fi->arguments << TypeInfo("ev_h", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "piConnect"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("src", "PIObject *"); + fi->arguments << TypeInfo("sig", "PIString &", Const); + fi->arguments << TypeInfo("dest", "PIString &", Const); + fi->arguments << TypeInfo("ev_h", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "piConnect"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("src", "PIString &", Const); + fi->arguments << TypeInfo("sig", "PIString &", Const); + fi->arguments << TypeInfo("dest", "PIString &", Const); + fi->arguments << TypeInfo("ev_h", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "piDisconnect"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("src", "PIObject *"); + fi->arguments << TypeInfo("sig", "PIString &", Const); + fi->arguments << TypeInfo("dest", "void *"); + fi->arguments << TypeInfo("ev_h", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "piDisconnect"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("src", "PIObject *"); + fi->arguments << TypeInfo("sig", "PIString &", Const); + fi->arguments << TypeInfo("dest", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "piDisconnect"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("src", "PIObject *"); + fi->arguments << TypeInfo("sig", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "piDisconnect"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("src", "PIObject *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "raiseEvent"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("sender", "PIObject *"); + fi->arguments << TypeInfo("event", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "raiseEvent"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("destObject", "PIString &", Const); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "findByName"; fi->return_type = TypeInfo("", "PIObject *", Static); + fi->arguments << TypeInfo("name", "PIString &", Const); + + ci = new ClassInfo(); + (*classesInfo)["PIObject::Connection"] = ci; + ci->name = "PIObject::Connection"; + ci->variables << TypeInfo("slot", "void*"); + ci->variables << TypeInfo("signal", "void*"); + ci->variables << TypeInfo("event", "PIString"); + ci->variables << TypeInfo("dest", "void*"); + + ci = new ClassInfo(); + (*classesInfo)["PIThread"] = ci; + ci->name = "PIThread"; + ci->parents << "PIObject"; + ci->variables << TypeInfo("terminating", "bool", Volatile); + ci->variables << TypeInfo("running", "bool", Volatile); + ci->variables << TypeInfo("lockRun", "bool", Volatile); + ci->variables << TypeInfo("timer", "int"); + ci->variables << TypeInfo("policy", "int"); + ci->variables << TypeInfo("data_", "void*"); + ci->variables << TypeInfo("mutex_", "PIMutex"); + ci->variables << TypeInfo("priority_", "PIThread::Priority"); + ci->variables << TypeInfo("ret_func", "ThreadFunc"); + ci->variables << TypeInfo("thread", "pthread_t"); + ci->variables << TypeInfo("sparam", "sched_param"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "className"; fi->return_type = TypeInfo("", "const char *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_start__"; fi->return_type = TypeInfo("", "bool", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "start"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_start__"; fi->return_type = TypeInfo("", "bool", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("timer_delay", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "start"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("timer_delay", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_start__"; fi->return_type = TypeInfo("", "bool", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("func", "ThreadFunc"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "start"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("func", "ThreadFunc"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_start__"; fi->return_type = TypeInfo("", "bool", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("func", "ThreadFunc"); + fi->arguments << TypeInfo("timer_delay", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "start"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("func", "ThreadFunc"); + fi->arguments << TypeInfo("timer_delay", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_startOnce__"; fi->return_type = TypeInfo("", "bool", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "startOnce"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_startOnce__"; fi->return_type = TypeInfo("", "bool", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("func", "ThreadFunc"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "startOnce"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("func", "ThreadFunc"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_stop__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "stop"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_stop__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("wait", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "stop"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("wait", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_terminate__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "terminate"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setData"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("d", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setSlot"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("func", "ThreadFunc"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setPriority"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("prior", "PIThread::Priority"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "priority"; fi->return_type = TypeInfo("", "PIThread::Priority"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isRunning"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isStopping"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_waitForStart__"; fi->return_type = TypeInfo("", "bool", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "waitForStart"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_waitForStart__"; fi->return_type = TypeInfo("", "bool", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("timeout_msecs", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "waitForStart"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("timeout_msecs", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_waitForFinish__"; fi->return_type = TypeInfo("", "bool", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "waitForFinish"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_waitForFinish__"; fi->return_type = TypeInfo("", "bool", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("timeout_msecs", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "waitForFinish"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("timeout_msecs", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "needLockRun"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("need", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_lock__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "lock"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_unlock__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "unlock"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "mutex"; fi->return_type = TypeInfo("", "PIMutex &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_started__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "started"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_stopped__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "stopped"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "thread_function"; fi->return_type = TypeInfo("", "void *", Static); + fi->arguments << TypeInfo("t", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "thread_function_once"; fi->return_type = TypeInfo("", "void *", Static); + fi->arguments << TypeInfo("t", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "begin"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "run"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "end"; fi->return_type = TypeInfo("", "void"); + + ci = new ClassInfo(); + (*classesInfo)["PITimer"] = ci; + ci->name = "PITimer"; + ci->parents << "PIThread"; + ci->variables << TypeInfo("st_time", "PISystemTime"); + ci->variables << TypeInfo("inc_time", "PISystemTime"); + ci->variables << TypeInfo("deferred_", "bool"); + ci->variables << TypeInfo("running_", "bool"); + ci->variables << TypeInfo("interval_", "double"); + ci->variables << TypeInfo("t_st", "timespec"); + ci->variables << TypeInfo("t_cur", "timespec"); + ci->variables << TypeInfo("data", "void*"); + ci->variables << TypeInfo("ret_func", "TimerEvent"); + ci->variables << TypeInfo("ret_funcs", "PIVector"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "className"; fi->return_type = TypeInfo("", "const char *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setData"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("data_", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setSlot"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("slot", "TimerEvent"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "interval"; fi->return_type = TypeInfo("", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_reset__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "reset"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_start__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("msecs", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "start"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("msecs", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_start__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("msecs", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "start"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("msecs", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_deferredStart__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("interval_msecs", "double"); + fi->arguments << TypeInfo("delay_msecs", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "deferredStart"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("interval_msecs", "double"); + fi->arguments << TypeInfo("delay_msecs", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_deferredStart__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("interval_msecs", "double"); + fi->arguments << TypeInfo("start_datetime", "PIDateTime &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "deferredStart"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("interval_msecs", "double"); + fi->arguments << TypeInfo("start_datetime", "PIDateTime &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_stop__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "stop"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addDelimiter"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("delim", "int"); + fi->arguments << TypeInfo("slot", "TimerEvent"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "removeDelimiter"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("delim", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "removeDelimiter"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("slot", "TimerEvent"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "removeDelimiter"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("delim", "int"); + fi->arguments << TypeInfo("slot", "TimerEvent"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setDelimiterValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("delim", "int"); + fi->arguments << TypeInfo("value", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setDelimiterValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("slot", "TimerEvent"); + fi->arguments << TypeInfo("value", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setDelimiterValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("delim", "int"); + fi->arguments << TypeInfo("slot", "TimerEvent"); + fi->arguments << TypeInfo("value", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "delimiterValue"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("delim", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "delimiterValue"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("delim", "int"); + fi->arguments << TypeInfo("slot", "TimerEvent"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_clearDelimiters__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "clearDelimiters"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "elapsed_n"; fi->return_type = TypeInfo("", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "elapsed_u"; fi->return_type = TypeInfo("", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "elapsed_m"; fi->return_type = TypeInfo("", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "elapsed_s"; fi->return_type = TypeInfo("", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "reset_time_n"; fi->return_type = TypeInfo("", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "reset_time_u"; fi->return_type = TypeInfo("", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "reset_time_m"; fi->return_type = TypeInfo("", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "reset_time_s"; fi->return_type = TypeInfo("", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "reset_time"; fi->return_type = TypeInfo("", "PISystemTime"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "elapsed_system_n"; fi->return_type = TypeInfo("", "double", Static); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "elapsed_system_u"; fi->return_type = TypeInfo("", "double", Static); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "elapsed_system_m"; fi->return_type = TypeInfo("", "double", Static); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "elapsed_system_s"; fi->return_type = TypeInfo("", "double", Static); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_timeout__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("data", "void *"); + fi->arguments << TypeInfo("delimiter", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "timeout"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("data", "void *"); + fi->arguments << TypeInfo("delimiter", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "tick"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("data", "void *"); + fi->arguments << TypeInfo("delimiter", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "run"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "end"; fi->return_type = TypeInfo("", "void"); + + ci = new ClassInfo(); + (*classesInfo)["PITimer::TimerSlot"] = ci; + ci->name = "PITimer::TimerSlot"; + ci->variables << TypeInfo("slot", "TimerEvent"); + ci->variables << TypeInfo("delim", "int"); + ci->variables << TypeInfo("tick", "int"); + + ci = new ClassInfo(); + (*classesInfo)["PIKbdListener"] = ci; + ci->name = "PIKbdListener"; + ci->parents << "PIThread"; + ci->variables << TypeInfo("exiting", "bool", Static); + ci->variables << TypeInfo("ret_func", "KBFunc"); + ci->variables << TypeInfo("exit_key", "char"); + ci->variables << TypeInfo("exit_enabled", "bool"); + ci->variables << TypeInfo("is_active", "bool"); + ci->variables << TypeInfo("data_", "void*"); + ci->variables << TypeInfo("rc", "int"); + ci->variables << TypeInfo("ret", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "className"; fi->return_type = TypeInfo("", "const char *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "data"; fi->return_type = TypeInfo("", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setData"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("_data", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setSlot"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("slot", "KBFunc"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "exitCaptured"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "exitKey"; fi->return_type = TypeInfo("", "char"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isActive"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_enableExitCapture__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "enableExitCapture"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_enableExitCapture__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("key", "char"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "enableExitCapture"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("key", "char"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_disableExitCapture__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "disableExitCapture"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_setActive__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setActive"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_setActive__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("yes", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setActive"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("yes", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_keyPressed__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("key", "char"); + fi->arguments << TypeInfo("data", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "keyPressed"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("key", "char"); + fi->arguments << TypeInfo("data", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "begin"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "run"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "end"; fi->return_type = TypeInfo("", "void"); + + ci = new ClassInfo(); + (*classesInfo)["PICollection"] = ci; + ci->name = "PICollection"; + ci->variables << TypeInfo("_groups", "PIVector*", Static); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "groups"; fi->return_type = TypeInfo("", "PIStringList", Static); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "groupElements"; fi->return_type = TypeInfo("", "PIVector", Static); + fi->arguments << TypeInfo("group", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addToGroup"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("group", "PIString &", Const); + fi->arguments << TypeInfo("element", "PIObject *", Const); + + ci = new ClassInfo(); + (*classesInfo)["PICollection::CollectionAdder"] = ci; + ci->name = "PICollection::CollectionAdder"; + + ci = new ClassInfo(); + (*classesInfo)["PICollection::Group"] = ci; + ci->name = "PICollection::Group"; + ci->variables << TypeInfo("name", "PIString"); + ci->variables << TypeInfo("elements", "PIVector"); + + ci = new ClassInfo(); + (*classesInfo)["__PICollectionInitializer"] = ci; + ci->name = "__PICollectionInitializer"; + ci->variables << TypeInfo("_inited_", "bool", Static); + + ci = new ClassInfo(); + (*classesInfo)["PIIODevice"] = ci; + ci->name = "PIIODevice"; + ci->parents << "PIThread"; + ci->variables << TypeInfo("mode_", "PIIODevice::DeviceMode"); + ci->variables << TypeInfo("ret_func_", "ReadRetFunc"); + ci->variables << TypeInfo("init_", "bool"); + ci->variables << TypeInfo("opened_", "bool"); + ci->variables << TypeInfo("thread_started_", "bool"); + ci->variables << TypeInfo("raise_threaded_read_", "bool"); + ci->variables << TypeInfo("ret_data_", "void*"); + ci->variables << TypeInfo("timer", "PITimer"); + ci->variables << TypeInfo("write_thread", "PIThread"); + ci->variables << TypeInfo("buffer_in", "PIByteArray"); + ci->variables << TypeInfo("buffer_tr", "PIByteArray"); + ci->variables << TypeInfo("write_queue", "PIQueue >"); + ci->variables << TypeInfo("tri", "ullong"); + ci->variables << TypeInfo("readed_", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "className"; fi->return_type = TypeInfo("", "const char *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "mode"; fi->return_type = TypeInfo("", "PIIODevice::DeviceMode"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "path"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setPath"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("path", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isReadable"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isWriteable"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isInitialized"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isOpened"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isClosed"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "canRead"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "canWrite"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setReopenEnabled"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("yes", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setReopenTimeout"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("msecs", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isReopenEnabled"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "reopenTimeout"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setThreadedReadSlot"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("func", "ReadRetFunc"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setThreadedReadData"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("d", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setThreadedReadBufferSize"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("new_size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "threadedReadBufferSize"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "threadedReadBuffer"; fi->return_type = TypeInfo("", "const uchar *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isThreadedRead"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "startThreadedRead"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "startThreadedRead"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("func", "ReadRetFunc"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "stopThreadedRead"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isThreadedWrite"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "startThreadedWrite"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "stopThreadedWrite"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "clearThreadedWriteQueue"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "start"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "stop"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("wait", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "read"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("read_to", "void *"); + fi->arguments << TypeInfo("max_size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "write"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("max_size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "read"; fi->return_type = TypeInfo("", "PIByteArray"); + fi->arguments << TypeInfo("max_size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "readForTime"; fi->return_type = TypeInfo("", "PIByteArray"); + fi->arguments << TypeInfo("timeout_ms", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "write"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("data", "PIByteArray &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeThreaded"; fi->return_type = TypeInfo("", "ullong"); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("max_size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeThreaded"; fi->return_type = TypeInfo("", "ullong"); + fi->arguments << TypeInfo("data", "PIByteArray &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "configure"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("config_file", "PIString &", Const); + fi->arguments << TypeInfo("section", "PIString &", Const); + fi->arguments << TypeInfo("parent_section", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "createFromFullPath"; fi->return_type = TypeInfo("", "PIIODevice *", Static); + fi->arguments << TypeInfo("full_path", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_open__"; fi->return_type = TypeInfo("", "bool", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "open"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_open__"; fi->return_type = TypeInfo("", "bool", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("_path", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "open"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("_path", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_open__"; fi->return_type = TypeInfo("", "bool", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("_type", "DeviceMode &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "open"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("_type", "DeviceMode &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_open__"; fi->return_type = TypeInfo("", "bool", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("_path", "PIString &", Const); + fi->arguments << TypeInfo("_mode", "DeviceMode &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "open"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("_path", "PIString &", Const); + fi->arguments << TypeInfo("_mode", "DeviceMode &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_close__"; fi->return_type = TypeInfo("", "bool", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "close"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_initialize__"; fi->return_type = TypeInfo("", "bool", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "initialize"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_flush__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "flush"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_opened__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "opened"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_closed__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "closed"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_threadedReadEvent__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("readed", "uchar *"); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "threadedReadEvent"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("readed", "uchar *"); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_threadedWriteEvent__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("id", "ullong"); + fi->arguments << TypeInfo("written_size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "threadedWriteEvent"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("id", "ullong"); + fi->arguments << TypeInfo("written_size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "init"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "configureDevice"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("e_main", "void *", Const); + fi->arguments << TypeInfo("e_parent", "void *", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "openDevice"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "closeDevice"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "threadedRead"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("readed", "uchar *"); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fullPathPrefix"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "constructFullPath"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "configureFromFullPath"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("full_path", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "terminate"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_check_start__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("data", "void *"); + fi->arguments << TypeInfo("delim", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "check_start"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("data", "void *"); + fi->arguments << TypeInfo("delim", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_write_func__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "write_func"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "copy"; fi->return_type = TypeInfo("", "PIIODevice *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "_init"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "begin"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "run"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "end"; fi->return_type = TypeInfo("", "void"); + + ci = new ClassInfo(); + (*classesInfo)["PISerial"] = ci; + ci->name = "PISerial"; + ci->parents << "PIIODevice"; + ci->variables << TypeInfo("desc", "termios"); + ci->variables << TypeInfo("sdesc", "termios"); + ci->variables << TypeInfo("readed", "uint"); + ci->variables << TypeInfo("fd", "int"); + ci->variables << TypeInfo("vtime", "int"); + ci->variables << TypeInfo("block_read", "bool"); + ci->variables << TypeInfo("timer", "PITimer"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "className"; fi->return_type = TypeInfo("", "const char *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "copy"; fi->return_type = TypeInfo("", "PIIODevice *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setSpeed"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("speed", "PISerial::Speed"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setOutSpeed"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("speed", "PISerial::Speed"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setInSpeed"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("speed", "PISerial::Speed"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setDevice"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("dev", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setParameters"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("parameters_", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setParameter"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("parameter", "PISerial::Parameters"); + fi->arguments << TypeInfo("on", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isParameterSet"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("parameter", "PISerial::Parameters"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "parameters"; fi->return_type = TypeInfo("", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setDataBitsCount"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("bits", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "dataBitsCount"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setPin"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("number", "int"); + fi->arguments << TypeInfo("on", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isPin"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("number", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setLE"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("on", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setDTR"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("on", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setRTS"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("on", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setCTS"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("on", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setST"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("on", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setSR"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("on", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setCAR"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("on", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setRNG"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("on", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setDSR"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("on", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isLE"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isDTR"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isRTS"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isCTS"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isST"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isSR"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isCAR"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isRNG"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isDSR"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setVTime"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("t", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setReadIsBlocking"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("yes", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "device"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "outSpeed"; fi->return_type = TypeInfo("", "PISerial::Speed"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "inSpeed"; fi->return_type = TypeInfo("", "PISerial::Speed"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "VTime"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "flush"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "read"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("read_to", "void *"); + fi->arguments << TypeInfo("max_size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "read"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("read_to", "void *"); + fi->arguments << TypeInfo("max_size", "int"); + fi->arguments << TypeInfo("timeout_ms", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "read"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("size", "int"); + fi->arguments << TypeInfo("timeout_ms", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "readData"; fi->return_type = TypeInfo("", "PIByteArray"); + fi->arguments << TypeInfo("size", "int"); + fi->arguments << TypeInfo("timeout_ms", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "write"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("max_size", "int"); + fi->arguments << TypeInfo("wait", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "send"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("size", "int"); + fi->arguments << TypeInfo("wait", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "send"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("data", "PIString &", Const); + fi->arguments << TypeInfo("wait", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "send"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("data", "PIByteArray &", Const); + fi->arguments << TypeInfo("wait", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "availableSpeeds"; fi->return_type = TypeInfo("", "PIVector", Static); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "availableDevices"; fi->return_type = TypeInfo("", "PIStringList", Static); + fi->arguments << TypeInfo("test", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fullPathPrefix"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "configureFromFullPath"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("full_path", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "configureDevice"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("e_main", "void *", Const); + fi->arguments << TypeInfo("e_parent", "void *", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "write"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("max_size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "received"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "_init"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "applySettings"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "convertSpeed"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("speed", "PISerial::Speed"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setBit"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("bit", "int"); + fi->arguments << TypeInfo("on", "bool"); + fi->arguments << TypeInfo("bname", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isBit"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("bit", "int"); + fi->arguments << TypeInfo("bname", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "openDevice"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "closeDevice"; fi->return_type = TypeInfo("", "bool"); + + ci = new ClassInfo(); + (*classesInfo)["PIFile"] = ci; + ci->name = "PIFile"; + ci->parents << "PIIODevice"; + ci->variables << TypeInfo("fd", "FILE*"); + ci->variables << TypeInfo("ret", "int"); + ci->variables << TypeInfo("prec_", "int"); + ci->variables << TypeInfo("prec_str", "string"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "className"; fi->return_type = TypeInfo("", "const char *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "copy"; fi->return_type = TypeInfo("", "PIIODevice *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "flush"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "seek"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("position", "llong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "seekToBegin"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "seekToEnd"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "seekToLine"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("line", "llong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "readChar"; fi->return_type = TypeInfo("", "char"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "readLine"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "readAll"; fi->return_type = TypeInfo("", "llong"); + fi->arguments << TypeInfo("data", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "readAll"; fi->return_type = TypeInfo("", "PIByteArray"); + fi->arguments << TypeInfo("forceRead", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setPath"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("path", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "size"; fi->return_type = TypeInfo("", "llong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "pos"; fi->return_type = TypeInfo("", "llong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isEnd"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isEmpty"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "precision"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setPrecision"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("prec", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "read"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("read_to", "void *"); + fi->arguments << TypeInfo("max_size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "write"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("max_size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeToBinLog"; fi->return_type = TypeInfo("", "PIFile &"); + fi->arguments << TypeInfo("id", "ushort"); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeBinary"; fi->return_type = TypeInfo("", "PIFile &"); + fi->arguments << TypeInfo("v", "char", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeBinary"; fi->return_type = TypeInfo("", "PIFile &"); + fi->arguments << TypeInfo("v", "short", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeBinary"; fi->return_type = TypeInfo("", "PIFile &"); + fi->arguments << TypeInfo("v", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeBinary"; fi->return_type = TypeInfo("", "PIFile &"); + fi->arguments << TypeInfo("v", "long", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeBinary"; fi->return_type = TypeInfo("", "PIFile &"); + fi->arguments << TypeInfo("v", "llong", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeBinary"; fi->return_type = TypeInfo("", "PIFile &"); + fi->arguments << TypeInfo("v", "uchar", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeBinary"; fi->return_type = TypeInfo("", "PIFile &"); + fi->arguments << TypeInfo("v", "ushort", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeBinary"; fi->return_type = TypeInfo("", "PIFile &"); + fi->arguments << TypeInfo("v", "uint", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeBinary"; fi->return_type = TypeInfo("", "PIFile &"); + fi->arguments << TypeInfo("v", "ulong", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeBinary"; fi->return_type = TypeInfo("", "PIFile &"); + fi->arguments << TypeInfo("v", "ullong", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeBinary"; fi->return_type = TypeInfo("", "PIFile &"); + fi->arguments << TypeInfo("v", "float", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeBinary"; fi->return_type = TypeInfo("", "PIFile &"); + fi->arguments << TypeInfo("v", "double", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_clear__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "clear"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_remove__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "remove"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_resize__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("new_size", "llong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "resize"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("new_size", "llong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_resize__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("new_size", "llong"); + fi->arguments << TypeInfo("fill", "uchar"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "resize"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("new_size", "llong"); + fi->arguments << TypeInfo("fill", "uchar"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "openTemporary"; fi->return_type = TypeInfo("", "PIFile", Static); + fi->arguments << TypeInfo("mode", "PIIODevice::DeviceMode"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isExists"; fi->return_type = TypeInfo("", "bool", Static); + fi->arguments << TypeInfo("path", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "remove"; fi->return_type = TypeInfo("", "bool", Static); + fi->arguments << TypeInfo("path", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fullPathPrefix"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "configureFromFullPath"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("full_path", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "openDevice"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "closeDevice"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "strType"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("type", "PIIODevice::DeviceMode", Const); + + ci = new ClassInfo(); + (*classesInfo)["PIProcess"] = ci; + ci->name = "PIProcess"; + ci->parents << "PIThread"; + ci->variables << TypeInfo("args", "PIStringList"); + ci->variables << TypeInfo("env", "PIStringList"); + ci->variables << TypeInfo("wd", "PIString"); + ci->variables << TypeInfo("out", "PIByteArray"); + ci->variables << TypeInfo("f_in", "PIFile"); + ci->variables << TypeInfo("f_out", "PIFile"); + ci->variables << TypeInfo("f_err", "PIFile"); + ci->variables << TypeInfo("g_in", "bool"); + ci->variables << TypeInfo("g_out", "bool"); + ci->variables << TypeInfo("g_err", "bool"); + ci->variables << TypeInfo("t_in", "bool"); + ci->variables << TypeInfo("t_out", "bool"); + ci->variables << TypeInfo("t_err", "bool"); + ci->variables << TypeInfo("pid", "pid_t"); + ci->variables << TypeInfo("tf_in", "FILE*"); + ci->variables << TypeInfo("tf_out", "FILE*"); + ci->variables << TypeInfo("tf_err", "FILE*"); + ci->variables << TypeInfo("exit_code", "int"); + ci->variables << TypeInfo("sz", "int"); + ci->variables << TypeInfo("as", "int"); + ci->variables << TypeInfo("is_exec", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "className"; fi->return_type = TypeInfo("", "const char *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "exitCode"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "pID"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setGrabInput"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("yes", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setGrabOutput"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("yes", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setGrabError"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("yes", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setInputFile"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("path", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setOutputFile"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("path", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setErrorFile"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("path", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "unsetInputFile"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "unsetOutputFile"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "unsetErrorFile"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "workingDirectory"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setWorkingDirectory"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("path", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "resetWorkingDirectory"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "readOutput"; fi->return_type = TypeInfo("", "PIByteArray"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "readError"; fi->return_type = TypeInfo("", "PIByteArray"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "environment"; fi->return_type = TypeInfo("", "PIStringList"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "clearEnvironment"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "removeEnvironmentVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("variable", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setEnvironmentVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("variable", "PIString &", Const); + fi->arguments << TypeInfo("value", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_exec__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("program", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "exec"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("program", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_exec__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("program", "PIString &", Const); + fi->arguments << TypeInfo("arg", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "exec"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("program", "PIString &", Const); + fi->arguments << TypeInfo("arg", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_exec__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("program", "PIString &", Const); + fi->arguments << TypeInfo("arg1", "PIString &", Const); + fi->arguments << TypeInfo("arg2", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "exec"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("program", "PIString &", Const); + fi->arguments << TypeInfo("arg1", "PIString &", Const); + fi->arguments << TypeInfo("arg2", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_exec__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("program", "PIString &", Const); + fi->arguments << TypeInfo("arg1", "PIString &", Const); + fi->arguments << TypeInfo("arg2", "PIString &", Const); + fi->arguments << TypeInfo("arg3", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "exec"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("program", "PIString &", Const); + fi->arguments << TypeInfo("arg1", "PIString &", Const); + fi->arguments << TypeInfo("arg2", "PIString &", Const); + fi->arguments << TypeInfo("arg3", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_exec__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("program", "PIString &", Const); + fi->arguments << TypeInfo("args_", "PIStringList &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "exec"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("program", "PIString &", Const); + fi->arguments << TypeInfo("args_", "PIStringList &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_terminate__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "terminate"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_waitForFinish__"; fi->return_type = TypeInfo("", "bool", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "waitForFinish"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_waitForFinish__"; fi->return_type = TypeInfo("", "bool", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("timeout_msecs", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "waitForFinish"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("timeout_msecs", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_execStarted__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("program", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "execStarted"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("program", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_execFinished__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("program", "PIString"); + fi->arguments << TypeInfo("exit_code", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "execFinished"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("program", "PIString"); + fi->arguments << TypeInfo("exit_code", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "currentEnvironment"; fi->return_type = TypeInfo("", "PIStringList", Static); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "currentPID"; fi->return_type = TypeInfo("", "int", Static); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "run"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "exec_"; fi->return_type = TypeInfo("", "void"); + + ci = new ClassInfo(); + (*classesInfo)["PIEthernet"] = ci; + ci->name = "PIEthernet"; + ci->parents << "PIIODevice"; + ci->variables << TypeInfo("sock", "int"); + ci->variables << TypeInfo("sock_s", "int"); + ci->variables << TypeInfo("port_", "int"); + ci->variables << TypeInfo("port_s", "int"); + ci->variables << TypeInfo("port_c", "int"); + ci->variables << TypeInfo("wrote", "int"); + ci->variables << TypeInfo("connected_", "bool"); + ci->variables << TypeInfo("connecting_", "bool"); + ci->variables << TypeInfo("addr_", "sockaddr_in"); + ci->variables << TypeInfo("saddr_", "sockaddr_in"); + ci->variables << TypeInfo("ip_", "PIString"); + ci->variables << TypeInfo("ip_s", "PIString"); + ci->variables << TypeInfo("ip_c", "PIString"); + ci->variables << TypeInfo("server_thread_", "PIThread"); + ci->variables << TypeInfo("clients_", "PIVector"); + ci->variables << TypeInfo("mcast_queue", "PIQueue"); + ci->variables << TypeInfo("mcast_groups", "PIStringList"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "className"; fi->return_type = TypeInfo("", "const char *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "copy"; fi->return_type = TypeInfo("", "PIIODevice *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setReadAddress"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("ip", "PIString &", Const); + fi->arguments << TypeInfo("port", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setReadAddress"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("ip_port", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setReadIP"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("ip", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setReadPort"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("port", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setSendAddress"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("ip", "PIString &", Const); + fi->arguments << TypeInfo("port", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setSendAddress"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("ip_port", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setSendIP"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("ip", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setSendPort"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("port", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "readAddress"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "readIP"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "readPort"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendAddress"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendIP"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendPort"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setParameters"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("parameters_", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setParameter"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("parameter", "PIEthernet::Parameters"); + fi->arguments << TypeInfo("on", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isParameterSet"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("parameter", "PIEthernet::Parameters"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "parameters"; fi->return_type = TypeInfo("", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "type"; fi->return_type = TypeInfo("", "PIEthernet::Type"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "joinMulticastGroup"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("group", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "leaveMulticastGroup"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("group", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "multicastGroups"; fi->return_type = TypeInfo("", "const PIStringList &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "connect"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "connect"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("ip", "PIString &", Const); + fi->arguments << TypeInfo("port", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "connect"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("ip_port", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isConnected"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "listen"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "listen"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("ip", "PIString &", Const); + fi->arguments << TypeInfo("port", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "listen"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("ip_port", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "client"; fi->return_type = TypeInfo("", "PIEthernet *"); + fi->arguments << TypeInfo("index", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "clientsCount"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "clients"; fi->return_type = TypeInfo("", "PIVector"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "send"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("ip", "PIString &", Const); + fi->arguments << TypeInfo("port", "int"); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("size", "int"); + fi->arguments << TypeInfo("threaded", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "send"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("ip_port", "PIString &", Const); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("size", "int"); + fi->arguments << TypeInfo("threaded", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "send"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("size", "int"); + fi->arguments << TypeInfo("threaded", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "send"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("data", "PIByteArray &", Const); + fi->arguments << TypeInfo("threaded", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "read"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("read_to", "void *"); + fi->arguments << TypeInfo("max_size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "write"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("max_size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "write"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("data", "PIByteArray &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_newConnection__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("client", "PIEthernet *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "newConnection"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("client", "PIEthernet *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_connected__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "connected"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_disconnected__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("withError", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "disconnected"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("withError", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "interfaces"; fi->return_type = TypeInfo("", "PIEthernet::InterfaceList", Static); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "interfaceAddress"; fi->return_type = TypeInfo("", "PIString", Static); + fi->arguments << TypeInfo("interface_", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "allAddresses"; fi->return_type = TypeInfo("", "PIStringList", Static); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "parseAddress"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("ipp", "PIString &", Const); + fi->arguments << TypeInfo("ip", "PIString *"); + fi->arguments << TypeInfo("port", "int *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "macFromBytes"; fi->return_type = TypeInfo("", "PIString", Static); + fi->arguments << TypeInfo("mac", "PIByteArray &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "macToBytes"; fi->return_type = TypeInfo("", "PIByteArray", Static); + fi->arguments << TypeInfo("mac", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "applyMask"; fi->return_type = TypeInfo("", "PIString", Static); + fi->arguments << TypeInfo("ip", "PIString &", Const); + fi->arguments << TypeInfo("mask", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getBroadcast"; fi->return_type = TypeInfo("", "PIString", Static); + fi->arguments << TypeInfo("ip", "PIString &", Const); + fi->arguments << TypeInfo("mask", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fullPathPrefix"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "configureFromFullPath"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("full_path", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "configureDevice"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("e_main", "void *", Const); + fi->arguments << TypeInfo("e_parent", "void *", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "received"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "init"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "openDevice"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "closeDevice"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "closeSocket"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("sd", "int &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getSockAddr"; fi->return_type = TypeInfo("", "PIString", Static); + fi->arguments << TypeInfo("s", "sockaddr *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "server_func"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("eth", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setType"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("t", "Type"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "ethErrorString"; fi->return_type = TypeInfo("", "std::string", Static); + + ci = new ClassInfo(); + (*classesInfo)["PIEthernet::Interface"] = ci; + ci->name = "PIEthernet::Interface"; + ci->variables << TypeInfo("index", "int"); + ci->variables << TypeInfo("name", "PIString"); + ci->variables << TypeInfo("mac", "PIString"); + ci->variables << TypeInfo("address", "PIString"); + ci->variables << TypeInfo("netmask", "PIString"); + ci->variables << TypeInfo("broadcast", "PIString"); + ci->variables << TypeInfo("ptp", "PIString"); + ci->variables << TypeInfo("flags", "InterfaceFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isActive"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isRunning"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isBroadcast"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isMulticast"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isLoopback"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isPTP"; fi->return_type = TypeInfo("", "bool"); + + ci = new ClassInfo(); + (*classesInfo)["PIEthernet::InterfaceList"] = ci; + ci->name = "PIEthernet::InterfaceList"; + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getByIndex"; fi->return_type = TypeInfo("", "const Interface *"); + fi->arguments << TypeInfo("index", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getByName"; fi->return_type = TypeInfo("", "const Interface *"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getByAddress"; fi->return_type = TypeInfo("", "const Interface *"); + fi->arguments << TypeInfo("address", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getLoopback"; fi->return_type = TypeInfo("", "const Interface *"); + + ci = new ClassInfo(); + (*classesInfo)["PIPacketExtractor"] = ci; + ci->name = "PIPacketExtractor"; + ci->parents << "PIIODevice"; + ci->variables << TypeInfo("dev", "PIIODevice*"); + ci->variables << TypeInfo("mheader", "PIByteArray"); + ci->variables << TypeInfo("buffer", "PIByteArray"); + ci->variables << TypeInfo("sbuffer", "PIByteArray"); + ci->variables << TypeInfo("ret_func_header", "HeaderCheckFunc"); + ci->variables << TypeInfo("headerPtr", "void*"); + ci->variables << TypeInfo("data", "void*"); + ci->variables << TypeInfo("buffer_size", "int"); + ci->variables << TypeInfo("dataSize", "int"); + ci->variables << TypeInfo("headerSize", "int"); + ci->variables << TypeInfo("packetSize", "int"); + ci->variables << TypeInfo("allReaded", "int"); + ci->variables << TypeInfo("addSize", "int"); + ci->variables << TypeInfo("curInd", "int"); + ci->variables << TypeInfo("missed", "ullong"); + ci->variables << TypeInfo("missed_packets", "ullong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "className"; fi->return_type = TypeInfo("", "const char *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "copy"; fi->return_type = TypeInfo("", "PIIODevice *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "device"; fi->return_type = TypeInfo("", "PIIODevice *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setDevice"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("device_", "PIIODevice *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "bufferSize"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setBufferSize"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("new_size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setHeaderCheckSlot"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("f", "HeaderCheckFunc"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setPacketData"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("recHeaderPtr", "void *"); + fi->arguments << TypeInfo("recHeaderSize", "int"); + fi->arguments << TypeInfo("recDataSize", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "missedBytes"; fi->return_type = TypeInfo("", "ullong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "missedPackets"; fi->return_type = TypeInfo("", "ullong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "missedBytes_ptr"; fi->return_type = TypeInfo("", "const ullong *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "missedPackets_ptr"; fi->return_type = TypeInfo("", "const ullong *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "lastHeader"; fi->return_type = TypeInfo("", "PIByteArray"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "read"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("read_to", "void *"); + fi->arguments << TypeInfo("max_size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "write"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("max_size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_packetReceived__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("data", "uchar *"); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "packetReceived"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("data", "uchar *"); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "packetHeaderValidate"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("src", "uchar *"); + fi->arguments << TypeInfo("rec", "uchar *"); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "packetValidate"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("rec", "uchar *"); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "threadedRead"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("readed", "uchar *"); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fullPathPrefix"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "openDevice"; fi->return_type = TypeInfo("", "bool"); + + ci = new ClassInfo(); + (*classesInfo)["PIConfig"] = ci; + ci->name = "PIConfig"; + ci->parents << "PIFile"; + ci->variables << TypeInfo("centry", "int"); + ci->variables << TypeInfo("delim", "PIString"); + ci->variables << TypeInfo("root", "PIConfig::Entry"); + ci->variables << TypeInfo("empty", "PIConfig::Entry"); + ci->variables << TypeInfo("lines", "uint"); + ci->variables << TypeInfo("other", "PIStringList"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "PIString &", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "PIString &", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "char *", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "PIStringList &", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "bool", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "short", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "int", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "long", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "uchar", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "ushort", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "uint", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "ulong", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "float", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "double", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "char *", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "PIStringList &", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "bool", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "short", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "int", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "long", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "uchar", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "ushort", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "uint", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "ulong", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "float", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "double", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValues"; fi->return_type = TypeInfo("", "PIConfig::Branch"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("value", "PIString &", Const); + fi->arguments << TypeInfo("type", "PIString &", Const); + fi->arguments << TypeInfo("write", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("value", "PIStringList &", Const); + fi->arguments << TypeInfo("write", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("value", "char *", Const); + fi->arguments << TypeInfo("write", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("value", "bool", Const); + fi->arguments << TypeInfo("write", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("value", "short", Const); + fi->arguments << TypeInfo("write", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("value", "int", Const); + fi->arguments << TypeInfo("write", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("value", "long", Const); + fi->arguments << TypeInfo("write", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("value", "uchar", Const); + fi->arguments << TypeInfo("write", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("value", "ushort", Const); + fi->arguments << TypeInfo("write", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("value", "uint", Const); + fi->arguments << TypeInfo("write", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("value", "ulong", Const); + fi->arguments << TypeInfo("write", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("value", "float", Const); + fi->arguments << TypeInfo("write", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("value", "double", Const); + fi->arguments << TypeInfo("write", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "rootEntry"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "entriesCount"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isEntryExists"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "allTree"; fi->return_type = TypeInfo("", "PIConfig::Branch"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "allLeaves"; fi->return_type = TypeInfo("", "PIConfig::Branch"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "entryIndex"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getName"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("number", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("number", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getType"; fi->return_type = TypeInfo("", "PIChar"); + fi->arguments << TypeInfo("number", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getComment"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("number", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addEntry"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("value", "PIString &", Const); + fi->arguments << TypeInfo("type", "PIString &", Const); + fi->arguments << TypeInfo("write", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setName"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("number", "uint"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("write", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("number", "uint"); + fi->arguments << TypeInfo("value", "PIString &", Const); + fi->arguments << TypeInfo("write", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setType"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("number", "uint"); + fi->arguments << TypeInfo("type", "PIString &", Const); + fi->arguments << TypeInfo("write", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setComment"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("number", "uint"); + fi->arguments << TypeInfo("comment", "PIString &", Const); + fi->arguments << TypeInfo("write", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "removeEntry"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("write", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "removeEntry"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("number", "uint"); + fi->arguments << TypeInfo("write", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "clear"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "readAll"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeAll"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "delimiter"; fi->return_type = TypeInfo("", "const PIString &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setDelimiter"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("d", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "childCount"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("e", "Entry *", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "entryExists"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("e", "Entry *", Const); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "buildFullNames"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("e", "Entry *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "allLeaves"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("b", "Branch &"); + fi->arguments << TypeInfo("e", "Entry *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setEntryDelim"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("e", "Entry *"); + fi->arguments << TypeInfo("d", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "entryByIndex"; fi->return_type = TypeInfo("", "PIConfig::Entry &"); + fi->arguments << TypeInfo("index", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "removeEntry"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("b", "Branch &"); + fi->arguments << TypeInfo("e", "Entry *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "deleteEntry"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("e", "Entry *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getPrefixFromLine"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("line", "PIString"); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "parse"; fi->return_type = TypeInfo("", "void"); + + ci = new ClassInfo(); + (*classesInfo)["PIConfig::Branch"] = ci; + ci->name = "PIConfig::Branch"; + ci->variables << TypeInfo("_empty", "Entry", Static); + ci->variables << TypeInfo("delim", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "PIString &", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "PIString &", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "char *", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "PIStringList &", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "bool", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "short", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "int", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "long", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "uchar", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "ushort", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "uint", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "ulong", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "float", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "double", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "char *", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "PIStringList &", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "bool", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "short", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "int", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "long", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "uchar", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "ushort", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "uint", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "ulong", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "float", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "double", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "allLeaves"; fi->return_type = TypeInfo("", "Branch"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValues"; fi->return_type = TypeInfo("", "Branch"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getLeaves"; fi->return_type = TypeInfo("", "Branch"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getBranches"; fi->return_type = TypeInfo("", "Branch"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "filter"; fi->return_type = TypeInfo("", "Branch &"); + fi->arguments << TypeInfo("f", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isEntryExists"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "indexOf"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("e", "Entry *", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "entryExists"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("e", "Entry *", Const); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "allLeaves"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("b", "Branch &"); + fi->arguments << TypeInfo("e", "Entry *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "coutt"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("s", "std::ostream &"); + fi->arguments << TypeInfo("p", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "piCoutt"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("s", "PICout"); + fi->arguments << TypeInfo("p", "PIString &", Const); + + ci = new ClassInfo(); + (*classesInfo)["PIConfig::Entry"] = ci; + ci->name = "PIConfig::Entry"; + ci->variables << TypeInfo("_empty", "PIConfig::Entry::EntryPtr", Static); + ci->variables << TypeInfo("_parent", "PIConfig::Entry::EntryPtr*"); + ci->variables << TypeInfo("_children", "Branch"); + ci->variables << TypeInfo("_tab", "PIString"); + ci->variables << TypeInfo("_name", "PIString"); + ci->variables << TypeInfo("_value", "PIString"); + ci->variables << TypeInfo("_type", "PIString"); + ci->variables << TypeInfo("_comment", "PIString"); + ci->variables << TypeInfo("_all", "PIString"); + ci->variables << TypeInfo("_full_name", "PIString"); + ci->variables << TypeInfo("delim", "PIString"); + ci->variables << TypeInfo("_line", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "parent"; fi->return_type = TypeInfo("", "Entry *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "childCount"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "children"; fi->return_type = TypeInfo("", "Branch &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "child"; fi->return_type = TypeInfo("", "Entry *"); + fi->arguments << TypeInfo("index", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "findChild"; fi->return_type = TypeInfo("", "Entry *"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "findChild"; fi->return_type = TypeInfo("", "const Entry *"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isLeaf"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "name"; fi->return_type = TypeInfo("", "const PIString &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "value"; fi->return_type = TypeInfo("", "const PIString &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "type"; fi->return_type = TypeInfo("", "const PIString &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "comment"; fi->return_type = TypeInfo("", "const PIString &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fullName"; fi->return_type = TypeInfo("", "const PIString &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setName"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("value", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setType"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("value", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setComment"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("value", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("value", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("value", "PIStringList &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("value", "char *", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("value", "bool", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("value", "char", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("value", "short", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("value", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("value", "long", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("value", "uchar", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("value", "ushort", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("value", "uint", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("value", "ulong", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("value", "float", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("value", "double", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "PIString &", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "PIString &", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "char *", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "PIStringList &", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "bool", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "short", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "int", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "long", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "uchar", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "ushort", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "uint", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "ulong", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "float", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "double", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "char *", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "PIStringList &", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "bool", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "short", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "int", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "long", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "uchar", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "ushort", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "uint", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "ulong", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "float", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValue"; fi->return_type = TypeInfo("", "Entry &"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + fi->arguments << TypeInfo("def", "double", Const); + fi->arguments << TypeInfo("exists", "bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getValues"; fi->return_type = TypeInfo("", "Branch"); + fi->arguments << TypeInfo("vname", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isEntryExists"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "compare"; fi->return_type = TypeInfo("", "int", Static); + fi->arguments << TypeInfo("f", "EntryPtr *", Const); + fi->arguments << TypeInfo("s", "EntryPtr *", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "entryExists"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("e", "Entry *", Const); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "buildLine"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "clear"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "coutt"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("s", "std::ostream &"); + fi->arguments << TypeInfo("p", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "piCoutt"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("s", "PICout"); + fi->arguments << TypeInfo("p", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "deleteBranch"; fi->return_type = TypeInfo("", "void"); + + ci = new ClassInfo(); + (*classesInfo)["PIMultiProtocolBase"] = ci; + ci->name = "PIMultiProtocolBase"; + ci->parents << "PIObject"; + ci->variables << TypeInfo("mutex_receive", "PIMutex"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "className"; fi->return_type = TypeInfo("", "const char *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "received"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("prot", "PIProtocol *"); + fi->arguments << TypeInfo("corrected", "bool"); + fi->arguments << TypeInfo("data", "uchar *"); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiveEvent"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("p", "PIMultiProtocolBase *"); + fi->arguments << TypeInfo("prot", "PIProtocol *"); + fi->arguments << TypeInfo("corrected", "bool"); + fi->arguments << TypeInfo("data", "uchar *"); + fi->arguments << TypeInfo("size", "int"); + + ci = new ClassInfo(); + (*classesInfo)["PIProtocol"] = ci; + ci->name = "PIProtocol"; + ci->parents << "PIObject"; + ci->variables << TypeInfo("ser", "PISerial*"); + ci->variables << TypeInfo("eth", "PIEthernet*"); + ci->variables << TypeInfo("dataSize", "uint"); + ci->variables << TypeInfo("headerSize", "uint"); + ci->variables << TypeInfo("sendDataSize", "uint"); + ci->variables << TypeInfo("dataPtr", "uchar*"); + ci->variables << TypeInfo("headerPtr", "uchar*"); + ci->variables << TypeInfo("sendDataPtr", "uchar*"); + ci->variables << TypeInfo("ret_func", "ReceiveFunc"); + ci->variables << TypeInfo("packet_ext", "PIPacketExtractor*"); + ci->variables << TypeInfo("diagTimer", "PITimer*"); + ci->variables << TypeInfo("sendTimer", "PITimer*"); + ci->variables << TypeInfo("secTimer", "PITimer*"); + ci->variables << TypeInfo("mp_owner", "PIMultiProtocolBase*"); + ci->variables << TypeInfo("type_send", "PIProtocol::Type"); + ci->variables << TypeInfo("type_rec", "PIProtocol::Type"); + ci->variables << TypeInfo("net_diag", "PIProtocol::Quality"); + ci->variables << TypeInfo("last_freq", "PIDeque"); + ci->variables << TypeInfo("last_packets", "PIDeque"); + ci->variables << TypeInfo("protName", "PIString"); + ci->variables << TypeInfo("devReceiverName", "PIString"); + ci->variables << TypeInfo("devReceiverState", "PIString"); + ci->variables << TypeInfo("devSenderName", "PIString"); + ci->variables << TypeInfo("devSenderState", "PIString"); + ci->variables << TypeInfo("speedIn", "PIString"); + ci->variables << TypeInfo("speedOut", "PIString"); + ci->variables << TypeInfo("history_path_rec", "PIString"); + ci->variables << TypeInfo("history_path_send", "PIString"); + ci->variables << TypeInfo("history_rsize_rec", "PIString"); + ci->variables << TypeInfo("history_rsize_send", "PIString"); + ci->variables << TypeInfo("history_file_rec", "PIFile"); + ci->variables << TypeInfo("history_file_send", "PIFile"); + ci->variables << TypeInfo("history_id_rec", "ushort"); + ci->variables << TypeInfo("history_id_send", "ushort"); + ci->variables << TypeInfo("work", "bool"); + ci->variables << TypeInfo("new_mp_prot", "bool"); + ci->variables << TypeInfo("history_write_rec", "bool"); + ci->variables << TypeInfo("history_write_send", "bool"); + ci->variables << TypeInfo("exp_freq", "float"); + ci->variables << TypeInfo("send_freq", "float"); + ci->variables << TypeInfo("ifreq", "float"); + ci->variables << TypeInfo("immediate_freq", "float"); + ci->variables << TypeInfo("integral_freq", "float"); + ci->variables << TypeInfo("timeout_", "float"); + ci->variables << TypeInfo("packets", "int[2]"); + ci->variables << TypeInfo("pckt_cnt", "int"); + ci->variables << TypeInfo("pckt_cnt_max", "int"); + ci->variables << TypeInfo("cur_pckt", "char"); + ci->variables << TypeInfo("wrong_count", "ullong"); + ci->variables << TypeInfo("receive_count", "ullong"); + ci->variables << TypeInfo("send_count", "ullong"); + ci->variables << TypeInfo("missed_count", "ullong"); + ci->variables << TypeInfo("packets_in_sec", "ullong"); + ci->variables << TypeInfo("packets_out_sec", "ullong"); + ci->variables << TypeInfo("bytes_in_sec", "ullong"); + ci->variables << TypeInfo("bytes_out_sec", "ullong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "className"; fi->return_type = TypeInfo("", "const char *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_startReceive__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "startReceive"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_startReceive__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("exp_frequency", "float"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "startReceive"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("exp_frequency", "float"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_stopReceive__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "stopReceive"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setExpectedFrequency"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("frequency", "float"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setReceiverDevice"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("device", "PIString &", Const); + fi->arguments << TypeInfo("speed", "PISerial::Speed"); + fi->arguments << TypeInfo("force", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setReceiverData"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("dataPtr", "void *"); + fi->arguments << TypeInfo("dataSize", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setReceiverDataHeader"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("headerPtr", "void *"); + fi->arguments << TypeInfo("headerSize", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setReceiverAddress"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("ip", "PIString &", Const); + fi->arguments << TypeInfo("port", "int"); + fi->arguments << TypeInfo("force", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setReceiverParameters"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("parameters", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setReceiveSlot"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("slot", "ReceiveFunc"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "expectedFrequency"; fi->return_type = TypeInfo("", "float"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_startSend__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "startSend"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_startSend__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("frequency", "float"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "startSend"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("frequency", "float"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_stopSend__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "stopSend"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setSenderFrequency"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("frequency", "float"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setSenderDevice"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("device", "PIString &", Const); + fi->arguments << TypeInfo("speed", "PISerial::Speed"); + fi->arguments << TypeInfo("force", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setSenderData"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("dataPtr", "void *"); + fi->arguments << TypeInfo("dataSize", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setSenderAddress"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("ip", "PIString &", Const); + fi->arguments << TypeInfo("port", "int"); + fi->arguments << TypeInfo("force", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setSenderIP"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("ip", "PIString &", Const); + fi->arguments << TypeInfo("force", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setSenderPort"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("port", "int"); + fi->arguments << TypeInfo("force", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setSenderParameters"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("parameters", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "senderFrequency"; fi->return_type = TypeInfo("", "float"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_start__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "start"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_stop__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "stop"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_send__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "send"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_send__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "send"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_send__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("size", "int"); + fi->arguments << TypeInfo("direct", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "send"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("size", "int"); + fi->arguments << TypeInfo("direct", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setName"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "name"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setDisconnectTimeout"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("timeout", "float"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "disconnectTimeout"; fi->return_type = TypeInfo("", "float"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "disconnectTimeout_ptr"; fi->return_type = TypeInfo("", "const float *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "immediateFrequency"; fi->return_type = TypeInfo("", "float"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "integralFrequency"; fi->return_type = TypeInfo("", "float"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "immediateFrequency_ptr"; fi->return_type = TypeInfo("", "const float *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "integralFrequency_ptr"; fi->return_type = TypeInfo("", "const float *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiveCountPerSec"; fi->return_type = TypeInfo("", "ullong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiveCountPerSec_ptr"; fi->return_type = TypeInfo("", "const ullong *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendCountPerSec"; fi->return_type = TypeInfo("", "ullong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendCountPerSec_ptr"; fi->return_type = TypeInfo("", "const ullong *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiveBytesPerSec"; fi->return_type = TypeInfo("", "ullong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiveBytesPerSec_ptr"; fi->return_type = TypeInfo("", "const ullong *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendBytesPerSec"; fi->return_type = TypeInfo("", "ullong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendBytesPerSec_ptr"; fi->return_type = TypeInfo("", "const ullong *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiveCount"; fi->return_type = TypeInfo("", "ullong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiveCount_ptr"; fi->return_type = TypeInfo("", "const ullong *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "wrongCount"; fi->return_type = TypeInfo("", "ullong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "wrongCount_ptr"; fi->return_type = TypeInfo("", "const ullong *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendCount"; fi->return_type = TypeInfo("", "ullong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendCount_ptr"; fi->return_type = TypeInfo("", "const ullong *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "missedCount"; fi->return_type = TypeInfo("", "ullong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "missedCount_ptr"; fi->return_type = TypeInfo("", "const ullong *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "quality"; fi->return_type = TypeInfo("", "PIProtocol::Quality"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "quality_ptr"; fi->return_type = TypeInfo("", "const int *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiverDeviceName"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "senderDeviceName"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiverDeviceState"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiverDeviceState_ptr"; fi->return_type = TypeInfo("", "const PIString *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "senderDeviceState"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "senderDeviceState_ptr"; fi->return_type = TypeInfo("", "const PIString *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiveSpeed"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiveSpeed_ptr"; fi->return_type = TypeInfo("", "const PIString *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendSpeed"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendSpeed_ptr"; fi->return_type = TypeInfo("", "const PIString *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiverHistorySize"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiverHistorySize_ptr"; fi->return_type = TypeInfo("", "const PIString *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "senderHistorySize"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "senderHistorySize_ptr"; fi->return_type = TypeInfo("", "const PIString *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeReceiverHistory"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeReceiverHistory_ptr"; fi->return_type = TypeInfo("", "const bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeSenderHistory"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeSenderHistory_ptr"; fi->return_type = TypeInfo("", "const bool *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiveData"; fi->return_type = TypeInfo("", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendData"; fi->return_type = TypeInfo("", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "packetExtractor"; fi->return_type = TypeInfo("", "PIPacketExtractor *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "lastHeader"; fi->return_type = TypeInfo("", "PIByteArray"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_receiverStarted__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiverStarted"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_receiverStopped__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiverStopped"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_senderStarted__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "senderStarted"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_senderStopped__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "senderStopped"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_received__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("validate_is_ok", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "received"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("validate_is_ok", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_qualityChanged__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("new_quality", "PIProtocol::Quality"); + fi->arguments << TypeInfo("old_quality", "PIProtocol::Quality"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "qualityChanged"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("new_quality", "PIProtocol::Quality"); + fi->arguments << TypeInfo("old_quality", "PIProtocol::Quality"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receive"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("data", "uchar *"); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "validate"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "headerValidate"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("src", "uchar *"); + fi->arguments << TypeInfo("rec", "uchar *"); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "checksum_i"; fi->return_type = TypeInfo("", "uint"); + fi->arguments << TypeInfo("data", "void *"); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "checksum_c"; fi->return_type = TypeInfo("", "uchar"); + fi->arguments << TypeInfo("data", "void *"); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "aboutSend"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "init"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "init_sender"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("b", "PIConfig::Entry &"); + fi->arguments << TypeInfo("sb", "PIConfig::Entry &"); + fi->arguments << TypeInfo("config", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "init_receiver"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("b", "PIConfig::Entry &"); + fi->arguments << TypeInfo("rb", "PIConfig::Entry &"); + fi->arguments << TypeInfo("config", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "check_state"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "calc_freq"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "calc_diag"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendEvent"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("e", "void *"); + fi->arguments << TypeInfo("nt", "i"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiveEvent"; fi->return_type = TypeInfo("", "bool", Static); + fi->arguments << TypeInfo("t", "void *"); + fi->arguments << TypeInfo("data", "uchar *"); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "headerValidateEvent"; fi->return_type = TypeInfo("", "bool", Static); + fi->arguments << TypeInfo("t", "void *"); + fi->arguments << TypeInfo("src", "uchar *"); + fi->arguments << TypeInfo("rec", "uchar *"); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "diagEvent"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("t", "void *"); + fi->arguments << TypeInfo("nt", "i"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "secEvent"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("t", "void *"); + fi->arguments << TypeInfo("nt", "i"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setMultiProtocolOwner"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("mp", "PIMultiProtocolBase *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "multiProtocolOwner"; fi->return_type = TypeInfo("", "PIMultiProtocolBase *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "changeDisconnectTimeout"; fi->return_type = TypeInfo("", "void"); + + ci = new ClassInfo(); + (*classesInfo)["PIDiagnostics"] = ci; + ci->name = "PIDiagnostics"; + ci->parents << "PITimer"; + ci->variables << TypeInfo("qual", "PIDiagnostics::Quality"); + ci->variables << TypeInfo("speedIn", "PIString"); + ci->variables << TypeInfo("speedOut", "PIString"); + ci->variables << TypeInfo("ifreq", "float"); + ci->variables << TypeInfo("immediate_freq", "float"); + ci->variables << TypeInfo("integral_freq", "float"); + ci->variables << TypeInfo("packets", "int[2]"); + ci->variables << TypeInfo("cur_pckt", "char"); + ci->variables << TypeInfo("rec_once", "char"); + ci->variables << TypeInfo("wrong_count", "ullong"); + ci->variables << TypeInfo("receive_count", "ullong"); + ci->variables << TypeInfo("send_count", "ullong"); + ci->variables << TypeInfo("packets_in_sec", "ullong"); + ci->variables << TypeInfo("packets_out_sec", "ullong"); + ci->variables << TypeInfo("bytes_in_sec", "ullong"); + ci->variables << TypeInfo("bytes_out_sec", "ullong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "className"; fi->return_type = TypeInfo("", "const char *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "immediateFrequency"; fi->return_type = TypeInfo("", "float"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "integralFrequency"; fi->return_type = TypeInfo("", "float"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiveCountPerSec"; fi->return_type = TypeInfo("", "ullong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendCountPerSec"; fi->return_type = TypeInfo("", "ullong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiveBytesPerSec"; fi->return_type = TypeInfo("", "ullong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendBytesPerSec"; fi->return_type = TypeInfo("", "ullong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiveCount"; fi->return_type = TypeInfo("", "ullong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "wrongCount"; fi->return_type = TypeInfo("", "ullong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendCount"; fi->return_type = TypeInfo("", "ullong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "quality"; fi->return_type = TypeInfo("", "PIDiagnostics::Quality"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiveSpeed"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendSpeed"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "immediateFrequency_ptr"; fi->return_type = TypeInfo("", "const float *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "integralFrequency_ptr"; fi->return_type = TypeInfo("", "const float *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiveCountPerSec_ptr"; fi->return_type = TypeInfo("", "const ullong *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendCountPerSec_ptr"; fi->return_type = TypeInfo("", "const ullong *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiveBytesPerSec_ptr"; fi->return_type = TypeInfo("", "const ullong *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendBytesPerSec_ptr"; fi->return_type = TypeInfo("", "const ullong *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiveCount_ptr"; fi->return_type = TypeInfo("", "const ullong *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "wrongCount_ptr"; fi->return_type = TypeInfo("", "const ullong *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendCount_ptr"; fi->return_type = TypeInfo("", "const ullong *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "quality_ptr"; fi->return_type = TypeInfo("", "const int *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiveSpeed_ptr"; fi->return_type = TypeInfo("", "const PIString *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendSpeed_ptr"; fi->return_type = TypeInfo("", "const PIString *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_start__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "start"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_start__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("msecs", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "start"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("msecs", "double"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_reset__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "reset"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_received__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "received"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_received__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("size", "int"); + fi->arguments << TypeInfo("correct", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "received"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("size", "int"); + fi->arguments << TypeInfo("correct", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_sended__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sended"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_qualityChanged__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("new_quality", "PIDiagnostics::Quality"); + fi->arguments << TypeInfo("old_quality", "PIDiagnostics::Quality"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "qualityChanged"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("new_quality", "PIDiagnostics::Quality"); + fi->arguments << TypeInfo("old_quality", "PIDiagnostics::Quality"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "tick"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("data", "void *"); + fi->arguments << TypeInfo("delimiter", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "changeDisconnectTimeout"; fi->return_type = TypeInfo("", "void"); + + ci = new ClassInfo(); + (*classesInfo)["PISystemMonitor"] = ci; + ci->name = "PISystemMonitor"; + ci->parents << "PIThread"; + ci->variables << TypeInfo("file", "PIFile"); + ci->variables << TypeInfo("filem", "PIFile"); + ci->variables << TypeInfo("stat", "PISystemMonitor::ProcessStats"); + ci->variables << TypeInfo("pID_", "int"); + ci->variables << TypeInfo("page_size", "int"); + ci->variables << TypeInfo("cpu_count", "int"); + ci->variables << TypeInfo("cycle", "int"); + ci->variables << TypeInfo("cpu_u_cur", "llong"); + ci->variables << TypeInfo("cpu_u_prev", "llong"); + ci->variables << TypeInfo("cpu_s_cur", "llong"); + ci->variables << TypeInfo("cpu_s_prev", "llong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "startOnProcess"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("pID", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "startOnSelf"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "statistic"; fi->return_type = TypeInfo("", "const PISystemMonitor::ProcessStats &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "run"; fi->return_type = TypeInfo("", "void"); + + ci = new ClassInfo(); + (*classesInfo)["PISystemMonitor::ProcessStats"] = ci; + ci->name = "PISystemMonitor::ProcessStats"; + ci->variables << TypeInfo("exec_name", "PIString"); + ci->variables << TypeInfo("state", "PIString"); + ci->variables << TypeInfo("ID", "int"); + ci->variables << TypeInfo("parent_ID", "int"); + ci->variables << TypeInfo("group_ID", "int"); + ci->variables << TypeInfo("session_ID", "int"); + ci->variables << TypeInfo("priority", "int"); + ci->variables << TypeInfo("threads", "int"); + ci->variables << TypeInfo("physical_memsize", "ulong"); + ci->variables << TypeInfo("resident_memsize", "ulong"); + ci->variables << TypeInfo("share_memsize", "ulong"); + ci->variables << TypeInfo("virtual_memsize", "ulong"); + ci->variables << TypeInfo("data_memsize", "ulong"); + ci->variables << TypeInfo("physical_memsize_readable", "PIString"); + ci->variables << TypeInfo("resident_memsize_readable", "PIString"); + ci->variables << TypeInfo("share_memsize_readable", "PIString"); + ci->variables << TypeInfo("virtual_memsize_readable", "PIString"); + ci->variables << TypeInfo("data_memsize_readable", "PIString"); + ci->variables << TypeInfo("cpu_load_system", "float"); + ci->variables << TypeInfo("cpu_load_user", "float"); + + ci = new ClassInfo(); + (*classesInfo)["PIConsole"] = ci; + ci->name = "PIConsole"; + ci->parents << "PIThread"; + ci->variables << TypeInfo("tabs", "PIVector"); + ci->variables << TypeInfo("binstr", "PIString"); + ci->variables << TypeInfo("rstr", "PIString"); + ci->variables << TypeInfo("rba", "PIByteArray"); + ci->variables << TypeInfo("tv", "PIConsole::Variable"); + ci->variables << TypeInfo("listener", "PIKbdListener*"); + ci->variables << TypeInfo("def_align", "PIConsole::Alignment"); + ci->variables << TypeInfo("ret_func", "KBFunc"); + ci->variables << TypeInfo("width", "int"); + ci->variables << TypeInfo("height", "int"); + ci->variables << TypeInfo("pwidth", "int"); + ci->variables << TypeInfo("pheight", "int"); + ci->variables << TypeInfo("ret", "int"); + ci->variables << TypeInfo("col_wid", "int"); + ci->variables << TypeInfo("num_format", "int"); + ci->variables << TypeInfo("systime_format", "int"); + ci->variables << TypeInfo("max_y", "uint"); + ci->variables << TypeInfo("vid", "int"); + ci->variables << TypeInfo("cur_tab", "uint"); + ci->variables << TypeInfo("col_cnt", "uint"); + ci->variables << TypeInfo("peer", "PIPeer*"); + ci->variables << TypeInfo("peer_timer", "PITimer"); + ci->variables << TypeInfo("server_name", "PIString"); + ci->variables << TypeInfo("server_mode", "bool"); + ci->variables << TypeInfo("state", "PIConsole::ConnectedState"); + ci->variables << TypeInfo("remote_clients", "PIVector"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "className"; fi->return_type = TypeInfo("", "const char *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addString"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("column", "int"); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("ptr", "PIString *", Const); + fi->arguments << TypeInfo("column", "int"); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("ptr", "char *", Const); + fi->arguments << TypeInfo("column", "int"); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("ptr", "bool *", Const); + fi->arguments << TypeInfo("column", "int"); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("ptr", "short *", Const); + fi->arguments << TypeInfo("column", "int"); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("ptr", "int *", Const); + fi->arguments << TypeInfo("column", "int"); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("ptr", "long *", Const); + fi->arguments << TypeInfo("column", "int"); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("ptr", "llong *", Const); + fi->arguments << TypeInfo("column", "int"); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("ptr", "uchar *", Const); + fi->arguments << TypeInfo("column", "int"); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("ptr", "ushort *", Const); + fi->arguments << TypeInfo("column", "int"); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("ptr", "uint *", Const); + fi->arguments << TypeInfo("column", "int"); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("ptr", "ulong *", Const); + fi->arguments << TypeInfo("column", "int"); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("ptr", "ullong *", Const); + fi->arguments << TypeInfo("column", "int"); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("ptr", "float *", Const); + fi->arguments << TypeInfo("column", "int"); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("ptr", "double *", Const); + fi->arguments << TypeInfo("column", "int"); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("ptr", "PISystemTime *", Const); + fi->arguments << TypeInfo("column", "int"); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("ptr", "PIProtocol *", Const); + fi->arguments << TypeInfo("column", "int"); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("ptr", "PIDiagnostics *", Const); + fi->arguments << TypeInfo("column", "int"); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("ptr", "PISystemMonitor *", Const); + fi->arguments << TypeInfo("column", "int"); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addBitVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("ptr", "void *", Const); + fi->arguments << TypeInfo("fromBit", "int"); + fi->arguments << TypeInfo("bitsCount", "int"); + fi->arguments << TypeInfo("column", "int"); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addEmptyLine"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("column", "int"); + fi->arguments << TypeInfo("count", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getString"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("x", "int"); + fi->arguments << TypeInfo("y", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getShort"; fi->return_type = TypeInfo("", "short"); + fi->arguments << TypeInfo("x", "int"); + fi->arguments << TypeInfo("y", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getInt"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("x", "int"); + fi->arguments << TypeInfo("y", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getFloat"; fi->return_type = TypeInfo("", "float"); + fi->arguments << TypeInfo("x", "int"); + fi->arguments << TypeInfo("y", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getDouble"; fi->return_type = TypeInfo("", "double"); + fi->arguments << TypeInfo("x", "int"); + fi->arguments << TypeInfo("y", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getString"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getShort"; fi->return_type = TypeInfo("", "short"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getInt"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getFloat"; fi->return_type = TypeInfo("", "float"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getDouble"; fi->return_type = TypeInfo("", "double"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "tabsCount"; fi->return_type = TypeInfo("", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "currentTab"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addTab"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("bind_key", "char"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "removeTab"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("index", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "removeTab"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setTab"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("index", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setTab"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setTabBindKey"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("index", "uint"); + fi->arguments << TypeInfo("bind_key", "char"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setTabBindKey"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("bind_key", "char"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "clearTabs"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("clearScreen", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addCustomStatus"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("str", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "clearCustomStatus"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "defaultAlignment"; fi->return_type = TypeInfo("", "PIConsole::Alignment"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setDefaultAlignment"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("align", "Alignment"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setColumnAlignment"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("col", "int"); + fi->arguments << TypeInfo("align", "Alignment"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setColumnAlignmentToAll"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("align", "Alignment"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fstr"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("f", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "enableExitCapture"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("key", "char"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "disableExitCapture"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "exitCaptured"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "exitKey"; fi->return_type = TypeInfo("", "char"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "startServer"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "stopPeer"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isServerStarted"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "clients"; fi->return_type = TypeInfo("", "PIStringList"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "listenServers"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "availableServers"; fi->return_type = TypeInfo("", "PIStringList"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "selectedServer"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "connectToServer"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "disconnect"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isConnected"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toUpperLeft"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "moveRight"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("n", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "moveLeft"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("n", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "moveTo"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("x", "int"); + fi->arguments << TypeInfo("y", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "clearScreen"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "clearScreenLower"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "clearLine"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "newLine"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "hideCursor"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "showCursor"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_clearVariables__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "clearVariables"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_clearVariables__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("clearScreen", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "clearVariables"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("clearScreen", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_waitForFinish__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "waitForFinish"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_start__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "start"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_start__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("wait", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "start"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("wait", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_stop__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "stop"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_stop__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("clear", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "stop"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("clear", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_keyPressed__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("key", "char"); + fi->arguments << TypeInfo("data", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "keyPressed"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("key", "char"); + fi->arguments << TypeInfo("data", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "begin"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "run"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fillLabels"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "status"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "checkColumn"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("col", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "bitsValue"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("src", "void *", Const); + fi->arguments << TypeInfo("offset", "int"); + fi->arguments << TypeInfo("count", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "toBin"; fi->return_type = TypeInfo("", "const char *"); + fi->arguments << TypeInfo("d", "void *", Const); + fi->arguments << TypeInfo("s", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "printLine"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("str", "PIString &", Const); + fi->arguments << TypeInfo("dx", "int"); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "printValue"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("str", "PIString &", Const); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "printValue"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("str", "char *", Const); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "printValue"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("value", "bool", Const); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "printValue"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("value", "int", Const); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "printValue"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("value", "long", Const); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "printValue"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("value", "llong", Const); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "printValue"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("value", "float", Const); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "printValue"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("value", "double", Const); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "printValue"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("value", "char", Const); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "printValue"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("value", "short", Const); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "printValue"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("value", "uchar", Const); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "printValue"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("value", "ushort", Const); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "printValue"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("value", "uint", Const); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "printValue"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("value", "ulong", Const); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "printValue"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("value", "ullong", Const); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "printValue"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("value", "PISystemTime &", Const); + fi->arguments << TypeInfo("format", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "key_event"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("key", "char"); + fi->arguments << TypeInfo("t", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "columns"; fi->return_type = TypeInfo("", "PIVector &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "column"; fi->return_type = TypeInfo("", "PIConsole::Column &"); + fi->arguments << TypeInfo("index", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "couts"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("v", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "couts"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("v", "char *", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "couts"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("v", "bool", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "couts"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("v", "char", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "couts"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("v", "short", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "couts"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("v", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "couts"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("v", "long", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "couts"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("v", "llong", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "couts"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("v", "uchar", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "couts"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("v", "ushort", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "couts"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("v", "uint", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "couts"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("v", "ulong", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "couts"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("v", "ullong", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "couts"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("v", "float", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "couts"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("v", "double", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "couts"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("v", "PISystemTime &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "serverSendInfo"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "serverSendData"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "remoteClient"; fi->return_type = TypeInfo("", "RemoteClient &"); + fi->arguments << TypeInfo("fname", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_peerReceived__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("from", "PIString &", Const); + fi->arguments << TypeInfo("data", "PIByteArray &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "peerReceived"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("from", "PIString &", Const); + fi->arguments << TypeInfo("data", "PIByteArray &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_peerTimer__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("data", "void *"); + fi->arguments << TypeInfo("delim", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "peerTimer"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("data", "void *"); + fi->arguments << TypeInfo("delim", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_peerDisconnectedEvent__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "peerDisconnectedEvent"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + + ci = new ClassInfo(); + (*classesInfo)["PIConsole::Variable"] = ci; + ci->name = "PIConsole::Variable"; + ci->variables << TypeInfo("name", "PIString"); + ci->variables << TypeInfo("format", "PIFlags"); + ci->variables << TypeInfo("nx", "int"); + ci->variables << TypeInfo("ny", "int"); + ci->variables << TypeInfo("type", "int"); + ci->variables << TypeInfo("offset", "int"); + ci->variables << TypeInfo("bitFrom", "int"); + ci->variables << TypeInfo("bitCount", "int"); + ci->variables << TypeInfo("size", "int"); + ci->variables << TypeInfo("id", "int"); + ci->variables << TypeInfo("remote", "bool"); + ci->variables << TypeInfo("ptr", "void*", Const); + ci->variables << TypeInfo("rdata", "PIByteArray"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isEmpty"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "data"; fi->return_type = TypeInfo("", "const void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeData"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("ba", "PIByteArray &"); + + ci = new ClassInfo(); + (*classesInfo)["PIConsole::VariableContent"] = ci; + ci->name = "PIConsole::VariableContent"; + ci->variables << TypeInfo("id", "int"); + ci->variables << TypeInfo("rdata", "PIByteArray"); + + ci = new ClassInfo(); + (*classesInfo)["PIConsole::Column"] = ci; + ci->name = "PIConsole::Column"; + ci->variables << TypeInfo("variables", "PIVector"); + ci->variables << TypeInfo("alignment", "Alignment"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "size"; fi->return_type = TypeInfo("", "uint"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "push_back"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("v", "Variable &", Const); + + ci = new ClassInfo(); + (*classesInfo)["PIConsole::Tab"] = ci; + ci->name = "PIConsole::Tab"; + ci->variables << TypeInfo("columns", "PIVector"); + ci->variables << TypeInfo("name", "PIString"); + ci->variables << TypeInfo("status", "PIString"); + ci->variables << TypeInfo("key", "char"); + + ci = new ClassInfo(); + (*classesInfo)["PIConsole::RemoteClient"] = ci; + ci->name = "PIConsole::RemoteClient"; + ci->variables << TypeInfo("name", "PIString"); + ci->variables << TypeInfo("state", "ConnectedState"); + + ci = new ClassInfo(); + (*classesInfo)["PICLI"] = ci; + ci->name = "PICLI"; + ci->parents << "PIObject"; + ci->variables << TypeInfo("_prefix_short", "PIString"); + ci->variables << TypeInfo("_prefix_full", "PIString"); + ci->variables << TypeInfo("_args_raw", "PIStringList"); + ci->variables << TypeInfo("_args_mand", "PIStringList"); + ci->variables << TypeInfo("_args_opt", "PIStringList"); + ci->variables << TypeInfo("keys_full", "PISet"); + ci->variables << TypeInfo("keys_short", "PISet"); + ci->variables << TypeInfo("_args", "PIVector"); + ci->variables << TypeInfo("_count_mand", "int"); + ci->variables << TypeInfo("_count_opt", "int"); + ci->variables << TypeInfo("needParse", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "className"; fi->return_type = TypeInfo("", "const char *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addArgument"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("value", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addArgument"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("shortKey", "PIChar &", Const); + fi->arguments << TypeInfo("value", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addArgument"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("shortKey", "char *", Const); + fi->arguments << TypeInfo("value", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addArgument"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("shortKey", "PIChar &", Const); + fi->arguments << TypeInfo("fullKey", "PIString &", Const); + fi->arguments << TypeInfo("value", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addArgument"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("shortKey", "char *", Const); + fi->arguments << TypeInfo("fullKey", "PIString &", Const); + fi->arguments << TypeInfo("value", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "rawArgument"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("index", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "mandatoryArgument"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("index", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "optionalArgument"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("index", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "rawArguments"; fi->return_type = TypeInfo("", "const PIStringList &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "mandatoryArguments"; fi->return_type = TypeInfo("", "const PIStringList &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "optionalArguments"; fi->return_type = TypeInfo("", "const PIStringList &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "programCommand"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "hasArgument"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "argumentValue"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "argumentShortKey"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "argumentFullKey"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "shortKeyPrefix"; fi->return_type = TypeInfo("", "const PIString &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fullKeyPrefix"; fi->return_type = TypeInfo("", "const PIString &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "mandatoryArgumentsCount"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "optionalArgumentsCount"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setShortKeyPrefix"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("prefix", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setFullKeyPrefix"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("prefix", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setMandatoryArgumentsCount"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("count", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setOptionalArgumentsCount"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("count", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "parse"; fi->return_type = TypeInfo("", "void"); + + ci = new ClassInfo(); + (*classesInfo)["PICLI::Argument"] = ci; + ci->name = "PICLI::Argument"; + ci->variables << TypeInfo("name", "PIString"); + ci->variables << TypeInfo("short_key", "PIChar"); + ci->variables << TypeInfo("full_key", "PIString"); + ci->variables << TypeInfo("value", "PIString"); + ci->variables << TypeInfo("has_value", "bool"); + ci->variables << TypeInfo("found", "bool"); + + ci = new ClassInfo(); + (*classesInfo)["Instruction"] = ci; + ci->name = "Instruction"; + ci->variables << TypeInfo("operation", "Operation"); + ci->variables << TypeInfo("out", "int"); + ci->variables << TypeInfo("function", "int"); + + ci = new ClassInfo(); + (*classesInfo)["Function"] = ci; + ci->name = "Function"; + ci->variables << TypeInfo("identifier", "PIString"); + ci->variables << TypeInfo("type", "BaseFunctions"); + ci->variables << TypeInfo("handler", "FuncFunc"); + ci->variables << TypeInfo("arguments", "int"); + + ci = new ClassInfo(); + (*classesInfo)["PIEvaluatorContent"] = ci; + ci->name = "PIEvaluatorContent"; + ci->variables << TypeInfo("functions", "PIVector"); + ci->variables << TypeInfo("variables", "PIVector"); + ci->variables << TypeInfo("cv_count", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addFunction"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("args", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("val", "complexd &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addCustomFunction"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("args_count", "int"); + fi->arguments << TypeInfo("func", "FuncFunc"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "functionsCount"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "variablesCount"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "customVariablesCount"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "findFunction"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "findVariable"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("var_name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "function"; fi->return_type = TypeInfo("", "PIEvaluatorTypes::Function"); + fi->arguments << TypeInfo("index", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "variable"; fi->return_type = TypeInfo("", "PIEvaluatorTypes::Variable"); + fi->arguments << TypeInfo("index", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "function"; fi->return_type = TypeInfo("", "PIEvaluatorTypes::Function"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "variable"; fi->return_type = TypeInfo("", "PIEvaluatorTypes::Variable"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "customVariable"; fi->return_type = TypeInfo("", "PIEvaluatorTypes::Variable"); + fi->arguments << TypeInfo("index", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setVariableValue"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("index", "int"); + fi->arguments << TypeInfo("new_value", "complexd"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setVariableName"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("index", "int"); + fi->arguments << TypeInfo("new_name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setVariableValue"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("var_name", "PIString &", Const); + fi->arguments << TypeInfo("new_value", "complexd &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setVariableName"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("var_name", "PIString &", Const); + fi->arguments << TypeInfo("new_name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "removeVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("index", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "removeVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("var_name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "clearCustomVariables"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sortVariables"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getBaseFunction"; fi->return_type = TypeInfo("", "PIEvaluatorTypes::BaseFunctions"); + fi->arguments << TypeInfo("name", "PIString &", Const); + + ci = new ClassInfo(); + (*classesInfo)["PIEvaluator"] = ci; + ci->name = "PIEvaluator"; + ci->variables << TypeInfo("content", "PIEvaluatorContent"); + ci->variables << TypeInfo("elements", "PIVector"); + ci->variables << TypeInfo("currentVariables", "PIVector"); + ci->variables << TypeInfo("variables", "PIVector"); + ci->variables << TypeInfo("tmpvars", "PIVector"); + ci->variables << TypeInfo("kvars", "PIVector*"); + ci->variables << TypeInfo("instructions", "PIVector"); + ci->variables << TypeInfo("unknownVars", "PIStringList"); + ci->variables << TypeInfo("currentString", "PIString"); + ci->variables << TypeInfo("lastError", "PIString"); + ci->variables << TypeInfo("out", "complexd"); + ci->variables << TypeInfo("correct", "bool"); + ci->variables << TypeInfo("data_", "void*"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "data"; fi->return_type = TypeInfo("", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setData"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("_data", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "check"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("string", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isCorrect"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setVariable"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("value", "complexd"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("index", "int"); + fi->arguments << TypeInfo("value", "complexd"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setCustomVariableValue"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("index", "int"); + fi->arguments << TypeInfo("value", "complexd"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "evaluate"; fi->return_type = TypeInfo("", "complexd"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "removeVariable"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "clearCustomVariables"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "variableIndex"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "unknownVariables"; fi->return_type = TypeInfo("", "const PIStringList &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "expression"; fi->return_type = TypeInfo("", "const PIString &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "error"; fi->return_type = TypeInfo("", "const PIString &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "lastResult"; fi->return_type = TypeInfo("", "const complexd &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "prepare"; fi->return_type = TypeInfo("", "const PIString &"); + fi->arguments << TypeInfo("string", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "preprocess"; fi->return_type = TypeInfo("", "const PIString &"); + fi->arguments << TypeInfo("string", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "parse"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("string", "PIString &", Const); + fi->arguments << TypeInfo("offset", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "convert"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "checkBrackets"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "removeSpaces"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "findUnknownVariables"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "removeJunk"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "replaceOperators"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "makeOutput"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("string", "PIString &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fillElements"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setSignes"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isSign"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("ch", "PIChar &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "inverse"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("string", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "check"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "execInstructions"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "inBrackets"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("string", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "operationChar"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("operation", "PIEvaluatorTypes::Operation &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "operationInOrder"; fi->return_type = TypeInfo("", "PIEvaluatorTypes::Operation"); + fi->arguments << TypeInfo("index", "int &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "value"; fi->return_type = TypeInfo("", "complexd"); + fi->arguments << TypeInfo("index", "int &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "residue"; fi->return_type = TypeInfo("", "complexd"); + fi->arguments << TypeInfo("f", "complexd &", Const); + fi->arguments << TypeInfo("s", "complexd &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "execFunction"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("ci", "PIEvaluatorTypes::Instruction &", Const); + + ci = new ClassInfo(); + (*classesInfo)["PIMultiProtocol"] = ci; + ci->name = "PIMultiProtocol"; + ci->parents << "PIMultiProtocolBase"; + ci->variables << TypeInfo("prots", "PIVector"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addProtocol"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("prot", "PIProtocol &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addProtocol"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("prot", "PIProtocol *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addProtocol"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("config", "PIString &", Const); + fi->arguments << TypeInfo("name", "PIString &", Const); + fi->arguments << TypeInfo("recHeaderPtr", "void *"); + fi->arguments << TypeInfo("recHeaderSize", "int"); + fi->arguments << TypeInfo("recDataPtr", "void *"); + fi->arguments << TypeInfo("recDataSize", "int"); + fi->arguments << TypeInfo("sendDataPtr", "void *"); + fi->arguments << TypeInfo("sendDataSize", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "protocol"; fi->return_type = TypeInfo("", "PIProtocol *"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "protocol"; fi->return_type = TypeInfo("", "PIProtocol *"); + fi->arguments << TypeInfo("index", "int", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "startSend"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "startReceive"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "start"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "stopSend"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "stopReceive"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "stop"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "worseQuality"; fi->return_type = TypeInfo("", "PIProtocol::Quality"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "bestQuality"; fi->return_type = TypeInfo("", "PIProtocol::Quality"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "count"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "clear"; fi->return_type = TypeInfo("", "void"); + + ci = new ClassInfo(); + (*classesInfo)["PIRepeater"] = ci; + ci->name = "PIRepeater"; + ci->parents << "PIMultiProtocol"; + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "firstChannelName"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "secondChannelName"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiveCount"; fi->return_type = TypeInfo("", "ullong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "receiveCount_ptr"; fi->return_type = TypeInfo("", "const ullong *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendCount"; fi->return_type = TypeInfo("", "ullong"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendCount_ptr"; fi->return_type = TypeInfo("", "const ullong *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "received"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("prot", "PIProtocol *"); + fi->arguments << TypeInfo("ool", "b"); + fi->arguments << TypeInfo("data", "uchar *"); + fi->arguments << TypeInfo("size", "int"); + + ci = new ClassInfo(); + (*classesInfo)["PICodec"] = ci; + ci->name = "PICodec"; + ci->parents << "PIProcess"; + ci->variables << TypeInfo("c_from", "PIString"); + ci->variables << TypeInfo("c_to", "PIString"); + ci->variables << TypeInfo("tf", "PIFile"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setFromCoding"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("from", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setToCoding"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("to", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setCodings"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("from", "PIString &", Const); + fi->arguments << TypeInfo("to", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "availableCodecs"; fi->return_type = TypeInfo("", "PIStringList"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "encode"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("str", "PIString &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "encode"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("str", "PIByteArray &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "decode"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("str", "PIString &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "decode"; fi->return_type = TypeInfo("", "PIString"); + fi->arguments << TypeInfo("str", "PIByteArray &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "exec_iconv"; fi->return_type = TypeInfo("", "PIByteArray"); + fi->arguments << TypeInfo("from", "PIString &", Const); + fi->arguments << TypeInfo("to", "PIString &", Const); + fi->arguments << TypeInfo("str", "PIByteArray &", Const); + + ci = new ClassInfo(); + (*classesInfo)["PISignals"] = ci; + ci->name = "PISignals"; + ci->variables << TypeInfo("ret_func", "PISignals::SignalEvent", Static); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setSlot"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("slot", "SignalEvent"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "grabSignals"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("signals_", "PIFlags"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "raiseSignal"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("signal", "PISignals::Signal"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "signalCode"; fi->return_type = TypeInfo("", "int", Static); + fi->arguments << TypeInfo("signal", "PISignals::Signal"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "signalFromCode"; fi->return_type = TypeInfo("", "PISignals::Signal", Static); + fi->arguments << TypeInfo("signal", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "signal_event"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("signal", "int"); + + ci = new ClassInfo(); + (*classesInfo)["PIPeer"] = ci; + ci->name = "PIPeer"; + ci->parents << "PIObject"; + ci->variables << TypeInfo("eths", "PIVector"); + ci->variables << TypeInfo("mc_eths", "PIVector"); + ci->variables << TypeInfo("eth_send", "PIEthernet*"); + ci->variables << TypeInfo("timer", "PITimer"); + ci->variables << TypeInfo("mc_mutex", "PIMutex"); + ci->variables << TypeInfo("eth_mutex", "PIMutex"); + ci->variables << TypeInfo("rec_mc", "bool"); + ci->variables << TypeInfo("rec_bc", "bool"); + ci->variables << TypeInfo("self_info", "PIPeer::PeerInfo"); + ci->variables << TypeInfo("peers", "PIVector"); + ci->variables << TypeInfo("addresses_map", "PIMap >"); + ci->variables << TypeInfo("diag_s", "PIDiagnostics"); + ci->variables << TypeInfo("diag_d", "PIDiagnostics"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "className"; fi->return_type = TypeInfo("", "const char *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "send"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("to", "PIString &", Const); + fi->arguments << TypeInfo("data", "PIByteArray &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "send"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("to", "PIString &", Const); + fi->arguments << TypeInfo("data", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "send"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("to", "PIString &", Const); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "send"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("to", "PeerInfo &", Const); + fi->arguments << TypeInfo("data", "PIByteArray &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "send"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("to", "PeerInfo &", Const); + fi->arguments << TypeInfo("data", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "send"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("to", "PeerInfo &", Const); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "send"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("to", "PeerInfo *", Const); + fi->arguments << TypeInfo("data", "PIByteArray &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "send"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("to", "PeerInfo *", Const); + fi->arguments << TypeInfo("data", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "send"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("to", "PeerInfo *", Const); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendToAll"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("data", "PIByteArray &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendToAll"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("data", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendToAll"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isMulticastReceive"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isBroadcastReceive"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "diagnosticService"; fi->return_type = TypeInfo("", "PIDiagnostics &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "diagnosticData"; fi->return_type = TypeInfo("", "PIDiagnostics &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "allPeers"; fi->return_type = TypeInfo("", "const PIVector &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isPeerExists"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getPeerByName"; fi->return_type = TypeInfo("", "const PIPeer::PeerInfo *"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "lock"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "unlock"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_dataReceivedEvent__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("from", "PIString &", Const); + fi->arguments << TypeInfo("data", "PIByteArray &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "dataReceivedEvent"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("from", "PIString &", Const); + fi->arguments << TypeInfo("data", "PIByteArray &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_peerConnectedEvent__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "peerConnectedEvent"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_peerDisconnectedEvent__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "peerDisconnectedEvent"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "dataReceived"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("from", "PIString &", Const); + fi->arguments << TypeInfo("data", "PIByteArray &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "peerConnected"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "peerDisconnected"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_dataRead__"; fi->return_type = TypeInfo("", "bool", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("readed", "uchar *"); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "dataRead"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("readed", "uchar *"); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_multicastRead__"; fi->return_type = TypeInfo("", "bool", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("readed", "uchar *"); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "multicastRead"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("readed", "uchar *"); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_timerEvent__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + fi->arguments << TypeInfo("data", "void *"); + fi->arguments << TypeInfo("delim", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "timerEvent"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("data", "void *"); + fi->arguments << TypeInfo("delim", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "hasPeer"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "removePeer"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("name", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendPeerInfo"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("info", "PeerInfo &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendPeerRemove"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("peer", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendSelfInfo"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendSelfRemove"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "syncPeers"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "findNearestAddresses"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "initEths"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("al", "PIStringList &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "initMulticasts"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("al", "PIStringList &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "destroyMulticasts"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendMulticast"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("ba", "PIByteArray &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "quickestPeer"; fi->return_type = TypeInfo("", "PIPeer::PeerInfo *"); + fi->arguments << TypeInfo("to", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "sendToNeighbour"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("peer", "PeerInfo *"); + fi->arguments << TypeInfo("ba", "PIByteArray &", Const); + + ci = new ClassInfo(); + (*classesInfo)["PIPeer::PeerData"] = ci; + ci->name = "PIPeer::PeerData"; + ci->variables << TypeInfo("data", "PIByteArray"); + ci->variables << TypeInfo("msg_count", "int"); + ci->variables << TypeInfo("msg_rec", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "clear"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isEmpty"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isFullReceived"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addData"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("ba", "PIByteArray &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setData"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("ba", "PIByteArray &", Const); + + ci = new ClassInfo(); + (*classesInfo)["PIPeer::PeerInfo"] = ci; + ci->name = "PIPeer::PeerInfo"; + ci->variables << TypeInfo("name", "PIString"); + ci->variables << TypeInfo("addresses", "PIStringList"); + ci->variables << TypeInfo("dist", "int"); + ci->variables << TypeInfo("ping", "int"); + ci->variables << TypeInfo("nearest_address", "PIString"); + ci->variables << TypeInfo("netmasks", "PIStringList"); + ci->variables << TypeInfo("neighbours", "PIStringList"); + ci->variables << TypeInfo("sync", "int"); + ci->variables << TypeInfo("_naddress", "PIString"); + ci->variables << TypeInfo("_neth", "PIEthernet*"); + ci->variables << TypeInfo("_nuses", "PIVector"); + ci->variables << TypeInfo("_first", "PeerInfo*"); + ci->variables << TypeInfo("_data", "PeerData"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isNeighbour"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addNeighbour"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("n", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "addNeighbours"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("l", "PIStringList &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "removeNeighbour"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("n", "PIString &", Const); + + ci = new ClassInfo(); + (*classesInfo)["PIPeer::PeerPacket"] = ci; + ci->name = "PIPeer::PeerPacket"; + ci->variables << TypeInfo("header", "int"); + + ci = new ClassInfo(); + (*classesInfo)["PIBinaryLog"] = ci; + ci->name = "PIBinaryLog"; + ci->parents << "PIIODevice"; + ci->variables << TypeInfo("filterID", "PIVector"); + ci->variables << TypeInfo("file", "PIFile"); + ci->variables << TypeInfo("lastrecord", "PIBinaryLog::BinLogRecord"); + ci->variables << TypeInfo("startlogtime", "PISystemTime"); + ci->variables << TypeInfo("play_time", "double"); + ci->variables << TypeInfo("is_started", "bool"); + ci->variables << TypeInfo("is_thread_ok", "bool"); + ci->variables << TypeInfo("binlog_sig", "uchar[6]"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "className"; fi->return_type = TypeInfo("", "const char *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "copy"; fi->return_type = TypeInfo("", "PIIODevice *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "playMode"; fi->return_type = TypeInfo("", "PIBinaryLog::PlayMode"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "logDir"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "filePrefix"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "defaultID"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "playSpeed"; fi->return_type = TypeInfo("", "float"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "rapidStart"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setPlayMode"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("mode", "PlayMode"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setLogDir"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("path", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setFilePrefix"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("prefix", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setDefaultID"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("id", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setRapidStart"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("enabled", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setPlaySpeed"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("speed", "float"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeBinLog"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("id", "int"); + fi->arguments << TypeInfo("data", "PIByteArray"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeBinLog"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("id", "int"); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "readBinLog"; fi->return_type = TypeInfo("", "PIByteArray"); + fi->arguments << TypeInfo("id", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "readBinLog"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("id", "int"); + fi->arguments << TypeInfo("read_to", "void *"); + fi->arguments << TypeInfo("max_size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isEnd"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isEmpty"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "lastReadedID"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "read"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("read_to", "void *"); + fi->arguments << TypeInfo("max_size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "write"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "restart"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_createNewFile__"; fi->return_type = TypeInfo("", "PIString", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "createNewFile"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_fileEnd__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fileEnd"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "__stat_eh_fileError__"; fi->return_type = TypeInfo("", "void", Static); + fi->arguments << TypeInfo("o", "void *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fileError"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fullPathPrefix"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "configureFromFullPath"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("full_path", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "openDevice"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "closeDevice"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "threadedRead"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("readed", "uchar *"); + fi->arguments << TypeInfo("size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "writeFileHeader"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "checkFileHeader"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "readRecord"; fi->return_type = TypeInfo("", "PIBinaryLog::BinLogRecord"); + + ci = new ClassInfo(); + (*classesInfo)["PIBinaryLog::BinLogRecord"] = ci; + ci->name = "PIBinaryLog::BinLogRecord"; + ci->variables << TypeInfo("id", "int"); + ci->variables << TypeInfo("size", "int"); + ci->variables << TypeInfo("timestamp", "PISystemTime"); + ci->variables << TypeInfo("data", "PIByteArray"); + + ci = new ClassInfo(); + (*classesInfo)["PIUSB"] = ci; + ci->name = "PIUSB"; + ci->parents << "PIIODevice"; + ci->variables << TypeInfo("eps", "PIVector"); + ci->variables << TypeInfo("vid_", "ushort"); + ci->variables << TypeInfo("pid_", "ushort"); + ci->variables << TypeInfo("intefrace_", "int"); + ci->variables << TypeInfo("timeout_r", "int"); + ci->variables << TypeInfo("timeout_w", "int"); + ci->variables << TypeInfo("interface_claimed", "int"); + ci->variables << TypeInfo("ep_read", "PIUSB::Endpoint"); + ci->variables << TypeInfo("ep_write", "PIUSB::Endpoint"); + ci->variables << TypeInfo("desc_", "PIUSB::Descriptor"); + ci->variables << TypeInfo("conf_", "PIUSB::Configuration"); + ci->variables << TypeInfo("iface_", "PIUSB::Interface"); + ci->variables << TypeInfo("hdev", "usb_dev_handle*"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "className"; fi->return_type = TypeInfo("", "const char *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "copy"; fi->return_type = TypeInfo("", "PIIODevice *"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "currentDescriptor"; fi->return_type = TypeInfo("", "const PIUSB::Descriptor &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "currentConfiguration"; fi->return_type = TypeInfo("", "const PIUSB::Configuration &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "currentInterface"; fi->return_type = TypeInfo("", "const PIUSB::Interface &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "vendorID"; fi->return_type = TypeInfo("", "ushort"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "productID"; fi->return_type = TypeInfo("", "ushort"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "deviceNumber"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "timeoutRead"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "timeoutWrite"; fi->return_type = TypeInfo("", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "endpointRead"; fi->return_type = TypeInfo("", "const PIUSB::Endpoint &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "endpointWrite"; fi->return_type = TypeInfo("", "const PIUSB::Endpoint &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "endpoints"; fi->return_type = TypeInfo("", "const PIVector &"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "endpointsRead"; fi->return_type = TypeInfo("", "PIVector"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "endpointsWrite"; fi->return_type = TypeInfo("", "PIVector"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "getEndpointByAddress"; fi->return_type = TypeInfo("", "PIUSB::Endpoint"); + fi->arguments << TypeInfo("address", "uchar"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setVendorID"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("vid", "ushort"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setProductID"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("pid", "ushort"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setConfiguration"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("value", "uchar"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setInterface"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("value", "uchar"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setEndpointRead"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("ep", "PIUSB::Endpoint &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setEndpointWrite"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("ep", "PIUSB::Endpoint &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setDeviceNumber"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("dn", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setTimeoutRead"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("t", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "setTimeoutWrite"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("t", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "read"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("read_to", "void *"); + fi->arguments << TypeInfo("max_size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "write"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("max_size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "controlWrite"; fi->return_type = TypeInfo("", "int"); + fi->arguments << TypeInfo("data", "void *", Const); + fi->arguments << TypeInfo("max_size", "int"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "flush"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "fullPathPrefix"; fi->return_type = TypeInfo("", "PIString"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "configureFromFullPath"; fi->return_type = TypeInfo("", "void"); + fi->arguments << TypeInfo("full_path", "PIString &", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "configureDevice"; fi->return_type = TypeInfo("", "bool"); + fi->arguments << TypeInfo("e_main", "void *", Const); + fi->arguments << TypeInfo("e_parent", "void *", Const); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "openDevice"; fi->return_type = TypeInfo("", "bool"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "closeDevice"; fi->return_type = TypeInfo("", "bool"); + + ci = new ClassInfo(); + (*classesInfo)["PIUSB::Endpoint"] = ci; + ci->name = "PIUSB::Endpoint"; + ci->variables << TypeInfo("address", "uchar"); + ci->variables << TypeInfo("attributes", "uchar"); + ci->variables << TypeInfo("max_packet_size", "ushort"); + ci->variables << TypeInfo("direction", "PIUSB::Endpoint::Direction"); + ci->variables << TypeInfo("transfer_type", "PIUSB::Endpoint::TransferType"); + ci->variables << TypeInfo("synchronisation_type", "PIUSB::Endpoint::SynchronisationType"); + ci->variables << TypeInfo("usage_type", "PIUSB::Endpoint::UsageType"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "parse"; fi->return_type = TypeInfo("", "void"); + ci->functions.push_back(FunctionInfo()); fi = &(ci->functions.back()); + fi->name = "isNull"; fi->return_type = TypeInfo("", "bool"); + + ci = new ClassInfo(); + (*classesInfo)["PIUSB::Interface"] = ci; + ci->name = "PIUSB::Interface"; + ci->variables << TypeInfo("index", "uchar"); + ci->variables << TypeInfo("value_to_select", "uchar"); + ci->variables << TypeInfo("class_code", "ushort"); + ci->variables << TypeInfo("subclass_code", "ushort"); + ci->variables << TypeInfo("protocol_code", "ushort"); + ci->variables << TypeInfo("endpoints", "PIVector"); + + ci = new ClassInfo(); + (*classesInfo)["PIUSB::Configuration"] = ci; + ci->name = "PIUSB::Configuration"; + ci->variables << TypeInfo("index", "uchar"); + ci->variables << TypeInfo("value_to_select", "uchar"); + ci->variables << TypeInfo("attributes", "uchar"); + ci->variables << TypeInfo("max_power", "ushort"); + ci->variables << TypeInfo("self_powered", "bool"); + ci->variables << TypeInfo("remote_wakeup", "bool"); + ci->variables << TypeInfo("interfaces", "PIVector"); + + ci = new ClassInfo(); + (*classesInfo)["PIUSB::Descriptor"] = ci; + ci->name = "PIUSB::Descriptor"; + ci->variables << TypeInfo("usb_spec_number", "ushort"); + ci->variables << TypeInfo("device_class", "uchar"); + ci->variables << TypeInfo("device_subclass", "uchar"); + ci->variables << TypeInfo("device_protocol", "uchar"); + ci->variables << TypeInfo("max_packet_size", "uchar"); + ci->variables << TypeInfo("id_vendor", "ushort"); + ci->variables << TypeInfo("id_product", "ushort"); + ci->variables << TypeInfo("id_device_release", "ushort"); + ci->variables << TypeInfo("index_manufacturer", "uchar"); + ci->variables << TypeInfo("index_product", "uchar"); + ci->variables << TypeInfo("index_serial", "uchar"); + ci->variables << TypeInfo("configurations", "PIVector"); + +// Enums + + ei = new EnumInfo(); + (*enumsInfo)["PICoutSpecialChar"] = ei; + ei->name = "PICoutSpecialChar"; + ei->members << PICodeInfo::EnumeratorInfo("Null", 0); + ei->members << PICodeInfo::EnumeratorInfo("NewLine", 1); + ei->members << PICodeInfo::EnumeratorInfo("Tab", 2); + ei->members << PICodeInfo::EnumeratorInfo("Esc", 3); + ei->members << PICodeInfo::EnumeratorInfo("Quote", 4); + + ei = new EnumInfo(); + (*enumsInfo)["PICoutAction"] = ei; + ei->name = "PICoutAction"; + ei->members << PICodeInfo::EnumeratorInfo("Flush", 0); + ei->members << PICodeInfo::EnumeratorInfo("Backspace", 1); + ei->members << PICodeInfo::EnumeratorInfo("ShowCursor", 2); + ei->members << PICodeInfo::EnumeratorInfo("HideCursor", 3); + ei->members << PICodeInfo::EnumeratorInfo("ClearScreen", 4); + ei->members << PICodeInfo::EnumeratorInfo("SaveContol", 5); + ei->members << PICodeInfo::EnumeratorInfo("RestoreControl", 6); + + ei = new EnumInfo(); + (*enumsInfo)["PICoutControl"] = ei; + ei->name = "PICoutControl"; + ei->members << PICodeInfo::EnumeratorInfo("AddNone", 0); + ei->members << PICodeInfo::EnumeratorInfo("AddSpaces", 1); + ei->members << PICodeInfo::EnumeratorInfo("AddNewLine", 2); + ei->members << PICodeInfo::EnumeratorInfo("AddQuotes", 4); + ei->members << PICodeInfo::EnumeratorInfo("AddAll", -1); + + ei = new EnumInfo(); + (*enumsInfo)["PICoutFormat"] = ei; + ei->name = "PICoutFormat"; + ei->members << PICodeInfo::EnumeratorInfo("Bin", 1); + ei->members << PICodeInfo::EnumeratorInfo("Oct", 2); + ei->members << PICodeInfo::EnumeratorInfo("Dec", 4); + ei->members << PICodeInfo::EnumeratorInfo("Hex", 8); + ei->members << PICodeInfo::EnumeratorInfo("Bold", 16); + ei->members << PICodeInfo::EnumeratorInfo("Faint", 32); + ei->members << PICodeInfo::EnumeratorInfo("Italic", 64); + ei->members << PICodeInfo::EnumeratorInfo("Underline", 128); + ei->members << PICodeInfo::EnumeratorInfo("Blink", 256); + ei->members << PICodeInfo::EnumeratorInfo("Black", 1024); + ei->members << PICodeInfo::EnumeratorInfo("Red", 2048); + ei->members << PICodeInfo::EnumeratorInfo("Green", 4096); + ei->members << PICodeInfo::EnumeratorInfo("Blue", 8192); + ei->members << PICodeInfo::EnumeratorInfo("Yellow", 16384); + ei->members << PICodeInfo::EnumeratorInfo("Magenta", 32768); + ei->members << PICodeInfo::EnumeratorInfo("Cyan", 65536); + ei->members << PICodeInfo::EnumeratorInfo("White", 131072); + ei->members << PICodeInfo::EnumeratorInfo("BackBlack", 262144); + ei->members << PICodeInfo::EnumeratorInfo("BackRed", 524288); + ei->members << PICodeInfo::EnumeratorInfo("BackGreen", 1048576); + ei->members << PICodeInfo::EnumeratorInfo("BackBlue", 2097152); + ei->members << PICodeInfo::EnumeratorInfo("BackYellow", 4194304); + ei->members << PICodeInfo::EnumeratorInfo("BackMagenta", 8388608); + ei->members << PICodeInfo::EnumeratorInfo("BackCyan", 16777216); + ei->members << PICodeInfo::EnumeratorInfo("BackWhite", 33554432); + ei->members << PICodeInfo::EnumeratorInfo("Default", 67108864); + + ei = new EnumInfo(); + (*enumsInfo)["Solver::Method"] = ei; + ei->name = "Solver::Method"; + ei->members << PICodeInfo::EnumeratorInfo("Global", -1); + ei->members << PICodeInfo::EnumeratorInfo("Eyler_1", 1); + ei->members << PICodeInfo::EnumeratorInfo("Eyler_2", 2); + ei->members << PICodeInfo::EnumeratorInfo("EylerKoshi", 3); + ei->members << PICodeInfo::EnumeratorInfo("RungeKutta_4", 14); + ei->members << PICodeInfo::EnumeratorInfo("AdamsBashfortMoulton_2", 22); + ei->members << PICodeInfo::EnumeratorInfo("AdamsBashfortMoulton_3", 23); + ei->members << PICodeInfo::EnumeratorInfo("AdamsBashfortMoulton_4", 24); + ei->members << PICodeInfo::EnumeratorInfo("PolynomialApproximation_2", 32); + ei->members << PICodeInfo::EnumeratorInfo("PolynomialApproximation_3", 33); + ei->members << PICodeInfo::EnumeratorInfo("PolynomialApproximation_4", 34); + ei->members << PICodeInfo::EnumeratorInfo("PolynomialApproximation_5", 35); + + ei = new EnumInfo(); + (*enumsInfo)["PIVariant::Type"] = ei; + ei->name = "PIVariant::Type"; + ei->members << PICodeInfo::EnumeratorInfo("Invalid", 0); + ei->members << PICodeInfo::EnumeratorInfo("Bool", 1); + ei->members << PICodeInfo::EnumeratorInfo("Char", 2); + ei->members << PICodeInfo::EnumeratorInfo("UChar", 3); + ei->members << PICodeInfo::EnumeratorInfo("Short", 4); + ei->members << PICodeInfo::EnumeratorInfo("UShort", 5); + ei->members << PICodeInfo::EnumeratorInfo("Int", 6); + ei->members << PICodeInfo::EnumeratorInfo("UInt", 7); + ei->members << PICodeInfo::EnumeratorInfo("Long", 8); + ei->members << PICodeInfo::EnumeratorInfo("ULong", 9); + ei->members << PICodeInfo::EnumeratorInfo("LLong", 10); + ei->members << PICodeInfo::EnumeratorInfo("ULLong", 11); + ei->members << PICodeInfo::EnumeratorInfo("Float", 12); + ei->members << PICodeInfo::EnumeratorInfo("Double", 13); + ei->members << PICodeInfo::EnumeratorInfo("LDouble", 14); + ei->members << PICodeInfo::EnumeratorInfo("Complexd", 15); + ei->members << PICodeInfo::EnumeratorInfo("Complexld", 16); + ei->members << PICodeInfo::EnumeratorInfo("BitArray", 17); + ei->members << PICodeInfo::EnumeratorInfo("ByteArray", 18); + ei->members << PICodeInfo::EnumeratorInfo("String", 19); + ei->members << PICodeInfo::EnumeratorInfo("StringList", 20); + ei->members << PICodeInfo::EnumeratorInfo("Time", 21); + ei->members << PICodeInfo::EnumeratorInfo("Date", 22); + ei->members << PICodeInfo::EnumeratorInfo("DateTime", 23); + ei->members << PICodeInfo::EnumeratorInfo("SystemTime", 24); + ei->members << PICodeInfo::EnumeratorInfo("Custom", 255); + + ei = new EnumInfo(); + (*enumsInfo)["PIThread::Priority"] = ei; + ei->name = "PIThread::Priority"; + ei->members << PICodeInfo::EnumeratorInfo("piHighest", -2); + ei->members << PICodeInfo::EnumeratorInfo("piHigh", -1); + ei->members << PICodeInfo::EnumeratorInfo("piNormal", 0); + ei->members << PICodeInfo::EnumeratorInfo("piLow", 1); + ei->members << PICodeInfo::EnumeratorInfo("piLowerst", 2); + + ei = new EnumInfo(); + (*enumsInfo)["PIKbdListener::SpecialSymbol"] = ei; + ei->name = "PIKbdListener::SpecialSymbol"; + ei->members << PICodeInfo::EnumeratorInfo("UpArrow", -1); + ei->members << PICodeInfo::EnumeratorInfo("DownArrow", -2); + ei->members << PICodeInfo::EnumeratorInfo("RightArrow", -3); + ei->members << PICodeInfo::EnumeratorInfo("LeftArrow", -4); + ei->members << PICodeInfo::EnumeratorInfo("CtrlUpArrow", -5); + ei->members << PICodeInfo::EnumeratorInfo("CtrlDownArrow", -6); + ei->members << PICodeInfo::EnumeratorInfo("CtrlRightArrow", -7); + ei->members << PICodeInfo::EnumeratorInfo("CtrlLeftArrow", -8); + + ei = new EnumInfo(); + (*enumsInfo)["PIIODevice::DeviceMode"] = ei; + ei->name = "PIIODevice::DeviceMode"; + ei->members << PICodeInfo::EnumeratorInfo("ReadOnly", 1); + ei->members << PICodeInfo::EnumeratorInfo("WriteOnly", 2); + ei->members << PICodeInfo::EnumeratorInfo("ReadWrite", 3); + + ei = new EnumInfo(); + (*enumsInfo)["PISerial::Parameters"] = ei; + ei->name = "PISerial::Parameters"; + ei->members << PICodeInfo::EnumeratorInfo("ParityControl", 1); + ei->members << PICodeInfo::EnumeratorInfo("ParityOdd", 2); + ei->members << PICodeInfo::EnumeratorInfo("TwoStopBits", 4); + + ei = new EnumInfo(); + (*enumsInfo)["PISerial::Speed"] = ei; + ei->name = "PISerial::Speed"; + ei->members << PICodeInfo::EnumeratorInfo("S50", 50); + ei->members << PICodeInfo::EnumeratorInfo("S75", 75); + ei->members << PICodeInfo::EnumeratorInfo("S110", 110); + ei->members << PICodeInfo::EnumeratorInfo("S300", 300); + ei->members << PICodeInfo::EnumeratorInfo("S600", 600); + ei->members << PICodeInfo::EnumeratorInfo("S1200", 1200); + ei->members << PICodeInfo::EnumeratorInfo("S2400", 2400); + ei->members << PICodeInfo::EnumeratorInfo("S4800", 4800); + ei->members << PICodeInfo::EnumeratorInfo("S9600", 9600); + ei->members << PICodeInfo::EnumeratorInfo("S19200", 19200); + ei->members << PICodeInfo::EnumeratorInfo("S38400", 38400); + ei->members << PICodeInfo::EnumeratorInfo("S57600", 57600); + ei->members << PICodeInfo::EnumeratorInfo("S115200", 115200); + ei->members << PICodeInfo::EnumeratorInfo("S1500000", 1500000); + ei->members << PICodeInfo::EnumeratorInfo("S2000000", 2000000); + ei->members << PICodeInfo::EnumeratorInfo("S2500000", 2500000); + ei->members << PICodeInfo::EnumeratorInfo("S3000000", 3000000); + ei->members << PICodeInfo::EnumeratorInfo("S3500000", 3500000); + ei->members << PICodeInfo::EnumeratorInfo("S4000000", 4000000); + + ei = new EnumInfo(); + (*enumsInfo)["PIEthernet::Type"] = ei; + ei->name = "PIEthernet::Type"; + ei->members << PICodeInfo::EnumeratorInfo("UDP", 0); + ei->members << PICodeInfo::EnumeratorInfo("TCP_Client", 1); + ei->members << PICodeInfo::EnumeratorInfo("TCP_Server", 2); + ei->members << PICodeInfo::EnumeratorInfo("TCP_SingleTCP", 3); + + ei = new EnumInfo(); + (*enumsInfo)["PIEthernet::Parameters"] = ei; + ei->name = "PIEthernet::Parameters"; + ei->members << PICodeInfo::EnumeratorInfo("ReuseAddress", 1); + ei->members << PICodeInfo::EnumeratorInfo("Broadcast", 2); + + ei = new EnumInfo(); + (*enumsInfo)["PIEthernet::InterfaceFlag"] = ei; + ei->name = "PIEthernet::InterfaceFlag"; + ei->members << PICodeInfo::EnumeratorInfo("ifActive", 1); + ei->members << PICodeInfo::EnumeratorInfo("ifRunning", 2); + ei->members << PICodeInfo::EnumeratorInfo("ifBroadcast", 4); + ei->members << PICodeInfo::EnumeratorInfo("ifMulticast", 8); + ei->members << PICodeInfo::EnumeratorInfo("ifLoopback", 16); + ei->members << PICodeInfo::EnumeratorInfo("ifPTP", 32); + + ei = new EnumInfo(); + (*enumsInfo)["PIProtocol::Type"] = ei; + ei->name = "PIProtocol::Type"; + ei->members << PICodeInfo::EnumeratorInfo("None", 0); + ei->members << PICodeInfo::EnumeratorInfo("Serial", 1); + ei->members << PICodeInfo::EnumeratorInfo("Ethernet", 2); + + ei = new EnumInfo(); + (*enumsInfo)["PIProtocol::Quality"] = ei; + ei->name = "PIProtocol::Quality"; + ei->members << PICodeInfo::EnumeratorInfo("Unknown", 1); + ei->members << PICodeInfo::EnumeratorInfo("Failure", 2); + ei->members << PICodeInfo::EnumeratorInfo("Bad", 3); + ei->members << PICodeInfo::EnumeratorInfo("Average", 4); + ei->members << PICodeInfo::EnumeratorInfo("Good", 5); + + ei = new EnumInfo(); + (*enumsInfo)["PIDiagnostics::Quality"] = ei; + ei->name = "PIDiagnostics::Quality"; + ei->members << PICodeInfo::EnumeratorInfo("Unknown", 1); + ei->members << PICodeInfo::EnumeratorInfo("Failure", 2); + ei->members << PICodeInfo::EnumeratorInfo("Bad", 3); + ei->members << PICodeInfo::EnumeratorInfo("Average", 4); + ei->members << PICodeInfo::EnumeratorInfo("Good", 5); + + ei = new EnumInfo(); + (*enumsInfo)["PIConsole::Format"] = ei; + ei->name = "PIConsole::Format"; + ei->members << PICodeInfo::EnumeratorInfo("Normal", 1); + ei->members << PICodeInfo::EnumeratorInfo("Bold", 2); + ei->members << PICodeInfo::EnumeratorInfo("Faint", 4); + ei->members << PICodeInfo::EnumeratorInfo("Italic", 8); + ei->members << PICodeInfo::EnumeratorInfo("Underline", 16); + ei->members << PICodeInfo::EnumeratorInfo("Blink", 32); + ei->members << PICodeInfo::EnumeratorInfo("Inverse", 64); + ei->members << PICodeInfo::EnumeratorInfo("Black", 256); + ei->members << PICodeInfo::EnumeratorInfo("Red", 512); + ei->members << PICodeInfo::EnumeratorInfo("Green", 1024); + ei->members << PICodeInfo::EnumeratorInfo("Yellow", 2048); + ei->members << PICodeInfo::EnumeratorInfo("Blue", 4096); + ei->members << PICodeInfo::EnumeratorInfo("Magenta", 8192); + ei->members << PICodeInfo::EnumeratorInfo("Cyan", 16384); + ei->members << PICodeInfo::EnumeratorInfo("White", 32768); + ei->members << PICodeInfo::EnumeratorInfo("BackBlack", 65536); + ei->members << PICodeInfo::EnumeratorInfo("BackRed", 131072); + ei->members << PICodeInfo::EnumeratorInfo("BackGreen", 262144); + ei->members << PICodeInfo::EnumeratorInfo("BackYellow", 524288); + ei->members << PICodeInfo::EnumeratorInfo("BackBlue", 1048576); + ei->members << PICodeInfo::EnumeratorInfo("BackMagenta", 2097152); + ei->members << PICodeInfo::EnumeratorInfo("BackCyan", 4194304); + ei->members << PICodeInfo::EnumeratorInfo("BackWhite", 8388608); + ei->members << PICodeInfo::EnumeratorInfo("Dec", 16777216); + ei->members << PICodeInfo::EnumeratorInfo("Hex", 33554432); + ei->members << PICodeInfo::EnumeratorInfo("Oct", 67108864); + ei->members << PICodeInfo::EnumeratorInfo("Bin", 134217728); + ei->members << PICodeInfo::EnumeratorInfo("Scientific", 268435456); + ei->members << PICodeInfo::EnumeratorInfo("SystemTimeSplit", 536870912); + ei->members << PICodeInfo::EnumeratorInfo("SystemTimeSeconds", 1073741824); + + ei = new EnumInfo(); + (*enumsInfo)["PIConsole::Alignment"] = ei; + ei->name = "PIConsole::Alignment"; + ei->members << PICodeInfo::EnumeratorInfo("Nothing", 0); + ei->members << PICodeInfo::EnumeratorInfo("Left", 1); + ei->members << PICodeInfo::EnumeratorInfo("Right", 2); + + ei = new EnumInfo(); + (*enumsInfo)["PIConsole::ConnectedState"] = ei; + ei->name = "PIConsole::ConnectedState"; + ei->members << PICodeInfo::EnumeratorInfo("Disconnected", 0); + ei->members << PICodeInfo::EnumeratorInfo("FetchingData", 1); + ei->members << PICodeInfo::EnumeratorInfo("Committing", 2); + ei->members << PICodeInfo::EnumeratorInfo("Connected", 3); + + ei = new EnumInfo(); + (*enumsInfo)["eType"] = ei; + ei->name = "eType"; + ei->members << PICodeInfo::EnumeratorInfo("etNumber", 0); + ei->members << PICodeInfo::EnumeratorInfo("etOperator", 1); + ei->members << PICodeInfo::EnumeratorInfo("etVariable", 2); + ei->members << PICodeInfo::EnumeratorInfo("etFunction", 3); + + ei = new EnumInfo(); + (*enumsInfo)["Operation"] = ei; + ei->name = "Operation"; + ei->members << PICodeInfo::EnumeratorInfo("oNone", 0); + ei->members << PICodeInfo::EnumeratorInfo("oAdd", 1); + ei->members << PICodeInfo::EnumeratorInfo("oSubtract", 2); + ei->members << PICodeInfo::EnumeratorInfo("oMultiply", 3); + ei->members << PICodeInfo::EnumeratorInfo("oDivide", 4); + ei->members << PICodeInfo::EnumeratorInfo("oResidue", 5); + ei->members << PICodeInfo::EnumeratorInfo("oPower", 6); + ei->members << PICodeInfo::EnumeratorInfo("oEqual", 7); + ei->members << PICodeInfo::EnumeratorInfo("oNotEqual", 8); + ei->members << PICodeInfo::EnumeratorInfo("oGreater", 9); + ei->members << PICodeInfo::EnumeratorInfo("oSmaller", 10); + ei->members << PICodeInfo::EnumeratorInfo("oGreaterEqual", 11); + ei->members << PICodeInfo::EnumeratorInfo("oSmallerEqual", 12); + ei->members << PICodeInfo::EnumeratorInfo("oAnd", 13); + ei->members << PICodeInfo::EnumeratorInfo("oOr", 14); + ei->members << PICodeInfo::EnumeratorInfo("oFunction", 15); + + ei = new EnumInfo(); + (*enumsInfo)["BaseFunctions"] = ei; + ei->name = "BaseFunctions"; + ei->members << PICodeInfo::EnumeratorInfo("bfUnknown", 0); + ei->members << PICodeInfo::EnumeratorInfo("bfSin", 1); + ei->members << PICodeInfo::EnumeratorInfo("bfCos", 2); + ei->members << PICodeInfo::EnumeratorInfo("bfTg", 3); + ei->members << PICodeInfo::EnumeratorInfo("bfCtg", 4); + ei->members << PICodeInfo::EnumeratorInfo("bfArcsin", 5); + ei->members << PICodeInfo::EnumeratorInfo("bfArccos", 6); + ei->members << PICodeInfo::EnumeratorInfo("bfArctg", 7); + ei->members << PICodeInfo::EnumeratorInfo("bfArcctg", 8); + ei->members << PICodeInfo::EnumeratorInfo("bfExp", 9); + ei->members << PICodeInfo::EnumeratorInfo("bfRandom", 10); + ei->members << PICodeInfo::EnumeratorInfo("bfSh", 11); + ei->members << PICodeInfo::EnumeratorInfo("bfCh", 12); + ei->members << PICodeInfo::EnumeratorInfo("bfTh", 13); + ei->members << PICodeInfo::EnumeratorInfo("bfCth", 14); + ei->members << PICodeInfo::EnumeratorInfo("bfSqrt", 15); + ei->members << PICodeInfo::EnumeratorInfo("bfSqr", 16); + ei->members << PICodeInfo::EnumeratorInfo("bfPow", 17); + ei->members << PICodeInfo::EnumeratorInfo("bfAbs", 18); + ei->members << PICodeInfo::EnumeratorInfo("bfLn", 19); + ei->members << PICodeInfo::EnumeratorInfo("bfLg", 20); + ei->members << PICodeInfo::EnumeratorInfo("bfLog", 21); + ei->members << PICodeInfo::EnumeratorInfo("bfSign", 22); + ei->members << PICodeInfo::EnumeratorInfo("bfIm", 23); + ei->members << PICodeInfo::EnumeratorInfo("bfRe", 24); + ei->members << PICodeInfo::EnumeratorInfo("bfArg", 25); + ei->members << PICodeInfo::EnumeratorInfo("bfLen", 26); + ei->members << PICodeInfo::EnumeratorInfo("bfConj", 27); + ei->members << PICodeInfo::EnumeratorInfo("bfRad", 28); + ei->members << PICodeInfo::EnumeratorInfo("bfDeg", 29); + ei->members << PICodeInfo::EnumeratorInfo("bfJ0", 30); + ei->members << PICodeInfo::EnumeratorInfo("bfJ1", 31); + ei->members << PICodeInfo::EnumeratorInfo("bfJN", 32); + ei->members << PICodeInfo::EnumeratorInfo("bfY0", 33); + ei->members << PICodeInfo::EnumeratorInfo("bfY1", 34); + ei->members << PICodeInfo::EnumeratorInfo("bfYN", 35); + ei->members << PICodeInfo::EnumeratorInfo("bfMin", 36); + ei->members << PICodeInfo::EnumeratorInfo("bfMax", 37); + ei->members << PICodeInfo::EnumeratorInfo("bfClamp", 38); + ei->members << PICodeInfo::EnumeratorInfo("bfStep", 39); + ei->members << PICodeInfo::EnumeratorInfo("bfMix", 40); + ei->members << PICodeInfo::EnumeratorInfo("bfDefined", 41); + ei->members << PICodeInfo::EnumeratorInfo("bfCustom", 65535); + + ei = new EnumInfo(); + (*enumsInfo)["PISignals::Signal"] = ei; + ei->name = "PISignals::Signal"; + ei->members << PICodeInfo::EnumeratorInfo("Interrupt", 1); + ei->members << PICodeInfo::EnumeratorInfo("Illegal", 2); + ei->members << PICodeInfo::EnumeratorInfo("Abort", 4); + ei->members << PICodeInfo::EnumeratorInfo("FPE", 8); + ei->members << PICodeInfo::EnumeratorInfo("SegFault", 16); + ei->members << PICodeInfo::EnumeratorInfo("Termination", 32); + ei->members << PICodeInfo::EnumeratorInfo("Hangup", 64); + ei->members << PICodeInfo::EnumeratorInfo("Quit", 128); + ei->members << PICodeInfo::EnumeratorInfo("Kill", 256); + ei->members << PICodeInfo::EnumeratorInfo("BrokenPipe", 512); + ei->members << PICodeInfo::EnumeratorInfo("Timer", 1024); + ei->members << PICodeInfo::EnumeratorInfo("UserDefined1", 2048); + ei->members << PICodeInfo::EnumeratorInfo("UserDefined2", 4096); + ei->members << PICodeInfo::EnumeratorInfo("ChildStopped", 8192); + ei->members << PICodeInfo::EnumeratorInfo("Continue", 16384); + ei->members << PICodeInfo::EnumeratorInfo("StopProcess", 32768); + ei->members << PICodeInfo::EnumeratorInfo("StopTTY", 65536); + ei->members << PICodeInfo::EnumeratorInfo("StopTTYInput", 131072); + ei->members << PICodeInfo::EnumeratorInfo("StopTTYOutput", 262144); + ei->members << PICodeInfo::EnumeratorInfo("All", 1048575); + + ei = new EnumInfo(); + (*enumsInfo)["PIBinaryLog::PlayMode"] = ei; + ei->name = "PIBinaryLog::PlayMode"; + ei->members << PICodeInfo::EnumeratorInfo("PlayRealTime", 0); + ei->members << PICodeInfo::EnumeratorInfo("PlayVariableSpeed", 1); + + ei = new EnumInfo(); + (*enumsInfo)["PIUSB::Endpoint::Direction"] = ei; + ei->name = "PIUSB::Endpoint::Direction"; + ei->members << PICodeInfo::EnumeratorInfo("Write", 0); + ei->members << PICodeInfo::EnumeratorInfo("Read", 1); + + ei = new EnumInfo(); + (*enumsInfo)["PIUSB::Endpoint::TransferType"] = ei; + ei->name = "PIUSB::Endpoint::TransferType"; + ei->members << PICodeInfo::EnumeratorInfo("Control", 0); + ei->members << PICodeInfo::EnumeratorInfo("Isochronous", 1); + ei->members << PICodeInfo::EnumeratorInfo("Bulk", 2); + ei->members << PICodeInfo::EnumeratorInfo("Interrupt", 3); + + ei = new EnumInfo(); + (*enumsInfo)["PIUSB::Endpoint::SynchronisationType"] = ei; + ei->name = "PIUSB::Endpoint::SynchronisationType"; + ei->members << PICodeInfo::EnumeratorInfo("NoSynchonisation", 0); + ei->members << PICodeInfo::EnumeratorInfo("Asynchronous", 2); + ei->members << PICodeInfo::EnumeratorInfo("Adaptive", 1); + ei->members << PICodeInfo::EnumeratorInfo("Synchronous", 3); + + ei = new EnumInfo(); + (*enumsInfo)["PIUSB::Endpoint::UsageType"] = ei; + ei->name = "PIUSB::Endpoint::UsageType"; + ei->members << PICodeInfo::EnumeratorInfo("DataEndpoint", 0); + ei->members << PICodeInfo::EnumeratorInfo("FeedbackEndpoint", 2); + ei->members << PICodeInfo::EnumeratorInfo("ExplicitFeedbackDataEndpoint", 1); +} + + +bool __ClassInfo_TEST_H_Initializer__::_inited_ = false; diff --git a/utils/code_model_generator/test.h b/utils/code_model_generator/test.h new file mode 100755 index 00000000..6f7e77a3 --- /dev/null +++ b/utils/code_model_generator/test.h @@ -0,0 +1,100 @@ +// Generated by "PIP Code model generator" 29.04.2014 18:03:05 + +#ifndef TEST_H +#define TEST_H + +#include "pivariant.h" +#include "picodeinfo.h" + +class PIMutex; +class PIBitArray; +class PIHuffman; +class PIByteArray; +class PIChar; +class PIString; +class PIStringList; +class PISystemTime; +struct PITime; +struct PIDate; +struct PIDateTime; +class Solver; +class PIFFT; +class PIVariant; +class PIObject; +class PIThread; +class PITimer; +class PIKbdListener; +class PIIODevice; +class PISerial; +class PIFile; +class PIProcess; +class PIEthernet; +class PIPacketExtractor; +class PIConfig; +class PIMultiProtocolBase; +class PIProtocol; +class PIDiagnostics; +class PISystemMonitor; +class PIConsole; +class PICLI; +class PIEvaluatorContent; +class PIEvaluator; +class PIMultiProtocol; +class PIRepeater; +class PICodec; +class PIPeer; +class PIBinaryLog; +class PIUSB; + + +PIVariant execFunction(PIMutex * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIBitArray * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIHuffman * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIByteArray * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIChar * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIString * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIStringList * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PISystemTime * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PITime * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIDate * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIDateTime * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(Solver * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIFFT * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIVariant * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIObject * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIThread * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PITimer * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIKbdListener * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIIODevice * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PISerial * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIFile * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIProcess * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIEthernet * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIPacketExtractor * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIConfig * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIMultiProtocolBase * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIProtocol * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIDiagnostics * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PISystemMonitor * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIConsole * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PICLI * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIEvaluatorContent * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIEvaluator * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIMultiProtocol * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIRepeater * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PICodec * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIPeer * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIBinaryLog * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); +PIVariant execFunction(PIUSB * object, const char * function, const PIVariant & arg0 = PIVariant(), const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant()); + + +class __ClassInfo_TEST_H_Initializer__ { +public: + __ClassInfo_TEST_H_Initializer__(); + static bool _inited_; +}; + +static __ClassInfo_TEST_H_Initializer__ __classinfo_test_h_initializer__; + + +#endif // TEST_H diff --git a/utils/remote_console/CMakeLists.txt b/utils/remote_console/CMakeLists.txt new file mode 100755 index 00000000..39955038 --- /dev/null +++ b/utils/remote_console/CMakeLists.txt @@ -0,0 +1,5 @@ +add_executable(pip_remote_console "main.cpp") +target_link_libraries(pip_remote_console pip) +if (DEFINED LIB) + install(TARGETS pip_remote_console DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +endif () diff --git a/utils/remote_console/Makefile b/utils/remote_console/Makefile new file mode 100644 index 00000000..4b9c885f --- /dev/null +++ b/utils/remote_console/Makefile @@ -0,0 +1,209 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 2.8 + +# Default target executed when no arguments are given to make. +default_target: all +.PHONY : default_target + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/andrey/linux_build/libs + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/andrey/linux_build/libs + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running interactive CMake command-line interface..." + /usr/bin/cmake -i . +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache +.PHONY : edit_cache/fast + +# Special rule for the target install +install: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." + /usr/bin/cmake -P cmake_install.cmake +.PHONY : install + +# Special rule for the target install +install/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." + /usr/bin/cmake -P cmake_install.cmake +.PHONY : install/fast + +# Special rule for the target install/local +install/local: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." + /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake +.PHONY : install/local + +# Special rule for the target install/local +install/local/fast: install/local +.PHONY : install/local/fast + +# Special rule for the target install/strip +install/strip: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..." + /usr/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake +.PHONY : install/strip + +# Special rule for the target install/strip +install/strip/fast: install/strip +.PHONY : install/strip/fast + +# Special rule for the target list_install_components +list_install_components: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\"" +.PHONY : list_install_components + +# Special rule for the target list_install_components +list_install_components/fast: list_install_components +.PHONY : list_install_components/fast + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." + /usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache +.PHONY : rebuild_cache/fast + +# The main all target +all: cmake_check_build_system + cd /home/andrey/linux_build/libs && $(CMAKE_COMMAND) -E cmake_progress_start /home/andrey/linux_build/libs/CMakeFiles /home/andrey/linux_build/libs/pip/utils/remote_console/CMakeFiles/progress.marks + cd /home/andrey/linux_build/libs && $(MAKE) -f CMakeFiles/Makefile2 pip/utils/remote_console/all + $(CMAKE_COMMAND) -E cmake_progress_start /home/andrey/linux_build/libs/CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + cd /home/andrey/linux_build/libs && $(MAKE) -f CMakeFiles/Makefile2 pip/utils/remote_console/clean +.PHONY : clean + +# The main clean target +clean/fast: clean +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + cd /home/andrey/linux_build/libs && $(MAKE) -f CMakeFiles/Makefile2 pip/utils/remote_console/preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + cd /home/andrey/linux_build/libs && $(MAKE) -f CMakeFiles/Makefile2 pip/utils/remote_console/preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + cd /home/andrey/linux_build/libs && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +# Convenience name for target. +pip/utils/remote_console/CMakeFiles/pip_remote_console.dir/rule: + cd /home/andrey/linux_build/libs && $(MAKE) -f CMakeFiles/Makefile2 pip/utils/remote_console/CMakeFiles/pip_remote_console.dir/rule +.PHONY : pip/utils/remote_console/CMakeFiles/pip_remote_console.dir/rule + +# Convenience name for target. +pip_remote_console: pip/utils/remote_console/CMakeFiles/pip_remote_console.dir/rule +.PHONY : pip_remote_console + +# fast build rule for target. +pip_remote_console/fast: + cd /home/andrey/linux_build/libs && $(MAKE) -f pip/utils/remote_console/CMakeFiles/pip_remote_console.dir/build.make pip/utils/remote_console/CMakeFiles/pip_remote_console.dir/build +.PHONY : pip_remote_console/fast + +main.o: main.cpp.o +.PHONY : main.o + +# target to build an object file +main.cpp.o: + cd /home/andrey/linux_build/libs && $(MAKE) -f pip/utils/remote_console/CMakeFiles/pip_remote_console.dir/build.make pip/utils/remote_console/CMakeFiles/pip_remote_console.dir/main.cpp.o +.PHONY : main.cpp.o + +main.i: main.cpp.i +.PHONY : main.i + +# target to preprocess a source file +main.cpp.i: + cd /home/andrey/linux_build/libs && $(MAKE) -f pip/utils/remote_console/CMakeFiles/pip_remote_console.dir/build.make pip/utils/remote_console/CMakeFiles/pip_remote_console.dir/main.cpp.i +.PHONY : main.cpp.i + +main.s: main.cpp.s +.PHONY : main.s + +# target to generate assembly for a file +main.cpp.s: + cd /home/andrey/linux_build/libs && $(MAKE) -f pip/utils/remote_console/CMakeFiles/pip_remote_console.dir/build.make pip/utils/remote_console/CMakeFiles/pip_remote_console.dir/main.cpp.s +.PHONY : main.cpp.s + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... edit_cache" + @echo "... install" + @echo "... install/local" + @echo "... install/strip" + @echo "... list_install_components" + @echo "... pip_remote_console" + @echo "... rebuild_cache" + @echo "... main.o" + @echo "... main.i" + @echo "... main.s" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + cd /home/andrey/linux_build/libs && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/utils/remote_console/cmake_install.cmake b/utils/remote_console/cmake_install.cmake new file mode 100644 index 00000000..f5bff204 --- /dev/null +++ b/utils/remote_console/cmake_install.cmake @@ -0,0 +1,60 @@ +# Install script for directory: /home/andrey/linux_build/libs/pip/utils/remote_console + +# Set the install prefix +IF(NOT DEFINED CMAKE_INSTALL_PREFIX) + SET(CMAKE_INSTALL_PREFIX "/usr") +ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) +STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + IF(BUILD_TYPE) + STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + ELSE(BUILD_TYPE) + SET(CMAKE_INSTALL_CONFIG_NAME "Release") + ENDIF(BUILD_TYPE) + MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + +# Set the component getting installed. +IF(NOT CMAKE_INSTALL_COMPONENT) + IF(COMPONENT) + MESSAGE(STATUS "Install component: \"${COMPONENT}\"") + SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + ELSE(COMPONENT) + SET(CMAKE_INSTALL_COMPONENT) + ENDIF(COMPONENT) +ENDIF(NOT CMAKE_INSTALL_COMPONENT) + +# Install shared libraries without execute permission? +IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + SET(CMAKE_INSTALL_SO_NO_EXE "1") +ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + +IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") + IF(EXISTS "$ENV{DESTDIR}/usr/bin/pip_remote_console" AND + NOT IS_SYMLINK "$ENV{DESTDIR}/usr/bin/pip_remote_console") + FILE(RPATH_CHECK + FILE "$ENV{DESTDIR}/usr/bin/pip_remote_console" + RPATH "") + ENDIF() + list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES + "/usr/bin/pip_remote_console") + IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) + message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) + IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) + message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) +FILE(INSTALL DESTINATION "/usr/bin" TYPE EXECUTABLE FILES "/home/andrey/linux_build/libs/pip/utils/remote_console/pip_remote_console") + IF(EXISTS "$ENV{DESTDIR}/usr/bin/pip_remote_console" AND + NOT IS_SYMLINK "$ENV{DESTDIR}/usr/bin/pip_remote_console") + FILE(RPATH_REMOVE + FILE "$ENV{DESTDIR}/usr/bin/pip_remote_console") + IF(CMAKE_INSTALL_DO_STRIP) + EXECUTE_PROCESS(COMMAND "/usr/bin/strip" "$ENV{DESTDIR}/usr/bin/pip_remote_console") + ENDIF(CMAKE_INSTALL_DO_STRIP) + ENDIF() +ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") + diff --git a/utils/remote_console/main.cpp b/utils/remote_console/main.cpp new file mode 100755 index 00000000..db43c449 --- /dev/null +++ b/utils/remote_console/main.cpp @@ -0,0 +1,64 @@ +/* + PIP - Platform Independent Primitives + Remote console viewer + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pip.h" + +void key_event(char key, void * ); + +PIConsole console(false, key_event); +PIStringList as; +bool selected = false; + +void key_event(char key, void * ) { + if (key < '1' || key > '9') return; + int ind = key - '1'; + if (ind < 0 || ind >= as.size_s()) return; + selected = true; + console.connectToServer(as[ind]); +} + +int main(int argc, char * argv[]) { + console.enableExitCapture(); + console.listenServers(); + while (!PIKbdListener::exiting) { + msleep(200); + if (selected) break; + console.clearScreen(); + as = console.availableServers(); + if (as.isEmpty()) { + piCout << "No servers are available!"; + } else { + piCout << "Select one with numeric key:"; + for (int i = 0; i < as.size_s(); ++i) + piCout << (i + 1) << as[i]; + } + } + if (!selected) return 0; + //console.clearScreen(); + piCout << "Connecting to" << console.selectedServer() << "..."; + while (!PIKbdListener::exiting) { + msleep(20); + if (console.isConnected()) + break; + } + if (PIKbdListener::exiting) + return 0; + console.start(); + console.waitForFinish(); +}; diff --git a/utils/remote_console/pip_remote_console b/utils/remote_console/pip_remote_console new file mode 100755 index 00000000..ec478061 Binary files /dev/null and b/utils/remote_console/pip_remote_console differ diff --git a/utils/remote_console/pip_remote_console.exe b/utils/remote_console/pip_remote_console.exe new file mode 100644 index 00000000..3a9eb63e Binary files /dev/null and b/utils/remote_console/pip_remote_console.exe differ diff --git a/utils/system_daemon/CMakeLists.txt b/utils/system_daemon/CMakeLists.txt new file mode 100755 index 00000000..c0a4eeb2 --- /dev/null +++ b/utils/system_daemon/CMakeLists.txt @@ -0,0 +1,7 @@ +file(GLOB CPPS "*.cpp") +file(GLOB HDRS "*.h") +add_executable(pisd ${CPPS} ${HDRS}) +target_link_libraries(pisd pip) +if (DEFINED LIB) + install(TARGETS pisd DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +endif () diff --git a/utils/system_daemon/Makefile b/utils/system_daemon/Makefile new file mode 100644 index 00000000..077fe6ff --- /dev/null +++ b/utils/system_daemon/Makefile @@ -0,0 +1,265 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "MinGW Makefiles" Generator, CMake Version 2.8 + +# Default target executed when no arguments are given to make. +default_target: all +.PHONY : default_target + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +SHELL = cmd.exe + +# The CMake executable. +CMAKE_COMMAND = "C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" + +# The command to remove a file. +RM = "C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The program to use to edit the cache. +CMAKE_EDIT_COMMAND = "C:\Program Files (x86)\CMake 2.8\bin\cmake-gui.exe" + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = C:\libs + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = C:\libs + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." + "C:\Program Files (x86)\CMake 2.8\bin\cmake-gui.exe" -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache +.PHONY : edit_cache/fast + +# Special rule for the target install +install: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." + "C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -P cmake_install.cmake +.PHONY : install + +# Special rule for the target install +install/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." + "C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -P cmake_install.cmake +.PHONY : install/fast + +# Special rule for the target install/local +install/local: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." + "C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake +.PHONY : install/local + +# Special rule for the target install/local +install/local/fast: install/local +.PHONY : install/local/fast + +# Special rule for the target install/strip +install/strip: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..." + "C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake +.PHONY : install/strip + +# Special rule for the target install/strip +install/strip/fast: install/strip +.PHONY : install/strip/fast + +# Special rule for the target list_install_components +list_install_components: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\"" +.PHONY : list_install_components + +# Special rule for the target list_install_components +list_install_components/fast: list_install_components +.PHONY : list_install_components/fast + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." + "C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache +.PHONY : rebuild_cache/fast + +# The main all target +all: cmake_check_build_system + cd /d C:\libs && $(CMAKE_COMMAND) -E cmake_progress_start C:\libs\CMakeFiles C:\libs\pip\utils\system_daemon\CMakeFiles\progress.marks + cd /d C:\libs && $(MAKE) -f CMakeFiles\Makefile2 pip/utils/system_daemon/all + $(CMAKE_COMMAND) -E cmake_progress_start C:\libs\CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + cd /d C:\libs && $(MAKE) -f CMakeFiles\Makefile2 pip/utils/system_daemon/clean +.PHONY : clean + +# The main clean target +clean/fast: clean +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + cd /d C:\libs && $(MAKE) -f CMakeFiles\Makefile2 pip/utils/system_daemon/preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + cd /d C:\libs && $(MAKE) -f CMakeFiles\Makefile2 pip/utils/system_daemon/preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + cd /d C:\libs && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles\Makefile.cmake 1 +.PHONY : depend + +# Convenience name for target. +pip/utils/system_daemon/CMakeFiles/pisd.dir/rule: + cd /d C:\libs && $(MAKE) -f CMakeFiles\Makefile2 pip/utils/system_daemon/CMakeFiles/pisd.dir/rule +.PHONY : pip/utils/system_daemon/CMakeFiles/pisd.dir/rule + +# Convenience name for target. +pisd: pip/utils/system_daemon/CMakeFiles/pisd.dir/rule +.PHONY : pisd + +# fast build rule for target. +pisd/fast: + cd /d C:\libs && $(MAKE) -f pip\utils\system_daemon\CMakeFiles\pisd.dir\build.make pip/utils/system_daemon/CMakeFiles/pisd.dir/build +.PHONY : pisd/fast + +daemon.obj: daemon.cpp.obj +.PHONY : daemon.obj + +# target to build an object file +daemon.cpp.obj: + cd /d C:\libs && $(MAKE) -f pip\utils\system_daemon\CMakeFiles\pisd.dir\build.make pip/utils/system_daemon/CMakeFiles/pisd.dir/daemon.cpp.obj +.PHONY : daemon.cpp.obj + +daemon.i: daemon.cpp.i +.PHONY : daemon.i + +# target to preprocess a source file +daemon.cpp.i: + cd /d C:\libs && $(MAKE) -f pip\utils\system_daemon\CMakeFiles\pisd.dir\build.make pip/utils/system_daemon/CMakeFiles/pisd.dir/daemon.cpp.i +.PHONY : daemon.cpp.i + +daemon.s: daemon.cpp.s +.PHONY : daemon.s + +# target to generate assembly for a file +daemon.cpp.s: + cd /d C:\libs && $(MAKE) -f pip\utils\system_daemon\CMakeFiles\pisd.dir\build.make pip/utils/system_daemon/CMakeFiles/pisd.dir/daemon.cpp.s +.PHONY : daemon.cpp.s + +file_manager.obj: file_manager.cpp.obj +.PHONY : file_manager.obj + +# target to build an object file +file_manager.cpp.obj: + cd /d C:\libs && $(MAKE) -f pip\utils\system_daemon\CMakeFiles\pisd.dir\build.make pip/utils/system_daemon/CMakeFiles/pisd.dir/file_manager.cpp.obj +.PHONY : file_manager.cpp.obj + +file_manager.i: file_manager.cpp.i +.PHONY : file_manager.i + +# target to preprocess a source file +file_manager.cpp.i: + cd /d C:\libs && $(MAKE) -f pip\utils\system_daemon\CMakeFiles\pisd.dir\build.make pip/utils/system_daemon/CMakeFiles/pisd.dir/file_manager.cpp.i +.PHONY : file_manager.cpp.i + +file_manager.s: file_manager.cpp.s +.PHONY : file_manager.s + +# target to generate assembly for a file +file_manager.cpp.s: + cd /d C:\libs && $(MAKE) -f pip\utils\system_daemon\CMakeFiles\pisd.dir\build.make pip/utils/system_daemon/CMakeFiles/pisd.dir/file_manager.cpp.s +.PHONY : file_manager.cpp.s + +main.obj: main.cpp.obj +.PHONY : main.obj + +# target to build an object file +main.cpp.obj: + cd /d C:\libs && $(MAKE) -f pip\utils\system_daemon\CMakeFiles\pisd.dir\build.make pip/utils/system_daemon/CMakeFiles/pisd.dir/main.cpp.obj +.PHONY : main.cpp.obj + +main.i: main.cpp.i +.PHONY : main.i + +# target to preprocess a source file +main.cpp.i: + cd /d C:\libs && $(MAKE) -f pip\utils\system_daemon\CMakeFiles\pisd.dir\build.make pip/utils/system_daemon/CMakeFiles/pisd.dir/main.cpp.i +.PHONY : main.cpp.i + +main.s: main.cpp.s +.PHONY : main.s + +# target to generate assembly for a file +main.cpp.s: + cd /d C:\libs && $(MAKE) -f pip\utils\system_daemon\CMakeFiles\pisd.dir\build.make pip/utils/system_daemon/CMakeFiles/pisd.dir/main.cpp.s +.PHONY : main.cpp.s + +# Help Target +help: + @echo The following are some of the valid targets for this Makefile: + @echo ... all (the default if no target is provided) + @echo ... clean + @echo ... depend + @echo ... edit_cache + @echo ... install + @echo ... install/local + @echo ... install/strip + @echo ... list_install_components + @echo ... pisd + @echo ... rebuild_cache + @echo ... daemon.obj + @echo ... daemon.i + @echo ... daemon.s + @echo ... file_manager.obj + @echo ... file_manager.i + @echo ... file_manager.s + @echo ... main.obj + @echo ... main.i + @echo ... main.s +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + cd /d C:\libs && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles\Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/utils/system_daemon/cmake_install.cmake b/utils/system_daemon/cmake_install.cmake new file mode 100644 index 00000000..468b2e87 --- /dev/null +++ b/utils/system_daemon/cmake_install.cmake @@ -0,0 +1,47 @@ +# Install script for directory: C:/libs/pip/utils/system_daemon + +# Set the install prefix +IF(NOT DEFINED CMAKE_INSTALL_PREFIX) + SET(CMAKE_INSTALL_PREFIX "C:/mingw/x32") +ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) +STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + IF(BUILD_TYPE) + STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + ELSE(BUILD_TYPE) + SET(CMAKE_INSTALL_CONFIG_NAME "Release") + ENDIF(BUILD_TYPE) + MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + +# Set the component getting installed. +IF(NOT CMAKE_INSTALL_COMPONENT) + IF(COMPONENT) + MESSAGE(STATUS "Install component: \"${COMPONENT}\"") + SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + ELSE(COMPONENT) + SET(CMAKE_INSTALL_COMPONENT) + ENDIF(COMPONENT) +ENDIF(NOT CMAKE_INSTALL_COMPONENT) + +IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") + list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES + "C:/mingw/x32/bin/pisd.exe") + IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) + message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) + IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) + message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) +FILE(INSTALL DESTINATION "C:/mingw/x32/bin" TYPE EXECUTABLE FILES "C:/libs/pip/utils/system_daemon/pisd.exe") + IF(EXISTS "$ENV{DESTDIR}/C:/mingw/x32/bin/pisd.exe" AND + NOT IS_SYMLINK "$ENV{DESTDIR}/C:/mingw/x32/bin/pisd.exe") + IF(CMAKE_INSTALL_DO_STRIP) + EXECUTE_PROCESS(COMMAND "C:/mingw/x32/bin/strip.exe" "$ENV{DESTDIR}/C:/mingw/x32/bin/pisd.exe") + ENDIF(CMAKE_INSTALL_DO_STRIP) + ENDIF() +ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") + diff --git a/utils/system_daemon/daemon.cpp b/utils/system_daemon/daemon.cpp new file mode 100644 index 00000000..0f655ce2 --- /dev/null +++ b/utils/system_daemon/daemon.cpp @@ -0,0 +1,252 @@ +#include "daemon.h" +#include "shared.h" +#include "pisysteminfo.h" + + +Daemon::Daemon(): PIPeer("_pisd_" + PISystemInfo::instance()->hostname + "_" + PIString(rand() % 100)) { + setName("Daemon"); + timer.setName("__S__Daemon_timer"); + enabled = false; + mode = offset = cur = height = 0; + CONNECTU(&console, keyPressed, this, keyEvent) + CONNECTU(&timer, tickEvent, this, timerEvent) + timer.addDelimiter(5); + timer.start(200); +} + + +void Daemon::keyEvent(char key) { + if (!enabled) return; + int num = key - '0'; + switch (mode) { + case 0: + if (num >= 0 && num <= 9) { + connectToDaemon(dnames.value(key - '0')); + return; + } + break; + case 1: + if (num >= 0 && num <= 9) { + mode = num + 10; + updateConsole(); + return; + } + break; + } + switch (key) { + case PIKbdListener::UpArrow: + /*cur--; + if (cur < 0) cur = 0; + if (cur - offset < 2) offset--; + if (offset < 0) offset = 0;*/ + updateConsole(); + break; + case PIKbdListener::Space: + /*if (cur < 0 || cur >= files.size_s()) return; + if (selected.contains(files[cur].name)) selected.removeOne(files[cur].name); + else selected << files[cur].name;*/ + case PIKbdListener::DownArrow: + /*cur++; + if (cur >= files.size_s()) cur = files.size_s() - 1; + if (cur - offset >= height - 2) offset++; + if (offset >= files.size_s() - height) offset = files.size_s() - height;*/ + updateConsole(); + break; + case PIKbdListener::Home: + //cur = offset = 0; + updateConsole(); + break; + case PIKbdListener::End: + //cur = files.size_s() - 1; + //offset = files.size_s() - height; + updateConsole(); + break; + case PIKbdListener::Return: + //if (cur < files.size_s() && cur >= 0) { + //} + break; + case 'A': + updateConsole(); + break; + case 'R': + updateConsole(); + break; + case PIKbdListener::Esc: + //selected.clear(); + //updateConsole(); + if (mode == 0) + menuRequest(); + else { + if (mode > 1) { + mode = 1; + updateConsole(); + } else + disconnect(); + } + break; + default: break; + } +} + + +void Daemon::timerEvent(void * _d, int delim) { + if (!enabled) return; + if (delim == 1) { + if (mode == 0) + updateConsole(); + + } + if (delim == 5) { + if (conn_name.isEmpty()) return; + PIByteArray ba; ba << int(RequestHostInfo); + send(conn_name, ba); + } +} + + +PIStringList Daemon::availableDaemons() const { + available_daemons.clear(); + piForeachC (PIPeer::PeerInfo & p, allPeers()) { + if (!p.name.startsWith("_pisd_")) continue; + available_daemons << p.name.mid(6); + } + return available_daemons; +} + + +void Daemon::connectToDaemon(const PIString & dn) { + if (dn.isEmpty()) return; + conn_name = "_pisd_" + dn; + mode = 1; + updateConsole(); +} + + +void Daemon::disconnect() { + conn_name.clear(); + mode = 0; + updateConsole(); +} + + +PIString Daemon::connectedDaemon() const { + return conn_name.mid(6); +} + + +void Daemon::peerDisconnected(const PIString & name) { + if (name == conn_name) { + conn_name.clear(); + mode = 0; + } +} + + +void Daemon::dataReceived(const PIString & from, const PIByteArray & data) { + //if (conn_name != from) return; + if (data.size() < 4) return; + PIByteArray ba(data), rba; + int type; ba >> type; + //piCout << "rec from" << from << type; + switch (type) { + case RequestHostInfo: + makeMyHostInfo(); + rba << int(ReplyHostInfo) << info_my; + break; + case ReplyHostInfo: + ba >> info_other; + makeOtherHostInfo(); + break; + }; + if (!rba.isEmpty()) send(from, rba); +} + + +void Daemon::makeMyHostInfo() { + info_my.execCommand = PISystemInfo::instance()->execCommand; + info_my.hostname = PISystemInfo::instance()->hostname; + info_my.user = PISystemInfo::instance()->user; + info_my.OS_name = PISystemInfo::instance()->OS_name; + info_my.OS_version = PISystemInfo::instance()->OS_version; + info_my.architecture = PISystemInfo::instance()->architecture; + info_my.execDateTime = PISystemInfo::instance()->execDateTime; + info_my.processorsCount = PISystemInfo::instance()->processorsCount; + info_my.ID = sys_mon.statistic().ID; + info_my.threads = sys_mon.statistic().threads; + info_my.priority = sys_mon.statistic().priority; + info_my.physical_memsize = sys_mon.statistic().physical_memsize; + info_my.share_memsize = sys_mon.statistic().share_memsize; + info_my.cpu_load_system = sys_mon.statistic().cpu_load_system; + info_my.cpu_load_user = sys_mon.statistic().cpu_load_user; +} + + +void Daemon::makeOtherHostInfo() { + PISystemMonitor::ProcessStats & ps(const_cast(sys_mon_other.statistic())); + ps.ID = info_other.ID; + ps.threads = info_other.threads; + ps.priority = info_other.priority; + ps.physical_memsize = info_other.physical_memsize; + ps.share_memsize = info_other.share_memsize; + ps.cpu_load_system = info_other.cpu_load_system; + ps.cpu_load_user = info_other.cpu_load_user; + sys_mon_other.setStatistic(ps); +} + + +void Daemon::updateConsole() { + if (!enabled) return; + switch (mode) { + case 0: tabConnect(); break; + case 1: tabFeature(); break; + case RequestHostInfo: tabInfo(); break; + } +} + + +void Daemon::tabConnectedHeader(int cols) { + console.addString("Connected to: " + connectedDaemon(), 1, PIConsole::BackGreen | PIConsole::Bold); + for (int i = 2; i <= cols; ++i) + console.addString(" ", i, PIConsole::Green | PIConsole::Inverse); +} + + +void Daemon::tabConnect() { + startTab(); + console.addString("Available daemons:"); + int num = 0; + dnames.clear(); + PIStringList adl = availableDaemons(); + piForeachC (PIString & p, adl) { + dnames[num] = p; + console.addString(" " + PIString(num++) + " - " + p); + } + finishTab(); +} + + +void Daemon::tabFeature() { + startTab(); + tabConnectedHeader(); + console.addString("What do you wish to do with this daemon?"); + console.addString(" 0 - show host info"); + console.addString(" 1 - file manager"); + console.addString(" 2 - execute command"); + finishTab(); +} + + +void Daemon::tabInfo() { + startTab(2); + tabConnectedHeader(2); + console.addString("Exec command: " + info_other.execCommand); + console.addString(" Executed on " + info_other.execDateTime.toString()); + console.addString(" Hostname: " + info_other.hostname); + console.addString(" Username: " + info_other.user); + console.addString(" OS name: " + info_other.OS_name); + console.addString(" OS version: " + info_other.OS_version); + console.addString("Architecture: " + info_other.architecture); + console.addString(" CPU count: " + PIString::fromNumber(info_other.processorsCount)); + console.addVariable("of this process", &sys_mon_other, 2); + finishTab(); +} diff --git a/utils/system_daemon/daemon.h b/utils/system_daemon/daemon.h new file mode 100644 index 00000000..dd0f5745 --- /dev/null +++ b/utils/system_daemon/daemon.h @@ -0,0 +1,93 @@ +#ifndef DAEMON_H +#define DAEMON_H + +#include "piconsole.h" +#include "pipeer.h" + +extern PIConsole console; +extern PISystemMonitor sys_mon; + +class Daemon: public PIPeer { + PIOBJECT(Daemon) +public: + Daemon(); + + struct HostInfo { + PIString execCommand; + PIString hostname; + PIString user; + PIString OS_name; + PIString OS_version; + PIString architecture; + PIDateTime execDateTime; + int processorsCount; + + int ID; + int threads; + int priority; + ulong physical_memsize; + ulong share_memsize; + float cpu_load_system; + float cpu_load_user; + }; + + void enable() {enabled = true;} + void disable() {enabled = false;} + + PIStringList availableDaemons() const; + void connectToDaemon(const PIString & dn); + void disconnect(); + + PIString connectedDaemon() const; + +private: + enum PacketType { + RequestHostInfo = 10, + + ReplyHostInfo = 20 + + }; + + EVENT_HANDLER1(void, keyEvent, char, key); + EVENT_HANDLER2(void, timerEvent, void * , _d, int, delim); + EVENT(menuRequest); + void peerDisconnected(const PIString & name); + void dataReceived(const PIString & from, const PIByteArray & data); + void makeMyHostInfo(); + void makeOtherHostInfo(); + void updateConsole(); + void tabConnectedHeader(int cols = 1); + void tabConnect(); + void tabFeature(); + void tabInfo(); + + mutable PIStringList available_daemons; + PITimer timer; + PIString conn_name; + PIMap dnames; + PISystemMonitor sys_mon_other; + HostInfo info_my, info_other; + bool enabled; + int mode, offset, cur, height; + + +}; + +inline PIByteArray & operator <<(PIByteArray & b, const Daemon::HostInfo & v) { + b << v.execCommand << v.hostname << v.user << v.OS_name + << v.OS_version << v.architecture << v.execDateTime + << v.processorsCount << v.ID << v.threads << v.priority + << v.physical_memsize << v.share_memsize + << v.cpu_load_system << v.cpu_load_user; + return b; +} +inline PIByteArray & operator >>(PIByteArray & b, Daemon::HostInfo & v) { + b >> v.execCommand >> v.hostname >> v.user >> v.OS_name + >> v.OS_version >> v.architecture >> v.execDateTime + >> v.processorsCount >> v.ID >> v.threads >> v.priority + >> v.physical_memsize >> v.share_memsize + >> v.cpu_load_system >> v.cpu_load_user; + return b; +} + +#endif // DAEMON_H diff --git a/utils/system_daemon/file_manager.cpp b/utils/system_daemon/file_manager.cpp new file mode 100644 index 00000000..0ca140d5 --- /dev/null +++ b/utils/system_daemon/file_manager.cpp @@ -0,0 +1,182 @@ +#include "file_manager.h" +#include "shared.h" + + +FileManager::FileManager() { + setName("FileManager"); + offset = cur = height = 0; + enabled = del_commit = false; + CONNECTU(&console, keyPressed, this, keyEvent) + dir = PIDir::current(); + //dir.setDir("/home/peri4/Documents"); + dir.setDir("/home/peri4"); + updateDir(); +} + + +void FileManager::keyEvent(char key) { + if (!enabled) return; + if (key == 'D') { + if (cur >= files.size_s() || cur < 0) return; + if (del_commit) { + piForeachC (PIString & f, selected) { + PIFile::remove(dir.absolutePath() + PIDir::separator + f); + //piCout << "remove" << (dir.absolutePath() + PIDir::separator + f); + } + selected.clear(); + updateDir(); + console.clearCustomStatus(); + del_commit = false; + } else { + if (selected.isEmpty()) selected << files[cur].path; + console.addCustomStatus("Delete " + PIString(selected.size_s()) + " file, are you sure? D as yes"); + del_commit = true; + } + updateConsole(); + return; + } + console.clearCustomStatus(); + del_commit = false; + PIStringList nsel; + switch (key) { + case PIKbdListener::UpArrow: + cur--; + if (cur < 0) cur = 0; + if (cur - offset < 3) offset--; + if (offset < 0) offset = 0; + updateConsole(); + break; + case PIKbdListener::Space: + if (cur < 0 || cur >= files.size_s()) return; + if (selected.contains(files[cur].path)) selected.removeOne(files[cur].path); + else selected << files[cur].path; + case PIKbdListener::DownArrow: + cur++; + if (cur >= files.size_s()) cur = files.size_s() - 1; + if (cur - offset >= height - 3) offset++; + if (offset >= files.size_s() - height) offset = files.size_s() - height; + updateConsole(); + //piCout << offset << files.size_s() << height; + break; + case PIKbdListener::Home: + cur = offset = 0; + updateConsole(); + break; + case PIKbdListener::End: + cur = files.size_s() - 1; + offset = files.size_s() - height; + updateConsole(); + //piCout << offset << files.size_s() << height; + break; + case PIKbdListener::Return: + if (cur < files.size_s() && cur >= 0) { + piCout << files[cur]; + if (files[cur].isDir()) { + prev_pos[dir.path()] = cur; + prev_off[dir.path()] = offset; + dir.cd(files[cur].name()); + cur = prev_pos.value(dir.path(), 0); + offset = prev_off.value(dir.path(), 0); + selected.clear(); + updateDir(); + updateConsole(); + } + } + break; + case 'A': + selected.clear(); + piForeach (PIFile::FileInfo & e, files) + selected << e.path; + updateConsole(); + break; + case 'R': + updateDir(); + piForeach (PIFile::FileInfo & e, files) + if (selected.contains(e.path)) + nsel << e.path; + selected = nsel; + updateConsole(); + break; + case PIKbdListener::Esc: + //selected.clear(); + //updateConsole(); + menuRequest(); + break; + default: break; + } +} + + +void FileManager::updateConsole() { + if (!enabled) return; + startTab(2); + console.addString("File manager", 1, PIConsole::Yellow | PIConsole::Inverse); + console.addString("Path: " + dir.absolutePath(), 1, PIConsole::Green | PIConsole::Inverse | PIConsole::Bold); + console.addString("Name", 1, PIConsole::Green | PIConsole::Inverse | PIConsole::Bold); + console.addString(" ", 2, PIConsole::Yellow | PIConsole::Inverse); + console.addString(" ", 2, PIConsole::Green | PIConsole::Inverse); + console.addString(" ", 2, PIConsole::Green | PIConsole::Inverse); + buildNames(); + console.addString("A - select all, D - remove, R - refresh, Esc - exit", 1, PIConsole::Green | PIConsole::Inverse | PIConsole::Bold); + finishTab(); +} + + +void FileManager::buildNames() { + if (!enabled) return; + height = console.windowHeight() - 10; + int is = piClampi(offset, 0, piMaxi(0, files.size_s() - 1)), ie = piClampi(offset + height, 0, files.size_s()); + console.addString((is > 0) ? (PIString(" /\\ ").repeat(console.windowWidth() / 8)) : " ", 1, PIConsole::Green | PIConsole::Bold); + console.addString(" ", 2); + PIChar t; + PIConsole::FormatFlags f = 0; + PIString scol; + piCout << cur; + for (int i = is; i < ie; ++i) { + if (files[i].isDir()) { + t = '/'; + f = PIConsole::Bold; + scol = " dir"; + } else { + if (files[i].perm_user.exec || files[i].perm_group.exec || files[i].perm_other.exec) { + f = PIConsole::Green | PIConsole::Bold; + t = '*'; + } else { + t = ' '; + f = 0; + } + scol = PIString::readableSize(files[i].size); + } + if (files[i].isSymbolicLink() && (t != '*')) t = '~'; + scol = scol.expandRightTo(9, ' ') + "| " + files[i].time_modification.toString("dd.MM hh:mm:ss") + " | " + + files[i].perm_user.toString() + " " + files[i].perm_group.toString() + " " + files[i].perm_other.toString(); + if (i == cur) f |= PIConsole::BackBlue; + if (selected.contains(files[i].path)) f |= PIConsole::Yellow | PIConsole::Bold; + console.addString(t + files[i].name(), 1, f); + console.addString(scol, 2, f); + } + console.addString((ie < files.size_s()) ? (PIString(" \\/ ").repeat(console.windowWidth() / 8)) : " ", 1, PIConsole::Green | PIConsole::Bold); + console.addString(" ", 2); +} + + +void FileManager::updateDir() { + if (!enabled) return; + files.clear(); + PIVector el = dir.entries(), fl, dl; + for (int i = 0; i < el.size_s(); ++i) { + if (el[i].path == ".") continue; + if (el[i].path == "..") { + dl.push_front(el[i]); + continue; + } + if (el[i].isDir()) dl << el[i]; + else fl << el[i]; + } + files << dl << fl; + if (cur >= files.size_s()) cur = files.size_s() - 1; + if (offset >= files.size_s() - height) offset = files.size_s() - height; + if (cur < 0) cur = 0; + if (offset < 0) offset = 0; +} + diff --git a/utils/system_daemon/file_manager.h b/utils/system_daemon/file_manager.h new file mode 100644 index 00000000..63894d06 --- /dev/null +++ b/utils/system_daemon/file_manager.h @@ -0,0 +1,33 @@ +#ifndef FILE_MANAGER_H +#define FILE_MANAGER_H + +#include "piconsole.h" +#include "pidir.h" + +extern PIConsole console; + +class FileManager: public PIObject { + PIOBJECT(FileManager) +public: + FileManager(); + + void enable() {enabled = true; updateDir(); updateConsole();} + void disable() {enabled = false;} + +private: + EVENT_HANDLER1(void, keyEvent, char, key); + EVENT(menuRequest); + void updateConsole(); + void updateDir(); + void buildNames(); + + int offset, cur, height; + bool enabled, del_commit; + PIDir dir; + PIVector files; + PIMap prev_pos, prev_off; + PIStringList selected; +}; + + +#endif // FILE_MANAGER_H diff --git a/utils/system_daemon/main.cpp b/utils/system_daemon/main.cpp new file mode 100755 index 00000000..f7af30c4 --- /dev/null +++ b/utils/system_daemon/main.cpp @@ -0,0 +1,244 @@ +/* + PIP - Platform Independent Primitives + Remote console viewer + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "picli.h" +#include "pisystemmonitor.h" +#include "pisysteminfo.h" +#include "file_manager.h" +#include "daemon.h" +#include "shared.h" + +void key_event(char key, void * ); + +class _Init { +public: + _Init() {srand(PISystemTime::current().toMicroseconds());} +}; +_Init _pisd_init; + +PIConsole console(false, key_event); +PISystemMonitor sys_mon; +FileManager file_manager; +Daemon daemon_; +int mode = 0, oldmode = -1; + +class MenuOperator: public PIObject { + PIOBJECT(MenuOperator) +public: + MenuOperator() { + CONNECTU(&file_manager, menuRequest, this, menuRequest) + CONNECTU(&daemon_, menuRequest, this, menuRequest) + } + EVENT_HANDLER(void, menuRequest) {mode = 0;} +}; + +MenuOperator menu_operator; + +void key_event(char key, void * ) { + if (key == PIKbdListener::Esc) { + ;//mode = 0; + } else { + if (mode != 3) { + if (key < '0' || key > '9') return; + mode = key - '0'; + } + } +} + + +void tabMenu() { + startTab(); + console.addString("Select with numeric key:"); + console.addString(" 0 - this screen"); + console.addString(" 1 - show host info"); + console.addString(" 2 - local file manager"); + console.addString(" 3 - connect to another daemon"); + finishTab(); +} + + +void tabInfo() { + startTab(); + console.addString("Exec command: " + PISystemInfo::instance()->execCommand); + console.addString(" Executed on " + PISystemInfo::instance()->execDateTime.toString()); + console.addString(" Hostname: " + PISystemInfo::instance()->hostname); + console.addString(" Username: " + PISystemInfo::instance()->user); + console.addString(" OS name: " + PISystemInfo::instance()->OS_name); + console.addString(" OS version: " + PISystemInfo::instance()->OS_version); + console.addString("Architecture: " + PISystemInfo::instance()->architecture); + console.addString(" CPU count: " + PIString::fromNumber(PISystemInfo::instance()->processorsCount)); + console.addString(" ", 2, PIConsole::Yellow | PIConsole::Inverse); + console.addVariable("of this process", &sys_mon, 2); + finishTab(); +} + + +void tabConnect() { +} + +#include +int main(int argc, char * argv[]) { + /*PICRC<16> crc(0xFF12FF34); + PIByteArray ba(4096); + for (int i = 0; i < ba.size_s(); ++i) ba[i] = i % 256; + PITimeMeasurer tm; + uint_cl<16> ret; + for (int i = 0; i < 1000; ++i) { + ret = crc.calculate(ba); + }*/ + + /*if (argc < 2) return 0; + PIFile af; + if (!af.open(argv[1], PIIODevice::ReadOnly)) + return 0; + piCout << "open" << af.path(); + PIByteArray sign, jfif, rsign, rdata; + int phase = 0, pos = 0, asize = af.size(); + ushort jct = 0, jcl = 0; + uint ct = 0, cl = 0, cc = 0, tend = 1229278788; + sign << uchar(0x89) << uchar(0x50) << uchar(0x4E) << uchar(0x47) << uchar(0x0D) << uchar(0x0A) << uchar(0x1A) << uchar(0x0A); + jfif << uchar(0x4A) << uchar(0x46) << uchar(0x49) << uchar(0x46); + rsign.resize(sign.size()); + PIByteArray nf; + PITimeMeasurer tm; + int cnt = 0, j = 0; + while (!af.isEnd()) { + if (tm.elapsed_m() >= 500) { + tm.reset(); + piCout << "readed" << PIString::readableSize(af.pos()); + } + if (pos >= asize) break; + switch (phase) { + case 0: + af.seek(pos); + af.read(rsign.data(), rsign.size_s()); + if (rsign == sign) { + phase = 1; + nf = rsign; + } else if (rsign.resized(4) == jfif) { + phase = 2; + af.seek(pos - 6); + nf.resize(2); + af.read(nf.data(), nf.size_s()); + } else + pos++; + break; + case 1: + af.read(&cl, 4); + af.read(&ct, 4); + rdata.resize(piLetobe(cl)); + af.read(rdata.data(), rdata.size_s()); + af.read(&cc, 4); + nf.append(&cl, 4); + nf.append(&ct, 4); + nf.append(rdata); + nf.append(&cc, 4); + if (piLetobe(ct) == tend) { + piCout << "found PNG size" << PIString::readableSize(nf.size_s()); + PIFile wf("./PNG/" + PIString(cnt++) + ".png"); + if (wf.open(PIIODevice::ReadWrite)) + wf.write(nf.data(), nf.size()); + nf.clear(); + phase = 0; + pos = af.pos(); + } + break; + case 2: + //jct = 0; + //while (jct != ushort(0xD9FF)) { + // af.read(&jct, 2); + // nf.append(&jct, 2); + //} + //if (++j >= 30) return 0; + af.read(&jct, 2); + nf.append(&jct, 2); + if (jct == ushort(0xD9FF)) { + piCout << "found JPG size" << PIString::readableSize(nf.size_s()); + PIFile wf("./PNG/" + PIString(cnt++) + ".jpg"); + if (wf.open(PIIODevice::ReadWrite)) + wf.write(nf.data(), nf.size()); + nf.clear(); + phase = 0; + pos = af.pos(); + break; + } + af.read(&jcl, 2); + nf.append(&jcl, 2); + if (jct == 0xDAFF) { + jct = 0; + int pp = af.pos(); + rdata.resize(1024*1024*3); + af.read(rdata.data(), rdata.size_s()); + nf.append(rdata); + //while (jct != ushort(0xFFD9)) { + // af.read(&jct, 2); + // nf.append(&jct, 2); + // //piCout << Hex << jct; + //} + piCout << "found JPG size" << PIString::readableSize(nf.size_s()); + PIFile wf("./PNG/" + PIString(cnt++) + ".jpg"); + if (wf.open(PIIODevice::ReadWrite)) + wf.write(nf.data(), nf.size()); + nf.clear(); + phase = 0; + pos = pp + 1; + break; + } + //piCout << "length" << piLetobe(jcl); + rdata.resize(piLetobe(jcl) - 2); + af.read(rdata.data(), rdata.size_s()); + nf.append(rdata); + break; + }; + }; + return 0;*/ + + //piCout << Hex << uint(ret) << tm.elapsed_m(); + PICLI cli(argc, argv); + //cli.addArgument(""); + sys_mon.startOnSelf(); + console.enableExitCapture(); + console.setDefaultAlignment(PIConsole::Right); + console.start(); + //WAIT_FOR_EXIT + //return 0; + while (!PIKbdListener::exiting) { + if (oldmode != mode) { + file_manager.disable(); + daemon_.disable(); + oldmode = mode; + switch (mode) { + case 0: /// menu + tabMenu(); + break; + case 1: /// host info + tabInfo(); + break; + case 2: /// file manager + file_manager.enable(); + break; + case 3: /// daemon + daemon_.enable(); + break; + } + } + piMSleep(100); + } + return 0; +}; diff --git a/utils/system_daemon/pisd.exe b/utils/system_daemon/pisd.exe new file mode 100644 index 00000000..58f69d2b Binary files /dev/null and b/utils/system_daemon/pisd.exe differ diff --git a/utils/system_daemon/shared.h b/utils/system_daemon/shared.h new file mode 100644 index 00000000..25187706 --- /dev/null +++ b/utils/system_daemon/shared.h @@ -0,0 +1,22 @@ +#include "piconsole.h" + +extern PIConsole console; + +inline void header(int cols = 1) { + console.addString("PIP System Daemon (PIP " + PIPVersion() + ")", 1, PIConsole::Yellow | PIConsole::Inverse); + for (int i = 2; i <= cols; ++i) + console.addString(" ", i, PIConsole::Yellow | PIConsole::Inverse); +} + +inline void startTab(int cols = 1) { + console.pause(true); + console.clearTab(0); + console.lock(); + header(cols); +} + +inline void finishTab() { + console.unlock(); + console.pause(false); + console.update(); +} diff --git a/utils/system_test/CMakeLists.txt b/utils/system_test/CMakeLists.txt new file mode 100755 index 00000000..03841c81 --- /dev/null +++ b/utils/system_test/CMakeLists.txt @@ -0,0 +1,5 @@ +add_executable(pip_system_test "main.cpp") +target_link_libraries(pip_system_test pip) +if (DEFINED LIB) + install(TARGETS pip_system_test DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +endif () diff --git a/utils/system_test/Makefile b/utils/system_test/Makefile new file mode 100644 index 00000000..9dc45c75 --- /dev/null +++ b/utils/system_test/Makefile @@ -0,0 +1,209 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 2.8 + +# Default target executed when no arguments are given to make. +default_target: all +.PHONY : default_target + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/andrey/linux_build/libs + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/andrey/linux_build/libs + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running interactive CMake command-line interface..." + /usr/bin/cmake -i . +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache +.PHONY : edit_cache/fast + +# Special rule for the target install +install: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." + /usr/bin/cmake -P cmake_install.cmake +.PHONY : install + +# Special rule for the target install +install/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..." + /usr/bin/cmake -P cmake_install.cmake +.PHONY : install/fast + +# Special rule for the target install/local +install/local: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..." + /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake +.PHONY : install/local + +# Special rule for the target install/local +install/local/fast: install/local +.PHONY : install/local/fast + +# Special rule for the target install/strip +install/strip: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..." + /usr/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake +.PHONY : install/strip + +# Special rule for the target install/strip +install/strip/fast: install/strip +.PHONY : install/strip/fast + +# Special rule for the target list_install_components +list_install_components: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\"" +.PHONY : list_install_components + +# Special rule for the target list_install_components +list_install_components/fast: list_install_components +.PHONY : list_install_components/fast + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." + /usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache +.PHONY : rebuild_cache/fast + +# The main all target +all: cmake_check_build_system + cd /home/andrey/linux_build/libs && $(CMAKE_COMMAND) -E cmake_progress_start /home/andrey/linux_build/libs/CMakeFiles /home/andrey/linux_build/libs/pip/utils/system_test/CMakeFiles/progress.marks + cd /home/andrey/linux_build/libs && $(MAKE) -f CMakeFiles/Makefile2 pip/utils/system_test/all + $(CMAKE_COMMAND) -E cmake_progress_start /home/andrey/linux_build/libs/CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + cd /home/andrey/linux_build/libs && $(MAKE) -f CMakeFiles/Makefile2 pip/utils/system_test/clean +.PHONY : clean + +# The main clean target +clean/fast: clean +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + cd /home/andrey/linux_build/libs && $(MAKE) -f CMakeFiles/Makefile2 pip/utils/system_test/preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + cd /home/andrey/linux_build/libs && $(MAKE) -f CMakeFiles/Makefile2 pip/utils/system_test/preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + cd /home/andrey/linux_build/libs && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +# Convenience name for target. +pip/utils/system_test/CMakeFiles/pip_system_test.dir/rule: + cd /home/andrey/linux_build/libs && $(MAKE) -f CMakeFiles/Makefile2 pip/utils/system_test/CMakeFiles/pip_system_test.dir/rule +.PHONY : pip/utils/system_test/CMakeFiles/pip_system_test.dir/rule + +# Convenience name for target. +pip_system_test: pip/utils/system_test/CMakeFiles/pip_system_test.dir/rule +.PHONY : pip_system_test + +# fast build rule for target. +pip_system_test/fast: + cd /home/andrey/linux_build/libs && $(MAKE) -f pip/utils/system_test/CMakeFiles/pip_system_test.dir/build.make pip/utils/system_test/CMakeFiles/pip_system_test.dir/build +.PHONY : pip_system_test/fast + +main.o: main.cpp.o +.PHONY : main.o + +# target to build an object file +main.cpp.o: + cd /home/andrey/linux_build/libs && $(MAKE) -f pip/utils/system_test/CMakeFiles/pip_system_test.dir/build.make pip/utils/system_test/CMakeFiles/pip_system_test.dir/main.cpp.o +.PHONY : main.cpp.o + +main.i: main.cpp.i +.PHONY : main.i + +# target to preprocess a source file +main.cpp.i: + cd /home/andrey/linux_build/libs && $(MAKE) -f pip/utils/system_test/CMakeFiles/pip_system_test.dir/build.make pip/utils/system_test/CMakeFiles/pip_system_test.dir/main.cpp.i +.PHONY : main.cpp.i + +main.s: main.cpp.s +.PHONY : main.s + +# target to generate assembly for a file +main.cpp.s: + cd /home/andrey/linux_build/libs && $(MAKE) -f pip/utils/system_test/CMakeFiles/pip_system_test.dir/build.make pip/utils/system_test/CMakeFiles/pip_system_test.dir/main.cpp.s +.PHONY : main.cpp.s + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... edit_cache" + @echo "... install" + @echo "... install/local" + @echo "... install/strip" + @echo "... list_install_components" + @echo "... pip_system_test" + @echo "... rebuild_cache" + @echo "... main.o" + @echo "... main.i" + @echo "... main.s" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + cd /home/andrey/linux_build/libs && $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/utils/system_test/cmake_install.cmake b/utils/system_test/cmake_install.cmake new file mode 100644 index 00000000..90856bd6 --- /dev/null +++ b/utils/system_test/cmake_install.cmake @@ -0,0 +1,60 @@ +# Install script for directory: /home/andrey/linux_build/libs/pip/utils/system_test + +# Set the install prefix +IF(NOT DEFINED CMAKE_INSTALL_PREFIX) + SET(CMAKE_INSTALL_PREFIX "/usr") +ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) +STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + IF(BUILD_TYPE) + STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + ELSE(BUILD_TYPE) + SET(CMAKE_INSTALL_CONFIG_NAME "Release") + ENDIF(BUILD_TYPE) + MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + +# Set the component getting installed. +IF(NOT CMAKE_INSTALL_COMPONENT) + IF(COMPONENT) + MESSAGE(STATUS "Install component: \"${COMPONENT}\"") + SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + ELSE(COMPONENT) + SET(CMAKE_INSTALL_COMPONENT) + ENDIF(COMPONENT) +ENDIF(NOT CMAKE_INSTALL_COMPONENT) + +# Install shared libraries without execute permission? +IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + SET(CMAKE_INSTALL_SO_NO_EXE "1") +ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + +IF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") + IF(EXISTS "$ENV{DESTDIR}/usr/bin/pip_system_test" AND + NOT IS_SYMLINK "$ENV{DESTDIR}/usr/bin/pip_system_test") + FILE(RPATH_CHECK + FILE "$ENV{DESTDIR}/usr/bin/pip_system_test" + RPATH "") + ENDIF() + list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES + "/usr/bin/pip_system_test") + IF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) + message(WARNING "ABSOLUTE path INSTALL DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + ENDIF (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION) + IF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) + message(FATAL_ERROR "ABSOLUTE path INSTALL DESTINATION forbidden (by caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}") + ENDIF (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION) +FILE(INSTALL DESTINATION "/usr/bin" TYPE EXECUTABLE FILES "/home/andrey/linux_build/libs/pip/utils/system_test/pip_system_test") + IF(EXISTS "$ENV{DESTDIR}/usr/bin/pip_system_test" AND + NOT IS_SYMLINK "$ENV{DESTDIR}/usr/bin/pip_system_test") + FILE(RPATH_REMOVE + FILE "$ENV{DESTDIR}/usr/bin/pip_system_test") + IF(CMAKE_INSTALL_DO_STRIP) + EXECUTE_PROCESS(COMMAND "/usr/bin/strip" "$ENV{DESTDIR}/usr/bin/pip_system_test") + ENDIF(CMAKE_INSTALL_DO_STRIP) + ENDIF() +ENDIF(NOT CMAKE_INSTALL_COMPONENT OR "${CMAKE_INSTALL_COMPONENT}" STREQUAL "Unspecified") + diff --git a/utils/system_test/main.cpp b/utils/system_test/main.cpp new file mode 100755 index 00000000..0d3ef03d --- /dev/null +++ b/utils/system_test/main.cpp @@ -0,0 +1,106 @@ +/* + PIP - Platform Independent Primitives + System tests program + Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pip.h" +#include "pisystemtests.h" + + +int main(int argc, char * argv[]) { +#ifdef WINDOWS + cout << "This program is useless for Windows" << endl; + return 0; +#else + if (getuid() != 0) { + cout << "You should run this program as root!" << endl; + return 0; + } + PIConfig conf( +#ifndef WINDOWS + "/etc/pip.conf" +#else + "pip.conf" +#endif + ); + PITimeMeasurer timer, tm; + timespec ts; + long stc = 0; + double st; + llong sts = 0; + clock_getres(CLOCK_REALTIME, &ts); + stc = long(ts.tv_sec) * 1000000000l + long(ts.tv_nsec); + conf.setValue("time_resolution_ns", stc); + cout << "Timer resolution is " << stc << " ns" << endl; + + cout << "\"PITimer.elapsed_*\" test ... " << flush; + stc = 0; + ts.tv_sec = 0; + ts.tv_nsec = 1000; + PIVector times; + times.resize(8192); + tm.reset(); + PISystemTests::time_elapsed_ns = 0; + while (tm.elapsed_s() < 3.) { + for (int i = 0; i < times.size_s(); ++i) { + timer.reset(); + times[i] = timer.elapsed_m(); + times[i] = timer.elapsed_s(); + times[i] = timer.elapsed_u(); + } + st = 0; + for (int i = 0; i < times.size_s(); ++i) + st += times[i]; + //cout << times[0] << endl; + //cout << st / times.size_s() / 3. * 1000. << endl; + sts += piRoundd(st / times.size_s() / 3. * 1000.); + //cout << sts << endl; + stc++; + } + sts /= stc; + conf.setValue("time_elapsed_ns", long(sts)); + cout << "ok, cost " << sts << " ns, average in " << stc << " series (" << (stc * 3 * times.size_s()) << " executes)" << endl; + + cout << "\"usleep\" offset test ... " << flush; + PISystemTests::time_elapsed_ns = sts; + tm.reset(); + stc = 0; + sts = 0; + times.resize(128); + while (tm.elapsed_s() < 3.) { + for (int i = 0; i < times.size_s(); ++i) { + timer.reset(); + usleep(1000); + times[i] = timer.elapsed_u(); + } + st = 0; + for (int i = 0; i < times.size_s(); ++i) + st += times[i] - 1000; + //cout << times[0] << endl; + //cout << st / times.size_s() / 3. * 1000. << endl; + sts += piRoundd(st / times.size_s()); + //cout << sts << endl; + stc++; + } + sts /= stc; + conf.setValue("usleep_offset_us", long(sts)); + cout << "ok, " << sts << " us, average in " << stc << " series (" << (stc * times.size_s()) << " executes)" << endl; + + //WAIT_FOR_EXIT + return 0; +#endif +}; diff --git a/utils/system_test/pip_system_test b/utils/system_test/pip_system_test new file mode 100755 index 00000000..2e765bfe Binary files /dev/null and b/utils/system_test/pip_system_test differ diff --git a/utils/system_test/pip_system_test.exe b/utils/system_test/pip_system_test.exe new file mode 100644 index 00000000..bff7c0cd Binary files /dev/null and b/utils/system_test/pip_system_test.exe differ