diff --git a/CMakeLists.txt b/CMakeLists.txt
index 036cde4b..30e5156b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,23 +1,29 @@
project(pip)
-find_package(Qt4)
cmake_minimum_required(VERSION 2.6)
-include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${QT_INCLUDES} . ../peri4_widgets)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR} .)
+set(VERSION "0.0304")
+set(SOVERSION ${VERSION})
+set(CMAKE_BUILD_TYPE "Release")
file(GLOB CPPS "pi*.cpp")
if (${WIN32})
- add_definitions(-Wall -O2)
-else (${WIN32})
- add_definitions(-Wall -O2 -g3 --fast-math)
-endif (${WIN32})
-add_library(pip SHARED ${CPPS})
-if (${WIN32})
- target_link_libraries(pip pthread ws2_32 Iphlpapi)
+ include(GenerateExportHeader)
+ execute_process(COMMAND "make_rc_win.bat")
+ add_definitions("-O2")
+ #add_definitions(-DEF)
+ list(APPEND CPPS "pip_resource_win.o")
+ add_library(pip SHARED ${CPPS})
+ generate_export_header(pip)
+ target_link_libraries(pip ws2_32 Iphlpapi)
else (${WIN32})
+ if(DEFINED ENV{QNX_HOST})
+ add_definitions("-O2")
+ add_library(pip STATIC ${CPPS})
+ else()
+ add_definitions("-Wall -O2 -g3")
+ add_library(pip SHARED ${CPPS})
+ endif()
target_link_libraries(pip pthread rt)
endif (${WIN32})
add_executable(pip_test "main.cpp")
-if (${WIN32})
- target_link_libraries(pip_test pthread ws2_32 Iphlpapi pip)
-else (${WIN32})
- target_link_libraries(pip_test pip ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} pcollection)
-endif (${WIN32})
+target_link_libraries(pip_test pip)
add_subdirectory(system_test)
diff --git a/main.cpp b/main.cpp
index 9b27b362..d07f29e4 100644
--- a/main.cpp
+++ b/main.cpp
@@ -16,7 +16,7 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
-
+//#define PIP_DEBUG
#include "pip.h"
@@ -52,7 +52,7 @@ private:
void signalFunc(PISignals::Signal signal) {
if (signal != PISignals::Interrupt) return;
- cout << "Ctrl+C pressed, exiting ..." << endl;
+ cout << endl << "Ctrl+C pressed, exiting ..." << endl;
exit(0);
};
@@ -71,293 +71,252 @@ void timerEvent2(void * data, int delim) {
class ObjectTest: public PIObject {
+ PIOBJECT(ObjectTest)
public:
ObjectTest(const PIString & name = PIString()): PIObject(name) {h = hi = ht = false;}
- EVENT_HANDLER(ObjectTest, void, handler) {h = true; cout << " handler in \"" << name() << "\"" << endl;}
- EVENT_HANDLER2(ObjectTest, void, handler_i_s, int, i, PIString, s) {hi = true; cout << " handler_i_s in \"" << name() << "\", i = " << i << ", s = \"" << s << "\"" << endl;}
- EVENT_HANDLER2(ObjectTest, void, handler_timeout, void * , data, int, delim) {ht = true; cout << " handler_timeout in \"" << name() << "\", data = " << data << ", delim = " << delim << endl;}
+ EVENT_HANDLER(void, handler) {h = true; cout << " handler in \"" << name() << "\"" << endl;}
+ EVENT_HANDLER2(void, handler_i_s, int, i, PIString, s) {hi = true; cout << " handler_i_s in \"" << name() << "\", i = " << i << ", s = \"" << s << "\"" << endl;}
+ EVENT_HANDLER2(void, handler_timeout, void * , data, int, delim) {ht = true; cout << " handler_timeout in \"" << name() << "\", data = " << data << ", delim = " << delim << endl;}
bool h, hi, ht;
};
class ObjectTest2: public PIObject {
+ PIOBJECT(ObjectTest2)
public:
ObjectTest2(const PIString & name = PIString()): PIObject(name) {;}
void raise0(const PIString & e) {cout << " event \"" << e << "\" from \"" << name() << "\"" << endl; raiseEvent(this, e);}
void raise2(const PIString & e, int i, const PIString & s) {cout << " event \"" << e << "\" from \"" << name() << "\"" << endl; raiseEvent(this, e, i, s);}
- EVENT(ObjectTest2, event0)
- EVENT(ObjectTest2, event2)
+ EVENT(event0)
+ EVENT(event2)
};
class CA: public PIObject {
+ PIOBJECT(CA)
public:
CA(const PIString & n): PIObject(n) {;}
- EVENT_HANDLER(CA, void, handler_ca) {a = true; cout << " handler CA" << endl;}
- EVENT(CA, event_ca)
+ EVENT_HANDLER(void, handler_ca) {a = true; cout << " handler CA" << endl;}
+ EVENT(event_ca)
bool a;
};
class CB: public CA {
+ PIOBJECT(CB)
public:
CB(const PIString & n): CA(n) {;}
- EVENT_HANDLER(CB, void, handler_cb) {b = true; cout << " handler CB" << endl;}
+ EVENT_HANDLER(void, handler_cb) {b = true; cout << " handler CB" << endl;}
bool b;
};
class CC: public CB {
+ PIOBJECT(CC)
public:
CC(const PIString & n): CB(n) {;}
- EVENT_HANDLER(CC, void, handler_cc) {c = true; cout << " handler CC" << endl;}
+ EVENT_HANDLER(void, handler_cc) {c = true; cout << " handler CC" << endl;}
bool c;
};
class CD: public CC {
+ PIOBJECT(CD)
public:
CD(const PIString & n): CC(n) {;}
- EVENT_HANDLER(CD, void, handler_cd) {d = true; cout << " handler CD" << endl;}
+ EVENT_HANDLER(void, handler_cd) {d = true; cout << " handler CD" << endl;}
bool d;
};
+PIDiagnostics diag;
+bool corr = true;
+void te(void * , int) {
+ diag.received(256, corr);
+ diag.sended(512);
+}
-struct Packet {
- int from;
- int to;
- float data;
- int cs;
+
+class ObjectA: public PIObject {
+ PIOBJECT(ObjectA)
+public:
+ EVENT_HANDLER1(void, handlerA, const PIString & , str) {piCout << "handler A:" << str;}
+ EVENT2(eventA2, int, i, float, f);
+ EVENT1(eventA1, const PIString & , str);
+};
+
+class ObjectB: public PIObject {
+ PIOBJECT(ObjectB)
+public:
+ EVENT_HANDLER2(void, handlerB, int, i, float, f) {piCout << "handler B:" << i << "," << f;}
+ EVENT1(eventB, PIString, str);
+};
+
+#pragma pack(push, 1)
+
+struct msgHeader {
+ msgHeader(ushort msg_id_ = 0) {
+ sign[0] = 'B';
+ sign[1] = 'R';
+ sign[2] = 'K';
+ sign[3] = 'D';
+ msg_id = msg_id_;
+ sys_id = 2;
+ subsys_id = 1;
+ fragment = security = cnt = 0;
+ size = sizeof(msgHeader);
+ }
+ char sign[4];
+ ushort size;
+ ushort cnt;
+ uchar fragment;
+ ushort msg_id;
+ uchar sys_id;
+ uchar subsys_id;
+ uchar security;
+ bool verify_sign() {return (sign[0] == 'B' && sign[1] == 'R' && sign[2] == 'K' && sign[3] == 'D');}
};
-#pragma pack(push,1)
+struct msg2105base {
+ msgHeader header;
+ union {
+ ullong msgTime;
+ struct {
+ uint time_ns;
+ uint time_s;
+ };
+ };
+ uint id;
+ ushort type1kod;
+ float type1ver;
+ ushort type2kod;
+ float type2ver;
+ ushort type3kod;
+ float type3ver;
+ double azimut;
+ ullong imp_recv_time;
+ double geo_width_PEC;
+ double geo_length_PEC;
+ double geo_width_CP;
+ double geo_length_CP;
+ float height;
+ float kurs_CP;
+ float kren_CP;
+ float tangaj_CP;
+};
+
struct InpuData {
- uint first_number; // Номер первого отсчета
- struct {
- uchar packet_number: 7; // Идентификационный код пакета
- uchar packet_last : 1; // Признак последнего пакета
- };
- struct {
- uchar antenna_number : 3; // Номер антенного канала
- uchar frequency_number: 3; // Номер частотного канала
- uchar data_type : 2; // Вид передаваемой информации: 0 – оцифровка, 1 – измеренные параметры
- };
- uchar data[122]; // Данные
-};
-
-struct msgHeader {
- char sign[4];
- unsigned short size;
- unsigned short cnt;
- unsigned char fragment;
- unsigned short msg_id;
- unsigned char sys_id;
- unsigned char subsys_id;
- unsigned char security;
- bool verify_sign()
- {
- bool ok;
- ok = sign[0] == 'B';
- ok = ok && sign[1] == 'R';
- ok = ok && sign[2] == 'K';
- ok = ok && sign[3] == 'D';
- return ok;
- }
-};
-struct FilterCommand {
- FilterCommand() {
- memset(this, 0, sizeof(FilterCommand));
- header.sign[0] = 'B'; header.sign[1] = 'R'; header.sign[2] = 'K'; header.sign[3] = 'D';
- header.size = sizeof(FilterCommand);
- header.cnt = header.fragment = header.security = 0;
- header.msg_id = 2102;
- header.sys_id = header.subsys_id = 2;
- command = 3;
- }
-
+ InpuData() {header.msg_id = 2113;}
msgHeader header;
- uchar command; // 3
+ uint first_number;
struct {
- uchar fi_number: 7; // номер частотного участка, 1 - 36
- uchar bort : 1; // борт: 0 - левый, 1 - правый
+ uchar packet_number: 7;
+ uchar packet_last : 1;
};
- ushort freq_start; // начальная частота, 0 - 6100
- ushort freq_end; // конечная частота, 0 - 6100
- uchar filter_bandwith; // полоса проспускания фильтра
- ushort filter_time_step; // время шага фильтра по времени
- uchar reserve;
- ushort record_time_start; // начальное время записи, 1 - 60 мс
- ushort record_time_end; // конечное время записи, 1 - 60 мс
- uchar record_channels; // номера каналов для записи, 0 - 5 биты
- uchar play_channels; // номера каналов для воспроизведения, 0 - 5 биты
- uchar signal_type; // тип сигнала для выдачи, 0 - С3, 1 - С4, 2 - С4Ф, 3 - выборка
- ushort play_time_start; // начальное время воспроизведения, 1 - 60 мс
- ushort play_time_end; // конечное время воспроизведения, 1 - 60 мс
- uchar checksum;
+ struct {
+ uchar antenna_number : 3;
+ uchar frequency_number: 3;
+ uchar data_type : 2;
+ };
+ uchar data[122];
};
#pragma pack(pop)
-void te(void*, int);
-PITimer tm_(te);
-PISerial ser("/dev/ttyS0");
-bool pins[9];
-void te(void*, int) {
- for (int i = 1; i <= 9; ++i)
- pins[i - 1] = ser.isPin(i);
-}
-void ke(char key, void*) {
- int p = key - '0';
- if (key >= '1' && key <= '9')
- ser.setPin(p, !pins[p - 1]);
-}
-int main(int argc, char * argv[]) {
- PIKbdListener kbd;
- kbd.enableExitCapture();
- PICLI cli(argc, argv);
- cli.addArgument("sender");
- PIEthernet eth;
- int i = 0;
- bool _ok;
- if (cli.hasArgument("sender")) {
- while (!PIKbdListener::exiting) {
- _ok = eth.send("234.0.2.1", 10101, &i, sizeof(i));
- cout << "send " << i << " - " << (_ok ? "ok" : "fail") << endl;
- i++;
- msleep(100);
- }
- } else {
- eth.setParameter(PIEthernet::Broadcast);
- eth.open(":10101");
- eth.joinMulticastGroup("234.0.2.1");
- while (!PIKbdListener::exiting) {
- eth.read(&i, sizeof(i));
- cout << "receive " << i << endl;
- }
- }
- return 0;
-
- /*tm_.start(10.);
- PIConsole con(false, ke);
- con.enableExitCapture();
- //ser.setParameter(PISerial::HardwareFlowControl);
- ser.open();
- con.addVariable("1 (CAR)", pins);
- con.addVariable("2 (SR) ", pins + 1);
- con.addVariable("3 (ST) ", pins + 2);
- con.addVariable("4 (DTR)", pins + 3);
- con.addVariable("5 (GND)", pins + 4);
- con.addVariable("6 (DSR)", pins + 5);
- con.addVariable("7 (RTS)", pins + 6);
- con.addVariable("8 (CTS)", pins + 7);
- con.addVariable("9 (RNG)", pins + 8);
- con.start();
- con.waitForFinish();
- return 0;*/
-
- /*FilterCommand fc;
- PIEthernet eth(PIEthernet::TCP_SingleTCP);
- eth.open("127.0.0.1:10201");
- while (1) {
- eth.read(&fc, sizeof(fc));
- cout << int(fc.fi_number) << ", " << int(fc.bort) << ", " << int(fc.freq_start) << ", " << int(fc.freq_end) << ", " << int(fc.play_channels) << ", " << int(fc.record_channels) << endl;
- }
- return 0;*/
+class RC: public PIObject {
+ PIOBJECT(RC)
+public:
+ EVENT_HANDLER2(void, re, ullong, id, int, size) {piCout << "written id =" << id << "size =" << size;}
+};
- /*PIDir dir(argv[1]);
- FILE*f = popen("cd ../ && pwd", "w");
- char fd[4096];
- int ret = fread(fd, 4096, 1, f);
- pclose(f);
- cout << PIString(fd, ret);
- f = popen("cd ../ && pwd", "w");
- ret = fread(fd, 4096, 1, f);
- pclose(f);
- cout << PIString(fd, ret);
- return 0;
- cout << dir.path() << endl;
- dir.up();
- cout << dir.path() << endl;
- PIVector ent = dir.entries();
- piForeachC (PIDir::DirEntry & i, ent)
- cout << i.mode << " " << PIString::readableSize(i.size).expandRightTo(10, ' ') << " " << i.name << endl;*/
-
- /*PISystemTime st_time, inc_time;
- PITimer tm_;
- tm_.reset();
- inc_time = PISystemTime::fromMilliseconds(50);
- st_time = currentSystemTime() + inc_time;
- int cnt = 100;
- while (cnt--) {
- (st_time - currentSystemTime()).sleep();
- {
- msleep(49);
- cout << "tick " << cnt << endl;
- }
- st_time += inc_time;
- }
- cout << tm_.elapsed_s() - 0.049 << endl;*/
-
- /*PISystemTime t0, inc_time;
- PITimer tm_;
- tm_.reset();
- inc_time = PISystemTime::fromMilliseconds(50);
- inc_time.sleep();
- int cnt = 100;
- while (cnt--) {
- t0 = currentSystemTime();
- {
- msleep(49);
- cout << "tick " << cnt << endl;
- }
- (inc_time - (currentSystemTime() - t0)).sleep();
- }
- cout << tm_.elapsed_s() - 0.049 << endl;*/
-
- //return 0;
-
- /*InpuData data;
+
+int main(int argc, char ** argv) {
+ InpuData data;
PIEthernet eth(PIEthernet::UDP);
- data.first_number = 0;
- data.packet_number = 0;
- data.packet_last = 0;
data.antenna_number = data.frequency_number = data.data_type = 0;
- PIBitArray ba_;
- for (int i = 0; i < 97; ++i) {
- for (int b = 0; b < 10; ++b)
- ba_.push_back(((i >> b) & 1) == 1);
+ float t = 0.f;
+ int pc = 20, cnt = 0;
+ for (int p = 0; p < pc; ++p) {
+ data.packet_number = p;
+ data.packet_last = (p == pc - 1 ? 1 : 0);
+ data.first_number = p * 97;
+ PIBitArray ba_;
+ int ci = 0;
+ for (int i = 0; i < 97; ++i) {
+ t += M_PI/4;
+ ci = sin(t) * 511 + 511;
+ if (cnt % 500 > 80) ci = 512;
+ cnt++;
+ for (int b = 0; b < 10; ++b)
+ ba_.push_back(((ci >> b) & 1) == 1);
+ }
+ //cout << ba_.byteSize() << ", " << ba_.bitSize() << endl;
+ memcpy(data.data, ba_.data(), 122);
+ eth.send("127.0.0.1:5000", &data, sizeof(data));
}
- //cout << ba_.byteSize() << ", " << ba_.bitSize() << endl;
- memcpy(data.data, ba_.data(), 122);
- cout << ba_ << endl;
+ /*cout << ba_ << endl;
for (int i = 0; i < 122; ++i)
cout << int(data.data[i]) << ", ";
- cout << endl;
- eth.send("127.0.0.1:5000", &data, sizeof(data));
+ cout << endl;*/
+ return 0;
+
+ /*PIKbdListener kbd;
+ kbd.enableExitCapture();
+ PIEthernet * _eth;
+ PIByteArray ba_(16);
+ if (PIString(argv[argc - 1]) == "s") {
+ _eth = new PIEthernet(PIEthernet::TCP_Server);
+ piCout << "listen" << _eth->listen("127.0.0.1:1111");
+ int cc = 0;
+ while (!PIKbdListener::exiting) {
+ if (cc != _eth->clientsCount()) {
+ piCout << "new client";
+ _eth->clients().back()->startThreadedRead();
+ cc++;
+ }
+ msleep(1);
+ }
+ } else {
+ _eth = new PIEthernet(PIEthernet::TCP_Client);
+ piCout << "connection" << _eth->connect("127.0.0.1:1111");
+ _eth->send(PIString("0123456789101112").data(), 16);
+ while (!PIKbdListener::exiting) {
+ msleep(1);
+ }
+ }
+ delete _eth;
+ return 0;
+
+ msg2105base msg;
+ msg.header.size = sizeof(msg);
+ msg.header.msg_id = 2105;
+ msg.msgTime = 1;
+ //PIKbdListener kbd;
+ //kbd.enableExitCapture();
+ RC rc_;
+ PIEthernet eth;
+ CONNECT2(void, ullong, int, ð, threadedWriteEvent, &rc_, re);
+ eth.setParameter(PIEthernet::Broadcast);
+ eth.open("127.0.0.1:10211");
+ eth.setSendAddress("234.0.2.1:10211");
+ eth.joinMulticastGroup("234.0.2.1");
+ eth.startThreadedWrite();
+ for (int i = 0; i < 100000; ++i) {
+ PISystemTime tm = currentSystemTime();
+ msg.type1kod = (i + 1) % 34;
+ msg.id = piRoundd(double(i) / 5. + 50);
+ if (i % 15 >= 10) msg.id += 10000;
+ msg.time_ns = tm.seconds;
+ msg.time_s = tm.nanoseconds;
+ msg.azimut = sin(float(i) / 20.) * 90;
+ msg.geo_width_PEC = sin(float(i) / 50.) * 90;
+ msg.geo_length_PEC = cos(float(i) / 50.) * 90;
+ piCout << "push to queue with id =" << eth.writeThreaded(&msg, sizeof(msg));
+ piMSleep(50);
+ if (PIKbdListener::exiting) break;
+ }
return 0;*/
- /*QApplication app(argc, argv);
- PIFFT fft;
- PIVector in;
- in.resize(50*1000);
- for (int i=400; i<404; i++) in[i] = complexd(1,0);
- PITimer timer_;
- fft.prepareFFT(in.size());
- timer_.reset();
- PIVector * out = fft.calcFFT(in);
- cout << timer_.elapsed_m() << endl;
- Graphic * g = new Graphic();
- QVector res;
- fft.getAmplitude();
- for (int i=0; isize(); i++) res.append(QPointF(i,abs(out->at(i))));
- g->setGraphicData(res);
- g->addGraphic("arg", Qt::darkBlue);
- res.clear();
- for (int i=0; i< out->size(); i++) res.append(QPointF(i,arg(out->at(i))));
- g->setGraphicData(res, 1);
- g->show();
-
- return app.exec();*/
-
+ PISignals::setSlot(signalFunc);
+ //PISignals::grabSignals(PISignals::Interrupt);
bool r_string = true, r_thread = true, r_mutex = true, r_timer = true, r_file = true, r_eval = true, r_event = true;
bool succ = true;
cout << "== PIP test program ==" << endl;
diff --git a/pibitarray.h b/pibitarray.h
index 807c237a..6fbe159a 100644
--- a/pibitarray.h
+++ b/pibitarray.h
@@ -22,7 +22,7 @@
#include "picontainers.h"
-class PIBitArray {
+class PIP_EXPORT PIBitArray {
public:
PIBitArray(const int & size = 0) {resize(size);}
PIBitArray(uchar val) {resize(sizeof(val) * 8); data_[0] = val;}
@@ -99,5 +99,6 @@ private:
};
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/pibytearray.h b/pibytearray.h
index c6342006..05c4b6c3 100644
--- a/pibytearray.h
+++ b/pibytearray.h
@@ -90,12 +90,24 @@ private:
PIVector nodes;
};
-class PIByteArray: public PIVector {
+class PIP_EXPORT PIByteArray: public PIVector {
public:
PIByteArray() {;}
PIByteArray(const uint size) {resize(size);}
PIByteArray(const void * data, const uint size) {for (uint i = 0; i < size; ++i) push_back(((uchar * )data)[i]);}
+ struct RawData {
+ friend PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v);
+ friend PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v);
+ public:
+ RawData(void * data, int size) {d = data; s = size;}
+ 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;
+ };
+
PIByteArray resized(int new_size) {PIByteArray tv(*this); tv.resize(new_size); return tv;}
PIByteArray & convertToBase64();
@@ -146,42 +158,56 @@ private:
};
-inline std::ostream & operator <<(std::ostream & s, const PIByteArray & ba) {for (uint i = 0; i < ba.size(); ++i) s << ba[i]; return s;}
+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;}
+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));
inline PIByteArray & operator <<(PIByteArray & s, uchar v) {s.push_back(v); return s;}
-inline PIByteArray & operator <<(PIByteArray & s, const short & v) {for (uint i = 0; i < sizeof(v); ++i) s.push_back(((uchar * )&v)[i]); return s;}
-inline PIByteArray & operator <<(PIByteArray & s, const int & v) {for (uint i = 0; i < sizeof(v); ++i) s.push_back(((uchar * )&v)[i]); return s;}
-inline PIByteArray & operator <<(PIByteArray & s, const long & v) {for (uint i = 0; i < sizeof(v); ++i) s.push_back(((uchar * )&v)[i]); return s;}
-inline PIByteArray & operator <<(PIByteArray & s, const llong & v) {for (uint i = 0; i < sizeof(v); ++i) s.push_back(((uchar * )&v)[i]); return s;}
-inline PIByteArray & operator <<(PIByteArray & s, const ushort & v) {for (uint i = 0; i < sizeof(v); ++i) s.push_back(((uchar * )&v)[i]); return s;}
-inline PIByteArray & operator <<(PIByteArray & s, const uint & v) {for (uint i = 0; i < sizeof(v); ++i) s.push_back(((uchar * )&v)[i]); return s;}
-inline PIByteArray & operator <<(PIByteArray & s, const ulong & v) {for (uint i = 0; i < sizeof(v); ++i) s.push_back(((uchar * )&v)[i]); return s;}
-inline PIByteArray & operator <<(PIByteArray & s, const ullong & v) {for (uint i = 0; i < sizeof(v); ++i) s.push_back(((uchar * )&v)[i]); return s;}
-inline PIByteArray & operator <<(PIByteArray & s, const float & v) {for (uint i = 0; i < sizeof(v); ++i) s.push_back(((uchar * )&v)[i]); return s;}
-inline PIByteArray & operator <<(PIByteArray & s, const double & v) {for (uint i = 0; i < sizeof(v); ++i) s.push_back(((uchar * )&v)[i]); return s;}
+inline PIByteArray & operator <<(PIByteArray & s, const short v) {PBA_OPERATOR_TO return s;}
+inline PIByteArray & operator <<(PIByteArray & s, const int v) {PBA_OPERATOR_TO return s;}
+inline PIByteArray & operator <<(PIByteArray & s, const long & v) {PBA_OPERATOR_TO return s;}
+inline PIByteArray & operator <<(PIByteArray & s, const llong & v) {PBA_OPERATOR_TO return s;}
+inline PIByteArray & operator <<(PIByteArray & s, const ushort v) {PBA_OPERATOR_TO return s;}
+inline PIByteArray & operator <<(PIByteArray & s, const uint v) {PBA_OPERATOR_TO return s;}
+inline PIByteArray & operator <<(PIByteArray & s, const ulong & v) {PBA_OPERATOR_TO return s;}
+inline PIByteArray & operator <<(PIByteArray & s, const ullong & v) {PBA_OPERATOR_TO return s;}
+inline PIByteArray & operator <<(PIByteArray & s, const float v) {PBA_OPERATOR_TO return s;}
+inline PIByteArray & operator <<(PIByteArray & s, const double & v) {PBA_OPERATOR_TO return s;}
+inline PIByteArray & operator <<(PIByteArray & s, const PIByteArray::RawData & v) {int os = s.size_s(); s.enlarge(v.s); memcpy(s.data(os), v.d, v.s); return s;}
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;}
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;}
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;}
+template
+inline PIByteArray & operator <<(PIByteArray & s, const T & v) {PBA_OPERATOR_TO return s;}
-inline PIByteArray & operator >>(PIByteArray & s, uchar & v) {v = s.take_front(); return s;}
-inline PIByteArray & operator >>(PIByteArray & s, short & v) {for (uint i = 0; i < sizeof(v); ++i) ((uchar * )&v)[i] = s.take_front(); return s;}
-inline PIByteArray & operator >>(PIByteArray & s, int & v) {for (uint i = 0; i < sizeof(v); ++i) ((uchar * )&v)[i] = s.take_front(); return s;}
-inline PIByteArray & operator >>(PIByteArray & s, long & v) {for (uint i = 0; i < sizeof(v); ++i) ((uchar * )&v)[i] = s.take_front(); return s;}
-inline PIByteArray & operator >>(PIByteArray & s, llong & v) {for (uint i = 0; i < sizeof(v); ++i) ((uchar * )&v)[i] = s.take_front(); return s;}
-inline PIByteArray & operator >>(PIByteArray & s, ushort & v) {for (uint i = 0; i < sizeof(v); ++i) ((uchar * )&v)[i] = s.take_front(); return s;}
-inline PIByteArray & operator >>(PIByteArray & s, uint & v) {for (uint i = 0; i < sizeof(v); ++i) ((uchar * )&v)[i] = s.take_front(); return s;}
-inline PIByteArray & operator >>(PIByteArray & s, ulong & v) {for (uint i = 0; i < sizeof(v); ++i) ((uchar * )&v)[i] = s.take_front(); return s;}
-inline PIByteArray & operator >>(PIByteArray & s, ullong & v) {for (uint i = 0; i < sizeof(v); ++i) ((uchar * )&v)[i] = s.take_front(); return s;}
-inline PIByteArray & operator >>(PIByteArray & s, float & v) {for (uint i = 0; i < sizeof(v); ++i) ((uchar * )&v)[i] = s.take_front(); return s;}
-inline PIByteArray & operator >>(PIByteArray & s, double & v) {for (uint i = 0; i < sizeof(v); ++i) ((uchar * )&v)[i] = s.take_front(); return s;}
+#undef PBA_OPERATOR_TO
+#define PBA_OPERATOR_FROM memcpy(&v, s.data(), sizeof(v)); s.remove(0, sizeof(v));
+
+inline PIByteArray & operator >>(PIByteArray & s, uchar & v) {assert(s.size() >= 1u); v = s.take_front(); return s;}
+inline PIByteArray & operator >>(PIByteArray & s, short & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
+inline PIByteArray & operator >>(PIByteArray & s, int & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
+inline PIByteArray & operator >>(PIByteArray & s, long & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
+inline PIByteArray & operator >>(PIByteArray & s, llong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
+inline PIByteArray & operator >>(PIByteArray & s, ushort & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
+inline PIByteArray & operator >>(PIByteArray & s, uint & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
+inline PIByteArray & operator >>(PIByteArray & s, ulong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
+inline PIByteArray & operator >>(PIByteArray & s, ullong & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
+inline PIByteArray & operator >>(PIByteArray & s, float & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
+inline PIByteArray & operator >>(PIByteArray & s, double & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
+inline PIByteArray & operator >>(PIByteArray & s, PIByteArray::RawData v) {assert(s.size_s() >= v.s); memcpy(v.d, s.data(), v.s); s.remove(0, v.s); return s;}
template
inline PIByteArray & operator >>(PIByteArray & s, PIVector & v) {int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;}
template
inline PIByteArray & operator >>(PIByteArray & s, PIList & v) {int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;}
template
inline PIByteArray & operator >>(PIByteArray & s, PIDeque & v) {int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;}
+template
+inline PIByteArray & operator >>(PIByteArray & s, T & v) {assert(s.size() >= sizeof(v)); PBA_OPERATOR_FROM return s;}
+
+#undef PBA_OPERATOR_FROM
#endif // PIBYTEARRAY_H
diff --git a/pichar.h b/pichar.h
index 552acc51..ac5ba124 100644
--- a/pichar.h
+++ b/pichar.h
@@ -1,3 +1,6 @@
+/*! \file pichar.h
+ * \brief Unicode char
+*/
/*
PIP - Platform Independent Primitives
Unicode char
@@ -21,24 +24,41 @@
#define PICHAR_H
#include "pibytearray.h"
-
-class PIChar
+/*! \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;}
- PIChar(const int c = 0) {ch = c;}
+
+ //! 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;}
- PIChar(const uint c) {ch = c;}
+
+ //! 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;}
@@ -46,6 +66,7 @@ public:
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());
@@ -57,6 +78,7 @@ public:
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);}
@@ -65,62 +87,134 @@ public:
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 static_cast(ch);}
- const wchar_t * toWCharPtr() const {return &ch;}
+ 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 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:
- wchar_t ch;
+ uint ch;
};
+
+//! 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/picli.cpp b/picli.cpp
index 81ccae40..07e766ba 100644
--- a/picli.cpp
+++ b/picli.cpp
@@ -69,7 +69,7 @@ void PICLI::parse() {
_args_opt << cra;
continue;
}
- piCout << "[PICli] Arguments overflow, \"" << cra << "\" ignored" << endl;
+ piCout << "[PICli] Arguments overflow, \"" << cra << "\" ignored";
}
if (last == 0 ? false : last->has_value) {
last->value = cra;
diff --git a/picli.h b/picli.h
index 8a9051e8..435a3310 100644
--- a/picli.h
+++ b/picli.h
@@ -22,7 +22,7 @@
#include "pistring.h"
-class PICLI
+class PIP_EXPORT PICLI
{
public:
PICLI(int argc, char * argv[]);
diff --git a/picodec.h b/picodec.h
index 21ee8fa6..25baefdf 100644
--- a/picodec.h
+++ b/picodec.h
@@ -22,7 +22,7 @@
#include "piprocess.h"
-class PICodec: private PIProcess
+class PIP_EXPORT PICodec: private PIProcess
{
public:
PICodec(): PIProcess() {setGrabOutput(true); tf = PIFile::openTemporary(PIIODevice::ReadWrite); tf.open();}
diff --git a/piconfig.cpp b/piconfig.cpp
index 48554566..2bcdc4f2 100644
--- a/piconfig.cpp
+++ b/piconfig.cpp
@@ -277,7 +277,7 @@ void PIConfig::addEntry(const PIString & name, const PIString & value, const PIS
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);
+ addEntry(name, value, type, write);
return;
}
e._value = value;
@@ -376,10 +376,14 @@ void PIConfig::removeEntry(Branch & b, PIConfig::Entry * e) {
void PIConfig::writeAll() {
+ //cout << this << " write < " << size() << endl;
clear();
+ //*this << "1234567894132456798\n"; return;
//writeEntry(&root);
buildFullNames(&root);
Branch b = allLeaves();
+ //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;
@@ -387,25 +391,27 @@ void PIConfig::writeAll() {
if (b[j]->_line == i) {
b[j]->buildLine();
*this << b[j]->_all << '\n';
+ //cout << this << " " << b[j]->_all << endl;
++j;
} else {
*this << other[i];
if (i < other.size_s() - 1) *this << '\n';
+ //cout << this << " " << other[i] << endl;
}
} else {
*this << other[i];
if (i < other.size_s() - 1) *this << '\n';
+ //cout << this << " " << other[i] << endl;
}
- //cout << other[i] << endl;
}
flush();
readAll();
+ //cout << this << " write > " << size() << endl;
}
void PIConfig::readAll() {
root.clear();
- flush();
parse();
}
diff --git a/piconfig.h b/piconfig.h
index e0bf7abd..d80ea41f 100644
--- a/piconfig.h
+++ b/piconfig.h
@@ -49,17 +49,17 @@
Entry & getValue(const PIString & vname, const float def, bool * exist = 0) const {return getValue(vname, ftos(def), exist);} \
Entry & getValue(const PIString & vname, const double def, bool * exist = 0) const {return getValue(vname, dtos(def), exist);}
-class PIConfig: public PIFile
+class PIP_EXPORT PIConfig: public PIFile
{
friend class Entry;
friend class Branch;
public:
PIConfig(const PIString & path, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
- ~PIConfig() {piForeach (Entry * i, root._children) deleteEntry(i); close();}
+ ~PIConfig() {/*piForeach (Entry * i, root._children) deleteEntry(i); close();*/}
class Entry;
- class Branch: public PIVector {
+ class PIP_EXPORT Branch: public PIVector {
friend class PIConfig;
friend class Entry;
friend std::ostream & operator <<(std::ostream & s, const Branch & v);
@@ -90,7 +90,7 @@ public:
};
- class Entry {
+ class PIP_EXPORT Entry {
friend class PIConfig;
friend class Branch;
public:
diff --git a/piconsole.cpp b/piconsole.cpp
index 70d70414..509782fe 100644
--- a/piconsole.cpp
+++ b/piconsole.cpp
@@ -20,12 +20,15 @@
#include "piconsole.h"
+extern PIMutex __PICout_mutex__;
+
+
PIConsole::PIConsole(bool startNow, KBFunc slot): PIThread() {
setPriority(piLow);
needLockRun(true);
ret_func = slot;
num_format = 0;
- cur_tab = width = height = pwidth = pheight = my = 0;
+ cur_tab = width = height = pwidth = pheight = max_y = 0;
def_align = Nothing;
#ifdef WINDOWS
ulcoord.X = ulcoord.Y = 0;
@@ -93,9 +96,11 @@ bool PIConsole::setTab(uint index) {
return true;
}
lock();
+ __PICout_mutex__.lock();
cur_tab = index;
clearScreen();
fillLabels();
+ __PICout_mutex__.unlock();
unlock();
return true;
}
@@ -135,6 +140,23 @@ bool PIConsole::setTabBindKey(const PIString & name, char 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);
@@ -148,7 +170,7 @@ void PIConsole::key_event(char key, void * t) {
void PIConsole::stop(bool clear) {
PIThread::stop(true);
if (clear) clearScreen();
- moveTo(0, my + 4);
+ moveTo(0, max_y + 4);
showCursor();
couts(fstr(Normal));
#ifdef WINDOWS
@@ -273,9 +295,12 @@ 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();
}
@@ -292,6 +317,7 @@ void PIConsole::run() {
width = ws.ws_col;
height = ws.ws_row;
#endif
+ __PICout_mutex__.lock();
if (pwidth != width || pheight != height) {
clearScreen();
fillLabels();
@@ -304,7 +330,7 @@ void PIConsole::run() {
PIVector & cvars(tabs[cur_tab].columns[i].variables);
cx = col_wid * i;
toUpperLeft();
- if (my < cvars.size()) my = cvars.size();
+ if (max_y < cvars.size()) max_y = cvars.size();
j = 0;
piForeachC (Variable & tv, cvars) {
if (j > height - 3) continue;
@@ -343,13 +369,19 @@ void PIConsole::run() {
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, my = 0, mx = 0, dx;
+ uint cx, cy, mx = 0, dx;
#ifdef WINDOWS
GetConsoleScreenBufferInfo(hOut, &sbi);
width = sbi.srWindow.Right - sbi.srWindow.Left;
@@ -360,6 +392,7 @@ void PIConsole::fillLabels() {
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) {
@@ -378,7 +411,7 @@ void PIConsole::fillLabels() {
toUpperLeft();
for (uint j = 0; j < cvars.size(); ++j) {
if (int(j) > height - 3) continue;
- if (my < j) my = j;
+ if (max_y < j) max_y = j;
moveRight(cx);
Variable & tv(cvars[j]);
cvars[j].nx = cx;
@@ -426,9 +459,9 @@ void PIConsole::fillLabels() {
}
}
#ifdef WINDOWS
- moveTo(0, my + 1);
+ moveTo(0, max_y + 1);
#else
- moveTo(0, my + 2);
+ moveTo(0, max_y + 2);
#endif
if (!tabs[cur_tab].status.isEmpty()) {
printValue(tabs[cur_tab].status);
@@ -446,7 +479,10 @@ void PIConsole::status() {
ctab = &tabs[i];
if (ctab->key == 0) continue;
printValue(ctab->key, PIConsole::White | PIConsole::Bold);
- printValue(ctab->name + " ", PIConsole::Cyan | PIConsole::Inverse);
+ if (i == cur_tab)
+ printValue(ctab->name + " ", PIConsole::BackYellow | PIConsole::Black);
+ else
+ printValue(ctab->name + " ", PIConsole::Cyan | PIConsole::Inverse);
printValue(" ");
}
newLine();
@@ -522,10 +558,10 @@ void PIConsole::addVariable(const PIString & name, const PIProtocol * ptr, int c
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("Sended count", ptr->sendCount_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);
@@ -535,6 +571,17 @@ void PIConsole::addVariable(const PIString & name, const PIProtocol * ptr, int c
addVariable("Disconnect Timeout, s", ptr->disconnectTimeout_ptr(), col, format);
addVariable("Quality", ptr->quality_ptr(), col, format);
}
+void PIConsole::addVariable(const PIString & name, const PIDiagnostics * ptr, int col, PIFlags 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, PIFlags format) {
addString("monitor " + name, col, format | PIConsole::Bold);
addVariable("state", &(ptr->statistic().state), col, format);
diff --git a/piconsole.h b/piconsole.h
index 0b76408d..c8975af6 100644
--- a/piconsole.h
+++ b/piconsole.h
@@ -22,6 +22,7 @@
#include "pikbdlistener.h"
#include "piprotocol.h"
+#include "pidiagnostics.h"
#include "pisystemmonitor.h"
#ifndef WINDOWS
# include
@@ -32,8 +33,9 @@
/// void clearVariables(bool clearScreen = true)
/// void start(bool wait = false)
/// void stop(bool clear = false)
-class PIConsole: public PIThread
+class PIP_EXPORT PIConsole: public PIThread
{
+ PIOBJECT(PIConsole)
public:
PIConsole(bool startNow = true, KBFunc slot = 0);
~PIConsole();
@@ -84,6 +86,7 @@ public:
void addVariable(const PIString & name, const float * ptr, int column = 1, PIFlags format = PIConsole::Normal);
void addVariable(const PIString & name, const double * ptr, int column = 1, PIFlags format = PIConsole::Normal);
void addVariable(const PIString & name, const PIProtocol * ptr, int column = 1, PIFlags format = PIConsole::Normal);
+ void addVariable(const PIString & name, const PIDiagnostics * ptr, int column = 1, PIFlags format = PIConsole::Normal);
void addVariable(const PIString & name, const PISystemMonitor * ptr, int column = 1, PIFlags format = PIConsole::Normal);
void addBitVariable(const PIString & name, const void * ptr, int fromBit, int bitCount, int column = 1, PIFlags format = PIConsole::Normal);
void addEmptyLine(int column = 1, uint count = 1);
@@ -117,14 +120,14 @@ public:
void setColumnAlignment(int col, Alignment align) {if (col < 0 || col >= columns().size_s()) return; column(col).alignment = align;}
void setColumnAlignmentToAll(Alignment align) {piForeach (Tab & i, tabs) piForeach (Column & j, i.columns) j.alignment = align; fillLabels();}
- EVENT_HANDLER0(PIConsole, void, clearVariables) {clearVariables(true);}
- EVENT_HANDLER1(PIConsole, void, clearVariables, bool, clearScreen) {if (clearScreen && isRunning()) {toUpperLeft(); clearScreenLower();} columns().clear();}
+ EVENT_HANDLER0(void, clearVariables) {clearVariables(true);}
+ EVENT_HANDLER1(void, clearVariables, bool, clearScreen) {if (clearScreen && isRunning()) {toUpperLeft(); clearScreenLower();} columns().clear();}
- EVENT_HANDLER0(PIConsole, void, waitForFinish) {WAIT_FOR_EXIT}
- EVENT_HANDLER0(PIConsole, void, start) {start(false);}
- EVENT_HANDLER1(PIConsole, void, start, bool, wait) {PIThread::start(40); if (wait) waitForFinish();}
- EVENT_HANDLER0(PIConsole, void, stop) {stop(false);}
- EVENT_HANDLER1(PIConsole, void, stop, bool, clear);
+ 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);
PIString fstr(PIFlags f);
void enableExitCapture(char key = 'Q') {listener->enableExitCapture(key);}
@@ -273,7 +276,7 @@ private:
Alignment def_align;
KBFunc ret_func;
int width, height, pwidth, pheight, ret, col_wid, num_format;
- uint my;
+ uint max_y;
uint cur_tab, col_cnt;
};
diff --git a/picontainers.h b/picontainers.h
index 46a0957f..810533f8 100644
--- a/picontainers.h
+++ b/picontainers.h
@@ -1,6 +1,12 @@
+/*! \file picontainers.h
+ * \brief Generic containers based on STL
+ *
+ * This file declare all containers and useful macroses
+ * to use them
+*/
/*
PIP - Platform Independent Primitives
- Generic containers, based on STL
+ Generic containers based on STL
Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
@@ -22,6 +28,37 @@
#include "piincludes.h"
+#ifdef DOXYGEN
+/*! \def piForeach(i,c)
+ * \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
+ */
+/*! \def piForeachC(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
+ */
+/*! \def piForeachR(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
+ */
+/*! \def piForeachCR(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
+ */
+#endif
+
#ifdef CC_GCC
template
@@ -126,42 +163,6 @@ template inline _PIForeachC * _PIForeachCastC(_PIForeachBase & c
#define piForTimes(c) for(int _i##c = 0; _i##c < c; ++_i##c)
-template
-class PIFlags {
-public:
- PIFlags(): flags(0) {;}
- PIFlags(Enum e): flags(e) {;}
- PIFlags(const PIFlags & f): flags(f.flags) {;}
- PIFlags(const int i): flags(i) {;}
- PIFlags & setFlag(const PIFlags & f, bool on = true) {if (on) flags |= f.flags; else flags &= ~f.flags; return *this;}
- PIFlags & setFlag(const Enum & e, bool on = true) {if (on) flags |= e; else flags &= ~e; return *this;}
- PIFlags & setFlag(const int & i, bool on = true) {if (on) flags |= i; else flags &= ~i; return *this;}
- void operator =(const PIFlags & f) {flags = f.flags;}
- void operator =(const Enum & e) {flags = e;}
- void operator =(const int & i) {flags = i;}
- void operator |=(const PIFlags & f) {flags |= f.flags;}
- void operator |=(const Enum & e) {flags |= e;}
- void operator |=(const int i) {flags |= i;}
- void operator &=(const PIFlags & f) {flags &= f.flags;}
- void operator &=(const Enum & e) {flags &= e;}
- void operator &=(const int i) {flags &= i;}
- void operator ^=(const PIFlags & f) {flags ^= f.flags;}
- void operator ^=(const Enum & e) {flags ^= e;}
- void operator ^=(const int i) {flags ^= i;}
- PIFlags operator |(PIFlags f) const {PIFlags tf(flags | f.flags); return tf;}
- PIFlags operator |(Enum e) const {PIFlags tf(flags | e); return tf;}
- PIFlags operator |(int i) const {PIFlags tf(flags | i); return tf;}
- PIFlags operator &(PIFlags f) const {PIFlags tf(flags & f.flags); return tf;}
- PIFlags operator &(Enum e) const {PIFlags tf(flags & e); return tf;}
- PIFlags operator &(int i) const {PIFlags tf(flags & i); return tf;}
- PIFlags operator ^(PIFlags f) const {PIFlags tf(flags ^ f.flags); return tf;}
- PIFlags operator ^(Enum e) const {PIFlags tf(flags ^ e); return tf;}
- PIFlags operator ^(int i) const {PIFlags tf(flags ^ i); return tf;}
- bool operator [](Enum e) const {return (flags & e) == e;}
- operator int() const {return flags;}
-private:
- int flags;
-};
/*
template
class PIVector {
@@ -269,7 +270,7 @@ public:
bool operator ==(const PIVector & t) const {if (size_ != t.size_) return false; for (uint i = 0; i < size_; ++i) if (t[i] != data_[i]) return false; return true;}
bool operator !=(const PIVector & t) const {if (size_ != t.size_) return true; for (uint i = 0; i < size_; ++i) if (t[i] != data_[i]) return true; return false;}
- bool contain(const T & v) const {for (uint i = 0; i < size_; ++i) if (v == data_[i]) return true; return false;}
+ bool contains(const T & v) const {for (uint i = 0; i < size_; ++i) if (v == data_[i]) return true; return false;}
T * data(int index = 0) {return &(data_[index]);}
const T * data(int index = 0) const {return &(data_[index]);}
@@ -370,35 +371,193 @@ private:
uint size_, rsize_, os;
};
*/
+
+/*! \brief Dynamic array for 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 there is stream operator <<.
+ * This class based on std::vector, expanding his
+ * functionality.
+ */
template >
-class PIVector: public vector {
+class PIP_EXPORT PIVector: public vector {
typedef PIVector _CVector;
typedef vector _stlc;
public:
+ //! Contructs an empty vector
PIVector() {piMonitor.containers++;}
+
+ //! Contructs vector with single element "value"
PIVector(const Type & value) {piMonitor.containers++; _stlc::push_back(value);}
+
+ //! Contructs vector with two elements "v0" and "v1"
PIVector(const Type & v0, const Type & v1) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1);}
+
+ //! Contructs vector with three elements "v0", "v1" and "v2"
PIVector(const Type & v0, const Type & v1, const Type & v2) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2);}
+
+ //! Contructs vector with four elements "v0", "v1", "v2" and "v3"
PIVector(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);}
+
+ /*! \brief Contructs vector with size "size" filled elements "value"
+ * \details Example: \snippet picontainers.cpp PIVector::PIVector */
PIVector(uint size, const Type & value = Type()) {piMonitor.containers++; _stlc::resize(size, value);}
~PIVector() {piMonitor.containers--;}
+
+ /*! \brief Read-only access to element by index "index"
+ * \details Example: \snippet picontainers.cpp PIVector::at_c
+ * \sa \a operator[] */
const Type & at(uint index) const {return (*this)[index];}
+
+ /*! \brief Full access to element by index "index"
+ * \details Example: \snippet picontainers.cpp PIVector::at
+ * \sa \a operator[] */
Type & at(uint index) {return (*this)[index];}
+
+ /*! \brief Read-only pointer to element by index "index"
+ * \details Example: \snippet picontainers.cpp PIVector::data_c */
const Type * data(uint index = 0) const {return &(*this)[index];}
+
+ /*! \brief Pointer to element by index "index"
+ * \details Example: \snippet picontainers.cpp PIVector::data */
Type * data(uint index = 0) {return &(*this)[index];}
+
+#ifdef DOXYGEN
+ //! Elements count
+ uint size() const;
+#endif
+
+ //! Elements count
int size_s() const {return static_cast(_stlc::size());}
+
+ //! Return \c "true" if vector is empty, i.e. size = 0
bool isEmpty() const {return _stlc::empty();}
+
+ //! Return \c "true" if vector has at least one element equal "t"
+ 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;}
+
+ //! Return how many times element "t" appears in vector
+ 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;}
typedef int (*CompareFunc)(const Type * , const Type * );
+
+ //! Standard compare function for type "Type". Return 0 if t0 = t1, -1 if t0 < t1 and 1 if t0 > t1.
static int compare_func(const Type * t0, const Type * t1) {return (*t0) == (*t1) ? 0 : ((*t0) < (*t1) ? -1 : 1);}
+#ifdef DOXYGEN
+
+ /*! \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() */
+ void resize(uint size, const Type & new_type = Type());
+
+ //! Increase vector size with "size" elements
+ PIVector & enlarge(uint size);
+
+ //! Clear vector. Equivalent to call "resize(0)"
+ void clear();
+
+ /*! \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 */
+ PIVector & sort(CompareFunc compare = compare_func) {qsort(&at(0), _stlc::size(), sizeof(Type), (int(*)(const void * , const void * ))compare); return *this;}
+
+ /*! \brief Fill vector with elements "t" leave size is unchanged and return reference to vector
+ * \details Example: \snippet picontainers.cpp PIVector::fill */
+ PIVector & fill(const Type & t) {_stlc::assign(_stlc::size(), t); return *this;}
+
+ //! Last element of vector
+ Type & back();
+
+ //! Last element of vector
+ const Type & back() const;
+
+ //! First element of vector
+ Type & front();
+
+ //! First element of vector
+ const Type & front() const;
+
+ //! Add new element "t" at the end of vector and return reference to vector
+ PIVector & push_back(const Type & t);
+
+ //! Add new element "t" at the beginning of vector and return reference to vector
+ PIVector & push_front(const Type & t) {_stlc::insert(_stlc::begin(), t); return *this;}
+
+ //! Remove one element from the end of vector and return reference to vector
+ PIVector & pop_back();
+
+ //! Remove one element from the beginning of vector and return reference to vector
+ PIVector & pop_front() {_stlc::erase(_stlc::begin()); return *this;}
+
+ //! Remove one element from the end of vector and return it
+ Type take_back() {Type t(_stlc::back()); _stlc::pop_back(); return t;}
+
+ //! Remove one element from the beginning of vector and return it
+ Type take_front() {Type t(_stlc::front()); pop_front(); return t;}
+
+ /*! \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() */
+ PIVector & remove(uint index) {_stlc::erase(_stlc::begin() + index); return *this;}
+
+ /*! \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() */
+ PIVector & remove(uint index, uint count) {_stlc::erase(_stlc::begin() + index, _stlc::begin() + index + count); return *this;}
+
+ /*! \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() */
+ PIVector & removeOne(const Type & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); return *this;} return *this;}
+
+ /*! \brief Remove all elements equal "v" and return reference to vector
+ * \details Example: \snippet picontainers.cpp PIVector::removeAll
+ * \sa \a remove(), \a removeOne() */ */
+ PIVector & removeAll(const Type & v) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (v == *i) {_stlc::erase(i); --i;} return *this;}
+
+ /*! \brief Insert element "t" after index "pos" and return reference to vector
+ * \details Example: \snippet picontainers.cpp PIVector::insert_0 */
+ PIVector & insert(uint pos, const Type & t) {_stlc::insert(_stlc::begin() + pos, t); return *this;}
+
+ /*! \brief Insert other vector "t" after index "pos" and return reference to vector
+ * \details Example: \snippet picontainers.cpp PIVector::insert_1 */
+ PIVector & insert(uint pos, const PIVector & t) {_stlc::insert(_stlc::begin() + pos, t.begin(), t.end()); return *this;}
+
+ /*! \brief Full access to element by index "index"
+ * \details Example: \snippet picontainers.cpp PIVector::()
+ * \sa \a at() */
+ Type & operator [](uint index);
+
+ /*! \brief Read-only access to element by index "index"
+ * \details Example: \snippet picontainers.cpp PIVector::()_c
+ * \sa \a at() */
+ const Type & operator [](uint index) const;
+
+ //! Add new element "t" at the end of vector and return reference to vector
+ PIVector & operator <<(const Type & t) {_stlc::push_back(t); return *this;}
+
+ //! Add vector "t" at the end of vector and return reference to vector
+ PIVector & operator <<(const PIVector & t) {for (typename _stlc::const_iterator i = t.begin(); i != t.end(); i++) _stlc::push_back(*i); return *this;}
+
+ //! Compare with vector "t"
+ bool operator ==(const PIVector & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return false; return true;}
+
+ //! Compare with vector "t"
+ 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 Type & v) const {for (uint i = 0; i < _stlc::size(); ++i) if (v == at(i)) return true; return false;}
+
+#else
+ _CVector & enlarge(uint 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(Type), (int(*)(const void * , const void * ))compare); return *this;}
_CVector & fill(const Type & t) {_stlc::assign(_stlc::size(), t); return *this;}
_CVector & pop_front() {_stlc::erase(_stlc::begin()); return *this;}
_CVector & push_front(const Type & t) {_stlc::insert(_stlc::begin(), t); return *this;}
Type take_front() {Type t(_stlc::front()); pop_front(); return t;}
Type take_back() {Type t(_stlc::back()); _stlc::pop_back(); return t;}
- _CVector & remove(uint num) {_stlc::erase(_stlc::begin() + num); return *this;}
- _CVector & remove(uint num, uint count) {_stlc::erase(_stlc::begin() + num, _stlc::begin() + num + count); return *this;}
- //_CVector & remove(const Type & t) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) {_stlc::erase(i); --i;} return *this;}
+ _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 Type & 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 Type & 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 Type & t) {_stlc::insert(_stlc::begin() + pos, t); return *this;}
@@ -407,14 +566,24 @@ public:
_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 contain(const Type & v) const {for (uint i = 0; i < _stlc::size(); ++i) if (v == at(i)) return true; return false;}
+ bool contains(const Type & v) const {for (uint i = 0; i < _stlc::size(); ++i) if (v == at(i)) return true; return false;}
+#endif
};
+/*! \brief Output operator for std::ostream
+ * \relates PIVector
+ * \details Example: \snippet picontainers.cpp PIVector::ostream<< */
template
inline std::ostream & operator <<(std::ostream & s, const PIVector & v) {s << "{"; for (uint i = 0; i < v.size(); ++i) {s << v[i]; if (i < v.size() - 1) s << ", ";} s << "}"; return s;}
+/*! \brief Output operator for PICout
+ * \relates PIVector
+ * \details Example: \snippet picontainers.cpp PIVector::PICout<< */
+template
+inline PICout operator <<(PICout s, const PIVector & 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;}
+
template >
-class PIList: public list {
+class PIP_EXPORT PIList: public list {
typedef PIList _CList;
typedef list _stlc;
public:
@@ -431,16 +600,18 @@ public:
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 num) {_stlc::erase(_stlc::begin() + num); return *this;}
- _CList & remove(uint num, uint count) {_stlc::erase(_stlc::begin() + num, _stlc::begin() + num + count); 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() {PIVector v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;}
};
template, typename Allocator = std::allocator >
-class PISet: public set {
+class PIP_EXPORT PISet: public set {
typedef PISet _CSet;
typedef set _stlc;
public:
@@ -452,15 +623,15 @@ public:
~PISet() {piMonitor.containers--;}
int size_s() const {return static_cast(_stlc::size());}
bool isEmpty() const {return _stlc::empty();}
- _CSet & remove(uint num) {_stlc::erase(_stlc::begin() + num); return *this;}
- _CSet & remove(uint num, uint count) {_stlc::erase(_stlc::begin() + num, _stlc::begin() + num + count); return *this;}
+ _CSet & remove(uint index) {_stlc::erase(_stlc::begin() + index); return *this;}
+ _CSet & remove(uint index, uint count) {_stlc::erase(_stlc::begin() + index, _stlc::begin() + index + count); return *this;}
_CSet & operator <<(const Type & t) {_stlc::insert(t); return *this;}
bool operator [](const Type & t) {return _stlc::find(t);}
PIVector toVector() {PIVector v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;}
};
template
-class PIStack: public PIVector {
+class PIP_EXPORT PIStack: public PIVector {
typedef PIStack _CStack;
public:
PIStack() {;}
@@ -476,7 +647,7 @@ public:
};
template >
-class PIDeque: public deque {
+class PIP_EXPORT PIDeque: public deque {
typedef PIDeque _CDeque;
typedef deque _stlc;
public:
@@ -488,12 +659,14 @@ public:
~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;}
PIVector toVector() {PIVector v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;}
};
template
-class PIQueue: public PIDeque {
+class PIP_EXPORT PIQueue: public PIDeque {
typedef PIQueue _CQueue;
public:
PIQueue() {;}
@@ -510,7 +683,7 @@ public:
template
-class PIPair {
+class PIP_EXPORT PIPair {
public:
PIPair() {first = Type0(); second = Type1();}
PIPair(const Type0 & value0, const Type1 & value1) {first = value0; second = value1;}
@@ -519,21 +692,62 @@ public:
};
template
inline bool operator <(const PIPair & value0, const PIPair & value1) {return value0.first < value1.first;}
+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;}
template
-class PIMap: public map {
+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_);}
- _CMap & insert(const Key & key_, const Type & value_) {_stlc::insert(std::pair(key_, value_)); return *this;}
- _CMap & insert(PIPair entry_) {_stlc::insert(std::pair(entry_.first, entry_.second)); return *this;}
+ bool isEmpty() const {return _stlc::empty();}
+ bool contains(const Key & key_) const {return _stlc::count(key_) > 0;}
+ _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 {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++) if (i->second == value_) return i->first; return Key();}
- Type & value(Key key_) {return (*this)[key_];}
- Type value(Key key_) const {return (*this)[key_];}
+ Type & value(const Key & key_) {typename _stlc::iterator it = _stlc::find(key_); if (it == _stlc::end()) it->second = Type(); return it->second;}
+ Type value(const Key & key_) const {return _stlc::find(key_)->second;}
};
+
+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 {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); i++) if (i->second == value_) return i->first; return Key();}
+ 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_) {return _stlc::find(key_)->second;}
+ Type value(const Key & key_) const {return _stlc::find(key_)->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;}
+};
+
+
#endif // PICONTAINERS_H
diff --git a/picrc.h b/picrc.h
index d855792f..4b0c08c0 100644
--- a/picrc.h
+++ b/picrc.h
@@ -23,7 +23,7 @@
#include "pistring.h"
template
-class uint_cl {
+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];}
@@ -160,7 +160,7 @@ inline std::ostream & operator <<(std::ostream & s, const uint_cl & v) {std::
template
-class PICRC {
+class PIP_EXPORT PICRC {
public:
PICRC(const uint_cl & poly) {poly_ = poly; reverse_poly = true; init_ = uint_cl(0).inversed(); out_ = uint_cl(0).inversed(); initTable();}
PICRC(const uint_cl & poly, bool reverse, const uint_cl & initial, const uint_cl & out_xor) {poly_ = poly; reverse_poly = reverse; init_ = initial; out_ = out_xor; initTable();}
diff --git a/pidir.h b/pidir.h
index 81f1c13c..10af5142 100644
--- a/pidir.h
+++ b/pidir.h
@@ -26,7 +26,7 @@
#include
#include
-class PIDir
+class PIP_EXPORT PIDir
{
public:
PIDir();
diff --git a/piethernet.cpp b/piethernet.cpp
index f906ce34..32f5b2bc 100644
--- a/piethernet.cpp
+++ b/piethernet.cpp
@@ -1,6 +1,6 @@
/*
PIP - Platform Independent Primitives
- Ethernet, UDP
+ Ethernet, UDP/TCP Broadcast/Multicast
Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
@@ -47,7 +47,7 @@ PIEthernet::PIEthernet(PIEthernet::Type type, void * data, ReadRetFunc slot): PI
sock = sock_s = -1;
ret_func_ = slot;
connected_ = false;
- params = PIEthernet::ReuseAddress;
+ params = (type == UDP ? PIEthernet::ReuseAddress : 0);
server_thread_.setData(this);
setThreadedReadBufferSize(65536);
if (type_ != UDP) init();
@@ -58,6 +58,7 @@ PIEthernet::PIEthernet(int sock_, PIString ip_port): PIIODevice("", ReadWrite) {
piMonitor.ethernets++;
setPriority(piHigh);
type_ = TCP_Client;
+ path_ = ip_port;
parseAddress(ip_port, &ip_s, &port_s);
sock = sock_;
sock_s = -1;
@@ -80,22 +81,28 @@ PIEthernet::~PIEthernet() {
bool PIEthernet::init() {
//cout << "init " << type_ << endl;
closeSocket(sock);
- int st = 0;
+ int st = 0, pr = 0;;
#ifdef WINDOWS
- int flags = WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF;
+ int flags = 0;
#else
int so = 1;
#endif
- if (type_ == UDP) st = SOCK_DGRAM;
- else st = SOCK_STREAM;
+ if (type_ == UDP) {
+ st = SOCK_DGRAM;
+ pr = IPPROTO_UDP;
+ } else {
+ st = SOCK_STREAM;
+ pr = IPPROTO_TCP;
+ }
#ifdef WINDOWS
+ if (type_ == UDP) flags = WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF;
if (params[ReuseAddress]) flags |= WSA_FLAG_OVERLAPPED;
- sock = WSASocket(AF_INET, st, type_ == UDP ? IPPROTO_UDP : IPPROTO_TCP, NULL, 0, flags);
+ sock = WSASocket(AF_INET, st, pr, NULL, 0, flags);
#else
- sock = socket(AF_INET, st, type_ == UDP ? IPPROTO_UDP : IPPROTO_TCP);
+ sock = socket(AF_INET, st, pr);
#endif
if (sock == -1) {
- piCout << "[PIEthernet] Cant`t create socket, " << EthErrorString() << endl;
+ piCout << "[PIEthernet] Cant`t create socket, " << ethErrorString();
return false;
}
#ifndef WINDOWS
@@ -116,9 +123,11 @@ void PIEthernet::parseAddress(const PIString & ipp, PIString * ip, int * port) {
bool PIEthernet::openDevice() {
if (connected_) return true;
- if (sock == -1) init();
+ init();
if (sock == -1 || path_.isEmpty()) return false;
parseAddress(path_, &ip_, &port_);
+ if (type_ != UDP)
+ return true;
//cout << " bind to " << sock << ": " << (params[PIEthernet::Broadcast] ? "0.0.0.0" : path_) << ": " << port_ << " ..." <= 0) received(read_to, rs);
+ piCout << "eth" << path_ << "read return" << rs << errno;
+ if (rs <= 0) {
+ connected_ = false;
+ disconnected(rs < 0);
+ piCout << "eth" << path_ << "disconnected";
+ }
+ if (rs > 0) received(read_to, rs);
return rs;
//return ::read(sock, read_to, max_size);
default: break;
@@ -313,10 +342,10 @@ int PIEthernet::read(void * read_to, int max_size) {
int PIEthernet::write(const void * data, int max_size) {
if (sock == -1) init();
if (sock == -1 || !isWriteable()) {
- //piCout << "[PIEthernet] Can`t send to uninitialized socket" << endl;
+ //piCout << "[PIEthernet] Can`t send to uninitialized socket";
return -1;
}
- //piCout << "[PIEthernet] sending to " << ip_s << ":" << port_s << " " << max_size << " bytes" << endl;
+ //piCout << "[PIEthernet] sending to " << ip_s << ":" << port_s << " " << max_size << " bytes";
int ret = 0;
switch (type_) {
case TCP_SingleTCP:
@@ -327,11 +356,14 @@ int PIEthernet::write(const void * data, int max_size) {
#ifdef QNX
addr_.sin_len = sizeof(addr_);
#endif
+ //piCout << "connect SingleTCP" << ip_s << ":" << port_s << "...";
if (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) != 0) {
- piCout << "[PIEthernet] Cant`t connect to " << ip_s << ":" << port_s << ", " << EthErrorString() << endl;
+ piCout << "[PIEthernet] Cant`t connect to " << ip_s << ":" << port_s << ", " << ethErrorString();
return -1;
}
- ret = ::write(sock, data, max_size);
+ //piCout << "ok, write SingleTCP" << int(data) << max_size << "bytes ...";
+ ret = ::send(sock, (const char *)data, max_size, 0);
+ //piCout << "ok, ret" << ret;
closeSocket(sock);
init();
return ret;
@@ -346,7 +378,7 @@ int PIEthernet::write(const void * data, int max_size) {
return sendto(sock, data, max_size, 0, (sockaddr * )&saddr_, sizeof(saddr_));
#endif
case TCP_Client:
- return ::write(sock, data, max_size);
+ return ::send(sock, (const char *)data, max_size, 0);
default: break;
//return ::read(sock, read_to, max_size);
}
@@ -359,12 +391,13 @@ void PIEthernet::server_func(void * eth) {
socklen_t slen = sizeof(client_addr);
int s = accept(ce->sock, (sockaddr * )&client_addr, &slen);
if (s == -1) {
- piCout << "[PIEthernet] Cant`t accept new connection, " << EthErrorString() << endl;
+ piCout << "[PIEthernet] Cant`t accept new connection, " << ethErrorString();
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;
@@ -375,7 +408,7 @@ void PIEthernet::server_func(void * eth) {
PIStringList PIEthernet::interfaces() {
#ifdef WINDOWS
- piCout << "[PIEthernet] Not implemented on Windows, use \"PIEthernet::allAddresses\" instead" << endl;
+ piCout << "[PIEthernet] Not implemented on Windows, use \"PIEthernet::allAddresses\" instead";
return PIStringList();
#else
# ifdef QNX
@@ -434,7 +467,7 @@ PIStringList PIEthernet::interfaces() {
PIString PIEthernet::interfaceAddress(const PIString & interface_) {
#ifdef WINDOWS
- piCout << "[PIEthernet] Not implemented on Windows, use \"PIEthernet::allAddresses\" instead" << endl;
+ piCout << "[PIEthernet] Not implemented on Windows, use \"PIEthernet::allAddresses\" instead";
return PIString();
#else
struct ifreq ifr;
@@ -459,14 +492,14 @@ PIStringList PIEthernet::allAddresses() {
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" << endl;
+ 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" << endl;
+ piCout << "[PIEthernet] Error allocating memory needed to call GetAdaptersinfo";
return PIStringList();
}
}
@@ -482,7 +515,7 @@ PIStringList PIEthernet::allAddresses() {
pAdapter = pAdapter->Next;
}
} else
- piCout << "[PIEthernet] GetAdaptersInfo failed with error: " << ret << endl;
+ piCout << "[PIEthernet] GetAdaptersInfo failed with error: " << ret;
if (pAdapterInfo)
HeapFree(GetProcessHeap(), 0, (pAdapterInfo));
return al;
@@ -490,6 +523,6 @@ PIStringList PIEthernet::allAddresses() {
PIStringList il = interfaces(), al;
piForeachC (PIString & i, il)
al << interfaceAddress(i);
- return al;
+ return al.removeStrings("0.0.0.0");
#endif
}
diff --git a/piethernet.h b/piethernet.h
index 89fbfdd7..c75d3fa0 100644
--- a/piethernet.h
+++ b/piethernet.h
@@ -1,6 +1,6 @@
/*
PIP - Platform Independent Primitives
- Ethernet, UDP
+ Ethernet, UDP/TCP Broadcast/Multicast
Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com
This program is free software: you can redistribute it and/or modify
@@ -24,8 +24,9 @@
#include "piiodevice.h"
#include "piprocess.h"
-class PIEthernet: public PIIODevice
+class PIP_EXPORT PIEthernet: public PIIODevice
{
+ PIOBJECT(PIEthernet)
friend class PIPeer;
public:
// slot is any function format "bool (void*, uchar*, int)"
@@ -35,7 +36,7 @@ public:
enum Parameters {ReuseAddress = 0x1, Broadcast = 0x2};
PIEthernet(Type type = UDP, void * data = 0, ReadRetFunc slot = 0);
- ~PIEthernet();
+ virtual ~PIEthernet();
void setReadAddress(const PIString & ip, int port) {path_ = ip + ":" + PIString::fromNumber(port);}
void setReadAddress(const PIString & ip_port) {path_ = ip_port;}
@@ -61,8 +62,9 @@ public:
bool joinMulticastGroup(const PIString & group);
bool leaveMulticastGroup(const PIString & group);
- bool connect(const PIString & ip, int port);
- bool connect(const PIString & ip_port) {parseAddress(ip_port, &ip_c, &port_c); return connect(ip_c, port_c);}
+ bool connect();
+ bool connect(const PIString & ip, int port) {path_ = ip + ":" + PIString::fromNumber(port); return connect();}
+ bool connect(const PIString & ip_port) {path_ = ip_port; return connect();}
bool isConnected() const {return connected_;}
bool listen();
@@ -73,9 +75,10 @@ public:
int clientsCount() const {return clients_.size_s();}
PIVector clients() {return clients_;}
- bool send(const PIString & ip, int port, const void * data, int size) {ip_s = ip; port_s = port; return send(data, size);}
- bool send(const PIString & ip_port, const void * data, int size) {parseAddress(ip_port, &ip_s, &port_s); return send(data, size);}
- bool send(const void * data, int size) {return (write(data, size) == size);}
+ 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);}
+ 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);}
+ bool send(const void * data, int size, bool threaded = false) {if (threaded) {writeThreaded(data, size); return true;} return (write(data, size) == size);}
+ bool send(const PIByteArray & ba, bool threaded = false) {if (threaded) {writeThreaded(ba); return true;} return (write(ba) == ba.size_s());}
int read(void * read_to, int max_size);
int write(const void * data, int max_size);
@@ -84,6 +87,10 @@ public:
static PIStringList interfaces();
static PIString interfaceAddress(const PIString & interface_);
static PIStringList allAddresses();
+
+ EVENT1(newConnection, PIEthernet * , client)
+ EVENT0(connected)
+ EVENT1(disconnected, bool, withError)
protected:
PIEthernet(int sock, PIString ip_port);
@@ -106,6 +113,7 @@ protected:
PIString ip_, ip_s, ip_c;
PIThread server_thread_;
PIVector clients_;
+ PIQueue mcast_queue;
#ifdef WINDOWS
PIMap leafs;
#endif
@@ -115,7 +123,7 @@ protected:
private:
static void server_func(void * eth);
- static std::string EthErrorString() {
+ static std::string ethErrorString() {
#ifdef WINDOWS
char * msg;
int err = WSAGetLastError();
diff --git a/pievaluator.h b/pievaluator.h
index 229ee3fc..38c4500b 100644
--- a/pievaluator.h
+++ b/pievaluator.h
@@ -72,7 +72,7 @@ namespace PIEvaluatorTypes {
⋀ &
⋁ |
*/
-class PIEvaluatorContent
+class PIP_EXPORT PIEvaluatorContent
{
friend class PIEvaluator;
public:
@@ -108,7 +108,7 @@ private:
};
-class PIEvaluator
+class PIP_EXPORT PIEvaluator
{
public:
PIEvaluator() {;}
diff --git a/pifile.cpp b/pifile.cpp
index 93f99a94..4587418f 100644
--- a/pifile.cpp
+++ b/pifile.cpp
@@ -32,7 +32,7 @@ bool PIFile::openDevice() {
bool PIFile::closeDevice() {
- if (!opened_) return true;
+ if (!opened_ || fd == 0) return true;
return (fclose(fd) == 0);
}
@@ -104,7 +104,7 @@ void PIFile::resize(llong new_size, char fill_) {
delete[] buff;
return;
}
- piCout << "[PIFile] Downsize is not support yet :-(" << endl;
+ piCout << "[PIFile] Downsize is not support yet :-(";
}
diff --git a/pifile.h b/pifile.h
index 694a8d3e..8133c03b 100644
--- a/pifile.h
+++ b/pifile.h
@@ -27,27 +27,29 @@
/// void clear()
/// void resize(llong new_size, char fill = 0)
/// void remove()
-class PIFile: public PIIODevice
+class PIP_EXPORT PIFile: public PIIODevice
{
+ PIOBJECT(PIFile)
public:
PIFile(const PIString & path = PIString(), DeviceMode type = ReadWrite): PIIODevice(path, type) {setPrecision(5); openDevice();}
+ ~PIFile() {close();}
//PIFile & operator =(const PIFile & f) {path_ = f.path_; type_ = f.type_; return *this;}
- void flush() {fflush(fd);}
- EVENT_HANDLER(PIFile, void, clear) {close(); fd = fopen(path_.data(), "w"); close(); open();}
+ void flush() {if (!opened_) fflush(fd);}
+ EVENT_HANDLER(void, clear) {close(); fd = fopen(path_.data(), "w"); if (fd != 0) fclose(fd); fd = 0; opened_ = false; open();}
void seek(llong position) {if (!opened_) return; fseek(fd, position, SEEK_SET); clearerr(fd);}
void seekToBegin() {if (!opened_) return; fseek(fd, 0, SEEK_SET); clearerr(fd);}
void seekToEnd() {if (!opened_) return; fseek(fd, 0, SEEK_END); clearerr(fd);}
void seekToLine(llong line) {if (!opened_) return; seekToBegin(); piForTimes (line) readLine(); clearerr(fd);} // line 0 - begin of file
- EVENT_HANDLER1(PIFile, void, resize, llong, new_size) {resize(new_size, 0);}
- EVENT_HANDLER2(PIFile, void, resize, llong, new_size, char, fill);
+ EVENT_HANDLER1(void, resize, llong, new_size) {resize(new_size, 0);}
+ EVENT_HANDLER2(void, resize, llong, new_size, char, fill);
//void fill(char c) {stream.fill(c);}
char readChar() {return (char)fgetc(fd);}
PIString readLine();
llong readAll(void * data);
PIByteArray readAll(bool forceRead = false);
- EVENT_HANDLER0(PIFile, void, remove) {close(); std::remove(path_.data());}
+ EVENT_HANDLER0(void, remove) {close(); std::remove(path_.data());}
void setPath(const PIString & path) {path_ = path; if (opened_) openDevice();}
llong size();
@@ -56,11 +58,11 @@ public:
bool isEmpty() {return (size() <= 0);}
int precision() const {return prec;}
- void setPrecision(int prec_) {prec = prec_; prec_str = "." + itos(prec_);}
+ void setPrecision(int prec_) {prec = prec_; if (prec >= 0) prec_str = "." + itos(prec_); else prec_str = "";}
- int read(void * read_to, int max_size) {if (!canRead()) return -1; return fread(read_to, max_size, 1, fd);}
- int write(const void * data, int max_size) {if (!canWrite()) return -1; return fwrite(data, max_size, 1, fd);}
- PIFile & writeToBinLog(ushort id, const void * data, int size) {if (!isWriteable()) return *this; writeBinary(id).writeBinary((ushort)size); write(data, size); flush(); return *this;}
+ int read(void * read_to, int max_size) {if (!canRead() || fd == 0) return -1; return fread(read_to, max_size, 1, fd);}
+ int write(const void * data, int max_size) {if (!canWrite() || fd == 0) return -1; return fwrite(data, max_size, 1, 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;}
PIFile & writeBinary(const char v) {write(&v, sizeof(v)); return *this;}
PIFile & writeBinary(const short v) {write(&v, sizeof(v)); return *this;}
@@ -75,7 +77,9 @@ public:
PIFile & writeBinary(const float v) {write(&v, sizeof(v)); return *this;}
PIFile & writeBinary(const double v) {write(&v, sizeof(v)); return *this;}
- PIFile & operator <<(const char & v) {if (!isWriteable()) return *this; write(&v, 1); return *this;}
+ PIFile & operator =(const PIFile & f) {path_ = f.path_; mode_ = f.mode_; return *this;}
+
+ PIFile & operator <<(const char v) {if (!isWriteable()) return *this; write(&v, 1); return *this;}
//PIFile & operator <<(const string & v) {write(v.c_str(), v.size()); return *this;}
PIFile & operator <<(const PIString & v) {if (!isWriteable()) return *this; write(v.data(), v.lengthAscii()); return *this;}
PIFile & operator <<(const PIByteArray & v) {if (!isWriteable()) return *this; write(v.data(), v.size()); return *this;}
@@ -83,11 +87,11 @@ public:
PIFile & operator <<(int v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%d", v); return *this;}
PIFile & operator <<(long v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%ld", v); return *this;}
PIFile & operator <<(llong v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%lld", v); return *this;}
- PIFile & operator <<(uchar v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%c", v); return *this;}
- PIFile & operator <<(ushort v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%hd", v); return *this;}
- PIFile & operator <<(uint v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%d", v); return *this;}
- PIFile & operator <<(ulong v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%ld", v); return *this;}
- PIFile & operator <<(ullong v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%lld", v); return *this;}
+ PIFile & operator <<(uchar v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%u", int(v)); return *this;}
+ PIFile & operator <<(ushort v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%hu", v); return *this;}
+ PIFile & operator <<(uint v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%u", v); return *this;}
+ PIFile & operator <<(ulong v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%lu", v); return *this;}
+ PIFile & operator <<(ullong v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%llu", v); return *this;}
PIFile & operator <<(float v) {if (!isWriteable()) return *this; ret = fprintf(fd, ("%" + prec_str + "f").c_str(), v); return *this;}
PIFile & operator <<(double v) {if (!isWriteable()) return *this; ret = fprintf(fd, ("%" + prec_str + "lf").c_str(), v); return *this;}
diff --git a/pigeometry.h b/pigeometry.h
index 1536f7b0..a743b481 100644
--- a/pigeometry.h
+++ b/pigeometry.h
@@ -23,7 +23,7 @@
#include "pimath.h"
template
-class PIPoint {
+class PIP_EXPORT PIPoint {
public:
Type x;
Type y;
@@ -55,7 +55,7 @@ template
std::ostream & operator <<(std::ostream & s, const PIPoint & v) {s << '{' << v.x << ", " << v.y << '}'; return s;}
template
-class PIRect {
+class PIP_EXPORT PIRect {
public:
Type x0;
Type y0;
diff --git a/piincludes.cpp b/piincludes.cpp
index e149d432..7ddab3c7 100644
--- a/piincludes.cpp
+++ b/piincludes.cpp
@@ -18,6 +18,7 @@
*/
#include "piincludes.h"
+#include "pimutex.h"
bool isPIInit = false;
bool piDebug = true;
@@ -29,3 +30,41 @@ lconv * currentLocale = std::localeconv();
#ifdef MAC_OS
clock_serv_t __pi_mac_clock;
#endif
+
+PIMutex __PICout_mutex__;
+
+
+/*! \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 Example
+ * \snippet picout.cpp 0
+ */
+
+
+PICout::PICout(PIFlags controls): fo_(true), cc_(false), co_(controls) {
+ __PICout_mutex__.lock();
+}
+
+
+PICout::~PICout() {
+ if (cc_) return;
+ newLine();
+ __PICout_mutex__.unlock();
+}
+
+
+/*! \mainpage Title
+ * This is main page
+ */
diff --git a/piincludes.h b/piincludes.h
index 5f7b3813..5cef4c1f 100644
--- a/piincludes.h
+++ b/piincludes.h
@@ -1,3 +1,9 @@
+/*! \file piincludes.h
+ * \brief Global includes of PIP
+ *
+ * This file include all needed STL and declare many useful
+ * macros and functions
+*/
/*
PIP - Platform Independent Primitives
Global includes
@@ -20,12 +26,58 @@
#ifndef PIINCLUDES_H
#define PIINCLUDES_H
-#define PIP_VERSION 0x000300
+//! Version of PIP in hex - 0x##(Major)##(Minor)##(Revision)
+#define PIP_VERSION 0x000304
+
+//! Major value of PIP version
#define PIP_VERSION_MAJOR (PIP_VERSION & 0xFF0000) >> 16
+
+//! Minor value of PIP version
#define PIP_VERSION_MINOR (PIP_VERSION & 0xFF00) >> 8
+
+//! Revision value of PIP version
#define PIP_VERSION_REVISION PIP_VERSION & 0xFF
+
+//! Suffix of PIP version
#define PIP_VERSION_SUFFIX ""
+#ifdef DOXYGEN
+
+//! 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 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
+
+#endif
+
#if WIN32 || WIN64 || _WIN32 || _WIN64 || __WIN32__ || __WIN64__
# define WINDOWS
#endif
@@ -60,6 +112,13 @@
#else
# define CC_OTHER
#endif
+#ifdef PIP_DEBUG
+# undef NDEBUG
+#else
+# ifndef NDEBUG
+# define NDEBUG
+# endif
+#endif
#ifdef WINDOWS
# ifdef CC_GCC
@@ -69,6 +128,11 @@
# define typeof __typeof__
#endif
+#include "pip_export.h"
+#if defined(DOXYGEN) || defined(CC_GCC)
+# undef PIP_EXPORT
+# define PIP_EXPORT
+#endif
#include
#ifdef CC_GCC
# include
@@ -90,6 +154,7 @@
#include
#include
#include
+#include
//#include
#include
#include
@@ -153,7 +218,10 @@ extern char ** environ;
extern PIMonitor piMonitor;
+//! Macro used for infinite loop
#define FOREVER for (;;)
+
+//! Macro used for infinite wait
#define FOREVER_WAIT FOREVER msleep(1);
typedef long long llong;
@@ -175,6 +243,7 @@ using std::deque;
using std::stack;
using std::set;
using std::map;
+using std::multimap;
using std::string;
#ifndef QNX
using std::wstring;
@@ -188,15 +257,118 @@ typedef std::basic_string wstring;
static locale_t currentLocale_t = 0;
#endif
+/*! \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 return round of float falue
+ * \details Round is the nearest integer value \n
+ * There is 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 is 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 is 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 is 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 is 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 is 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 is 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 is 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 is 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));}
#define piRoundf piRound
@@ -231,10 +403,11 @@ template inline T piClamp(const T & v, const T & min, const T & max)
#define piClampd piClamp
extern bool isPIInit;
-extern bool piDebug;
-extern string ifconfigPath;
-#define piCout if (piDebug) cout
+//! global variable enabling output to piCout
+extern bool piDebug;
+
+extern string ifconfigPath;
class PIInit {
public:
@@ -245,10 +418,8 @@ public:
sigset_t ss;
sigemptyset(&ss);
sigaddset(&ss, SIGALRM);
- if (pthread_sigmask(SIG_BLOCK, &ss, 0) == -1) {
- //cout << "[PITimer] sigaction error: " << errorString() << endl;
- //return 0;
- }
+ sigprocmask(SIG_BLOCK, &ss, 0);
+ pthread_sigmask(SIG_BLOCK, &ss, 0);
ifconfigPath = "/bin/ifconfig";
if (!fileExists(ifconfigPath)) {
ifconfigPath = "/sbin/ifconfig";
@@ -305,8 +476,8 @@ inline double round(const double & v) {return floor(v + 0.5);}
#endif
inline ushort letobe_s(ushort v) {return v = (v << 8) | (v >> 8);}
-inline bool atob(const string & str) { return str == "1" ? true : false;};
-inline string btos(const bool num) { return num ? "0" : "1";};
+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
@@ -314,7 +485,7 @@ inline string itos(const int num) {
#else
sprintf_s(ch, 256, "%d", num);
#endif
- return string(ch); };
+ return string(ch);}
inline string ltos(const long num) {
char ch[256];
#ifndef CC_VC
@@ -322,23 +493,23 @@ inline string ltos(const long num) {
#else
sprintf_s(ch, 256, "%ld", num);
#endif
- return string(ch); };
+ return string(ch);}
inline string uitos(const uint num) {
char ch[256];
#ifndef CC_VC
- sprintf(ch, "%ud", num);
+ sprintf(ch, "%u", num);
#else
- sprintf_s(ch, 256, "%ud", num);
+ sprintf_s(ch, 256, "%u", num);
#endif
- return string(ch); };
+ return string(ch);}
inline string ultos(const ulong num) {
char ch[256];
#ifndef CC_VC
- sprintf(ch, "%lud", num);
+ sprintf(ch, "%lu", num);
#else
- sprintf_s(ch, 256, "%lud", num);
+ sprintf_s(ch, 256, "%lu", num);
#endif
- return string(ch); };
+ return string(ch);}
inline string ftos(const float num) {
char ch[256];
#ifndef CC_VC
@@ -346,7 +517,7 @@ inline string ftos(const float num) {
#else
sprintf_s(ch, 256, "%g", num);
#endif
- return string(ch); };
+ return string(ch);}
inline string dtos(const double num) {
char ch[256];
#ifndef CC_VC
@@ -354,9 +525,11 @@ inline string dtos(const double num) {
#else
sprintf_s(ch, 256, "%g", num);
#endif
- return string(ch); };
+ return string(ch);}
-#ifdef CC_VC
+/*! \fn errorString()
+ * \brief Return readable error description in format "code - " */
+#ifdef WINDOWS
inline string errorString() {
char * msg;
int err = GetLastError();
@@ -368,6 +541,259 @@ inline void errorClear() {errno = 0;}
inline string errorString() {int e = errno; return "code " + itos(e) + " - " + string(strerror(e));}
#endif
+/// Return readable version of PIP
inline string PIPVersion() {return itos(PIP_VERSION_MAJOR) + "." + itos(PIP_VERSION_MINOR) + "." + itos(PIP_VERSION_REVISION) + PIP_VERSION_SUFFIX;}
+/*! \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
+ void operator ==(const PIFlags & f) {flags == f.flags;}
+ //! compare operator
+ void operator ==(const Enum & e) {flags == e;}
+ //! compare operator
+ void operator ==(const int i) {flags == i;}
+ //! compare operator
+ void operator !=(const PIFlags & f) {flags != f.flags;}
+ //! compare operator
+ void operator !=(const Enum & e) {flags != e;}
+ //! compare operator
+ void operator !=(const int i) {flags != i;}
+ //! compare operator
+ void operator >(const PIFlags & f) {flags > f.flags;}
+ //! compare operator
+ void operator >(const Enum & e) {flags > e;}
+ //! compare operator
+ void operator >(const int i) {flags > i;}
+ //! compare operator
+ void operator <(const PIFlags & f) {flags < f.flags;}
+ //! compare operator
+ void operator <(const Enum & e) {flags < e;}
+ //! compare operator
+ void operator <(const int i) {flags < i;}
+ //! compare operator
+ void operator >=(const PIFlags & f) {flags >= f.flags;}
+ //! compare operator
+ void operator >=(const Enum & e) {flags >= e;}
+ //! compare operator
+ void operator >=(const int i) {flags >= i;}
+ //! compare operator
+ void operator <=(const PIFlags & f) {flags <= f.flags;}
+ //! compare operator
+ void operator <=(const Enum & e) {flags <= e;}
+ //! compare operator
+ void operator <=(const int i) {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;
+};
+
+//! Macro used for conditional (piDebug) output to PICout
+#define piCout if (piDebug) PICout()
+
+class PIMutex;
+extern PIMutex __PICout_mutex__;
+
+//! \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 */
+ };
+
+ //! \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
+ };
+};
+
+using namespace PICoutManipulators;
+
+typedef PIFlags PICoutControls;
+
+class PIP_EXPORT PICout {
+public:
+ //! Default constructor with default features
+ PICout(PIFlags controls = AddSpaces | AddNewLine);
+
+ PICout(const PICout & other): fo_(other.fo_), cc_(true), co_(other.co_) {;}
+ ~PICout();
+
+ //! Output operator for strings with "const char * " type
+ PICout operator <<(const char * v) {space(); quote(); std::cout << v; quote(); return *this;}
+
+ //! Output operator for strings with "std::string" type
+ PICout operator <<(const string & v) {space(); quote(); std::cout << v; quote(); return *this;}
+
+ //! Output operator for boolean values
+ PICout operator <<(const bool v) {space(); std::cout << v; return *this;}
+
+ //! Output operator for "char" values
+ PICout operator <<(const char v) {space(); std::cout << v; return *this;}
+
+ //! Output operator for "unsigned char" values
+ PICout operator <<(const uchar v) {space(); std::cout << ushort(v); return *this;}
+
+ //! Output operator for "short" values
+ PICout operator <<(const short v) {space(); std::cout << v; return *this;}
+
+ //! Output operator for "unsigned short" values
+ PICout operator <<(const ushort v) {space(); std::cout << v; return *this;}
+
+ //! Output operator for "int" values
+ PICout operator <<(const int v) {space(); std::cout << v; return *this;}
+
+ //! Output operator for "unsigned int" values
+ PICout operator <<(const uint v) {space(); std::cout << v; return *this;}
+
+ //! Output operator for "long" values
+ PICout operator <<(const long v) {space(); std::cout << v; return *this;}
+
+ //! Output operator for "unsigned long" values
+ PICout operator <<(const ulong v) {space(); std::cout << v; return *this;}
+
+ //! Output operator for "long long" values
+ PICout operator <<(const llong v) {space(); std::cout << v; return *this;}
+
+ //! Output operator for "unsigned long long" values
+ PICout operator <<(const ullong v) {space(); std::cout << v; return *this;}
+
+ //! Output operator for "float" values
+ PICout operator <<(const float v) {space(); std::cout << v; return *this;}
+
+ //! Output operator for "double" values
+ PICout operator <<(const double v) {space(); std::cout << v; return *this;}
+
+ //! Output operator for \a PICoutSpecialChar values
+ PICout operator <<(const PICoutSpecialChar v) {
+ switch (v) {
+ case Null: std::cout << char(0);
+ case NewLine: std::cout << '\n';
+ case Tab: std::cout << '\t';
+ case Esc: std::cout << '\e';
+ case Quote: std::cout << '"';
+ };
+ return *this;
+ }
+
+ //! Do some action
+ PICout operator <<(const PICoutAction v) {
+ switch (v) {
+ case Flush: std::cout << std::flush;
+ };
+ return *this;
+ }
+
+ //! Set control flag "c" is "on" state
+ void setControl(PICoutControl c, bool on = true) {co_.setFlag(c, on);}
+
+ //! Set control flags "c" and if "save" exec \a saveControl()
+ void setControl(PICoutControls c, bool save = false) {if (save) saveControl(); co_ = c;}
+
+ //! Save control flags to internal stack \sa \a restoreControl()
+ void saveControl() {cos_.push(co_);}
+
+ //! Restore control flags from internal stack \sa \a saveControl()
+ void restoreControl() {if (!cos_.empty()) {co_ = cos_.top(); cos_.pop();}}
+
+ /*! \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() */
+ inline void space() {if (!fo_ && co_[AddSpaces]) std::cout << ' '; fo_ = false;}
+
+ /*! \brief Conditional put quote character to output
+ * \details If control \a AddQuotes is set
+ * quote character is put \sa \a space(), \a newLine() */
+ inline void quote() {if (co_[AddQuotes]) std::cout << '"'; fo_ = false;}
+
+ /*! \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() */
+ inline void newLine() {if (co_[AddNewLine]) std::cout << std::endl; fo_ = false;}
+
+private:
+ bool fo_, cc_;
+ PICoutControls co_;
+ std::stack cos_;
+};
+
#endif // PIINCLUDES_H
diff --git a/piiodevice.cpp b/piiodevice.cpp
index 41912d9b..3e0a4843 100644
--- a/piiodevice.cpp
+++ b/piiodevice.cpp
@@ -20,6 +20,45 @@
#include "piiodevice.h"
+/*! \class PIIODevice
+ * \brief Base class for input/output classes
+ *
+ * \section PIIODevice_sec0 Synopsis
+ * This class provide open/close logic, threaded read 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 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_sec4 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_ex0 Example
+ * \snippet piiodevice.cpp 0
+ */
+
+
+//! Constructs a empty PIIODevice
PIIODevice::PIIODevice(): PIThread() {
mode_ = ReadOnly;
opened_ = init_ = thread_started_ = false;
@@ -27,12 +66,18 @@ PIIODevice::PIIODevice(): PIThread() {
reopen_timeout_ = 1000;
ret_func_ = 0;
ret_data_ = 0;
+ tri = 0;
buffer_tr.resize(4096);
CONNECT2(void, void * , int, &timer, timeout, this, check_start);
+ CONNECT(void, &write_thread, started, this, write_func);
init();
}
+/*! \brief Constructs a PIIODevice with path and mode
+ * \param path path to device
+ * \param type mode for open
+ * \param initNow init or not in constructor */
PIIODevice::PIIODevice(const PIString & path, PIIODevice::DeviceMode type, bool initNow): PIThread() {
path_ = path;
mode_ = type;
@@ -41,8 +86,10 @@ PIIODevice::PIIODevice(const PIString & path, PIIODevice::DeviceMode type, bool
reopen_timeout_ = 1000;
ret_func_ = 0;
ret_data_ = 0;
+ tri = 0;
buffer_tr.resize(4096);
CONNECT2(void, void * , int, &timer, timeout, this, check_start);
+ CONNECT(void, &write_thread, started, this, write_func);
if (initNow) init();
}
@@ -56,6 +103,21 @@ void PIIODevice::check_start(void * data, int delim) {
}
+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;
@@ -103,4 +165,14 @@ void PIIODevice::run() {
return;
}
threadedRead(buffer_tr.data(), readed_);
+ threadedReadEvent(buffer_tr.data(), readed_);
+}
+
+
+ullong PIIODevice::writeThreaded(const PIByteArray & data) {
+ write_thread.lock();
+ write_queue.enqueue(PIPair(data, tri));
+ ++tri;
+ write_thread.unlock();
+ return tri - 1;
}
diff --git a/piiodevice.h b/piiodevice.h
index bc8b7181..47692c7f 100644
--- a/piiodevice.h
+++ b/piiodevice.h
@@ -1,3 +1,6 @@
+/*! \file piiodevice.h
+ * \brief Abstract input/output device
+*/
/*
PIP - Platform Independent Primitives
Abstract input/output device
@@ -25,36 +28,59 @@
// function executed from threaded read, pass ThreadedReadData, readedData, sizeOfData
typedef bool (*ReadRetFunc)(void * , uchar * , int );
-/// events:
-/// void opened()
-/// void closed()
-///
-/// handlers:
-/// bool open()
-/// bool open(const PIString & path)
-/// bool open(const DeviceMode & type)
-/// bool open(const PIString & path, const DeviceMode & type)
-/// bool close()
-/// bool initialize()
-/// void flush()
-class PIIODevice: public PIThread {
+// events:
+// void opened()
+// void closed()
+//
+// handlers:
+// bool open()
+// bool open(const PIString & path)
+// bool open(const DeviceMode & type)
+// bool open(const PIString & path, const DeviceMode & type)
+// bool close()
+// bool initialize()
+// void flush()
+
+class PIP_EXPORT PIIODevice: public PIThread
+{
+ PIOBJECT(PIIODevice)
public:
PIIODevice();
- enum DeviceMode {ReadOnly = 0x01, WriteOnly = 0x02, ReadWrite = 0x03};
+ //! \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 type = ReadWrite, bool initNow = true);
- virtual ~PIIODevice() {if (opened_) {closeDevice(); if (!opened_) closed();}}
-
+ virtual ~PIIODevice() {stop(); write_thread.stop(); if (opened_) {closeDevice(); if (!opened_) closed();}}
+ //! Current open mode of device
DeviceMode mode() const {return mode_;}
+
+ //! Current path of device
PIString path() const {return 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
bool canRead() const {return opened_ && (mode_ & ReadOnly);}
+
+ //! return \b true if device can write \b now
bool canWrite() const {return opened_ && (mode_ & WriteOnly);}
@@ -74,34 +100,83 @@ public:
int threadedReadBufferSize() const {return buffer_tr.size_s();}
const uchar * threadedReadBuffer() const {return buffer_tr.data();}
+ bool isThreadedRead() const {return isRunning();}
void startThreadedRead() {if (!isRunning()) start();}
void startThreadedRead(ReadRetFunc func) {ret_func_ = func; if (!isRunning()) start();}
-
- EVENT_HANDLER(PIIODevice, bool, open) {if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;}
- EVENT_HANDLER1(PIIODevice, bool, open, const PIString &, _path) {path_ = _path; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;}
- EVENT_HANDLER1(PIIODevice, bool, open, const DeviceMode &, _type) {mode_ = _type; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;}
- EVENT_HANDLER2(PIIODevice, bool, open, const PIString &, _path, const DeviceMode &, _type) {path_ = _path; mode_ = _type; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;}
- EVENT_HANDLER(PIIODevice, bool, close) {opened_ = !closeDevice(); if (!opened_) closed(); return !opened_;}
- EVENT_HANDLER(PIIODevice, bool, initialize) {init_ = init(); return init_;}
-
- // Flush device
- EVENT_VHANDLER(PIIODevice, void, flush) {;}
-
- EVENT(PIIODevice, opened)
- EVENT(PIIODevice, closed)
+
+ bool isThreadedWrite() const {return write_thread.isRunning();}
+ void startThreadedWrite() {if (!write_thread.isRunning()) write_thread.startOnce();}
+ void stopThreadedWrite() {write_thread.stop();}
+ void clearThreadedWriteQueue() {write_thread.lock(); write_queue.clear(); write_thread.unlock();}
// Read from device to "read_to" maximum "max_size" bytes, return readed bytes count
- virtual int read(void * read_to, int max_size) {piCout << "[PIIODevice] \"read\" not implemented!" << endl; return -2;}
+ virtual int read(void * read_to, int max_size) {piCout << "[PIIODevice] \"read\" not implemented!"; return -2;}
// Write to device "data" maximum "max_size" bytes, return written bytes count
- virtual int write(const void * data, int max_size) {piCout << "[PIIODevice] \"write\" not implemented!" << endl; return -2;}
+ virtual int write(const void * data, int max_size) {piCout << "[PIIODevice] \"write\" 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);}
int write(const PIByteArray & data) {return write(data.data(), data.size_s());}
+
+ ullong writeThreaded(const void * data, int max_size) {return writeThreaded(PIByteArray(data, uint(max_size)));}
+ ullong writeThreaded(const PIByteArray & data);
+ EVENT_HANDLER(bool, open) {if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;}
+ EVENT_HANDLER1(bool, open, const PIString &, _path) {path_ = _path; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;}
+ EVENT_HANDLER1(bool, open, const DeviceMode &, _type) {mode_ = _type; if (!init_) init(); opened_ = openDevice(); if (opened_) opened(); return opened_;}
+ EVENT_HANDLER2(bool, open, const PIString &, _path, const DeviceMode &, _type) {path_ = _path; mode_ = _type; 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"
+
+//! \}
+//! \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 queue item with id "id"
+
+//! \}
protected:
// Function executed before first openDevice() or from constructor
@@ -124,14 +199,18 @@ protected:
void * ret_data_;
private:
- EVENT_HANDLER2(PIIODevice, void, check_start, void * , data, int, delim);
+ EVENT_HANDLER2(void, check_start, void * , data, int, delim);
+ EVENT_HANDLER(void, write_func);
void begin();
void run();
void end() {terminate();}
PITimer timer;
+ PIThread write_thread;
PIByteArray buffer_in, buffer_tr;
+ PIQueue > write_queue;
+ ullong tri;
int readed_;
};
diff --git a/pikbdlistener.cpp b/pikbdlistener.cpp
index 3fc84153..cd364a95 100644
--- a/pikbdlistener.cpp
+++ b/pikbdlistener.cpp
@@ -42,8 +42,8 @@ PIKbdListener::PIKbdListener(KBFunc slot, void * data_): PIThread() {
void PIKbdListener::begin() {
//cout << "list begin" << endl;
#ifdef WINDOWS
- SetConsoleMode(hIn, ENABLE_PROCESSED_INPUT);
GetConsoleMode(hIn, &tmode);
+ SetConsoleMode(hIn, ENABLE_PROCESSED_INPUT);
#else
struct termios term;
tcgetattr(0, &term);
@@ -55,17 +55,68 @@ void PIKbdListener::begin() {
void PIKbdListener::run() {
+ rc = 0;
+ char lc = 0;
#ifdef WINDOWS
- ReadConsole(hIn, &rc, 1, &ret, 0);
+ 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));
+ //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 = ker.uChar.AsciiChar; break;
+ }
+ if (lc == 0) return;
+ } else return;
+ } else 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
- ret = read(0, &rc, 1);
+ ret = read(0, &rc, 4);
+ 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;
+ 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
+ }
+ }
+ }
+ 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
+ }
+ }
#endif
- if (exit_enabled && rc == exit_key) {
+ if (exit_enabled && ret == 1 && lc == exit_key) {
PIKbdListener::exiting = true;
return;
}
- keyPressed(rc, data);
- if (ret_func != 0 && ret > 0) ret_func(rc, data);
+ keyPressed(lc, data);
+ if (ret_func != 0 && ret > 0) ret_func(lc, data);
}
diff --git a/pikbdlistener.h b/pikbdlistener.h
index 9d122477..508439e3 100644
--- a/pikbdlistener.h
+++ b/pikbdlistener.h
@@ -35,25 +35,38 @@ typedef void (*KBFunc)(char, void * );
/// handlers:
/// void enableExitCapture(char key = 'Q')
/// void setActive(bool yes = true)
-class PIKbdListener: public PIThread {
+class PIP_EXPORT PIKbdListener: public PIThread
+{
+ PIOBJECT(PIKbdListener)
friend class PIConsole;
public:
+ enum SpecialSymbol {
+ UpArrow = -1,
+ DownArrow = -2,
+ RightArrow = -3,
+ LeftArrow = -4,
+ CtrlUpArrow = -5,
+ CtrlDownArrow = -6,
+ CtrlRightArrow = -7,
+ CtrlLeftArrow = -8
+ };
+
// slot is any function format "void (char, void * )"
PIKbdListener(KBFunc slot = 0, void * data = 0);
~PIKbdListener() {terminate(); end();}
void setData(void * data_) {data = data_;}
void setSlot(KBFunc slot_) {ret_func = slot_;}
- EVENT_HANDLER(PIKbdListener, void, enableExitCapture) {enableExitCapture('Q');}
- EVENT_HANDLER1(PIKbdListener, void, enableExitCapture, char, key) {exit_enabled = true; exit_key = key;}
+ EVENT_HANDLER( void, enableExitCapture) {enableExitCapture('Q');}
+ EVENT_HANDLER1(void, enableExitCapture, char, key) {exit_enabled = true; exit_key = key;}
void disableExitCapture() {exit_enabled = false;}
bool exitCaptured() const {return exit_enabled;}
char exitKey() const {return exit_key;}
bool isActive() {return is_active;}
- EVENT_HANDLER(PIKbdListener, void, setActive) {setActive(true);}
- EVENT_HANDLER1(PIKbdListener, void, setActive, bool, yes);
+ EVENT_HANDLER(void, setActive) {setActive(true);}
+ EVENT_HANDLER1(void, setActive, bool, yes);
- EVENT2(PIKbdListener, keyPressed, char, key, void * , data)
+ EVENT2(keyPressed, char, key, void * , data)
static bool exiting;
@@ -61,6 +74,8 @@ private:
void begin();
void run();
void end();
+
+ void raiseSpecial();
KBFunc ret_func;
char exit_key;
@@ -71,7 +86,7 @@ private:
void * hIn;
DWORD smode, tmode;
#else
- char rc;
+ int rc;
int ret;
struct termios sterm, tterm;
#endif
diff --git a/pimath.h b/pimath.h
index 94838ddd..2a4a7cbf 100644
--- a/pimath.h
+++ b/pimath.h
@@ -96,16 +96,18 @@ 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;}
-inline PIVector abs(const PIVector &v) {
+inline PIVector abs(const PIVector & v) {
PIVector result;
result.resize(v.size());
- for(uint i=0; i abs(const PIVector &v) {
+inline PIVector abs(const PIVector & v) {
PIVector result;
result.resize(v.size());
- for(uint i=0; i
-class PIMathVectorT {
+class PIP_EXPORT PIMathVectorT {
typedef PIMathVectorT _CVector;
public:
PIMathVectorT() {resize(Size);}
@@ -139,7 +141,7 @@ public:
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 toGrad(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; PIMV_FOR(i, 0) c[i] /= tv; return *this;}
_CVector normalized() {_CVector tv(*this); tv.normalize(); return tv;}
@@ -207,7 +209,7 @@ typedef PIMathVectorT<4u, double> PIMathVectorT4d;
#define PIMM_FOR_R(v) for (uint v = 0; v < Rows; ++v)
template
-class PIMathMatrixT {
+class PIP_EXPORT PIMathMatrixT {
typedef PIMathMatrixT _CMatrix;
typedef PIMathMatrixT _CMatrixI;
typedef PIMathVectorT _CMCol;
@@ -417,7 +419,7 @@ class PIMathMatrix;
#define PIMV_FOR(v, s) for (uint v = s; v < size_; ++v)
template
-class PIMathVector {
+class PIP_EXPORT PIMathVector {
typedef PIMathVector _CVector;
public:
PIMathVector(const uint size = 3) {resize(size);}
@@ -440,7 +442,7 @@ public:
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 toGrad(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; PIMV_FOR(i, 0) c[i] /= tv; return *this;}
_CVector normalized() {_CVector tv(*this); tv.normalize(); return tv;}
@@ -499,7 +501,7 @@ typedef PIMathVector PIMathVectord;
#define PIMM_FOR_R(v) for (uint v = 0; v < rows_; ++v)
template
-class PIMathMatrix {
+class PIP_EXPORT PIMathMatrix {
typedef PIMathMatrix _CMatrix;
typedef PIMathVector _CMCol;
typedef PIMathVector _CMRow;
@@ -716,7 +718,7 @@ struct TransferFunction { // Для задания передаточной фу
// Эйлера
// Рунге-Кутта 4-го порядка
// Адамса-Бэшфортса-Моултона 2, 3, 4 порядков
-class Solver
+class PIP_EXPORT Solver
{
public:
enum Method {Global = -1,
@@ -774,7 +776,7 @@ private:
-class PIFFT
+class PIP_EXPORT PIFFT
{
public:
PIFFT();
@@ -827,7 +829,7 @@ private:
};
-class PIStatistic {
+class PIP_EXPORT PIStatistic {
public:
PIStatistic();
bool calculate(const PIVector &val);
diff --git a/pimonitor.h b/pimonitor.h
index 34aab13a..95f4f8e9 100644
--- a/pimonitor.h
+++ b/pimonitor.h
@@ -20,7 +20,14 @@
#ifndef PIMONITOR_H
#define PIMONITOR_H
-class PIMonitor
+#include "pip_export.h"
+
+#if defined(DOXYGEN) || defined(__GNUC__)
+# undef PIP_EXPORT
+# define PIP_EXPORT
+#endif
+
+class PIP_EXPORT PIMonitor
{
public:
PIMonitor();
diff --git a/pimultiprotocol.h b/pimultiprotocol.h
index c045de1b..362fd357 100644
--- a/pimultiprotocol.h
+++ b/pimultiprotocol.h
@@ -64,12 +64,12 @@ public:
PIRepeater(const PIString & config, const PIString & name) {
PIConfig conf(config, PIIODevice::ReadOnly);
if (!conf.isOpened()) {
- piCout << "[PIRepeater \"" << name << "\"] Can`t open \"" << config << "\"!" << endl;
+ piCout << "[PIRepeater \"" << name << "\"] Can`t open \"" << config << "\"!";
return;
}
PIConfig::Entry & b(conf.getValue(name));
if (b.childCount() != 2) {
- piCout << "[PIRepeater \"" << name << "\"] \"" << config << "\" should consist 2 nodes!" << endl;
+ piCout << "[PIRepeater \"" << name << "\"] \"" << config << "\" should consist 2 nodes!";
return;
}
addProtocol(config, b.child(0)->fullName());
diff --git a/pimutex.h b/pimutex.h
index 43d5930e..b7c68bdd 100644
--- a/pimutex.h
+++ b/pimutex.h
@@ -21,11 +21,11 @@
#define PIMUTEX_H
#include "piincludes.h"
-#ifdef CC_GCC
-#include
+#ifndef WINDOWS
+# include
#endif
-class PIMutex
+class PIP_EXPORT PIMutex
{
public:
#ifndef WINDOWS
@@ -59,7 +59,8 @@ private:
};
-class PIMutexLocker
+
+class PIP_EXPORT PIMutexLocker
{
public:
PIMutexLocker(PIMutex * m): mutex(m) {mutex->lock();}
diff --git a/piobject.h b/piobject.h
index 8005898f..58cc2185 100644
--- a/piobject.h
+++ b/piobject.h
@@ -1,3 +1,8 @@
+/*! \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
@@ -22,31 +27,166 @@
#include "pistring.h"
-/// declare event handler \"event\" inside class \"obj\" with name \"name\", ret name()
-#define EVENT_HANDLER0(obj, ret, name) static ret __stat_eh_##name##__(void * o) {return ((obj*)o)->name();} ret name()
-#define EVENT_HANDLER1(obj, ret, name, a0, n0) static ret __stat_eh_##name##__(void * o, a0 n0) {return ((obj*)o)->name(n0);} ret name(a0 n0)
-#define EVENT_HANDLER2(obj, ret, name, a0, n0, a1, n1) static ret __stat_eh_##name##__(void * o, a0 n0, a1 n1) {return ((obj*)o)->name(n0, n1);} ret name(a0 n0, a1 n1)
-#define EVENT_HANDLER3(obj, ret, name, a0, n0, a1, n1, a2, n2) static ret __stat_eh_##name##__(void * o, a0 n0, a1 n1, a2 n2) {return ((obj*)o)->name(n0, n1, n2);} ret name(a0 n0, a1 n1, a2 n2)
-#define EVENT_HANDLER4(obj, 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 ((obj*)o)->name(n0, n1, n2, n3);} ret name(a0 n0, a1 n1, a2 n2, a3 n3)
+
+#ifdef DOXYGEN
+
+
+/// \relatesalso PIObject \brief you should use this macro after class declaration to use EVENT and EVENT_HANDLER
+#define PIOBJECT(name)
+
+
+/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\", ret name()
+#define EVENT_HANDLER0(ret, name) ret name()
+
+/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\", 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\", 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\", 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\", 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
-/// declare virtual event handler \"event\" inside class \"obj\" with name \"name\", virtual ret name()
-#define EVENT_VHANDLER0(obj, ret, name) static ret __stat_eh_##name##__(void * o) {return ((obj*)o)->name();} virtual ret name()
-#define EVENT_VHANDLER1(obj, ret, name, a0, n0) static ret __stat_eh_##name##__(void * o, a0 n0) {return ((obj*)o)->name(n0);} virtual ret name(a0 n0)
-#define EVENT_VHANDLER2(obj, ret, name, a0, n0, a1, n1) static ret __stat_eh_##name##__(void * o, a0 n0, a1 n1) {return ((obj*)o)->name(n0, n1);} virtual ret name(a0 n0, a1 n1)
-#define EVENT_VHANDLER3(obj, ret, name, a0, n0, a1, n1, a2, n2) static ret __stat_eh_##name##__(void * o, a0 n0, a1 n1, a2 n2) {return ((obj*)o)->name(n0, n1, n2);} virtual ret name(a0 n0, a1 n1, a2 n2)
-#define EVENT_VHANDLER4(obj, 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 ((obj*)o)->name(n0, n1, n2, n3);} virtual ret name(a0 n0, a1 n1, a2 n2, a3 n3)
+
+/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\", virtual ret name()
+#define EVENT_VHANDLER0(ret, name) virtual ret name()
+
+/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\", 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\", 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\", 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\", 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
-/// declare event \"event\" inside class \"obj\" with name \"name\", void name();
-#define EVENT0(obj, name) EVENT_HANDLER0(obj, void, name) {PIObject::raiseEvent(this, #name);}
-#define EVENT1(obj, name, a0, n0) EVENT_HANDLER1(obj, void, name, a0, n0) {PIObject::raiseEvent(this, #name, n0);}
-#define EVENT2(obj, name, a0, n0, a1, n1) EVENT_HANDLER2(obj, void, name, a0, n0, a1, n1) {PIObject::raiseEvent(this, #name, n0, n1);}
-#define EVENT3(obj, name, a0, n0, a1, n1, a2, n2) EVENT_HANDLER3(obj, void, name, a0, n0, a1, n1, a2, n2) {PIObject::raiseEvent(this, #name, n0, n1, n2);}
-#define EVENT4(obj, name, a0, n0, a1, n1, a2, n2, a3, n3) EVENT_HANDLER4(obj, void, name, a0, n0, a1, n1, a2, n2, a3, n3) {PIObject::raiseEvent(this, #name, n0, n1, n2, n3);}
+
+/// \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\" 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\" 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\" 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\" 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\" 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\" 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\" 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\" 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\" 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\" 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\" from object \"dest\"
+#define DISCONNECT0(ret, src, event, dest, handler)
+
+/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" from object \"dest\"
+#define DISCONNECT1(ret, type0, src, event, dest, handler)
+
+/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" 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\" 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\" 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)
+
+
+#else
+
+
+#define PIOBJECT(obj) typedef obj __PIObject__;
+
+#define EVENT_HANDLER0(ret, name) static ret __stat_eh_##name##__(void * o) {return ((__PIObject__*)o)->name();} ret name()
+#define EVENT_HANDLER1(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) 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) 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) 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) static ret __stat_eh_##name##__(void * o) {return ((__PIObject__*)o)->name();} virtual ret name()
+#define EVENT_VHANDLER1(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) 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) 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) 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
-/// raise event \"event\" from object \"src\"
#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);
@@ -54,31 +194,62 @@
#define RAISE_EVENT4(src, event, v0, v1, v2, v3) (src)->event(v0, v1, v2, v3);
#define RAISE_EVENT RAISE_EVENT0
-/// connect event \"event\" from object \"src\" to event handler \"handler\" from object \"dst\" with check of event and handler exists
-#define CONNECT0(ret, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*))(&(dst)->__stat_eh_##handler##__), (void*)(void(*)(void*))(&(src)->__stat_eh_##event##__));
-#define CONNECT1(ret, a0, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*, a0))(&(dst)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0))(&(src)->__stat_eh_##event##__));
-#define CONNECT2(ret, a0, a1, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1))(&(dst)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1))(&(src)->__stat_eh_##event##__));
-#define CONNECT3(ret, a0, a1, a2, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1, a2))(&(dst)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1, a2))(&(src)->__stat_eh_##event##__));
-#define CONNECT4(ret, a0, a1, a2, a3, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dst)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1, a2, a3))(&(src)->__stat_eh_##event##__));
+#define CONNECT0(ret, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*))(&(src)->__stat_eh_##event##__));
+#define CONNECT1(ret, a0, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0))(&(src)->__stat_eh_##event##__));
+#define CONNECT2(ret, a0, a1, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1))(&(src)->__stat_eh_##event##__));
+#define CONNECT3(ret, a0, a1, a2, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1, a2))(&(src)->__stat_eh_##event##__));
+#define CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1, a2, a3))(&(src)->__stat_eh_##event##__));
#define CONNECT CONNECT0
-/// connect event \"event\" from object \"src\" to event handler \"handler\" from object \"dst\" without check of event exists
-#define WEAK_CONNECT0(ret, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*))(&(dst)->__stat_eh_##handler##__));
-#define WEAK_CONNECT1(ret, a0, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*, a0))(&(dst)->__stat_eh_##handler##__));
-#define WEAK_CONNECT2(ret, a0, a1, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1))(&(dst)->__stat_eh_##handler##__));
-#define WEAK_CONNECT3(ret, a0, a1, a2, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1, a2))(&(dst)->__stat_eh_##handler##__));
-#define WEAK_CONNECT4(ret, a0, a1, a2, a3, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dst)->__stat_eh_##handler##__));
+#define WEAK_CONNECT0(ret, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__));
+#define WEAK_CONNECT1(ret, a0, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__));
+#define WEAK_CONNECT2(ret, a0, a1, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__));
+#define WEAK_CONNECT3(ret, a0, a1, a2, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__));
+#define WEAK_CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) PIObject::piConnect(src, #event, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__));
#define WEAK_CONNECT WEAK_CONNECT0
-/// piDisconnect event \"event\" from object \"src\" from event handler \"handler\" from object \"dst\"
-#define DISCONNECT0(ret, src, event, dst, handler) PIObject::piDisconnect(src, #event, dst, (void*)(ret(*)(void*))(&(dst)->__stat_eh_##handler##__));
-#define DISCONNECT1(ret, a0, src, event, dst, handler) PIObject::piDisconnect(src, #event, dst, (void*)(ret(*)(void*, a0))(&(dst)->__stat_eh_##handler##__));
-#define DISCONNECT2(ret, a0, a1, src, event, dst, handler) PIObject::piDisconnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1))(&(dst)->__stat_eh_##handler##__));
-#define DISCONNECT3(ret, a0, a1, a2, src, event, dst, handler) PIObject::piDisconnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1, a2))(&(dst)->__stat_eh_##handler##__));
-#define DISCONNECT4(ret, a0, a1, a2, a3, src, event, dst, handler) PIObject::piDisconnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dst)->__stat_eh_##handler##__));
+#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
-class PIObject
+#define HANDLER(handler) __stat_eh_##handler##__
+
+#endif
+
+typedef void (*Handler)(void * );
+
+/** \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.
+ *
+ * Example: \snippet piobject.cpp main
+ * Result:
+ * \code{.cpp}
+ * handler B: 2 , 0.5
+ * handler A: event to handler
+ * handler A: event to event
+ * \endcode
+ */
+class PIP_EXPORT PIObject
{
friend class PIObjectManager;
public:
@@ -133,7 +304,7 @@ public:
slots_.insert(NamedFunction(func, name, PIStringList(typeid(T0).name(), typeid(T1).name(), typeid(T2).name(), typeid(T3).name())), name);
}
*/
- /// Direct connect
+ // / Direct connect
static void piConnect(PIObject * src, const PIString & sig, void * dest, void * ev_h) {src->connections << Connection(ev_h, 0, sig, dest);}
static void piConnect(PIObject * src, const PIString & sig, void * dest, void * ev_h, void * e_h) {src->connections << Connection(ev_h, e_h, sig, dest);}
static void piDisconnect(PIObject * src, const PIString & sig, void * dest, void * ev_h) {
@@ -145,6 +316,25 @@ public:
}
}
}
+ static void piDisconnect(PIObject * src, const PIString & sig, void * dest) {
+ for (int i = 0; i < src->connections.size_s(); ++i) {
+ Connection & cc(src->connections[i]);
+ if (cc.event == sig && cc.dest == dest) {
+ src->connections.remove(i);
+ i--;
+ }
+ }
+ }
+ static void piDisconnect(PIObject * src, const PIString & sig) {
+ for (int i = 0; i < src->connections.size_s(); ++i) {
+ Connection & cc(src->connections[i]);
+ if (cc.event == sig) {
+ src->connections.remove(i);
+ i--;
+ }
+ }
+ }
+ static void piDisconnect(PIObject * src) {src->connections.clear();}
//static void piConnect(PIObject & src, const PIString & sig, PIObject * dest, void * ev_h) {src.connections << Connection(ev_h, sig, dest);}
//static void piConnect(PIObject * src, const PIString & sig, PIObject & dest, void * ev_h) {src->connections << Connection(ev_h, sig, &dest);}
//static void piConnect(PIObject & src, const PIString & sig, PIObject & dest, void * ev_h) {src.connections << Connection(ev_h, sig, &dest);}
@@ -164,7 +354,7 @@ public:
return PIObject::piConnect(src, event, dest, handler, force);
}*/
- /// Raise events
+ // / 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]);
@@ -226,7 +416,7 @@ public:
destObject->raiseEvent(name, v0, v1, v2, v3);
}
*/
- /// Raise events through manager
+ // / Raise events through manager
static void raiseEvent(const PIString & destObject, const PIString & name) {
PIObject * dest = findByName(destObject);
if (dest == 0) {
diff --git a/pip.h b/pip.h
index bd1fb55b..d354cd9f 100644
--- a/pip.h
+++ b/pip.h
@@ -29,3 +29,4 @@
#include "pisystemmonitor.h"
#include "pipeer.h"
#include "picrc.h"
+#include "pistatemachine.h"
diff --git a/pip.pro b/pip.pro
index 5731c7c9..19e49c2e 100644
--- a/pip.pro
+++ b/pip.pro
@@ -1,66 +1,83 @@
-######################################################################
-# Automatically generated by qmake (2.01a) ?? ???. 5 22:55:18 2011
-######################################################################
-
-TEMPLATE = app
-TARGET = pip_test
-DEPENDPATH += .
-INCLUDEPATH += .
-QT -= core gui
-LIBS = -lpthread -lrt
-
-# Input
-HEADERS += pibitarray.h \
- pibytearray.h \
- pichar.h \
- picli.h \
- picodec.h \
- piconfig.h \
- piconsole.h \
- picontainers.h \
- pidir.h \
- piethernet.h \
- pievaluator.h \
- pifile.h \
- pigeometry.h \
- piincludes.h \
- pikbdlistener.h \
- pimath.h \
- pimonitor.h \
- pimultiprotocol.h \
- pimutex.h \
- piobject.h \
- pip.h \
- piprocess.h \
- piprotocol.h \
- piserial.h \
- pisignals.h \
- pistring.h \
- pisystemmonitor.h \
- pithread.h \
- pitimer.h \
- pivariable.h
-SOURCES += main.cpp \
- pibytearray.cpp \
- picli.cpp \
- picodec.cpp \
- piconfig.cpp \
- piconsole.cpp \
- pidir.cpp \
- piethernet.cpp \
- pievaluator.cpp \
- pifile.cpp \
- pikbdlistener.cpp \
- pimath.cpp \
- pimonitor.cpp \
- pimultiprotocol.cpp \
- piobject.cpp \
- piprocess.cpp \
- piprotocol.cpp \
- piserial.cpp \
- pisignals.cpp \
- pistring.cpp \
- pisystemmonitor.cpp \
- pithread.cpp \
- pitimer.cpp \
- pivariable.cpp
+######################################################################
+# Automatically generated by qmake (2.01a) ?? ???. 5 22:55:18 2011
+######################################################################
+
+TEMPLATE = lib
+TARGET = pip
+DEPENDPATH += .
+INCLUDEPATH += .
+QT -= core gui
+CONFIG -= qt
+CONFIG += dll
+VERSION = 0.3.4
+
+# Input
+HEADERS += \
+ pivariable.h \
+ pitimer.h \
+ pithread.h \
+ pisystemtests.h \
+ pisystemmonitor.h \
+ pistring.h \
+ pisignals.h \
+ piserial.h \
+ piprotocol.h \
+ piprocess.h \
+ pipeer.h \
+ pipacketextractor.h \
+ pip.h \
+ piobject.h \
+ pimutex.h \
+ pimultiprotocol.h \
+ pimonitor.h \
+ pimath.h \
+ pikbdlistener.h \
+ piiodevice.h \
+ piincludes.h \
+ pigeometry.h \
+ pifile.h \
+ pievaluator.h \
+ piethernet.h \
+ pidir.h \
+ picrc.h \
+ picontainers.h \
+ piconsole.h \
+ piconfig.h \
+ picodec.h \
+ picli.h \
+ pichar.h \
+ pibytearray.h \
+ pibitarray.h
+SOURCES += main.cpp \
+ pivariable.cpp \
+ pitimer.cpp \
+ pithread.cpp \
+ pisystemtests.cpp \
+ pisystemmonitor.cpp \
+ pistring.cpp \
+ pisignals.cpp \
+ piserial.cpp \
+ piprotocol.cpp \
+ piprocess.cpp \
+ pipeer.cpp \
+ pipacketextractor.cpp \
+ piobject.cpp \
+ pimonitor.cpp \
+ pimath.cpp \
+ pikbdlistener.cpp \
+ piiodevice.cpp \
+ piincludes.cpp \
+ pifile.cpp \
+ pievaluator.cpp \
+ piethernet.cpp \
+ pidir.cpp \
+ piconsole.cpp \
+ piconfig.cpp \
+ picodec.cpp \
+ picli.cpp \
+ pibytearray.cpp
+win32 {
+ LIBS += -lws2_32 -lIphlpapi
+} else {
+ LIBS = -lpthread -lrt
+}
diff --git a/pipacketextractor.h b/pipacketextractor.h
index a293caa6..ade0ad30 100644
--- a/pipacketextractor.h
+++ b/pipacketextractor.h
@@ -26,7 +26,7 @@
// Pass data, recHeaderPtr, received_data, recHeaderSize. Return true if packet is correct nor return false.
typedef bool (*HeaderCheckFunc)(void * , uchar * , uchar * , int );
-class PIPacketExtractor: public PIIODevice
+class PIP_EXPORT PIPacketExtractor: public PIIODevice
{
public:
PIPacketExtractor(PIIODevice * device_ = 0, void * recHeaderPtr = 0, int recHeaderSize = 0, int recDataSize = 0);
diff --git a/pipeer.h b/pipeer.h
index db39a9b1..698000df 100644
--- a/pipeer.h
+++ b/pipeer.h
@@ -22,8 +22,9 @@
#include "piethernet.h"
-class PIPeer: public PIEthernet
+class PIP_EXPORT PIPeer: public PIEthernet
{
+ PIOBJECT(PIPeer)
struct PeerInfo;
friend PIByteArray & operator <<(PIByteArray & s, const PIPeer::PeerInfo & v);
friend PIByteArray & operator >>(PIByteArray & s, PIPeer::PeerInfo & v);
@@ -37,7 +38,7 @@ protected:
bool threadedRead(uchar * readed, int size);
private:
- EVENT_HANDLER2(PIPeer, void, timerEvent, void * , data, int, delim);
+ EVENT_HANDLER2(void, timerEvent, void * , data, int, delim);
static bool func_readed(void * peer, uchar * data, int size);
struct PeerInfo {
diff --git a/piprocess.cpp b/piprocess.cpp
index 4d944be6..537a8c54 100644
--- a/piprocess.cpp
+++ b/piprocess.cpp
@@ -141,12 +141,12 @@ void PIProcess::run() {
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
} else
- piCout << "[PIProcess] \"CreateProcess\" error, " << errorString() << endl;
+ piCout << "[PIProcess] \"CreateProcess\" error, " << errorString();
#else
//cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl;
if (execve(str.c_str(), a, e) < 0)
- piCout << "[PIProcess] \"execve\" error, " << errorString() << endl;
+ piCout << "[PIProcess] \"execve\" error, " << errorString();
} else {
msleep(1);
//cout << "wait" << endl;
diff --git a/piprocess.h b/piprocess.h
index aa1ea544..a3ddf923 100644
--- a/piprocess.h
+++ b/piprocess.h
@@ -40,11 +40,12 @@
/// bool exec(const PIString & program, const PIStringList & args)
/// void terminate()
/// bool waitForFinish(int timeout_msecs = 60000)
-class PIProcess: private PIThread
+class PIP_EXPORT PIProcess: private PIThread
{
+ PIOBJECT(PIProcess)
public:
PIProcess();
- ~PIProcess();
+ virtual ~PIProcess();
int exitCode() const {return exit_code;}
#ifdef WINDOWS
@@ -65,18 +66,18 @@ public:
PIString workingDirectory() const {return wd;}
void setWorkingDirectory(const PIString & path) {wd = path;}
void resetWorkingDirectory() {wd.clear();}
- EVENT_HANDLER1(PIProcess, void, exec, const PIString & , program) {args.clear(); args << program; exec_();}
- EVENT_HANDLER2(PIProcess, void, exec, const PIString & , program, const PIString & , arg) {args.clear(); args << program << arg; exec_();}
- EVENT_HANDLER3(PIProcess, void, exec, const PIString & , program, const PIString & , arg1, const PIString & , arg2) {args.clear(); args << program << arg1 << arg2; exec_();}
- EVENT_HANDLER4(PIProcess, void, exec, const PIString & , program, const PIString & , arg1, const PIString & , arg2, const PIString & , arg3) {args.clear(); args << program << arg1 << arg2 << arg3; exec_();}
- EVENT_HANDLER2(PIProcess, void, exec, const PIString & , program, const PIStringList & , args_) {args << program << args_; exec_();}
+ 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_();}
#ifdef WINDOWS
- EVENT_HANDLER(PIProcess, void, terminate) {if (is_exec) if (!TerminateProcess(pi.hProcess, 0)) return; pi.dwProcessId = 0;}
+ EVENT_HANDLER(void, terminate) {if (is_exec) if (!TerminateProcess(pi.hProcess, 0)) return; pi.dwProcessId = 0;}
#else
- EVENT_HANDLER(PIProcess, void, terminate) {if (is_exec) kill(pid, SIGKILL); pid = 0;}
+ EVENT_HANDLER(void, terminate) {if (is_exec) kill(pid, SIGKILL); pid = 0;}
#endif
- EVENT_HANDLER(PIProcess, bool, waitForFinish) {return waitForFinish(60000);}
- EVENT_HANDLER1(PIProcess, bool, waitForFinish, int, timeout_msecs) {return PIThread::waitForFinish(timeout_msecs);}
+ EVENT_HANDLER(bool, waitForFinish) {return waitForFinish(60000);}
+ EVENT_HANDLER1(bool, waitForFinish, int, timeout_msecs) {return PIThread::waitForFinish(timeout_msecs);}
PIByteArray readOutput() {f_out.open(PIIODevice::ReadOnly); return f_out.readAll();}
PIByteArray readError() {f_err.open(PIIODevice::ReadOnly); return f_err.readAll();}
@@ -92,8 +93,8 @@ public:
static int currentPID() {return getpid();}
#endif
- EVENT1(PIProcess, execStarted, PIString, program)
- EVENT2(PIProcess, execFinished, PIString, program, int, exit_code)
+ EVENT1(execStarted, PIString, program)
+ EVENT2(execFinished, PIString, program, int, exit_code)
private:
virtual void run();
diff --git a/piprotocol.cpp b/piprotocol.cpp
index 5889313e..51a00db7 100644
--- a/piprotocol.cpp
+++ b/piprotocol.cpp
@@ -26,7 +26,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
PIObject::setName(name);
PIConfig conf(config, PIIODevice::ReadOnly);
if (!conf.isOpened()) {
- piCout << "[PIProtocol \"" << name << "\"] Can`t open \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Can`t open \"" << config << "\"!";
devReceiverState = devSenderState = "Config error";
return;
}
@@ -41,7 +41,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
/// receiver section
if (rb.isEntryExists("ip") && rb.isEntryExists("device")) {
- piCout << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -50,7 +50,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) dev = gdev;
if (gok && ok && (dev != gdev)) {
- piCout << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -59,7 +59,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) ps = gps;
if (gok && ok && (ps != gps)) {
- piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive port in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive port in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -74,7 +74,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) flag = gflag;
if (gok && ok && (flag != gflag)) {
- piCout << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -85,18 +85,18 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) freq = gfreq;
if (gok && ok && (freq != gfreq)) {
- piCout << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
eth->setReopenTimeout(freq * 1000);
}
if (recDataPtr == 0)
- piCout << "[PIProtocol \"" << name << "\"] Warning: null receive data pointer!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Warning: null receive data pointer!";
if (recDataSize == 0)
- piCout << "[PIProtocol \"" << name << "\"] Warning: null receive data size!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Warning: null receive data size!";
} else {
- piCout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".receiver.port\" or \"" << name << ".port\" in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".receiver.port\" or \"" << name << ".port\" in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -106,7 +106,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) dev = gdev;
if (gok && ok && (dev != gdev)) {
- piCout << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Ambiguous receiver type in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -115,7 +115,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) ps = gps;
if (gok && ok && (ps != gps)) {
- piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"speed\" in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"speed\" in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -124,7 +124,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) flag = gflag;
if (gok && ok && (flag != gflag)) {
- piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"parity\" in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"parity\" in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -135,7 +135,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) flag = gflag;
if (gok && ok && (flag != gflag)) {
- piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"twoStopBits\" parity in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"twoStopBits\" parity in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -154,7 +154,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) ps = gps;
if (gok && ok && (ps != gps)) {
- piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"vtime\" in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Ambiguous receive \"vtime\" in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -162,11 +162,11 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
}
has_dev = true;
if (recDataPtr == 0)
- piCout << "[PIProtocol \"" << name << "\"] Warning: null receive data pointer!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Warning: null receive data pointer!";
if (recDataSize == 0)
- piCout << "[PIProtocol \"" << name << "\"] Warning: null receive data size!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Warning: null receive data size!";
} else {
- piCout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".receiver.speed\" or \"" << name << ".speed\" in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".receiver.speed\" or \"" << name << ".speed\" in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -176,7 +176,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) history_write_rec = ghist;
if (gok && ok && (history_write_rec != ghist)) {
- piCout << "[PIProtocol \"" << name << "\"] Ambiguous receiver history in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Ambiguous receiver history in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -187,7 +187,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
history_id_rec = rb.getValue("historyID", 0, &ok);
if (!ok) {
history_id_rec = protName.toByteArray().checksumCRC16();
- piCout << "[PIProtocol \"" << name << "\"] Warning: no receiver history ID defined, write with ID = " << history_id_rec << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Warning: no receiver history ID defined, write with ID = " << history_id_rec;
}
history_file_rec.open(history_path_rec, PIIODevice::WriteOnly);
}
@@ -196,21 +196,21 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
gfreq = b.getValue("frequency", -1.f, &gok);
if (gok && !ok) freq = gfreq;
if (gok && ok && (freq != gfreq)) {
- piCout << "[PIProtocol \"" << name << "\"] Ambiguous expected frequency in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Ambiguous expected frequency in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
if (freq > 0.f && !has_dev)
- piCout << "[PIProtocol \"" << name << "\"] Warning: no receiver device and not null expected frequency!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Warning: no receiver device and not null expected frequency!";
float tm = b.getValue("disconnectTimeout", 3.f);
if (tm <= 0.f)
- piCout << "[PIProtocol \"" << name << "\"] Warning: diconnect timeout <= 0 s!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Warning: diconnect timeout <= 0 s!";
timeout_ = (tm < 0.f) ? 0.f : tm;
setExpectedFrequency(freq);
/// sender section
if (sb.isEntryExists("ip") && sb.isEntryExists("device")) {
- piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!";
devSenderState = "Config error";
return;
}
@@ -220,7 +220,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) dev = gdev;
if (gok && ok && (dev != gdev)) {
- piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!";
devSenderState = "Config error";
return;
}
@@ -229,7 +229,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) ps = gps;
if (gok && ok && (ps != gps)) {
- piCout << "[PIProtocol \"" << name << "\"] Ambiguous send port in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Ambiguous send port in \"" << config << "\"!";
devSenderState = "Config error";
return;
}
@@ -243,7 +243,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) flag = gflag;
if (gok && ok && (flag != gflag)) {
- piCout << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
@@ -254,18 +254,18 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) freq = gfreq;
if (gok && ok && (freq != gfreq)) {
- piCout << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!";
devReceiverState = "Config error";
return;
}
eth->setReopenTimeout(freq * 1000);
}
if (sendDataPtr_ == 0)
- piCout << "[PIProtocol \"" << name << "\"] Warning: null send data pointer!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Warning: null send data pointer!";
if (sendDataSize_ == 0)
- piCout << "[PIProtocol \"" << name << "\"] Warning: null send data size!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Warning: null send data size!";
} else {
- piCout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".sender.port\" or \"" << name << ".port\" in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".sender.port\" or \"" << name << ".port\" in \"" << config << "\"!";
devSenderState = "Config error";
return;
}
@@ -275,7 +275,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) dev = gdev;
if (gok && ok && (dev != gdev)) {
- piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender type in \"" << config << "\"!";
devSenderState = "Config error";
return;
}
@@ -284,7 +284,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) ps = gps;
if (gok && ok && (ps != gps)) {
- piCout << "[PIProtocol \"" << name << "\"] Ambiguous send \"speed\" in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Ambiguous send \"speed\" in \"" << config << "\"!";
devSenderState = "Config error";
return;
}
@@ -293,7 +293,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) flag = gflag;
if (gok && ok && (flag != gflag)) {
- piCout << "[PIProtocol \"" << name << "\"] Ambiguous send \"parity\" in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Ambiguous send \"parity\" in \"" << config << "\"!";
devSenderState = "Config error";
return;
}
@@ -304,14 +304,14 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
if (ok || gok) {
if (gok && !ok) flag = gflag;
if (gok && ok && (flag != gflag)) {
- piCout << "[PIProtocol \"" << name << "\"] Ambiguous send \"twoStopBits\" parity in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Ambiguous send \"twoStopBits\" parity in \"" << config << "\"!";
devSenderState = "Config error";
return;
}
pp.setFlag(PISerial::TwoStopBits, flag);
}
} else {
- piCout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".sender.speed\" or \"" << name << ".speed\" in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".sender.speed\" or \"" << name << ".speed\" in \"" << config << "\"!";
devSenderState = "Config error";
return;
}
@@ -322,16 +322,16 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
ser->setParameters(pp);
has_dev = true;
if (sendDataPtr_ == 0)
- piCout << "[PIProtocol \"" << name << "\"] Warning: null send data pointer!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Warning: null send data pointer!";
if (sendDataSize_ == 0)
- piCout << "[PIProtocol \"" << name << "\"] Warning: null send data size!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Warning: null send data size!";
}
history_write_send = sb.getValue("writeHistory", false, &ok);
ghist = b.getValue("writeHistory", false, &gok);
if (ok || gok) {
if (gok && !ok) history_write_send = ghist;
if (gok && ok && (history_write_send != ghist)) {
- piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender history in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender history in \"" << config << "\"!";
devSenderState = "Config error";
return;
}
@@ -342,7 +342,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
history_id_send = sb.getValue("historyID", 0, &ok);
if (!ok) {
history_id_send = protName.toByteArray().checksumCRC16() + 1;
- piCout << "[PIProtocol \"" << name << "\"] Warning: no sender history ID defined, write with ID = " << history_id_send << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Warning: no sender history ID defined, write with ID = " << history_id_send;
}
history_file_send.open(history_path_send, PIIODevice::WriteOnly);
}
@@ -351,12 +351,12 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
gfreq = b.getValue("frequency", -1.f, &gok);
if (gok && !ok) freq = gfreq;
if (gok && ok && (freq != gfreq)) {
- piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender frequency in \"" << config << "\"!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Ambiguous sender frequency in \"" << config << "\"!";
devSenderState = "Config error";
return;
}
if (freq > 0.f && !has_dev)
- piCout << "[PIProtocol \"" << name << "\"] Warning: no sender device and not null send frequency!" << endl;
+ piCout << "[PIProtocol \"" << name << "\"] Warning: no sender device and not null send frequency!";
setSenderFrequency(freq);
headerPtr = (uchar * )recHeaderPtr;
@@ -643,7 +643,7 @@ void PIProtocol::calc_diag() {
else if (good_percents > 20.f && good_percents <= 80.f) diag = PIProtocol::Average;
else diag = PIProtocol::Good;
if (diag != net_diag) {
- qualityChanged(net_diag, diag);
+ qualityChanged(diag, net_diag);
net_diag = diag;
}
}
diff --git a/piprotocol.h b/piprotocol.h
index 9bd60ad9..10afed2a 100644
--- a/piprotocol.h
+++ b/piprotocol.h
@@ -29,7 +29,7 @@
class PIProtocol;
-class PIMultiProtocolBase
+class PIP_EXPORT PIMultiProtocolBase
{
friend class PIProtocol;
public:
@@ -65,12 +65,12 @@ typedef void (*ReceiveFunc)(void * );
/// void stop()
/// void send()
/// void send(const void * data, int size, bool direct = false)
-class PIProtocol: public PIObject
+class PIP_EXPORT PIProtocol: public PIObject
{
+ PIOBJECT(PIProtocol)
friend class PIMultiProtocolBase;
friend class PIMultiProtocol;
enum Type {None, Serial, Ethernet};
-
public:
PIProtocol(): PIObject() {init();}
PIProtocol(const PIString & config, const PIString & name, void * recHeaderPtr = 0, int recHeaderSize = 0,
@@ -79,9 +79,9 @@ public:
enum Quality {Unknown = 1, Failure = 2, Bad = 3, Average = 4, Good = 5};
- EVENT_HANDLER0(PIProtocol, void, startReceive) {startReceive(-1.f);}
- EVENT_HANDLER1(PIProtocol, void, startReceive, float, exp_frequency); // if "frequency = -1" used last passed value
- EVENT_HANDLER0(PIProtocol, void, stopReceive);
+ 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->setPacketData(headerPtr, headerSize, dataSize);}
@@ -91,9 +91,9 @@ public:
void setReceiveSlot(ReceiveFunc slot) {ret_func = slot;}
float expectedFrequency() const {return exp_freq;}
- EVENT_HANDLER0(PIProtocol, void, startSend) {startSend(-1.f);} // if "frequency = -1" used last passed value
- EVENT_HANDLER1(PIProtocol, void, startSend, float, frequency); // if "frequency = -1" used last passed value
- EVENT_HANDLER0(PIProtocol, void, stopSend) {sendTimer->stop(); senderStopped();}
+ 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;}
@@ -103,11 +103,11 @@ public:
void setSenderParameters(PIFlags parameters) {if (type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial
float senderFrequency() const {return send_freq;}
- EVENT_HANDLER0(PIProtocol, void, start) {startReceive(); startSend();}
- EVENT_HANDLER0(PIProtocol, void, stop) {stopReceive(); stopSend();}
- EVENT_HANDLER0(PIProtocol, void, send);
- EVENT_HANDLER2(PIProtocol, void, send, const void *, data, int, size) {send(data, size, false);}
- EVENT_HANDLER3(PIProtocol, void, send, const void *, data, int, size, bool, direct);
+ 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;}
@@ -161,12 +161,12 @@ public:
PIPacketExtractor * packetExtractor() {return packet_ext;}
PIByteArray lastHeader() {return packet_ext->lastHeader();}
- EVENT0(PIProtocol, receiverStarted)
- EVENT0(PIProtocol, receiverStopped)
- EVENT0(PIProtocol, senderStarted)
- EVENT0(PIProtocol, senderStopped)
- EVENT1(PIProtocol, received, bool, validate_is_ok)
- EVENT2(PIProtocol, qualityChanged, PIProtocol::Quality, old_quality, PIProtocol::Quality, new_quality)
+ 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
diff --git a/piserial.cpp b/piserial.cpp
index 2370c5e1..cefef69b 100644
--- a/piserial.cpp
+++ b/piserial.cpp
@@ -67,14 +67,14 @@ bool PISerial::setPin(int number, bool on) {
case 3: return setST(on); break;
case 4: return setDTR(on); break;
case 5:
- piCout << "[PISerial] Pin number 5 is ground" << endl;
+ piCout << "[PISerial] 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:
- piCout << "[PISerial] Pin number " << number << " doesn`t exists!" << endl;
+ piCout << "[PISerial] Pin number " << number << " doesn`t exists!";
return false;
}
return false;
@@ -93,7 +93,7 @@ bool PISerial::isPin(int number) const {
case 8: return isCTS(); break;
case 9: return isRNG(); break;
default:
- piCout << "[PISerial] Pin number " << number << " doesn`t exists!" << endl;
+ piCout << "[PISerial] Pin number " << number << " doesn`t exists!";
return false;
}
return false;
@@ -103,7 +103,7 @@ bool PISerial::isPin(int number) const {
bool PISerial::setBit(int bit, bool on, const PIString & bname) {
#ifndef WINDOWS
if (fd < 0) {
- piCout << "[PISerial] set" << bname << " error: \"" << path_ << "\" is not opened!" << endl;
+ piCout << "[PISerial] set" << bname << " error: \"" << path_ << "\" is not opened!";
return false;
}
if (ioctl(fd, on ? TIOCMBIS : TIOCMBIC, &bit) < 0) {
@@ -112,7 +112,7 @@ bool PISerial::setBit(int bit, bool on, const PIString & bname) {
}
return true;
#else
- piCout << "[PISerial] set" << bname << " doesn`t implemented on Windows, sorry :-(" << endl;
+ piCout << "[PISerial] set" << bname << " doesn`t implemented on Windows, sorry :-(";
return false;
#endif
}
@@ -121,7 +121,7 @@ bool PISerial::setBit(int bit, bool on, const PIString & bname) {
bool PISerial::isBit(int bit, const PIString & bname) const {
#ifndef WINDOWS
if (fd < 0) {
- piCout << "[PISerial] is" << bname << " error: \"" << path_ << "\" is not opened!" << endl;
+ piCout << "[PISerial] is" << bname << " error: \"" << path_ << "\" is not opened!";
return false;
}
int ret = 0;
@@ -129,7 +129,7 @@ bool PISerial::isBit(int bit, const PIString & bname) const {
piCout << "[PISerial] is" << bname << " error: " << errorString();
return ret & bit;
#else
- piCout << "[PISerial] set" << bname << " doesn`t implemented on Windows, sorry :-(" << endl;
+ piCout << "[PISerial] set" << bname << " doesn`t implemented on Windows, sorry :-(";
return false;
#endif
}
@@ -301,7 +301,7 @@ bool PISerial::openDevice() {
if (isWriteable()) {ds |= GENERIC_WRITE; sm |= FILE_SHARE_WRITE;}
hCom = CreateFileA(path_.data(), ds, sm, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
if(hCom == INVALID_HANDLE_VALUE) {
- piCout << "[PISerial] Unable to open \"" << path_ << "\"" << endl;
+ piCout << "[PISerial] Unable to open \"" << path_ << "\"";
return false;
}
fd = 0;
@@ -312,7 +312,7 @@ bool PISerial::openDevice() {
times.WriteTotalTimeoutConstant = 1;
times.WriteTotalTimeoutMultiplier = 0;
if (SetCommTimeouts(hCom, ×) == -1) {
- piCout << "[PISerial] Unable to set timeouts for \"" << path_ << "\"" << endl;
+ piCout << "[PISerial] Unable to set timeouts for \"" << path_ << "\"";
CloseHandle(hCom);
fd = -1;
return false;
@@ -330,7 +330,7 @@ bool PISerial::openDevice() {
}
desc.StopBits = params[PISerial::TwoStopBits] ? TWOSTOPBITS : ONESTOPBIT;
if (SetCommState(hCom, &desc) == -1) {
- piCout << "[PISerial] Unable to set comm state for \"" << path_ << "\"" << endl;
+ piCout << "[PISerial] Unable to set comm state for \"" << path_ << "\"";
CloseHandle(hCom);
fd = -1;
return false;
@@ -345,7 +345,7 @@ bool PISerial::openDevice() {
//cout << "init ser " << path_ << " mode " << om << " param " << params << endl;
fd = ::open(path_.data(), O_NOCTTY | om);
if(fd == -1) {
- piCout << "[PISerial] Unable to open \"" << path_ << "\"" << endl;
+ piCout << "[PISerial] Unable to open \"" << path_ << "\"";
return false;
}
@@ -371,20 +371,20 @@ bool PISerial::openDevice() {
fcntl(fd, F_SETFL, 0);
if(tcsetattr(fd, TCSANOW, &desc) < 0) {
- piCout << "[PISerial] Can`t set attributes for \"" << path_ << "\"" << endl;
+ piCout << "[PISerial] Can`t set attributes for \"" << path_ << "\"";
::close(fd);
return false;
}
- //piCout << "[PISerial] Initialized " << path_ << endl;
+ //piCout << "[PISerial] Initialized " << path_;
#endif
return true;
}
int PISerial::write(const void * data, int max_size, bool wait) {
- //piCout << "[PISerial] send " << max_size << ": " << PIString((char*)data, max_size) << endl;
+ //piCout << "[PISerial] send " << max_size << ": " << PIString((char*)data, max_size);
if (fd == -1 || !canWrite()) {
- //piCout << "[PISerial] Can`t write to uninitialized COM" << endl;
+ //piCout << "[PISerial] Can`t write to uninitialized COM";
return -1;
}
#ifdef WINDOWS
@@ -402,6 +402,6 @@ int PISerial::write(const void * data, int max_size, bool wait) {
if (wait) tcdrain(fd);
#endif
return (int)wrote;
- //piCout << "[PISerial] Error while sending" << endl;
- //piCout << "[PISerial] Wrote " << wrote << " bytes in " << path_ << endl;
+ //piCout << "[PISerial] Error while sending";
+ //piCout << "[PISerial] Wrote " << wrote << " bytes in " << path_;
}
diff --git a/piserial.h b/piserial.h
index 4e00e2d8..dd0e9a7e 100644
--- a/piserial.h
+++ b/piserial.h
@@ -29,7 +29,7 @@
# ifndef B50
# define B50 0000001
# endif
-# ifndef B50
+# ifndef B75
# define B75 0000002
# endif
# ifndef B1500000
@@ -83,8 +83,11 @@
# define B3500000 3500000
# define B4000000 4000000
#endif
+#ifndef CRTSCTS
+# define CRTSCTS 020000000000
+#endif
-class PISerial: public PIIODevice {
+class PIP_EXPORT PISerial: public PIIODevice {
public:
// slot is any function format "bool (void*, uchar*, int)"
// slot_header is any function format "bool (void*, uchar*, uchar*, int)"
diff --git a/pisignals.h b/pisignals.h
index b1e9ec3d..3cd8c872 100644
--- a/pisignals.h
+++ b/pisignals.h
@@ -23,7 +23,7 @@
#include "picontainers.h"
#include
-class PISignals
+class PIP_EXPORT PISignals
{
public:
enum Signal {
diff --git a/pistring.cpp b/pistring.cpp
index bbd1721e..51179ac7 100644
--- a/pistring.cpp
+++ b/pistring.cpp
@@ -20,6 +20,41 @@
#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',
@@ -346,25 +381,24 @@ int PIString::lengthAscii() const {
const char * PIString::data() const {
- PIByteArray & d_(*(const_cast(&data_)));
- d_.clear();
+ data_.clear();
int wc;
uchar tc;
for (int i = 0, j = 0; i < size_s(); ++i) {
wc = at(i).toInt();
while (tc = wc & 0xFF, tc) {
- d_.push_back(uchar(tc)); ++j;
+ data_.push_back(uchar(tc)); ++j;
wc >>= 8;
}
/*if (at(i).isAscii())
- d_.push_back(uchar(at(i).toAscii()));
+ data_.push_back(uchar(at(i).toAscii()));
else {
- d_.push_back((at(i).toCharPtr()[0])); ++j;
- d_.push_back((at(i).toCharPtr()[1]));
+ data_.push_back((at(i).toCharPtr()[0])); ++j;
+ data_.push_back((at(i).toCharPtr()[1]));
}*/
}
- d_.push_back(uchar('\0'));
- return (const char * )d_.data();
+ data_.push_back(uchar('\0'));
+ return (const char * )data_.data();
}
@@ -439,25 +473,29 @@ llong PIString::toLLong() const {
}
*/
-PIString & PIString::setReadableSize(long bytes) {
+PIString & PIString::setReadableSize(llong bytes) {
clear();
if (bytes < 1024) {*this += (PIString::fromNumber(bytes) + " B"); return *this;}
double fres = bytes / 1024.;
- long res = bytes / 1024;
+ llong res = bytes / 1024;
fres -= res;
- if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(int(fres * 10)).left(1) + " kB"); return *this;}
+ 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(int(fres * 10)).left(1) + " MB"); return *this;}
+ 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(int(fres * 10)).left(1) + " GB"); return *this;}
+ if (res < 1024) {*this += (PIString::fromNumber(res) + "." + PIString::fromNumber(llong(fres * 10)).left(1) + " GB"); return *this;}
fres = res / 1024.;
res /= 1024;
fres -= res;
- *this += (PIString::fromNumber(res) + "." + PIString::fromNumber(int(fres * 10)).left(1) + " PB");
+ 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;
}
@@ -476,6 +514,7 @@ inline char chrLwr(char c) {
}
+
PIStringList& PIStringList::removeDuplicates() {
PIStringList l;
PIString s;
diff --git a/pistring.h b/pistring.h
index 35e12a7b..03b679b2 100644
--- a/pistring.h
+++ b/pistring.h
@@ -1,3 +1,8 @@
+/*! \file pistring.h
+ * \brief String
+ *
+ * This file declare string and string list classes
+*/
/*
PIP - Platform Independent Primitives
String
@@ -26,13 +31,14 @@
class PIStringList;
-class PIString: public PIVector
+class PIP_EXPORT PIString: public PIVector
{
public:
- PIString() {piMonitor.strings++; piMonitor.containers--;}
+ //! Contructs an empty string
+ PIString() {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 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;}
@@ -43,107 +49,335 @@ public:
#endif
//PIString(const char c) {*this += c;}
- PIString(const PIChar c) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += c;}
+
+ //! Contructs string with single symbol "c"
+ PIString(const PIChar & c) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += 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) {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) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
+
+ //! Contructs string from std::string "str"
PIString(const string & str) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
-#ifdef HAS_LOCALE
+
+ #ifdef HAS_LOCALE
PIString(const wstring & str) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
#endif
+
+ //! Contructs string from byte array "ba"
PIString(const PIByteArray & ba) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += ba;}
+
+ /*! \brief Contructs string from "len" characters of buffer "str"
+ * \details Example: \snippet pistring.cpp PIString(char * , int) */
PIString(const char * str, const int len) {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) {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) {reserve(256); piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);}
+
+ //! Contructs string from other string "str"
PIString(const PIString & str) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
+
~PIString() {piMonitor.strings--; piMonitor.containers++;}
+
+ /*! \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 const reference 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);}
+
+ /*! \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;}
- PIString & operator <<(const PIChar 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;}
+
+ /*! \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;}
+
+ /*! \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;}
+
+ /*! \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 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 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) {PIVector::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;}
//const char * data() {return convertToStd().c_str();}
+
+
+ /*! \brief Return real bytes count of this string
+ * \details It`s equivalent length os 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
const 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);}
@@ -151,60 +385,199 @@ public:
PIString toNativeDecimalPoints() const {PIString s(*this); return s;}
#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 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" or "on" or positive numeric value
bool toBool() const {PIString s(*this); if (atof(s.toNativeDecimalPoints().data()) > 0. || s.trimmed().toLowerCase() == "true" || 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 {PIString s(*this); return (float)atof(s.toNativeDecimalPoints().data());}
+
+ //! \brief Return \c double numeric value of string
+ //! \details Example: \snippet pistring.cpp PIString::toFloat
double toDouble() const {PIString s(*this); return atof(s.toNativeDecimalPoints().data());}
+
+ //! \brief Return \c ldouble numeric value of string
+ //! \details Example: \snippet pistring.cpp PIString::toFloat
ldouble toLDouble() const {PIString s(*this); return atof(s.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;}
- PIString & setNumber(const llong value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
- 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" 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;}
- PIString & setNumber(const double value) {clear(); *this += dtos(value); return *this;}
- PIString & setNumber(const ldouble value) {clear(); *this += dtos(value); return *this;}
- PIString & setReadableSize(long bytes);
+
+ //! \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 fromNumberBase(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 fromNumberBase(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 int value, int base = 10, bool * ok = 0) {return fromNumberBase(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 fromNumberBase(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 long value, int base = 10, bool * ok = 0) {return fromNumberBase(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 fromNumberBase(llong(value), base, ok);}
- static PIString fromNumber(const llong value, int base = 10, bool * ok = 0) {return fromNumberBase(value, base, ok);}
- static PIString fromNumber(const ullong value, int base = 10, bool * ok = 0) {return fromNumberBase(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 llong & value, int base = 10, bool * ok = 0) {return fromNumberBase(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 fromNumberBase(llong(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));}
- static PIString fromNumber(const double value) {return PIString(dtos(value));}
- static PIString fromNumber(const ldouble value) {return PIString(dtos(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");}
- static PIString readableSize(long bytes) {PIString s; s.setReadableSize(bytes); return s;}
+
+ //! \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;}
private:
static const char toBaseN[];
@@ -254,45 +627,92 @@ private:
wstring convertToWString() const {wstring s; for (int i = 0; i < length(); ++i) s.push_back(at(i).toWChar()); return s;}
#endif
- PIByteArray data_;
+ 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) {s << v.size_s(); for (int i = 0; i < v.length(); ++i) s << v[i]; return s;}
+
+//! \relatesalso PIString \relatesalso PIByteArray \brief Input operator from PIByteArray
inline PIByteArray & operator >>(PIByteArray & s, PIString & v) {int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; 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);
-class PIStringList: public PIVector
+
+/*!\brief Strings array class
+ * \details This class is based on \a PIVector and
+ * expand it functionality. */
+class PIP_EXPORT PIStringList: public PIVector
{
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);}
+
+ //! \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) {PIVector::remove(num); return *this;}
PIStringList & remove(uint num, uint count) {PIVector::remove(num, count); return *this;}
+
+ //! \brief Remove duplicated strings and return this
+ //! \details Example: \snippet pistring.cpp PIStringList::removeDuplicates
PIStringList & removeDuplicates();
+
+ //! 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;}
PIStringList & operator <<(const PIString & str) {push_back(str); return *this;}
@@ -308,6 +728,10 @@ public:
};
+//! \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/pisystemmonitor.cpp b/pisystemmonitor.cpp
index b880ac0c..774bbfc6 100644
--- a/pisystemmonitor.cpp
+++ b/pisystemmonitor.cpp
@@ -42,7 +42,7 @@ bool PISystemMonitor::startOnProcess(int pID) {
file.open("/proc/" + PIString::fromNumber(pID_) + "/stat", PIIODevice::ReadOnly);
filem.open("/proc/" + PIString::fromNumber(pID_) + "/statm", PIIODevice::ReadOnly);
if (!file.isOpened()) {
- piCout << "[PISystemMonitor] Can`t find process with ID = " << pID_ << "!" << endl;
+ piCout << "[PISystemMonitor] Can`t find process with ID = " << pID_ << "!";
return false;
}
cycle = -1;
diff --git a/pisystemmonitor.h b/pisystemmonitor.h
index 2f013092..51ed5068 100644
--- a/pisystemmonitor.h
+++ b/pisystemmonitor.h
@@ -23,7 +23,7 @@
#include "pithread.h"
#include "piprocess.h"
-class PISystemMonitor: public PIThread
+class PIP_EXPORT PISystemMonitor: public PIThread
{
public:
PISystemMonitor();
diff --git a/pisystemtests.h b/pisystemtests.h
index 1c8e4539..eea34196 100644
--- a/pisystemtests.h
+++ b/pisystemtests.h
@@ -23,9 +23,9 @@
#include "piconfig.h"
namespace PISystemTests {
- extern long time_resolution_ns;
- extern long time_elapsed_ns;
- extern long usleep_offset_us;
+ PIP_EXPORT extern long time_resolution_ns;
+ PIP_EXPORT extern long time_elapsed_ns;
+ PIP_EXPORT extern long usleep_offset_us;
class PISystemTestReader {
public:
diff --git a/pithread.cpp b/pithread.cpp
index b9e97860..9ff6b122 100644
--- a/pithread.cpp
+++ b/pithread.cpp
@@ -31,6 +31,36 @@ void piUSleep(int usecs) {
}
+/*! \class PIThread
+ * \brief Thread class
+ * \details This class allow you exec your code in separate thread.
+ *
+ * \section PIThread_sec0 Synopsis
+ * Multithread .
+ *
+ * \section PIThread_sec1 To/from data convertions
+ * Most common constructor is \a PIThread(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 PIThread from single \a PIChar, \a PIByteArray,
+ * other \a PIThread 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 PIThread_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 PIThread. \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().
+ *
+ */
+
+
PIThread::PIThread(void * data, ThreadFunc func, bool startNow, int timer_delay): PIObject() {
piMonitor.threads++;
data_ = data;
@@ -58,12 +88,14 @@ PIThread::~PIThread() {
#ifndef WINDOWS
pthread_cancel(thread);
#else
+ TerminateThread(thread, 0);
CloseHandle(thread);
#endif
}
bool PIThread::start(int timer_delay) {
+ if (running) return false;
terminating = running = false;
timer = timer_delay;
#ifndef WINDOWS
@@ -88,6 +120,7 @@ bool PIThread::start(int timer_delay) {
bool PIThread::startOnce() {
+ if (running) return false;
terminating = running = false;
#ifndef WINDOWS
pthread_attr_t attr;
@@ -110,13 +143,13 @@ bool PIThread::startOnce() {
}
-void PIThread::terminate(bool hard) {
+void PIThread::terminate() {
if (thread == 0) return;
running = false;
#ifndef WINDOWS
- if (hard) kill((ullong)thread, SIGKILL);
- else pthread_cancel(thread);
+ pthread_cancel(thread);
#else
+ TerminateThread(thread, 0);
CloseHandle(thread);
#endif
thread = 0;
@@ -125,6 +158,10 @@ void PIThread::terminate(bool hard) {
void * PIThread::thread_function(void * t) {
+#ifndef WINDOWS
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
+ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
+#endif
PIThread & ct = *((PIThread * )t);
ct.running = true;
ct.begin();
@@ -150,6 +187,10 @@ void * PIThread::thread_function(void * t) {
void * PIThread::thread_function_once(void * t) {
+#ifndef WINDOWS
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
+ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
+#endif
PIThread & ct = *((PIThread * )t);
ct.running = true;
ct.begin();
diff --git a/pithread.h b/pithread.h
index d9f109e0..0de14501 100644
--- a/pithread.h
+++ b/pithread.h
@@ -1,3 +1,8 @@
+/*! \file pithread.h
+ * \brief Thread
+ *
+ * This file declare thread class and some wait functions
+*/
/*
PIP - Platform Independent Primitives
Thread
@@ -24,86 +29,188 @@
#include "pimutex.h"
#include "piobject.h"
-#ifdef WINDOWS
-inline void msleep(int msecs) {Sleep(msecs);}
+#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(int msecs) {piUSleep(msecs * 1000);} // on !Windows consider constant "usleep" offset
typedef void (*ThreadFunc)(void * );
-/// events:
-/// void started()
-/// void stopped()
-///
-/// handlers:
-/// bool start(int timer_delay = -1)
-/// bool start(ThreadFunc func, int timer_delay = -1)
-/// bool startOnce()
-/// bool startOnce(ThreadFunc func)
-/// void stop(bool wait = false)
-/// void terminate(bool hard = false)
-/// bool waitForStart(int timeout_msecs = -1)
-/// bool waitForFinish(int timeout_msecs = -1)
-/// void lock()
-/// void unlock()
-class PIThread: public PIObject {
+
+class PIP_EXPORT PIThread: public PIObject
+{
+ PIOBJECT(PIThread)
public:
PIThread(void * data, ThreadFunc func, bool startNow = false, int timer_delay = -1);
PIThread(bool startNow = false, int timer_delay = -1);
virtual ~PIThread();
-#ifdef QNX
+#ifdef DOXYGEN
+ //! Priority of thread
+ enum Priority {piHighest /** Highest */,
+ piHigh /** High */,
+ piNormal /** Normal, default */,
+ piLow /** Low */,
+ piLowerst /** Lowest */
+ };
+#else
+# ifdef QNX
enum Priority {piHighest = 12,
piHigh = 11,
piNormal = 10,
piLow = 9,
piLowerst = 8 };
-#else
+# else
enum Priority {piHighest = -2,
piHigh = -1,
piNormal = 0,
piLow = 1,
piLowerst = 2 };
+# endif
#endif
- //bool start(int timer_delay = -1);
- EVENT_HANDLER0(PIThread, bool, start) {return start(-1);}
- EVENT_HANDLER1(PIThread, bool, start, int, timer_delay);
- EVENT_HANDLER1(PIThread, bool, start, ThreadFunc, func) {ret_func = func; return start(-1);}
- EVENT_HANDLER2(PIThread, bool, start, ThreadFunc, func, int, timer_delay) {ret_func = func; return start(timer_delay);}
- EVENT_HANDLER0(PIThread, bool, startOnce);
- EVENT_HANDLER1(PIThread, bool, startOnce, ThreadFunc, func) {ret_func = func; return startOnce();}
- EVENT_HANDLER0(PIThread, void, stop) {stop(false);}
- EVENT_HANDLER1(PIThread, void, stop, bool, wait) {terminating = true; if (wait) waitForFinish();}
- EVENT_HANDLER0(PIThread, void, terminate) {terminate(false);}
- EVENT_HANDLER1(PIThread, void, terminate, bool, hard);
+ 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 Return priority of thread
PIThread::Priority priority() const {return priority_;}
+
+ //! \brief Return \c true if thread is running
bool isRunning() const {return running;}
- EVENT_HANDLER0(PIThread, bool, waitForFinish) {return waitForFinish(-1);}
- EVENT_HANDLER1(PIThread, bool, waitForFinish, int, timeout_msecs);
- EVENT_HANDLER0(PIThread, bool, waitForStart) {return waitForStart(-1);}
- EVENT_HANDLER1(PIThread, bool, waitForStart, int, timeout_msecs);
+
+ 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(PIThread, void, lock) {mutex_.lock();}
- EVENT_HANDLER0(PIThread, void, unlock) {mutex_.unlock();}
+ EVENT_HANDLER0(void, lock) {mutex_.lock();}
+ EVENT_HANDLER0(void, unlock) {mutex_.unlock();}
+
+ //! \brief Return internal mutex
PIMutex & mutex() {return mutex_;}
- EVENT(PIThread, started)
- EVENT(PIThread, stopped)
+ 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);
- virtual void begin() {;} // executed at start
- virtual void run() {;} // main loop executed with "timer_delay" timeout
- virtual void end() {;} // executed at finish
+ virtual void begin() {;}
+ virtual void run() {;}
+ virtual void end() {;}
volatile bool terminating, running, lockRun;
int timer, policy;
diff --git a/pitimer.cpp b/pitimer.cpp
index da90d0c2..400ee637 100644
--- a/pitimer.cpp
+++ b/pitimer.cpp
@@ -20,6 +20,73 @@
#include "pitimer.h"
#include "pisystemtests.h"
+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;
+}
+
#ifdef PIP_TIMER_RT
PITimer::TimerPool * pool = 0;
@@ -34,17 +101,20 @@ PITimer::PITimer(TimerEvent slot, void * data_, bool threaded_)
#endif
ret_func = slot;
data = data_;
+ running_ = false;
+ interval_ = 0.;
#ifdef PIP_TIMER_RT
piMonitor.timers++;
ti = -1;
threaded = threaded_;
- running = false;
memset(&se, 0, sizeof(se));
se.sigev_notify = SIGEV_THREAD;
se.sigev_value.sival_ptr = this;
se.sigev_notify_function = PITimer::timer_event;
se.sigev_notify_attributes = 0;
lockRun = false;
+#else
+ deferred_ = false;
#endif
reset();
}
@@ -58,17 +128,20 @@ PITimer::PITimer(bool threaded_)
#endif
ret_func = 0;
data = 0;
+ running_ = false;
+ interval_ = 0.;
#ifdef PIP_TIMER_RT
piMonitor.timers++;
ti = -1;
threaded = threaded_;
- running = false;
memset(&se, 0, sizeof(se));
se.sigev_notify = SIGEV_THREAD;
se.sigev_value.sival_ptr = this;
se.sigev_notify_function = PITimer::timer_event;
se.sigev_notify_attributes = 0;
lockRun = false;
+#else
+ deferred_ = false;
#endif
reset();
}
@@ -84,14 +157,15 @@ PITimer::~PITimer() {
#ifdef PIP_TIMER_RT
void PITimer::start(double msecs) {
- if (ti != -1 || msecs < 0 || running) return;
+ if (ti != -1 || msecs < 0 || running_) return;
+ interval_ = msecs;
if (!threaded) {
ticks = int(msecs);
if (pool == 0) pool = new TimerPool();
pool->add(this);
//cout << "not threaded timer start " << msecs << " msecs\n";
if (!pool->isRunning()) pool->start();
- running = true;
+ running_ = true;
return;
}
spec.it_interval.tv_nsec = ((int)(msecs * 1000) % 1000000) * 1000;
@@ -100,16 +174,17 @@ void PITimer::start(double msecs) {
ti = timer_create(CLOCK_REALTIME, &se, &timer);
//cout << "***create timer " << msecs << " msecs\n";
if (ti == -1) {
- piCout << "[PITimer] Can`t create timer for " << msecs << " msecs: " << errorString() << endl;
+ piCout << "[PITimer] Can`t create timer for " << msecs << " msecs: " << errorString();
return;
}
timer_settime(timer, 0, &spec, 0);
- running = true;
+ running_ = true;
}
void PITimer::deferredStart(double interval_msecs, double delay_msecs) {
- if (ti != -1 || interval_msecs < 0 || running) return;
+ if (ti != -1 || interval_msecs < 0 || running_) return;
+ interval_ = interval_msecs;
spec.it_interval.tv_nsec = ((int)(interval_msecs * 1000) % 1000000) * 1000;
spec.it_interval.tv_sec = (time_t)(interval_msecs / 1000);
spec.it_value.tv_nsec = ((int)(delay_msecs * 1000) % 1000000) * 1000;
@@ -117,16 +192,17 @@ void PITimer::deferredStart(double interval_msecs, double delay_msecs) {
ti = timer_create(CLOCK_REALTIME, &se, &timer);
//cout << "***create timer\n";
if (ti == -1) {
- piCout << "[PITimer] Can`t create timer for " << interval_msecs << " msecs: " << errorString() << endl;
+ piCout << "[PITimer] Can`t create timer for " << interval_msecs << " msecs: " << errorString();
return;
}
timer_settime(timer, 0, &spec, 0);
- running = true;
+ running_ = true;
}
void PITimer::deferredStart(double interval_msecs, const PIDateTime & start_datetime) {
- if (ti != -1 || interval_msecs < 0 || running) return;
+ if (ti != -1 || interval_msecs < 0 || running_) return;
+ interval_ = interval_msecs;
spec.it_interval.tv_nsec = ((int)(interval_msecs * 1000) % 1000000) * 1000;
spec.it_interval.tv_sec = (time_t)(interval_msecs / 1000);
struct tm dtm;
@@ -142,11 +218,11 @@ void PITimer::deferredStart(double interval_msecs, const PIDateTime & start_date
ti = timer_create(CLOCK_REALTIME, &se, &timer);
//cout << "***create timer\n";
if (ti == -1) {
- piCout << "[PITimer] Can`t create timer for " << interval_msecs << " msecs: " << errorString() << endl;
+ piCout << "[PITimer] Can`t create timer for " << interval_msecs << " msecs: " << errorString();
return;
}
timer_settime(timer, TIMER_ABSTIME, &spec, 0);
- running = true;
+ running_ = true;
}
@@ -170,7 +246,7 @@ void PITimer::TimerPool::begin() {
sa.sa_handler = empty_handler;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGALRM, &sa, 0) == -1) {
- piCout << "[PITimer] sigaction error: " << errorString() << endl;
+ piCout << "[PITimer] sigaction error: " << errorString();
stop();
return;
}*/
@@ -184,12 +260,12 @@ void PITimer::TimerPool::begin() {
spec.it_value = spec.it_interval;
//cout << "***create pool timer\n";
if (timer_create(CLOCK_REALTIME, &se, &timer) == -1) {
- piCout << "[PITimer] Can`t create timer for pool: " << errorString() << endl;
+ piCout << "[PITimer] Can`t create timer for pool: " << errorString();
stop();
return;
}
if (timer_settime(timer, 0, &spec, 0) == -1) {
- piCout << "[PITimer] Can`t set timer for pool: " << errorString() << endl;
+ piCout << "[PITimer] Can`t set timer for pool: " << errorString();
stop();
return;
}
@@ -221,8 +297,8 @@ void PITimer::TimerPool::run() {
void PITimer::stop() {
- if (!running) return;
- running = false;
+ if (!running_) return;
+ running_ = false;
if (!threaded) {
if (pool != 0) {
pool->remove(this);
@@ -231,12 +307,13 @@ void PITimer::stop() {
}
if (ti != -1) timer_delete(timer);
ti = -1;
+ interval_ = 0.;
}
void PITimer::timer_event(sigval e) {
PITimer * ct = (PITimer * )e.sival_ptr;
- if (!ct->running) return;
+ if (!ct->running_) return;
if (ct->lockRun) ct->lock();
if (ct->ret_func != 0) ct->ret_func(ct->data, 1);
ct->timeout(ct->data, 1);
@@ -255,12 +332,12 @@ void PITimer::timer_event(sigval e) {
bool PITimer::waitForFinish(int timeout_msecs) {
if (timeout_msecs < 0) {
- while (running)
+ while (running_)
msleep(1);
return true;
}
int cnt = 0;
- while (running && cnt < timeout_msecs) {
+ while (running_ && cnt < timeout_msecs) {
msleep(1);
++cnt;
}
@@ -270,18 +347,65 @@ bool PITimer::waitForFinish(int timeout_msecs) {
#else
void PITimer::start(double msecs) {
- if (msecs < 0 || running) return;
+ if (msecs < 0 || running_) return;
+ interval_ = msecs;
inc_time = PISystemTime::fromMilliseconds(msecs);
st_time = currentSystemTime() + inc_time;
+ deferred_ = false;
+ running_ = true;
PIThread::start();
}
+void PITimer::deferredStart(double interval_msecs, double delay_msecs) {
+ //piCout << "defStart exec with" << delay_msecs << interval_msecs;
+ if (interval_msecs < 0 || running_) return;
+ interval_ = interval_msecs;
+ PISystemTime cst = currentSystemTime();
+ inc_time = PISystemTime::fromMilliseconds(interval_msecs);
+ st_time = currentSystemTime() + PISystemTime::fromMilliseconds(delay_msecs);
+ if (st_time < cst) st_time = cst;
+ running_ = deferred_ = true;
+ PIThread::start();
+ //piCout << "timer start def";
+}
+
+
+void PITimer::deferredStart(double interval_msecs, const PIDateTime & start_datetime) {
+ //piCout << "defStart exec to" << start_datetime.toString() << interval_msecs;
+ if (interval_msecs < 0 || running_) return;
+ interval_ = interval_msecs;
+ PISystemTime cst = currentSystemTime();
+ inc_time = PISystemTime::fromMilliseconds(interval_msecs);
+ st_time = start_datetime.toSystemTime();
+ if (st_time < cst) st_time = cst;
+ running_ = deferred_ = true;
+ PIThread::start();
+ //piCout << "timer start def";
+}
+
+
void PITimer::run() {
- if (!running) return;
+ if (!running_) return;
+ while (deferred_) {
+ PISystemTime tst = st_time - currentSystemTime();
+ if (tst.seconds > 0) {
+ piMSleep(100);
+ if (!running_) return;
+ continue;
+ }
+ if (tst.nanoseconds > 100000000) {
+ piMSleep(100);
+ if (!running_) return;
+ continue;
+ }
+ tst.sleep();
+ deferred_ = false;
+ if (!running_) return;
+ }
(st_time - currentSystemTime()).sleep();
st_time += inc_time;
- if (lockRun) lock();
+ //if (lockRun) lock();
if (ret_func != 0) ret_func(data, 1);
timeout(data, 1);
tick(data, 1);
@@ -293,7 +417,7 @@ void PITimer::run() {
timeout(data, i.delim);
tick(data, i.delim);
}
- if (lockRun) unlock();
+ //if (lockRun) unlock();
}
#endif
@@ -524,7 +648,7 @@ PISystemTime currentSystemTime() {
}
-PIString PITime::toString(const PIString & format) {
+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));
@@ -532,11 +656,14 @@ PIString PITime::toString(const PIString & format) {
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) {
+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));
@@ -549,14 +676,8 @@ PIString PIDate::toString(const PIString & format) {
}
-PIString PIDateTime::toString(const PIString & format) {
+PIString PIDateTime::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("yyyy", PIString::fromNumber(year).expandLeftTo(4, '0'));
ts.replace("yy", PIString::fromNumber(year).right(2));
ts.replace("y", PIString::fromNumber(year).right(1));
@@ -564,10 +685,45 @@ PIString PIDateTime::toString(const PIString & format) {
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;
}
+time_t PIDateTime::toSecondSinceEpoch() const {
+ tm pt;
+ pt.tm_sec = seconds;
+ pt.tm_min = minutes;
+ pt.tm_hour = hours;
+ pt.tm_mday = day;
+ pt.tm_mon = month - 1;
+ pt.tm_year = year - 1900;
+ 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'));
diff --git a/pitimer.h b/pitimer.h
index 10c9d7a2..9359ccbd 100644
--- a/pitimer.h
+++ b/pitimer.h
@@ -28,7 +28,7 @@
typedef void (*TimerEvent)(void * , int );
-class PISystemTime {
+class PIP_EXPORT PISystemTime {
public:
PISystemTime() {seconds = nanoseconds = 0;}
PISystemTime(long s, long ns) {seconds = s; nanoseconds = ns; checkOverflows();}
@@ -71,29 +71,65 @@ private:
inline PIByteArray & operator <<(PIByteArray & s, const PISystemTime & v) {s << v.seconds << v.nanoseconds; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PISystemTime & v) {s >> v.seconds >> v.nanoseconds; return s;}
-struct PITime {
+struct PIP_EXPORT PITime {
+ PITime() {hours = minutes = seconds = milliseconds = 0;}
+ int milliseconds;
int seconds;
int minutes;
int hours;
- PIString toString(const PIString & format = "h:mm:ss");
+ PIString toString(const PIString & format = "h:mm:ss") const;
};
+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);}
-struct PIDate {
+struct PIP_EXPORT PIDate {
+ PIDate() {year = month = day = 0;}
int day;
int month;
int year;
- PIString toString(const PIString & format = "d.MM.yyyy");
+ PIString toString(const PIString & format = "d.MM.yyyy") const;
};
+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);}
-struct PIDateTime {
+struct PIP_EXPORT PIDateTime {
+ PIDateTime() {year = month = day = hours = minutes = seconds = 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;}
+ int milliseconds;
int seconds;
int minutes;
int hours;
int day;
int month;
int year;
- PIString toString(const PIString & format = "h:mm:ss d.MM.yyyy");
+ 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);}
+ 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;}
};
+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);}
/// events:
/// void timeout(void * data, int delimiter)
@@ -108,13 +144,14 @@ struct PIDateTime {
/// void clearDelimiters()
/// void lock()
/// void unlock()
-class PITimer
+class PIP_EXPORT PITimer
#ifndef PIP_TIMER_RT
: public PIThread
#else
: public PIObject
#endif
{
+ PIOBJECT(PITimer)
public:
PITimer(TimerEvent slot = 0, void * data = 0, bool threaded = true);
PITimer(bool threaded);
@@ -122,53 +159,53 @@ public:
void setData(void * data_) {data = data_;}
void setSlot(TimerEvent slot) {ret_func = slot;}
+ double interval() const {return interval_;}
#ifndef PIP_TIMER_RT
# ifdef WINDOWS
- EVENT_HANDLER0(PITimer, void, reset) {t_st = GetCurrentTime();}
- EVENT_HANDLER1(PIThread, bool, start, int, timer_delay) {start(double(timer_delay)); return true;}
- EVENT_HANDLER1(PITimer, void, start, double, msecs);
+ EVENT_HANDLER0(void, reset) {t_st = GetCurrentTime();}
# elif defined(MAC_OS)
- EVENT_HANDLER0(PITimer, void, reset) {clock_get_time(__pi_mac_clock, &t_st);}
- EVENT_HANDLER1(PIThread, bool, start, int, timer_delay) {start(double(timer_delay)); return true;}
- EVENT_HANDLER1(PITimer, void, start, double, msecs);
+ EVENT_HANDLER0(void, reset) {clock_get_time(__pi_mac_clock, &t_st);}
# else
- EVENT_HANDLER0(PITimer, void, reset) {clock_gettime(0, &t_st);}
- EVENT_HANDLER1(PIThread, bool, start, int, timer_delay) {start(double(timer_delay)); return true;}
- EVENT_HANDLER1(PITimer, void, start, double, msecs);
+ EVENT_HANDLER0(void, reset) {clock_gettime(0, &t_st);}
# endif
+ EVENT_HANDLER1(bool, start, int, timer_delay) {start(double(timer_delay)); return true;}
+ EVENT_HANDLER1(void, start, double, msecs);
+ EVENT_HANDLER0(void, stop) {running_ = false;}
+ EVENT_HANDLER2(void, deferredStart, double, interval_msecs, double, delay_msecs);
+ EVENT_HANDLER2(void, deferredStart, double, interval_msecs, const PIDateTime &, start_datetime);
#else
- EVENT_HANDLER0(PITimer, void, reset) {clock_gettime(0, &t_st);}
- EVENT_HANDLER1(PITimer, void, start, double, msecs);
- EVENT_HANDLER2(PITimer, void, deferredStart, double, interval_msecs, double, delay_msecs);
- EVENT_HANDLER2(PITimer, void, deferredStart, double, interval_msecs, const PIDateTime &, start_datetime);
- EVENT_HANDLER0(PITimer, void, stop);
- EVENT_HANDLER0(PITimer, bool, waitForFinish) {return waitForFinish(-1);}
- EVENT_HANDLER1(PITimer, bool, waitForFinish, int, timeout_msecs);
- bool isRunning() const {return running;}
+ EVENT_HANDLER0(void, reset) {clock_gettime(0, &t_st);}
+ EVENT_HANDLER1(void, start, double, msecs);
+ EVENT_HANDLER2(void, deferredStart, double, interval_msecs, double, delay_msecs);
+ EVENT_HANDLER2(void, deferredStart, double, interval_msecs, const PIDateTime &, start_datetime);
+ EVENT_HANDLER0(void, stop);
+ EVENT_HANDLER0(bool, waitForFinish) {return waitForFinish(-1);}
+ EVENT_HANDLER1(bool, waitForFinish, int, timeout_msecs);
+ bool isRunning() const {return running_;}
void needLockRun(bool need) {lockRun = need;}
- EVENT_HANDLER0(PITimer, void, lock) {mutex_.lock();}
- EVENT_HANDLER0(PITimer, void, unlock) {mutex_.unlock();}
+ EVENT_HANDLER0(void, lock) {mutex_.lock();}
+ EVENT_HANDLER0(void, unlock) {mutex_.unlock();}
#endif
void addDelimiter(int delim, TimerEvent slot = 0) {ret_funcs << TimerSlot(slot, delim);}
void removeDelimiter(int delim) {for (int i = 0; i < ret_funcs.size_s(); ++i) if (ret_funcs[i].delim == delim) {ret_funcs.remove(i); i--;}}
void removeDelimiter(TimerEvent slot) {for (int i = 0; i < ret_funcs.size_s(); ++i) if (ret_funcs[i].slot == slot) {ret_funcs.remove(i); i--;}}
void removeDelimiter(int delim, TimerEvent slot) {for (int i = 0; i < ret_funcs.size_s(); ++i) if (ret_funcs[i].slot == slot && ret_funcs[i].delim == delim) {ret_funcs.remove(i); i--;}}
- EVENT_HANDLER0(PITimer, void, clearDelimiters) {ret_funcs.clear();}
+ EVENT_HANDLER0(void, clearDelimiters) {ret_funcs.clear();}
double elapsed_n(); // nanoseconds
double elapsed_u(); // microseconds
- double elapsed_m(); // miliseconds
+ double elapsed_m(); // milliseconds
double elapsed_s(); // seconds
double reset_time_n(); // nanoseconds
double reset_time_u(); // microseconds
- double reset_time_m(); // miliseconds
+ double reset_time_m(); // milliseconds
double reset_time_s(); // seconds
PISystemTime reset_time();
static double elapsed_system_n(); // nanoseconds
static double elapsed_system_u(); // microseconds
- static double elapsed_system_m(); // miliseconds
+ static double elapsed_system_m(); // milliseconds
static double elapsed_system_s(); // seconds
@@ -200,7 +237,7 @@ public:
int ticks;
#endif
- EVENT2(PITimer, timeout, void * , data, int, delimiter)
+ EVENT2(timeout, void * , data, int, delimiter)
protected:
virtual void tick(void * data, int delimiter) {;}
@@ -208,10 +245,12 @@ protected:
private:
#ifndef PIP_TIMER_RT
void run();
+ void end() {interval_ = 0.;}
PISystemTime st_time, inc_time;
+ bool deferred_;
#else
- bool running, threaded;
+ bool threaded;
volatile bool lockRun;
PIMutex mutex_;
int ti;
@@ -219,6 +258,8 @@ private:
timer_t timer;
sigevent se;
#endif
+ bool running_;
+ double interval_;
#ifdef WINDOWS
long
@@ -246,12 +287,12 @@ private:
extern PITimer::TimerPool * pool;
#endif
-PITime currentTime();
-PIDate currentDate();
-PIDateTime currentDateTime();
-PISystemTime currentSystemTime();
-PIString time2string(const PITime & time, const PIString & format = "h:mm:ss"); // obsolete, use PITime.toString() instead
-PIString date2string(const PIDate & date, const PIString & format = "d.MM.yyyy"); // obsolete, use PITime.toString() instead
-PIString datetime2string(const PIDateTime & datetime, const PIString & format = "h:mm:ss d.MM.yyyy"); // obsolete, use PIDateTime.toString() instead
+PIP_EXPORT PITime currentTime();
+PIP_EXPORT PIDate currentDate();
+PIP_EXPORT PIDateTime currentDateTime();
+PIP_EXPORT PISystemTime currentSystemTime();
+PIP_EXPORT PIString time2string(const PITime & time, const PIString & format = "h:mm:ss"); // obsolete, use PITime.toString() instead
+PIP_EXPORT PIString date2string(const PIDate & date, const PIString & format = "d.MM.yyyy"); // obsolete, use PITime.toString() instead
+PIP_EXPORT PIString datetime2string(const PIDateTime & datetime, const PIString & format = "h:mm:ss d.MM.yyyy"); // obsolete, use PIDateTime.toString() instead
#endif // PITIMER_H
diff --git a/pivariable.h b/pivariable.h
index 6f20de90..08fc51e8 100644
--- a/pivariable.h
+++ b/pivariable.h
@@ -22,11 +22,11 @@
#include "piconfig.h"
-class PIVariant {
+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);}
@@ -45,7 +45,7 @@ public:
PIVariant(const ldouble & v) {setValue(v);}
PIVariant(const PIString & v) {setValue(v);}
PIVariant(const PIStringList & v) {setValue(v);}
-
+
inline void setValue(const char * v) {setValue(PIString(v));}
inline void setValue(const bool & v) {type = PIVariant::Bool; vBool = v;}
inline void setValue(const char & v) {type = PIVariant::Char; vChar = v;}
@@ -92,7 +92,7 @@ public:
inline void operator =(const ldouble & v) {type = PIVariant::LDouble; vLDouble = v;}
inline void operator =(const PIString & v) {type = PIVariant::String; vString = v;}
inline void operator =(const PIStringList & v) {type = PIVariant::StringList; vStringList = v;}
-
+
bool operator ==(const PIVariant & v) const;
inline bool operator !=(const PIVariant & v) const {return !(*this == v);}
@@ -115,25 +115,25 @@ public:
};
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 char * var_ptr, const PIVariant::Type & var);
-
+
};
inline std::ostream & operator <<(std::ostream & s, const PIVariant & v) {s << v.typeName() << ": " << v.stringValue(); return s;}
-class PIVariable {
+class PIP_EXPORT PIVariable {
public:
PIVariable() {;}
PIVariable(const PIString & str) {setVariable(str);}
~PIVariable() {;}
-
+
void setVariable(const PIString & str);
void writeVariable(char * dest);
inline void readVariable(const char * var_ptr) {value_ = PIVariant::variableValue((char * )((long)var_ptr + offset), type_);}
@@ -143,37 +143,37 @@ public:
inline void setName(const PIString & str) {name_ = str;}
inline double value() const {return value_;}
inline 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 PIStruct {
+class PIP_EXPORT PIStruct {
public:
PIStruct() {;}
PIStruct(const PIString & str) {parseFile(str);}
-
+
void parseFile(const PIString & file);
void readData(const char * data);
void writeData(char * data);
@@ -184,17 +184,12 @@ public:
inline void setName(const PIString & str) {name_ = str;}
inline PIVariable & operator[](const uint & index) {return vars[index];}
inline PIVariable & operator[](const PIString & name) {for (uint i = 0; i < vars.size(); ++i) if (vars[i].name() == name) return vars[i];}
-
+
private:
uint size_;
PIString name_;
PIVector vars;
-
+
};
#endif // PIVARIABLE_H
-
-#/** PhEDIT attribute block
-#-11:16777215
-#0:7338:monospace10:-3:-3:0
-#** PhEDIT attribute block ends (-0000117)**/