diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b95cf08..036cde4b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,22 +1,23 @@ project(pip) find_package(Qt4) cmake_minimum_required(VERSION 2.6) -include_directories(${CMAKE_CURRENT_SOURCE_DIR} . ${QT_INCLUDES}) +include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${QT_INCLUDES} . ../peri4_widgets) file(GLOB CPPS "pi*.cpp") if (${WIN32}) add_definitions(-Wall -O2) else (${WIN32}) - add_definitions(-Wall -O2 -g3) + add_definitions(-Wall -O2 -g3 --fast-math) endif (${WIN32}) add_library(pip SHARED ${CPPS}) if (${WIN32}) - target_link_libraries(pip pthread ws2_32) + target_link_libraries(pip pthread ws2_32 Iphlpapi) else (${WIN32}) target_link_libraries(pip pthread rt) endif (${WIN32}) add_executable(pip_test "main.cpp") if (${WIN32}) - target_link_libraries(pip_test pthread ws2_32 pip) + target_link_libraries(pip_test pthread ws2_32 Iphlpapi pip) else (${WIN32}) - target_link_libraries(pip_test pthread rt pip ${QT_QTCORE_LIBRARY}) + target_link_libraries(pip_test pip ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} pcollection) endif (${WIN32}) +add_subdirectory(system_test) diff --git a/clean b/clean index ac8674c1..395a12c3 100755 --- a/clean +++ b/clean @@ -1,19 +1,7 @@ -#! /bin/bash +#! /bin/sh VERBOSE=1 make clean -rm -vf ./lib/* -#for i in $( ls -1 ); do -# if [ "`ls -1 --file-type | grep $i | grep -o /`" = "/" ]; then -# cd $i -# rm -rvf ./CMakeFiles -# rm -vf ./CMakeCache.txt ./Makefile ./cmake_install.cmake ./install_manifest.txt ./*~ -# cd ../ -# fi -#done rm -rvf ./CMakeFiles -rm -vf ./CMakeCache.txt ./Makefile ./cmake_install.cmake ./install_manifest.txt ./*~ ./*cxx ./moc_* ./*.o -#cd ./include -#for i in $( ls -1 ); do -# if [ "`ls -1 --file-type $i | grep -v @`" = "" ]; then -# rm -v $i -# fi -#done +rm -vf ./CMakeCache.txt ./Makefile ./cmake_install.cmake ./install_manifest.txt ./*~ ./*cxx ./moc_* ./*.o ./core +cd system_test +rm -rvf ./CMakeFiles +rm -vf ./CMakeCache.txt ./Makefile ./cmake_install.cmake ./install_manifest.txt ./*~ ./*cxx ./moc_* ./*.o ./core diff --git a/main.cpp b/main.cpp old mode 100755 new mode 100644 index c7b55c43..cca29f94 --- a/main.cpp +++ b/main.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Test program - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -63,8 +63,7 @@ void timerEvent(void * data, int delim) { cout << " tick from constuctor, delimiter = " << delim << ", data = " << data << endl; }; -bool -t2 = false; +bool t2 = false; void timerEvent2(void * data, int delim) { t2 = true; cout << " tick from delimiter " << delim << ", data = " << data << endl; @@ -86,12 +85,16 @@ 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) + }; class CA: public PIObject { public: CA(const PIString & n): PIObject(n) {;} EVENT_HANDLER(CA, void, handler_ca) {a = true; cout << " handler CA" << endl;} + EVENT(CA, event_ca) bool a; }; @@ -124,60 +127,212 @@ struct Packet { int cs; }; -bool retH(void * d, uchar * src, uchar * rec, int size) { - return (*((int*)rec)) == 1; + +#pragma pack(push,1) + +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; + } + + msgHeader header; + uchar command; // 3 + struct { + uchar fi_number: 7; // номер частотного участка, 1 - 36 + uchar bort : 1; // борт: 0 - левый, 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; }; -bool retF(void * d, uchar * data, int size) { - cout << "rec " << size << endl; - return true; -}; +#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[]) { - /*Packet p, mp; - p.from = mp.from = 1; - p.to = mp.to = 2; - PISerial ser("/dev/ttyS0"); - ser.setSpeed(PISerial::S115200); + /*tm_.start(10.); + PIConsole con(false, ke); + con.enableExitCapture(); + //ser.setParameter(PISerial::HardwareFlowControl); ser.open(); - ser.setReadIsBlocking(true); - PIPacketExtractor pe(&ser, &mp, 8, 8); - pe.setThreadedReadSlot(retF); - pe.setHeaderCheckSlot(retH); - pe.startThreadedRead(); - ser.write(&p, sizeof(p)); - p.from = 2; - ser.write(&p, sizeof(p)); - msleep(1000); - exit(0);*/ - PICodec codec; + 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;*/ - exit(0); -/* - vec my_v; vector stl_v; QVector qt_v; - double el; - PITimer tm; + /*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; + 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); + } + //cout << ba_.byteSize() << ", " << ba_.bitSize() << endl; + memcpy(data.data, ba_.data(), 122); + 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)); + 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(); - tm.reset(); - for (uint i = 0; i < 500000; ++i) - my_v.push_back(i); - el = tm.elapsed_m(); - cout << el << endl; - - tm.reset(); - for (uint i = 0; i < 500000; ++i) - stl_v.push_back(i); - el = tm.elapsed_m(); - cout << el << endl; - - tm.reset(); - for (uint i = 0; i < 500000; ++i) - qt_v.append(i); - el = tm.elapsed_m(); - cout << el << endl; - - exit(0); -*/ + return app.exec();*/ + 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; @@ -189,8 +344,10 @@ int main(int argc, char * argv[]) { cout << " to char * = \"" << string.data() << "\"" << endl; cout << " to std::string = \"" << string.stdString() << "\"" << endl; if (string.stdString().length() != 11) succ = r_string = false; +#ifdef HAS_LOCALE cout << " to std::wstring = \"" << string.stdWString() << "\"" << endl; if (string.stdWString().length() != 11) succ = r_string = false; +#endif if (succ) cout << " convertions success" << endl; else cout << " convertions fail" << endl; succ = true; @@ -199,9 +356,11 @@ int main(int argc, char * argv[]) { if (string.length() != 5) succ = r_string = false; cout << " to char * = \"" << string.data() << "\"" << endl; cout << " to std::string = \"" << string.stdString() << "\"" << endl; - if (string.stdString().length() != 10) succ = r_string = false; + if (string.stdString().length() != 11) succ = r_string = false; +#ifdef HAS_LOCALE cout << " to std::wstring = \"" << string.stdWString() << "\"" << endl; if (string.stdWString().length() != 5) succ = r_string = false; +#endif if (succ) cout << " complex convertions success" << endl; else cout << " complex convertions fail" << endl; if (r_string) cout << "== Success ==" << endl; @@ -244,6 +403,7 @@ int main(int argc, char * argv[]) { cout << " file \"" << file.path() << "\" is "; if (!file.isOpened()) cout << "not "; cout << "opened" << endl; + file.clear(); file << "test string"; cout << " write " << file.pos() << " bytes" << endl; if (file.pos() != 11) r_file = false; @@ -264,7 +424,7 @@ int main(int argc, char * argv[]) { cout << " error = \"" << evaluator.error() << '\"' << endl; cout << " \"x\" = " << evaluator.content.variable("x").value << endl; cout << " result = " << evaluator.evaluate() << endl; - r_eval = round(evaluator.lastResult()) == complexd(9., 12.); + r_eval = round(evaluator.lastResult()) == complexd(6., 9.); if (r_eval) cout << "== Success ==" << endl; else cout << "== Fail ==" << endl; diff --git a/make.sh b/make.sh old mode 100755 new mode 100644 index d218016a..64fcb2ab --- a/make.sh +++ b/make.sh @@ -1,3 +1,3 @@ -#! /bin/bash +#! /bin/sh cmake ./ make $@ diff --git a/make_install.sh b/make_install.sh index 9e65aa38..2f5f4628 100755 --- a/make_install.sh +++ b/make_install.sh @@ -1,4 +1,4 @@ -#! /bin/bash +#! /bin/sh cmake . make $@ cp -vf *.h /usr/include/ diff --git a/pibitarray.h b/pibitarray.h old mode 100755 new mode 100644 index f67bd600..807c237a --- a/pibitarray.h +++ b/pibitarray.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Bit array - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pibytearray.cpp b/pibytearray.cpp old mode 100755 new mode 100644 index 589a4b7f..127755e9 --- a/pibytearray.cpp +++ b/pibytearray.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Byte array - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -59,29 +59,29 @@ PIByteArray & PIByteArray::convertToBase64() { if (size() == 0) return *this; int sz = (size_s() / 3) * 3; for (int i = 0; i < sz; ++i) { - hs.byte0 = hs.byte1 = hs.byte2 = 0; - hs.byte0 = at(i); - hs.byte1 = at(++i); - hs.byte2 = at(++i); - t.push_back(base64Table[hs.ascii0]); - t.push_back(base64Table[hs.ascii1]); - t.push_back(base64Table[hs.ascii2]); - t.push_back(base64Table[hs.ascii3]); + hs.byte.byte0 = hs.byte.byte1 = hs.byte.byte2 = 0; + hs.byte.byte0 = at(i); + hs.byte.byte1 = at(++i); + hs.byte.byte2 = at(++i); + t.push_back(base64Table[hs.ascii.ascii0]); + t.push_back(base64Table[hs.ascii.ascii1]); + t.push_back(base64Table[hs.ascii.ascii2]); + t.push_back(base64Table[hs.ascii.ascii3]); } - hs.byte0 = hs.byte1 = hs.byte2 = 0; sz = size() % 3; + hs.byte.byte0 = hs.byte.byte1 = hs.byte.byte2 = 0; sz = size() % 3; switch (sz) { case 1: - hs.byte0 = back(); - t.push_back(base64Table[hs.ascii0]); - t.push_back(base64Table[hs.ascii1]); + hs.byte.byte0 = back(); + t.push_back(base64Table[hs.ascii.ascii0]); + t.push_back(base64Table[hs.ascii.ascii1]); t.push_back('='); t.push_back('='); break; case 2: - hs.byte0 = at(size() - 2); hs.byte1 = back(); - t.push_back(base64Table[hs.ascii0]); - t.push_back(base64Table[hs.ascii1]); - t.push_back(base64Table[hs.ascii2]); + hs.byte.byte0 = at(size() - 2); hs.byte.byte1 = back(); + t.push_back(base64Table[hs.ascii.ascii0]); + t.push_back(base64Table[hs.ascii.ascii1]); + t.push_back(base64Table[hs.ascii.ascii2]); t.push_back('='); break; default: break; @@ -97,14 +97,14 @@ PIByteArray & PIByteArray::convertFromBase64() { uint sz = size(); if (sz == 0) return *this; for (uint i = 0; i < sz; ++i) { - hs.byte0 = hs.byte1 = hs.byte2 = 0; - hs.ascii0 = base64InvTable[at(i)]; - hs.ascii1 = base64InvTable[at(++i)]; - hs.ascii2 = base64InvTable[at(++i)]; - hs.ascii3 = base64InvTable[at(++i)]; - t.push_back(hs.byte0); - t.push_back(hs.byte1); - t.push_back(hs.byte2); + hs.byte.byte0 = hs.byte.byte1 = hs.byte.byte2 = 0; + hs.ascii.ascii0 = base64InvTable[at(i)]; + hs.ascii.ascii1 = base64InvTable[at(++i)]; + hs.ascii.ascii2 = base64InvTable[at(++i)]; + hs.ascii.ascii3 = base64InvTable[at(++i)]; + t.push_back(hs.byte.byte0); + t.push_back(hs.byte.byte1); + t.push_back(hs.byte.byte2); } if (back() == '=') t.pop_back(); if (sz > 1) if (at(sz - 2) == '=') t.pop_back(); diff --git a/pibytearray.h b/pibytearray.h old mode 100755 new mode 100644 index 3f607c97..c6342006 --- a/pibytearray.h +++ b/pibytearray.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Byte array - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -110,6 +110,15 @@ public: PIByteArray & compressHuffman() {*this = huffman.compress(*this); return *this;} + PIByteArray & append(void * data, int size) {for (int i = 0; i < size; ++i) push_back(((uchar*)data)[i]); return *this;} + /*PIByteArray & operator <<(short v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;} + PIByteArray & operator <<(ushort v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;} + PIByteArray & operator <<(int v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;} + PIByteArray & operator <<(uint v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;} + PIByteArray & operator <<(llong v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;} + PIByteArray & operator <<(ullong v) {for (uint i = 0; i < sizeof(v); ++i) push_back(((uchar*)(&v))[i]); return *this;}*/ + PIByteArray & operator <<(const PIByteArray & v) {for (uint i = 0; i < v.size(); ++i) push_back(v[i]); return *this;} + uchar checksumPlain8(); uint checksumPlain32(); uchar checksumCRC8(); @@ -125,12 +134,12 @@ private: uchar ascii1: 6; uchar ascii2: 6; uchar ascii3: 6; - }; + } ascii; struct { uchar byte0; uchar byte1; uchar byte2; - }; + } byte; }; static PIHuffman huffman; @@ -139,4 +148,40 @@ 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 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;} +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;} + +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;} +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;} + #endif // PIBYTEARRAY_H diff --git a/pichar.h b/pichar.h old mode 100755 new mode 100644 index 65b5d262..552acc51 --- a/pichar.h +++ b/pichar.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Unicode char - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,11 +20,13 @@ #ifndef PICHAR_H #define PICHAR_H -#include "piincludes.h" +#include "pibytearray.h" class PIChar { friend class PIString; + friend PIByteArray & operator <<(PIByteArray & s, const PIChar & v); + friend PIByteArray & operator >>(PIByteArray & s, PIChar & v); public: PIChar(const char c) {ch = c; ch &= 0xFF;} PIChar(const short c) {ch = c; ch &= 0xFFFF;} @@ -33,17 +35,17 @@ public: PIChar(const ushort c) {ch = c; ch &= 0xFFFF;} PIChar(const uint c) {ch = c;} PIChar(const char * c) {ch = *reinterpret_cast(c);} - + //inline operator const int() {return static_cast(ch);} //inline operator const char() {return toAscii();} - + PIChar & operator =(const char v) {ch = v; return *this;} /*inline PIChar & operator =(const short v) {ch = v; return *this;} inline PIChar & operator =(const int v) {ch = v; return *this;} inline PIChar & operator =(const uchar v) {ch = v; return *this;} inline PIChar & operator =(const ushort v) {ch = v; return *this;} inline PIChar & operator =(const uint v) {ch = v; return *this;}*/ - + 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()); @@ -54,7 +56,7 @@ public: inline bool operator ==(const uchar o) const {return (PIChar(o) == *this);} inline bool operator ==(const ushort o) const {return (PIChar(o) == *this);} inline bool operator ==(const uint o) const {return (PIChar(o) == *this);}*/ - + 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);} @@ -62,12 +64,12 @@ public: inline bool operator !=(const uchar o) const {return (PIChar(o) != *this);} inline bool operator !=(const ushort o) const {return (PIChar(o) != *this);} inline bool operator !=(const uint o) const {return (PIChar(o) != *this);}*/ - + bool operator >(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) < 0;} bool operator <(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) > 0;} bool operator >=(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) <= 0;} bool operator <=(const PIChar & o) const {return strcmp(o.toCharPtr(), toCharPtr()) >= 0;} - + bool isDigit() const {return isdigit(ch) != 0;} bool isHex() const {return isxdigit(ch) != 0;} bool isGraphical() const {return isgraph(ch) != 0;} @@ -78,7 +80,7 @@ public: bool isSpace() const {return isspace(ch) != 0;} bool isAlpha() const {return isalpha(ch) != 0;} bool isAscii() const {return isascii(ch) != 0;} - + int toInt() const {return static_cast(ch);} const wchar_t * toWCharPtr() const {return &ch;} const char * toCharPtr() const {return reinterpret_cast(&ch);} @@ -92,14 +94,17 @@ public: PIChar toUpper() const {return PIChar(toupper(ch));} PIChar toLower() const {return PIChar(tolower(ch));} //#endif - + private: wchar_t ch; - + }; inline std::ostream & operator <<(std::ostream & s, const PIChar & v) {s << v.toCharPtr(); return s;} +inline PIByteArray & operator <<(PIByteArray & s, const PIChar & v) {s << uint(v.ch); return s;} +inline PIByteArray & operator >>(PIByteArray & s, PIChar & v) {uint i; s >> i; v.ch = wchar_t(i); return s;} + inline bool operator ==(const char v, const PIChar & c) {return (PIChar(v) == c);} inline bool operator >(const char v, const PIChar & c) {return (PIChar(v) > c);} inline bool operator <(const char v, const PIChar & c) {return (PIChar(v) < c);} diff --git a/picli.cpp b/picli.cpp old mode 100755 new mode 100644 index 93ba9014..81ccae40 --- a/picli.cpp +++ b/picli.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Command-Line Parser - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,7 +25,7 @@ PICLI::PICLI(int argc, char * argv[]) { _prefix_short = "-"; _prefix_full = "--"; _count_opt = 0; - _count_mand = 1; + _count_mand = 0; for (int i = 0; i < argc; ++i) _args_raw << argv[i]; } diff --git a/picli.h b/picli.h old mode 100755 new mode 100644 index 6b835e1d..8a9051e8 --- a/picli.h +++ b/picli.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Command-Line Parser - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/picodec.cpp b/picodec.cpp old mode 100755 new mode 100644 index 564dfbd5..afd0ff05 --- a/picodec.cpp +++ b/picodec.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Text codings coder, based on "iconv" - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/picodec.h b/picodec.h old mode 100755 new mode 100644 index 6793428e..21ee8fa6 --- a/picodec.h +++ b/picodec.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Text codings coder, based on "iconv" - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/piconfig.cpp b/piconfig.cpp old mode 100755 new mode 100644 index 8e6e81b9..48554566 --- a/piconfig.cpp +++ b/piconfig.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Config parser - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -396,6 +396,7 @@ void PIConfig::writeAll() { *this << other[i]; if (i < other.size_s() - 1) *this << '\n'; } + //cout << other[i] << endl; } flush(); readAll(); @@ -433,9 +434,9 @@ void PIConfig::parse() { while (!isEnd()) { other.push_back(PIString()); src = str = readLine(); - //cout << str << endl; tab = str.left(str.find(str.trimmed().left(1))); str.trim(); + //cout << endl << str << endl << endl; all = str; ind = str.find('='); if ((ind > 0) && !(str[0] == '#')) { diff --git a/piconfig.h b/piconfig.h old mode 100755 new mode 100644 index 23de194b..e0bf7abd --- a/piconfig.h +++ b/piconfig.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Config parser - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/piconsole.cpp b/piconsole.cpp old mode 100755 new mode 100644 index f5d7e19f..70d70414 --- a/piconsole.cpp +++ b/piconsole.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Console output/input - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -56,16 +56,20 @@ PIConsole::~PIConsole() { int PIConsole::addTab(const PIString & name, char bind_key) { + if (isRunning()) lock(); tabs.push_back(Tab(name, bind_key)); cur_tab = tabs.size() - 1; + if (isRunning()) unlock(); return tabs.size(); } void PIConsole::removeTab(uint index) { if (index >= tabs.size()) return; + if (isRunning()) lock(); tabs.remove(index); if (cur_tab >= tabs.size()) cur_tab = tabs.size() - 1; + if (isRunning()) unlock(); } @@ -84,9 +88,12 @@ void PIConsole::removeTab(const PIString & name) { bool PIConsole::setTab(uint index) { if (index >= tabs.size()) return false; - cur_tab = index; - if (!isRunning()) return true; + if (!isRunning()) { + cur_tab = index; + return true; + } lock(); + cur_tab = index; clearScreen(); fillLabels(); unlock(); @@ -156,6 +163,7 @@ PIString PIConsole::fstr(PIFlags f) { if (f[PIConsole::Dec]) num_format = 0; if (f[PIConsole::Hex]) num_format = 1; if (f[PIConsole::Oct]) num_format = 2; + if (f[PIConsole::Bin]) num_format = 4; if (f[PIConsole::Scientific]) num_format = 3; #ifdef WINDOWS @@ -232,15 +240,15 @@ PIString PIConsole::fstr(PIFlags f) { #endif } -#define siprint(x) switch (num_format) {case (1): return printf("0x%.4hX", x); break; case (2): return printf("%o", x); break; default: return printf("%hd", x); break;} -#define iprint(x) switch (num_format) {case (1): return printf("0x%.8X", x); break; case (2): return printf("%o", x); break; default: return printf("%d", x); break;} -#define liprint(x) switch (num_format) {case (1): return printf("0x%.16lX", x); break; case (2): return printf("%lo", x); break; default: return printf("%ld", x); break;} -#define lliprint(x) switch (num_format) {case (1): return printf("0x%.16llX", x); break; case (2): return printf("%llo", x); break; default: return printf("%lld", x); break;} -#define cuprint(x) switch (num_format) {case (1): return printf("0x%.2X", x); break; case (2): return printf("%o", x); break; default: return printf("%u", x); break;} -#define suprint(x) switch (num_format) {case (1): return printf("0x%.4hX", x); break; case (2): return printf("%o", x); break; default: return printf("%hu", x); break;} -#define uprint(x) switch (num_format) {case (1): return printf("0x%.8X", x); break; case (2): return printf("%o", x); break; default: return printf("%u", x); break;} -#define luprint(x) switch (num_format) {case (1): return printf("0x%.16lX", x); break; case (2): return printf("%lo", x); break; default: return printf("%lu", x); break;} -#define lluprint(x) switch (num_format) {case (1): return printf("0x%.16llX", x); break; case (2): return printf("%llo", x); break; default: return printf("%llu", x); break;} +#define siprint(x) switch (num_format) {case (1): return printf("0x%.4hX", x); break; case (2): return printf("%o", x); break; case (4): return printf("%s", toBin(&x, 2)); break; default: return printf("%hd", x); break;} +#define iprint(x) switch (num_format) {case (1): return printf("0x%.8X", x); break; case (2): return printf("%o", x); break; case (4): return printf("%s", toBin(&x, 4)); break; default: return printf("%d", x); break;} +#define liprint(x) switch (num_format) {case (1): return printf("0x%.16lX", x); break; case (2): return printf("%lo", x); break; case (4): return printf("%s", toBin(&x, sizeof(x))); break; default: return printf("%ld", x); break;} +#define lliprint(x) switch (num_format) {case (1): return printf("0x%.16llX", x); break; case (2): return printf("%llo", x); break; case (4): return printf("%s", toBin(&x, sizeof(x))); break; default: return printf("%lld", x); break;} +#define cuprint(x) switch (num_format) {case (1): return printf("0x%.2X", x); break; case (2): return printf("%o", x); break; case (4): return printf("%s", toBin(&x, 1)); break; default: return printf("%u", x); break;} +#define suprint(x) switch (num_format) {case (1): return printf("0x%.4hX", x); break; case (2): return printf("%o", x); break; case (4): return printf("%s", toBin(&x, 2)); break; default: return printf("%hu", x); break;} +#define uprint(x) switch (num_format) {case (1): return printf("0x%.8X", x); break; case (2): return printf("%o", x); break; case (4): return printf("%s", toBin(&x, 4)); break; default: return printf("%u", x); break;} +#define luprint(x) switch (num_format) {case (1): return printf("0x%.16lX", x); break; case (2): return printf("%lo", x); break; case (4): return printf("%s", toBin(&x, sizeof(x))); break; default: return printf("%lu", x); break;} +#define lluprint(x) switch (num_format) {case (1): return printf("0x%.16llX", x); break; case (2): return printf("%llo", x); break; case (4): return printf("%s", toBin(&x, sizeof(x))); break; default: return printf("%llu", x); break;} #define fprint(x) switch (num_format) {case (3): return printf("%e", x); break; default: return printf("%.5g", x); break;} #define dprint(x) switch (num_format) {case (3): return printf("%le", x); break; default: return printf("%.5lg", x); break;} @@ -312,20 +320,20 @@ void PIConsole::run() { case 1: clen = printValue(tv.b != 0 ? *tv.b : false, tv.format); break; case 2: clen = printValue(tv.i != 0 ? *tv.i : 0, tv.format); break; case 3: clen = printValue(tv.l != 0 ? *tv.l : 0l, tv.format); break; - case 4: clen = printValue(tv.c != 0 ? *tv.c : 0, tv.format); break; + case 4: clen = printValue(tv.c != 0 ? *tv.c : char(0), tv.format); break; case 5: clen = printValue(tv.f != 0 ? *tv.f : 0.f, tv.format); break; case 6: clen = printValue(tv.d != 0 ? *tv.d : 0., tv.format); break; - case 7: clen = printValue(tv.sh != 0 ? *tv.sh : 0, tv.format); break; + case 7: clen = printValue(tv.sh != 0 ? *tv.sh : short(0), tv.format); break; case 8: clen = printValue(tv.ui != 0 ? *tv.ui : 0u, tv.format); break; case 9: clen = printValue(tv.ul != 0 ? *tv.ul : 0ul, tv.format); break; - case 10: clen = printValue(tv.ush != 0 ? *tv.ush : 0u, tv.format); break; - case 11: clen = printValue(tv.uc != 0 ? *tv.uc : 0u, tv.format); break; + case 10: clen = printValue(tv.ush != 0 ? *tv.ush : ushort(0), tv.format); break; + case 11: clen = printValue(tv.uc != 0 ? *tv.uc : uchar(0), tv.format); break; case 12: clen = printValue(tv.ll != 0 ? *tv.ll : 0l, tv.format); break; case 13: clen = printValue(tv.ull != 0 ? *tv.ull : 0ull, tv.format); break; case 14: clen = printValue(bitsValue(tv.ptr, tv.bitFrom, tv.bitCount), tv.format); break; } if (clen + tv.offset < (uint)col_wid) { -#ifdef QNX +#if defined(QNX) || defined(FREE_BSD) string ts = PIString(col_wid - clen - tv.offset - 1, ' ').stdString(); #else string ts = PIString(col_wid - clen - tv.offset, ' ').stdString(); @@ -340,6 +348,7 @@ void PIConsole::run() { void PIConsole::fillLabels() { + if (!isRunning()) return; uint cx, cy, my = 0, mx = 0, dx; #ifdef WINDOWS GetConsoleScreenBufferInfo(hOut, &sbi); @@ -359,7 +368,7 @@ void PIConsole::fillLabels() { if (ccol.alignment != Nothing) { mx = 0; piForeachC (Variable & j, cvars) - if (j.type != 0 && j.s != 0) + if (j.s != 0) if (mx < j.name.size()) mx = j.name.size(); mx += 2; @@ -390,25 +399,27 @@ void PIConsole::fillLabels() { cy++; continue; } - switch (ccol.alignment) { - case Nothing: - cvars[j].offset = (tv.name + ": ").length(); - cvars[j].nx += cvars[j].offset; - printValue(tv.name + ": ", tv.format); - break; - case Left: - cvars[j].offset = mx; - cvars[j].nx += cvars[j].offset; - printValue(tv.name + ": ", tv.format); - break; - case Right: - cvars[j].offset = mx; - cvars[j].nx += cvars[j].offset; - dx = mx - (tv.name + ": ").length(); - moveRight(dx); - printValue(tv.name + ": ", tv.format); - moveLeft(dx); - break; + if (tv.s != 0) { + switch (ccol.alignment) { + case Nothing: + cvars[j].offset = (tv.name + ": ").length(); + cvars[j].nx += cvars[j].offset; + printValue(tv.name + ": ", tv.format); + break; + case Left: + cvars[j].offset = mx; + cvars[j].nx += cvars[j].offset; + printValue(tv.name + ": ", tv.format); + break; + case Right: + cvars[j].offset = mx; + cvars[j].nx += cvars[j].offset; + dx = mx - (tv.name + ": ").length(); + moveRight(dx); + printValue(tv.name + ": ", tv.format); + moveLeft(dx); + break; + } } newLine(); cy++; @@ -442,78 +453,98 @@ void PIConsole::status() { } -int PIConsole::bitsValue(void * src, int offset, int count) { +int PIConsole::bitsValue(const void * src, int offset, int count) { int ret = 0, stbyte = offset / 8, cbit = offset - stbyte * 8; - char cbyte = reinterpret_cast(src)[stbyte]; + char cbyte = reinterpret_cast(src)[stbyte]; for (int i = 0; i < count; i++) { ret |= ((cbyte >> cbit & 1) << i); cbit++; if (cbit == 8) { cbit = 0; stbyte++; - cbyte = reinterpret_cast(src)[stbyte]; + cbyte = reinterpret_cast(src)[stbyte]; } } return ret; } + +const char * PIConsole::toBin(const void * d, int s) { + binstr.clear(); + uchar cc, b; + for (int i = 0; i < s; ++i) { + cc = ((const uchar *)d)[i]; + b = 1; + for (int j = 0; j < 8; ++j) { + binstr << (cc & b ? "1" : "0"); + b <<= 1; + } + if (i < s - 1) binstr << " "; + } + binstr.reverse(); + return binstr.data(); +} + + #define ADD_VAR_BODY tv.name = name; tv.bitFrom = tv.bitCount = 0; tv.format = format; checkColumn(col); void PIConsole::addString(const PIString & name, int col, PIFlags format) { ADD_VAR_BODY tv.type = 0; tv.s = 0; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, PIString* ptr, int col, PIFlags format) { +void PIConsole::addVariable(const PIString & name, const PIString* ptr, int col, PIFlags format) { ADD_VAR_BODY tv.type = 0; tv.s = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, bool * ptr, int col, PIFlags format) { +void PIConsole::addVariable(const PIString & name, const bool * ptr, int col, PIFlags format) { ADD_VAR_BODY tv.type = 1; tv.b = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, int * ptr, int col, PIFlags format) { +void PIConsole::addVariable(const PIString & name, const int * ptr, int col, PIFlags format) { ADD_VAR_BODY tv.type = 2; tv.i = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, long * ptr, int col, PIFlags format) { +void PIConsole::addVariable(const PIString & name, const long * ptr, int col, PIFlags format) { ADD_VAR_BODY tv.type = 3; tv.l = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, char * ptr, int col, PIFlags format) { +void PIConsole::addVariable(const PIString & name, const char * ptr, int col, PIFlags format) { ADD_VAR_BODY tv.type = 4; tv.c = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, float * ptr, int col, PIFlags format) { +void PIConsole::addVariable(const PIString & name, const float * ptr, int col, PIFlags format) { ADD_VAR_BODY tv.type = 5; tv.f = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, double * ptr, int col, PIFlags format) { +void PIConsole::addVariable(const PIString & name, const double * ptr, int col, PIFlags format) { ADD_VAR_BODY tv.type = 6; tv.d = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, short * ptr, int col, PIFlags format) { +void PIConsole::addVariable(const PIString & name, const short * ptr, int col, PIFlags format) { ADD_VAR_BODY tv.type = 7; tv.sh = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, uint * ptr, int col, PIFlags format) { +void PIConsole::addVariable(const PIString & name, const uint * ptr, int col, PIFlags format) { ADD_VAR_BODY tv.type = 8; tv.ui = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, ulong * ptr, int col, PIFlags format) { +void PIConsole::addVariable(const PIString & name, const ulong * ptr, int col, PIFlags format) { ADD_VAR_BODY tv.type = 9; tv.ul = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, ushort * ptr, int col, PIFlags format) { +void PIConsole::addVariable(const PIString & name, const ushort * ptr, int col, PIFlags format) { ADD_VAR_BODY tv.type = 10; tv.ush = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, uchar * ptr, int col, PIFlags format) { +void PIConsole::addVariable(const PIString & name, const uchar * ptr, int col, PIFlags format) { ADD_VAR_BODY tv.type = 11; tv.uc = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, llong * ptr, int col, PIFlags format) { +void PIConsole::addVariable(const PIString & name, const llong * ptr, int col, PIFlags format) { ADD_VAR_BODY tv.type = 12; tv.ll = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, ullong * ptr, int col, PIFlags format) { +void PIConsole::addVariable(const PIString & name, const ullong * ptr, int col, PIFlags format) { ADD_VAR_BODY tv.type = 13; tv.ull = ptr; column(col).push_back(tv);} -void PIConsole::addVariable(const PIString & name, PIProtocol * ptr, int col, PIFlags format) { +void PIConsole::addVariable(const PIString & name, const PIProtocol * ptr, int col, PIFlags format) { addString("protocol " + name, col, format | PIConsole::Bold); - addVariable("Rec :" + ptr->receiverDeviceName() + " ", ptr->receiverDeviceState_ptr(), col, format); - addVariable("Send:" + ptr->senderDeviceName() + " ", ptr->senderDeviceState_ptr(), col, format); + addVariable("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("Immediate Frequency, Hz", ptr->immediateFrequency_ptr(), col, format); addVariable("Integral Frequency, Hz", ptr->integralFrequency_ptr(), col, format); - addVariable("Disconnect Timeout, s", ptr->disconnectTimeout_ptr(), col, format); + addVariable("Receive speed", ptr->receiveSpeed_ptr(), col, format); + addVariable("Send speed", ptr->sendSpeed_ptr(), col, format); addVariable("Receiver history size", ptr->receiverHistorySize_ptr(), col, format); addVariable("Sender history size", ptr->senderHistorySize_ptr(), col, format); + addVariable("Disconnect Timeout, s", ptr->disconnectTimeout_ptr(), col, format); addVariable("Quality", ptr->quality_ptr(), col, format); } -void PIConsole::addVariable(const PIString & name, PISystemMonitor * ptr, int col, PIFlags 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); - addVariable("threads ", &(ptr->statistic().threads), col, format); + addVariable("state", &(ptr->statistic().state), col, format); + addVariable("threads", &(ptr->statistic().threads), col, format); addVariable("priority", &(ptr->statistic().priority), col, format); addVariable("memory physical", &(ptr->statistic().physical_memsize_readable), col, format); - addVariable("memory shared ", &(ptr->statistic().share_memsize_readable), col, format); + addVariable("memory shared", &(ptr->statistic().share_memsize_readable), col, format); addVariable("cpu load", &(ptr->statistic().cpu_load_system), col, format); } -void PIConsole::addBitVariable(const PIString & name, void * ptr, int fromBit, int bitCount, int col, PIFlags format) { +void PIConsole::addBitVariable(const PIString & name, const void * ptr, int fromBit, int bitCount, int col, PIFlags format) { tv.name = name; tv.bitFrom = fromBit; tv.bitCount = bitCount; tv.type = 14; tv.ptr = ptr; tv.format = format; checkColumn(col); column(col).push_back(tv);} void PIConsole::addEmptyLine(int col, uint count) { @@ -562,7 +593,7 @@ PIString PIConsole::getString(const PIString & name) { inline void PIConsole::printLine(const PIString & value, int dx, PIFlags format) { int i = width - value.length() - dx; -#ifdef QNX +#if defined(QNX) || defined(FREE_BSD) --i; #endif PIString ts = fstr(format); diff --git a/piconsole.h b/piconsole.h old mode 100755 new mode 100644 index 2afd4bbf..0b76408d --- a/piconsole.h +++ b/piconsole.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Console output/input - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,6 +28,10 @@ # include #endif +/// handlers: +/// void clearVariables(bool clearScreen = true) +/// void start(bool wait = false) +/// void stop(bool clear = false) class PIConsole: public PIThread { public: @@ -60,27 +64,28 @@ public: Dec = 0x1000000, Hex = 0x2000000, Oct = 0x4000000, - Scientific = 0x8000000}; + Bin = 0x8000000, + Scientific = 0x10000000}; enum Alignment {Nothing, Left, Right}; void addString(const PIString & name, int column = 1, PIFlags format = PIConsole::Normal); - void addVariable(const PIString & name, PIString * ptr, int column = 1, PIFlags format = PIConsole::Normal); - void addVariable(const PIString & name, char * ptr, int column = 1, PIFlags format = PIConsole::Normal); - void addVariable(const PIString & name, bool * ptr, int column = 1, PIFlags format = PIConsole::Normal); - void addVariable(const PIString & name, short * ptr, int column = 1, PIFlags format = PIConsole::Normal); - void addVariable(const PIString & name, int * ptr, int column = 1, PIFlags format = PIConsole::Normal); - void addVariable(const PIString & name, long * ptr, int column = 1, PIFlags format = PIConsole::Normal); - void addVariable(const PIString & name, llong * ptr, int column = 1, PIFlags format = PIConsole::Normal); - void addVariable(const PIString & name, uchar * ptr, int column = 1, PIFlags format = PIConsole::Normal); - void addVariable(const PIString & name, ushort * ptr, int column = 1, PIFlags format = PIConsole::Normal); - void addVariable(const PIString & name, uint * ptr, int column = 1, PIFlags format = PIConsole::Normal); - void addVariable(const PIString & name, ulong * ptr, int column = 1, PIFlags format = PIConsole::Normal); - void addVariable(const PIString & name, ullong * ptr, int column = 1, PIFlags format = PIConsole::Normal); - void addVariable(const PIString & name, float * ptr, int column = 1, PIFlags format = PIConsole::Normal); - void addVariable(const PIString & name, double * ptr, int column = 1, PIFlags format = PIConsole::Normal); - void addVariable(const PIString & name, PIProtocol * ptr, int column = 1, PIFlags format = PIConsole::Normal); - void addVariable(const PIString & name, PISystemMonitor * ptr, int column = 1, PIFlags format = PIConsole::Normal); - void addBitVariable(const PIString & name, void * ptr, int fromBit, int bitCount, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, const PIString * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, const char * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, const bool * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, const short * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, const int * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, const long * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, const llong * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, const uchar * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, const ushort * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, const uint * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, const ulong * ptr, int column = 1, PIFlags format = PIConsole::Normal); + void addVariable(const PIString & name, const ullong * ptr, int column = 1, PIFlags format = PIConsole::Normal); + 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 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); PIString getString(int x, int y); @@ -162,7 +167,8 @@ private: #endif void status(); void checkColumn(uint col) {while (columns().size() < col) columns().push_back(Column(def_align));} - int bitsValue(void * src, int offset, int count); + int bitsValue(const void * src, int offset, int count); + const char * toBin(const void * d, int s); inline void printLine(const PIString & str, int dx = 0, PIFlags format = PIConsole::Normal); inline int printValue(const PIString & str, PIFlags format = PIConsole::Normal); inline int printValue(const char * str, PIFlags format = PIConsole::Normal); @@ -191,21 +197,21 @@ private: int bitFrom; int bitCount; union { - PIString * s; - bool * b; - short * sh; - int * i; - long * l; - llong * ll; - float * f; - double * d; - char * c; - uchar * uc; - ushort * ush; - uint * ui; - ulong * ul; - ullong * ull; - void * ptr; + const PIString * s; + const bool * b; + const short * sh; + const int * i; + const long * l; + const llong * ll; + const float * f; + const double * d; + const char * c; + const uchar * uc; + const ushort * ush; + const uint * ui; + const ulong * ul; + const ullong * ull; + const void * ptr; }; void operator =(const Variable & src) {name = src.name; format = src.format; type = src.type; offset = src.offset; bitFrom = src.bitFrom; bitCount = src.bitCount; ptr = src.ptr; nx = src.nx; ny = src.ny;} @@ -261,6 +267,7 @@ private: struct termios sterm, vterm; #endif PIVector tabs; + PIString binstr; Variable tv; PIKbdListener * listener; Alignment def_align; diff --git a/picontainers.h b/picontainers.h old mode 100755 new mode 100644 index 635a3540..46a0957f --- a/picontainers.h +++ b/picontainers.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Generic containers, based on STL - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -157,7 +157,7 @@ public: 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) {return (flags & e) == e;} + bool operator [](Enum e) const {return (flags & e) == e;} operator int() const {return flags;} private: int flags; @@ -394,12 +394,15 @@ public: _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 & 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;} + _CVector & insert(uint pos, const _CVector & t) {_stlc::insert(_stlc::begin() + pos, t.begin(), t.end()); return *this;} _CVector & operator <<(const Type & t) {_stlc::push_back(t); return *this;} _CVector & operator <<(const _CVector & t) {for (typename _stlc::const_iterator i = t.begin(); i != t.end(); i++) _stlc::push_back(*i); return *this;} bool operator ==(const _CVector & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return false; return true;} @@ -518,16 +521,19 @@ template inline bool operator <(const PIPair & value0, const PIPair & value1) {return value0.first < value1.first;} -template -class PIMap: public PISet > { - typedef PIMap _CMap; - typedef PISet > _CSet; +template +class PIMap: public map { + typedef PIMap _CMap; + typedef map _stlc; + typedef std::pair _stlpair; public: PIMap() {;} - PIMap(const Type & value, const Key & key) {insert(value, key);} - _CMap & insert(const Type & value, const Key & key) {_CSet::insert(PIPair(key, value)); return *this;} - Type value(Key key) const {for (typename _CMap::iterator i = _CMap::begin(); i != _CMap::end(); i++) if ((*i).first == key) return (*i).second; return Type();} - Type operator[](Key key) const {return value(key);} + 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;} + 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_];} }; #endif // PICONTAINERS_H diff --git a/picrc.h b/picrc.h new file mode 100644 index 00000000..d855792f --- /dev/null +++ b/picrc.h @@ -0,0 +1,216 @@ +/* + PIP - Platform Independent Primitives + Abstract input/output device + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PICRC_H +#define PICRC_H + +#include "pistring.h" + +template +class uint_cl { +public: + uint_cl() {for (int i = 0; i < L / 8; ++i) data_[i] = 0;} + uint_cl(const uint_cl & v) {for (int i = 0; i < L / 8; ++i) data_[i] = v.data_[i];} + uint_cl(uchar v) {for (int i = 0; i < L / 8; ++i) data_[i] = (i == 0 ? v : 0);} + uint_cl(char v) {for (int i = 0; i < L / 8; ++i) data_[i] = (i == 0 ? v : 0);} + uint_cl(ushort v) {int l = piMin(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;} + uint_cl(short v) {int l = piMin(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;} + uint_cl(uint v) {int l = piMin(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;} + uint_cl(int v) {int l = piMin(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;} + uint_cl(ulong v) {int l = piMin(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;} + uint_cl(long v) {int l = piMin(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;} + uint_cl(ullong v) {int l = piMin(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;} + uint_cl(llong v) {int l = piMin(L / 8, sizeof(v)); memcpy(data_, &v, l); for (int i = l; i < L / 8; ++i) data_[i] = 0;} + + operator bool() {for (int i = 0; i < L / 8; ++i) if (data_[i] > 0) return true; return false;} + operator char() {return (char)data_[0];} + operator short() {short t(0); int l = piMin(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;} + operator int() {int t(0); int l = piMin(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;} + operator long() {long t(0); int l = piMin(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;} + operator llong() {llong t(0); int l = piMin(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;} + operator uchar() {return data_[0];} + operator ushort() {ushort t(0); int l = piMin(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;} + operator uint() {uint t(0); int l = piMin(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;} + operator ulong() {ulong t(0); int l = piMin(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;} + operator ullong() {ullong t(0); int l = piMin(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;} + + uint_cl operator +(const uint_cl & v) { + uint_cl t; + uint cv; + bool ov = false; + for (int i = 0; i < L / 8; ++i) { + cv = v.data_[i] + data_[i]; + if (ov) ++cv; + ov = cv > 255; + t.data_[i] = ov ? cv - 256 : cv; + } + return t; + } + + uint_cl operator &(const uint_cl & v) const {uint_cl t; for (int i = 0; i < L / 8; ++i) t.data_[i] = v.data_[i] & data_[i]; return t;} + uint_cl operator &(const uchar & v) const {return *this & uint_cl(v);} + uint_cl operator &(const ushort & v) const {return *this & uint_cl(v);} + uint_cl operator &(const uint & v) const {return *this & uint_cl(v);} + uint_cl operator &(const ulong & v) const {return *this & uint_cl(v);} + uint_cl operator &(const ullong & v) const {return *this & uint_cl(v);} + uint_cl operator &(const char & v) const {return *this & uint_cl(v);} + uint_cl operator &(const short & v) const {return *this & uint_cl(v);} + uint_cl operator &(const int & v) const {return *this & uint_cl(v);} + uint_cl operator &(const long & v) const {return *this & uint_cl(v);} + uint_cl operator &(const llong & v) const {return *this & uint_cl(v);} + + uint_cl operator |(const uint_cl & v) const {uint_cl t; for (int i = 0; i < L / 8; ++i) t.data_[i] = v.data_[i] | data_[i]; return t;} + uint_cl operator |(const uchar & v) const {return *this | uint_cl(v);} + uint_cl operator |(const ushort & v) const {return *this | uint_cl(v);} + uint_cl operator |(const uint & v) const {return *this | uint_cl(v);} + uint_cl operator |(const ulong & v) const {return *this | uint_cl(v);} + uint_cl operator |(const ullong & v) const {return *this | uint_cl(v);} + uint_cl operator |(const char & v) const {return *this | uint_cl(v);} + uint_cl operator |(const short & v) const {return *this | uint_cl(v);} + uint_cl operator |(const int & v) const {return *this | uint_cl(v);} + uint_cl operator |(const long & v) const {return *this | uint_cl(v);} + uint_cl operator |(const llong & v) const {return *this | uint_cl(v);} + + uint_cl operator ^(const uint_cl & v) const {uint_cl t; for (int i = 0; i < L / 8; ++i) t.data_[i] = v.data_[i] ^ data_[i]; return t;} + uint_cl operator ^(const uchar & v) const {return *this ^ uint_cl(v);} + uint_cl operator ^(const ushort & v) const {return *this ^ uint_cl(v);} + uint_cl operator ^(const uint & v) const {return *this ^ uint_cl(v);} + uint_cl operator ^(const ulong & v) const {return *this ^ uint_cl(v);} + uint_cl operator ^(const ullong & v) const {return *this ^ uint_cl(v);} + uint_cl operator ^(const char & v) const {return *this ^ uint_cl(v);} + uint_cl operator ^(const short & v) const {return *this ^ uint_cl(v);} + uint_cl operator ^(const int & v) const {return *this ^ uint_cl(v);} + uint_cl operator ^(const long & v) const {return *this ^ uint_cl(v);} + uint_cl operator ^(const llong & v) const {return *this ^ uint_cl(v);} + + bool operator <(const uint_cl & v) const {for (int i = 0; i < L / 8; ++i) {if (v.data_[i] > data_[i]) return true; if (v.data_[i] < data_[i]) return false;} return false;} + bool operator <=(const uint_cl & v) const {for (int i = 0; i < L / 8; ++i) {if (v.data_[i] > data_[i]) return true; if (v.data_[i] < data_[i]) return false;} return true;} + bool operator >(const uint_cl & v) const {for (int i = 0; i < L / 8; ++i) {if (v.data_[i] < data_[i]) return true; if (v.data_[i] > data_[i]) return false;} return false;} + bool operator >=(const uint_cl & v) const {for (int i = 0; i < L / 8; ++i) {if (v.data_[i] < data_[i]) return true; if (v.data_[i] > data_[i]) return false;} return true;} + bool operator ==(const uint_cl & v) const {for (int i = 0; i < L / 8; ++i) if (v.data_[i] != data_[i]) return false; return true;} + bool operator !=(const uint_cl & v) const {for (int i = 0; i < L / 8; ++i) if (v.data_[i] != data_[i]) return true; return false;} + + uint_cl operator >>(const int & c) const { + uint_cl t; + int l = L - c; + bool bit; + if (l <= 0) return t; + for (int i = 0; i < l; ++i) { + bit = 1 & (data_[(i + c) / 8] >> ((i + c) % 8)); + if (bit) t.data_[i / 8] |= (1 << (i % 8)); + else t.data_[i / 8] &= ~(1 << (i % 8)); + } + return t; + } + uint_cl operator >>(const uint & c) const {return (*this << (int)c);} + uint_cl operator <<(const int & c) const { + uint_cl t; + int l = L - c; + bool bit; + if (l <= 0) return t; + for (int i = c; i < L; ++i) { + bit = 1 & (data_[(i - c) / 8] >> ((i - c) % 8)); + if (bit) t.data_[i / 8] |= (1 << (i % 8)); + else t.data_[i / 8] &= ~(1 << (i % 8)); + } + return t; + } + uint_cl operator <<(const uint & c) const {return (*this >> (int)c);} + + uint_cl & inverse() const {for (int i = 0; i < L / 8; ++i) data_[i] = ~data_[i]; return *this;} + uint_cl inversed() const {uint_cl t(*this); for (int i = 0; i < L / 8; ++i) t.data_[i] = ~t.data_[i]; return t;} + uint_cl reversed() const { + uint_cl t; + bool bit; + for (int i = 0; i < L; ++i) { + bit = 1 & (data_[(L - i - 1) / 8] >> ((L - i - 1) % 8)); + if (bit) t.data_[i / 8] |= (1 << (i % 8)); + else t.data_[i / 8] &= ~(1 << (i % 8)); + } + return t; + } + + const uchar * data() const {return data_;} + uchar * data() {return data_;} + uint length() const {return L / 8;} + +private: + uchar data_[L / 8]; + +}; + +template +inline std::ostream & operator <<(std::ostream & s, const uint_cl & v) {std::ios::fmtflags f = s.flags(); s << std::hex; for (uint i = 0; i < v.length(); ++i) {s << int(v.data()[i]); if (v.data()[i] < 0x10) s << '0'; s << ' ';} s.flags(f); return s;} + + +template +class 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();} + + void setInitial(const uint_cl & v) {init_ = v;} + void setOutXor(const uint_cl & v) {out_ = v;} + void setReversePolynome(bool yes) {reverse_poly = yes; initTable();} + + void initTable() { + uint_cl tmp, pol = reverse_poly ? poly_.reversed() : poly_; + //cout << std::hex << "poly " << (uint)uint_cl(poly_) << " -> " << (uint)uint_cl(pol) << endl; + for (int i = 0; i < 256; ++i) { + tmp = uchar(i); + for (int j = 0; j < 8; ++j) + tmp = ((tmp & 1) ? ((tmp >> 1) ^ pol) : (tmp >> 1)); + table[i] = tmp; + } + + } + + uint_cl calculate(const void * data, int size) { + uint_cl crc = init_; + uchar * data_ = (uchar * )data; + //cout << "process " << size << endl; + uchar nTemp; + for (int i = 0; i < size; ++i) { + nTemp = data_[i] ^ uchar(crc); + crc = crc >> 8; + crc = crc ^ table[nTemp]; + } + return crc ^ out_; + + } + uint_cl calculate(const PIByteArray & d) {return calculate(d.data(), d.size());} + uint_cl calculate(const char * str) {string s(str); return calculate((void * )s.data(), s.size());} + +private: + uint_cl table[256]; + uint_cl poly_, init_, out_; + bool reverse_poly; + +}; + +typedef PICRC<32> CRC_32; +typedef PICRC<24> CRC_24; +typedef PICRC<16> CRC_16; +typedef PICRC<8> CRC_8; + +inline CRC_32 standardCRC_32() {return CRC_32(0x04C11DB7, true, 0xFFFFFFFF, 0xFFFFFFFF);} +inline CRC_16 standardCRC_16() {return CRC_16(0x8005, true, 0x0, 0x0);} +inline CRC_8 standardCRC_8() {return CRC_8(0xD5, true, 0x0, 0x0);} + +#endif // CRC_H diff --git a/pidir.cpp b/pidir.cpp old mode 100755 new mode 100644 index bfde7fcb..36e83093 --- a/pidir.cpp +++ b/pidir.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Directory - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -78,17 +78,11 @@ PIDir & PIDir::cleanPath() { open(); return *this; } + path_.replaceAll(PIString(separator) + PIString(separator), PIString(separator)); bool isAbs = isAbsolute(); - for (uint i = p.size() - 1; i > 0; --i) { - if (p[i] == separator && p[i - 1] == separator) { - p.cutLeft(i); - isAbs = true; - break; - } - } PIStringList l = PIString(p).split(separator); - l.removeStrings("."); - l.removeStrings(""); + l.removeAll("."); + l.removeAll(""); bool found = true; while (found) { found = false; @@ -118,20 +112,19 @@ PIDir & PIDir::cleanPath() { PIDir & PIDir::cd(const PIString & path) { if (path_.size() == 0) return *this; - if (path_[path_.size() - 1] == separator) path_ << path; - else path_ << separator << path; + if (path_[path_.size() - 1] != separator) path_ << separator; + path_ << path; return cleanPath(); } bool PIDir::mkDir(bool withParents) { PIDir d = cleanedPath(); - string p = d.path_; PIString tp; int ret; bool isAbs = isAbsolute(); if (withParents) { - PIStringList l = PIString(p).split(separator); + PIStringList l = d.path_.split(separator); for (int i = l.size_s() - 1; i >= 0; --i) { if (i > 1) tp = PIStringList(l).remove(i, l.size_s() - i).join(separator); else { @@ -143,19 +136,18 @@ bool PIDir::mkDir(bool withParents) { for (int j = i + 1; j <= l.size_s(); ++j) { tp = PIStringList(l).remove(j, l.size_s() - j).join(separator); //cout << tp << endl; - p = tp.stdString(); - ret = mkdir(p.c_str(), 16877); + ret = mkdir(tp.data(), 16877); if (ret == 0) continue; - printf("[PIDir] mkDir(\"%s\") error: %s\n", p.c_str(), strerror(errno)); + printf("[PIDir] mkDir(\"%s\") error: %s\n", d.path_.data(), strerror(errno)); return false; } break; }; } } else { - ret = mkdir(p.c_str(), 16877); + ret = mkdir(d.path_.data(), 16877); if (ret == 0) return true; - printf("[PIDir] mkDir(\"%s\") error: %s\n", p.c_str(), strerror(errno)); + printf("[PIDir] mkDir(\"%s\") error: %s\n", d.path_.data(), strerror(errno)); } return false; } diff --git a/pidir.h b/pidir.h old mode 100755 new mode 100644 index c6fd7d97..81f1c13c --- a/pidir.h +++ b/pidir.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Directory - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,6 +21,7 @@ #define PIDIR_H #include "pifile.h" +#include "pistring.h" #ifndef WINDOWS #include #include @@ -43,23 +44,23 @@ public: bool isDir() const {return (mode & S_IFDIR);} bool isFile() const {return (mode & S_IFREG);} - bool isSymLink() const {return (mode & S_IFLNK);} - bool isBlkDevice() const {return (mode & S_IFBLK);} - bool isChrDevice() const {return (mode & S_IFCHR);} + bool isSymbolicLink() const {return (mode & S_IFLNK);} + bool isBlockDevice() const {return (mode & S_IFBLK);} + bool isCharacterDevice() const {return (mode & S_IFCHR);} bool isSocket() const {return (mode & S_IFSOCK);} }; - inline const bool isExists() {return (dir_ != 0);} - inline const bool isAbsolute() {if (path_.size() == 0) return false; return (path_[0] == separator);} - inline PIString path() {return PIString(path_);} - PIDir & cleanPath(); - inline PIDir cleanedPath() {PIDir d(path_); d.cleanPath(); return d;} + const bool isExists() {return (dir_ != 0);} + const bool isAbsolute() {if (path_.size() == 0) return false; return (path_[0] == separator);} + PIString path() {return PIString(path_);} + PIDir & cleanPath(); + PIDir cleanedPath() {PIDir d(path_); d.cleanPath(); return d;} PIString absolutePath(); bool mkDir(bool withParents = true); PIVector entries(); - PIDir & cd(const PIString & path); - inline PIDir & up() {return cd("..");} + PIDir & cd(const PIString & path); + PIDir & up() {return cd("..");} bool operator ==(const PIDir & d) const; diff --git a/piethernet.cpp b/piethernet.cpp old mode 100755 new mode 100644 index 1fd93494..bab1fc1e --- a/piethernet.cpp +++ b/piethernet.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Ethernet, UDP - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,16 +27,13 @@ PIEthernet::PIEthernet(void * data, ReadRetFunc slot): PIIODevice("", ReadWrite) ret_data_ = data; ip_ = ip_s = ""; port_ = port_s = 0; - sock = -1; + sock = sock_s = -1; ret_func_ = slot; connected_ = false; + params = PIEthernet::ReuseAddress; server_thread_.setData(this); setThreadedReadBufferSize(65536); -#ifdef WINDOWS - WSADATA wsaData; - WSAStartup(MAKEWORD(2, 2), &wsaData); -#endif - init(); + if (type_ != UDP) init(); } @@ -47,16 +44,13 @@ PIEthernet::PIEthernet(PIEthernet::Type type, void * data, ReadRetFunc slot): PI ret_data_ = data; ip_ = ip_s = ""; port_ = port_s = 0; - sock = -1; + sock = sock_s = -1; ret_func_ = slot; connected_ = false; + params = PIEthernet::ReuseAddress; server_thread_.setData(this); setThreadedReadBufferSize(65536); -#ifdef WINDOWS - WSADATA wsaData; - WSAStartup(MAKEWORD(2, 2), &wsaData); -#endif - init(); + if (type_ != UDP) init(); } @@ -66,13 +60,11 @@ PIEthernet::PIEthernet(int sock_, PIString ip_port): PIIODevice("", ReadWrite) { type_ = TCP_Client; parseAddress(ip_port, &ip_s, &port_s); sock = sock_; + sock_s = -1; server_thread_.setData(this); + params = PIEthernet::ReuseAddress; init_ = opened_ = connected_ = true; setThreadedReadBufferSize(65536); -#ifdef WINDOWS - WSADATA wsaData; - WSAStartup(MAKEWORD(2, 2), &wsaData); -#endif } @@ -80,9 +72,6 @@ PIEthernet::~PIEthernet() { piMonitor.ethernets--; if (server_thread_.isRunning()) server_thread_.terminate(); closeSocket(sock); -#ifdef WINDOWS - WSACleanup(); -#endif //if (buffer_ != 0) delete buffer_; //buffer_ = 0; } @@ -91,15 +80,29 @@ PIEthernet::~PIEthernet() { bool PIEthernet::init() { //cout << "init " << type_ << endl; closeSocket(sock); - int st = 0, so = 1; + int st = 0; +#ifdef WINDOWS + int flags = WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF; +#else + int so = 1; +#endif if (type_ == UDP) st = SOCK_DGRAM; - if (type_ == TCP_Client || type_ == TCP_Server) st = SOCK_STREAM; - sock = socket(PF_INET, st, 0); + else st = SOCK_STREAM; +#ifdef WINDOWS + if (params[ReuseAddress]) flags |= WSA_FLAG_OVERLAPPED; + sock = WSASocket(AF_INET, st, type_ == UDP ? IPPROTO_UDP : IPPROTO_TCP, NULL, 0, flags); +#else + sock = socket(AF_INET, st, type_ == UDP ? IPPROTO_UDP : IPPROTO_TCP); +#endif if (sock == -1) { - piCout << "[PIEthernet] Cant`t create socket, " << errorString() << endl; + piCout << "[PIEthernet] Cant`t create socket, " << EthErrorString() << endl; return false; } - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &so, sizeof(so)); +#ifndef WINDOWS + if (params[PIEthernet::ReuseAddress]) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &so, sizeof(so)); + if (params[PIEthernet::Broadcast]) setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &so, sizeof(so)); +#endif + //cout << "inited " << sock << ": bc = " << params << endl; //fcntl(sock, F_SETFL, 0/*O_NONBLOCK*/); return true; } @@ -114,15 +117,24 @@ void PIEthernet::parseAddress(const PIString & ipp, PIString * ip, int * port) { bool PIEthernet::openDevice() { if (connected_) return true; if (sock == -1) init(); - if (sock == -1) return false; - //cout << " bind to " << path_ << " ..." <= 0) received(read_to, rs); + return rs; //return ::read(sock, read_to, max_size); default: break; //return ::read(sock, (char * )read_to, max_size); @@ -201,12 +315,34 @@ int PIEthernet::write(const void * data, int max_size) { return -1; } //piCout << "[PIEthernet] sending to " << ip_s << ":" << port_s << " " << max_size << " bytes" << endl; + int ret = 0; switch (type_) { + case TCP_SingleTCP: + memset(&addr_, 0, sizeof(addr_)); + addr_.sin_port = htons(port_s); + addr_.sin_addr.s_addr = inet_addr(ip_s.data()); + addr_.sin_family = AF_INET; +#ifdef QNX + addr_.sin_len = sizeof(addr_); +#endif + if (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) != 0) { + piCout << "[PIEthernet] Cant`t connect to " << ip_s << ":" << port_s << ", " << EthErrorString() << endl; + return -1; + } + ret = ::write(sock, data, max_size); + closeSocket(sock); + init(); + return ret; case UDP: saddr_.sin_port = htons(port_s); - saddr_.sin_addr.s_addr = inet_addr(ip_s.data()); - saddr_.sin_family = PF_INET; + if (params[PIEthernet::Broadcast]) saddr_.sin_addr.s_addr = INADDR_BROADCAST; + else saddr_.sin_addr.s_addr = inet_addr(ip_s.data()); + saddr_.sin_family = AF_INET; +#ifdef WINDOWS + return sendto(sock, (const char * )data, max_size, 0, (sockaddr * )&saddr_, sizeof(saddr_)); +#else return sendto(sock, data, max_size, 0, (sockaddr * )&saddr_, sizeof(saddr_)); +#endif case TCP_Client: return ::write(sock, data, max_size); default: break; @@ -219,18 +355,139 @@ void PIEthernet::server_func(void * eth) { PIEthernet * ce = (PIEthernet * )eth; sockaddr_in client_addr; socklen_t slen = sizeof(client_addr); - int s; - s = accept(ce->sock, (sockaddr * )&client_addr, &slen); + int s = accept(ce->sock, (sockaddr * )&client_addr, &slen); if (s == -1) { - piCout << "[PIEthernet] Cant`t accept new connection, " << errorString() << endl; + piCout << "[PIEthernet] Cant`t accept new connection, " << EthErrorString() << endl; return; } PIString ip(inet_ntoa(client_addr.sin_addr)); ip += ":" + PIString::fromNumber(htons(client_addr.sin_port)); ce->clients_ << new PIEthernet(s, ip); - cout << "connected " << ip << endl; + //cout << "connected " << ip << endl; //char d[256]; //cout << " recv " << recv(s, d, 256, 0) << endl; //cout << recv(ce->clients_.back()->sock, d, 256, 0) << endl; } + + +PIStringList PIEthernet::interfaces() { +#ifdef WINDOWS + piCout << "[PIEthernet] Not implemented on Windows, use \"PIEthernet::allAddresses\" instead" << endl; + return PIStringList(); +#else +# ifdef QNX + PIStringList il, sl; + /*struct if_nameindex * ni = if_nameindex(); + for (int i = 0; ; ++i) { + if (ni[i].if_name == 0 || ni[i].if_index == 0) break; + sl << PIString(ni[i].if_name); + } + if_freenameindex(ni);*/ + PIProcess proc; + proc.setGrabOutput(true); + proc.exec(ifconfigPath.c_str(), "-l"); + if (!proc.waitForFinish(1000)) return sl; + PIString out(proc.readOutput()); + il = out.split(" "); + il.removeAll(""); + piForeachC (PIString & i, il) { + proc.exec(ifconfigPath.c_str(), i); + if (!proc.waitForFinish(1000)) return il; + sl << i.trimmed(); + out = proc.readOutput(); + int al = out.length(); + al = (al - out.replaceAll("alias", "").length()) / 5; + for (int j = 0; j < al; ++j) + sl << i.trimmed() + ":" + PIString::fromNumber(j); + } + //cout << out; + //cout << sl << endl; + return sl; +# else + PIStringList sl; + /*struct if_nameindex * ni = if_nameindex(); + for (int i = 0; ; ++i) { + if (ni[i].if_name == 0 || ni[i].if_index == 0) break; + sl << PIString(ni[i].if_name); + } + if_freenameindex(ni);*/ + PIProcess proc; + proc.setGrabOutput(true); + proc.exec(ifconfigPath.c_str(), "-s"); + if (!proc.waitForFinish(1000)) return sl; + PIString out(proc.readOutput()); + //cout << out << endl; + out.cutLeft(out.find('\n') + 1); + while (!out.isEmpty()) { + sl << out.left(out.find(' ')); + out.cutLeft(out.find('\n') + 1); + } + //cout << sl << endl; + return sl; +# endif +#endif +} + + +PIString PIEthernet::interfaceAddress(const PIString & interface_) { +#ifdef WINDOWS + piCout << "[PIEthernet] Not implemented on Windows, use \"PIEthernet::allAddresses\" instead" << endl; + return PIString(); +#else + struct ifreq ifr; + memset(&ifr, 0, sizeof(ifr)); + strcpy(ifr.ifr_name, interface_.data()); + int s = socket(AF_INET, SOCK_DGRAM, 0); + ioctl(s, SIOCGIFADDR, &ifr); + ::close(s); + struct sockaddr_in * sa = (struct sockaddr_in * )&ifr.ifr_addr; + return PIString(inet_ntoa(sa->sin_addr)); +#endif + +} + + +PIStringList PIEthernet::allAddresses() { +#ifdef WINDOWS + PIStringList al; + PIString ca; + PIP_ADAPTER_INFO pAdapterInfo, pAdapter = 0; + int ret = 0; + ulong ulOutBufLen = sizeof(IP_ADAPTER_INFO); + pAdapterInfo = (IP_ADAPTER_INFO * ) HeapAlloc(GetProcessHeap(), 0, (sizeof (IP_ADAPTER_INFO))); + if (pAdapterInfo == 0) { + piCout << "[PIEthernet] Error allocating memory needed to call GetAdaptersinfo" << endl; + 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; + return PIStringList(); + } + } + if ((ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) { + pAdapter = pAdapterInfo; + while (pAdapter) { + /*if (pAdapter->Type != MIB_IF_TYPE_ETHERNET && pAdapter->Type != MIB_IF_TYPE_LOOPBACK) { + pAdapter = pAdapter->Next; + continue; + }*/ + ca = PIString(pAdapter->IpAddressList.IpAddress.String); + if (ca != "0.0.0.0") al << ca; + pAdapter = pAdapter->Next; + } + } else + piCout << "[PIEthernet] GetAdaptersInfo failed with error: " << ret << endl; + if (pAdapterInfo) + HeapFree(GetProcessHeap(), 0, (pAdapterInfo)); + return al; +#else + PIStringList il = interfaces(), al; + piForeachC (PIString & i, il) + al << interfaceAddress(i); + return al; +#endif +} diff --git a/piethernet.h b/piethernet.h old mode 100755 new mode 100644 index 50e95db3..89fbfdd7 --- a/piethernet.h +++ b/piethernet.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Ethernet, UDP - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,61 +22,74 @@ #include "pitimer.h" #include "piiodevice.h" -#ifndef WINDOWS -# include -# include -# include -# include -#else -# ifdef CC_VC -# include -# define SHUT_RDWR 2 -# else -# include -# define SHUT_RDWR SD_BOTH -# endif -#endif +#include "piprocess.h" class PIEthernet: public PIIODevice { + friend class PIPeer; public: // slot is any function format "bool (void*, uchar*, int)" PIEthernet(void * data, ReadRetFunc slot); - enum Type {UDP, TCP_Client, TCP_Server}; + enum Type {UDP, TCP_Client, TCP_Server, TCP_SingleTCP}; + enum Parameters {ReuseAddress = 0x1, Broadcast = 0x2}; PIEthernet(Type type = UDP, void * data = 0, ReadRetFunc slot = 0); ~PIEthernet(); - void setReadAddress(PIString ip, int port) {path_ = ip + ":" + PIString::fromNumber(port);} - void setReadAddress(PIString ip_port) {path_ = ip_port;} - void setSendAddress(PIString ip, int port) {ip_s = ip; port_s = port;} - void setSendAddress(PIString ip_port) {parseAddress(ip_port, &ip_s, &port_s);} + void setReadAddress(const PIString & ip, int port) {path_ = ip + ":" + PIString::fromNumber(port);} + void setReadAddress(const PIString & ip_port) {path_ = ip_port;} + void setReadIP(const PIString & ip) {parseAddress(path_, &ip_, &port_); path_ = ip + ":" + PIString::fromNumber(port_);} + void setReadPort(int port) {parseAddress(path_, &ip_, &port_); path_ = ip_ + ":" + PIString::fromNumber(port);} + void setSendAddress(const PIString & ip, int port) {ip_s = ip; port_s = port;} + void setSendAddress(const PIString & ip_port) {parseAddress(ip_port, &ip_s, &port_s);} + void setSendIP(const PIString & ip) {ip_s = ip;} + void setSendPort(int port) {port_s = port;} + PIString readIP() {parseAddress(path_, &ip_, &port_); return ip_;} + int readPort() {parseAddress(path_, &ip_, &port_); return port_;} + PIString sendIP() {return ip_s;} + int sendPort() {return port_s;} + void setParameters(PIFlags parameters_) {params = parameters_;} + void setParameter(PIEthernet::Parameters parameter, bool on = true) {params.setFlag(parameter, on);} + bool isParameterSet(PIEthernet::Parameters parameter) const {return params[parameter];} + PIFlags parameters() const {return params;} + + //PIByteArray macAddress() {if (!init_) init(); struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); memcpy(ifr.ifr_name, "eth0", 5); ioctl(sock, SIOCSIFHWADDR, &ifr); return PIByteArray(&ifr.ifr_hwaddr.sa_data, 6);} Type type() const {return type_;} - bool connect(PIString ip, int port); - bool connect(PIString ip_port) {parseAddress(ip_port, &ip_c, &port_c); return connect(ip_c, port_c);} + 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 isConnected() const {return connected_;} bool listen(); - bool listen(PIString ip, int port) {setReadAddress(ip, port); return listen();} - bool listen(PIString ip_port) {setReadAddress(ip_port); return listen();} + bool listen(const PIString & ip, int port) {setReadAddress(ip, port); return listen();} + bool listen(const PIString & ip_port) {setReadAddress(ip_port); return listen();} PIEthernet * client(int index) {return clients_[index];} int clientsCount() const {return clients_.size_s();} PIVector clients() {return clients_;} - bool send(PIString ip, int port, const void * data, int size) {ip_s = ip; port_s = port; return send(data, size);} - bool send(PIString ip_port, const void * data, int size) {parseAddress(ip_port, &ip_s, &port_s); return send(data, size);} + 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);} int read(void * read_to, int max_size); int write(const void * data, int max_size); + int write(const PIByteArray & data) {return write(data.data(), data.size_s());} + + static PIStringList interfaces(); + static PIString interfaceAddress(const PIString & interface_); + static PIStringList allAddresses(); protected: PIEthernet(int sock, PIString ip_port); + virtual void received(void * data, int size) {;} + bool init(); bool openDevice(); bool closeDevice(); @@ -87,17 +100,32 @@ protected: #endif void parseAddress(const PIString & ipp, PIString * ip, int * port); - int sock, port_, port_s, port_c, wrote; + int sock, sock_s, port_, port_s, port_c, wrote; bool connected_; sockaddr_in addr_, saddr_; PIString ip_, ip_s, ip_c; PIThread server_thread_; PIVector clients_; +#ifdef WINDOWS + PIMap leafs; +#endif + PIFlags params; Type type_; private: static void server_func(void * eth); + static std::string EthErrorString() { +#ifdef WINDOWS + char * msg; + int err = WSAGetLastError(); + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msg, 0, NULL); + return "code " + itos(err) + " - " + string(msg); +#else + return errorString(); +#endif + } + }; #endif // PIETHERNET_H diff --git a/pievaluator.cpp b/pievaluator.cpp old mode 100755 new mode 100644 index 5bef2b45..049f9ce9 --- a/pievaluator.cpp +++ b/pievaluator.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Evaluator designed for stream computing - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pievaluator.h b/pievaluator.h old mode 100755 new mode 100644 index 545c78cd..229ee3fc --- a/pievaluator.h +++ b/pievaluator.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Evaluator designed for stream computing - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pifile.cpp b/pifile.cpp old mode 100755 new mode 100644 index ac4d5cad..93f99a94 --- a/pifile.cpp +++ b/pifile.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives File - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -33,21 +33,20 @@ bool PIFile::openDevice() { bool PIFile::closeDevice() { if (!opened_) return true; - return (fclose(fd) != 0); + return (fclose(fd) == 0); } PIString PIFile::readLine() { PIString str; if (!opened_) return str; - char cc; - int cp = 0; + int cc, cp = 0; while (!isEnd() && cp < 4095) { - cc = char(fgetc(fd)); - if (cc == '\n') break; - str.push_back(cc); + cc = fgetc(fd); + if (char(cc) == '\n' || cc == EOF) break; + str.push_back(char(cc)); } - //cout << "readline: " << buff << endl; + //cout << "readline: " << str << endl; return str; } @@ -66,17 +65,20 @@ llong PIFile::readAll(void * data) { PIByteArray PIFile::readAll(bool forceRead) { - llong cp = pos(), s = size(); PIByteArray a; - if (s < 0) { - if (!forceRead) return a; + llong cp = pos(); + if (forceRead) { + seekToBegin(); while (!isEnd()) a.push_back(readChar()); seek(cp); return a; } + llong s = size(); + if (s < 0) return a; a.resize(s); s = readAll(a.data()); + seek(cp); if (s >= 0) a.resize(s); return a; } diff --git a/pifile.h b/pifile.h old mode 100755 new mode 100644 index 6c378f86..f8966976 --- a/pifile.h +++ b/pifile.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives File - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,10 +23,14 @@ #include "piiodevice.h" #include +/// handlers: +/// void clear() +/// void resize(llong new_size, char fill = 0) +/// void remove() class PIFile: public PIIODevice { public: - PIFile(const PIString & path = PIString(), DeviceMode type = ReadWrite): PIIODevice(path, type) {openDevice();} + PIFile(const PIString & path = PIString(), DeviceMode type = ReadWrite): PIIODevice(path, type) {setPrecision(5); openDevice();} //PIFile & operator =(const PIFile & f) {path_ = f.path_; type_ = f.type_; return *this;} @@ -51,6 +55,9 @@ public: bool isEnd() {return (feof(fd) || ferror(fd));} bool isEmpty() {return (size() <= 0);} + int precision() const {return prec;} + void setPrecision(int prec_) {prec = prec_; prec_str = "." + itos(prec_);} + 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;} @@ -59,10 +66,12 @@ public: PIFile & writeBinary(const short v) {write(&v, sizeof(v)); return *this;} PIFile & writeBinary(const int v) {write(&v, sizeof(v)); return *this;} PIFile & writeBinary(const long v) {write(&v, sizeof(v)); return *this;} + PIFile & writeBinary(const llong v) {write(&v, sizeof(v)); return *this;} PIFile & writeBinary(const uchar v) {write(&v, sizeof(v)); return *this;} PIFile & writeBinary(const ushort v) {write(&v, sizeof(v)); return *this;} PIFile & writeBinary(const uint v) {write(&v, sizeof(v)); return *this;} PIFile & writeBinary(const ulong v) {write(&v, sizeof(v)); return *this;} + PIFile & writeBinary(const ullong v) {write(&v, sizeof(v)); return *this;} PIFile & writeBinary(const float v) {write(&v, sizeof(v)); return *this;} PIFile & writeBinary(const double v) {write(&v, sizeof(v)); return *this;} @@ -70,26 +79,30 @@ public: //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;} - PIFile & operator <<(short v) {if (!isWriteable()) return *this; fprintf(fd, "%hd", v); return *this;} - PIFile & operator <<(int v) {if (!isWriteable()) return *this; fprintf(fd, "%d", v); return *this;} - PIFile & operator <<(long v) {if (!isWriteable()) return *this; fprintf(fd, "%ld", v); return *this;} - PIFile & operator <<(uchar v) {if (!isWriteable()) return *this; fprintf(fd, "%c", v); return *this;} - PIFile & operator <<(ushort v) {if (!isWriteable()) return *this; fprintf(fd, "%hd", v); return *this;} - PIFile & operator <<(uint v) {if (!isWriteable()) return *this; fprintf(fd, "%d", v); return *this;} - PIFile & operator <<(ulong v) {if (!isWriteable()) return *this; fprintf(fd, "%ld", v); return *this;} - PIFile & operator <<(float v) {if (!isWriteable()) return *this; fprintf(fd, "%f", v); return *this;} - PIFile & operator <<(double v) {if (!isWriteable()) return *this; fprintf(fd, "%lf", v); return *this;} + PIFile & operator <<(short v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%hd", v); return *this;} + 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 <<(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;} - PIFile & operator >>(char & v) {if (!isWriteable()) return *this; fscanf(fd, "%hhn", &v); return *this;} - PIFile & operator >>(short & v) {if (!isWriteable()) return *this; fscanf(fd, "%hn", &v); return *this;} - PIFile & operator >>(int & v) {if (!isWriteable()) return *this; fscanf(fd, "%n", &v); return *this;} - PIFile & operator >>(long & v) {if (!isWriteable()) return *this; fscanf(fd, "%ln", &v); return *this;} - PIFile & operator >>(uchar & v) {if (!isWriteable()) return *this; fscanf(fd, "%hhn", &v); return *this;} - PIFile & operator >>(ushort & v) {if (!isWriteable()) return *this; fscanf(fd, "%hn", &v); return *this;} - PIFile & operator >>(uint & v) {if (!isWriteable()) return *this; fscanf(fd, "%n", &v); return *this;} - PIFile & operator >>(ulong & v) {if (!isWriteable()) return *this; fscanf(fd, "%ln", &v); return *this;} - PIFile & operator >>(float & v) {if (!isWriteable()) return *this; fscanf(fd, "%f", &v); return *this;} - PIFile & operator >>(double & v) {if (!isWriteable()) return *this; fscanf(fd, "%lf", &v); return *this;} + PIFile & operator >>(char & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%hhn", &v); return *this;} + PIFile & operator >>(short & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%hn", &v); return *this;} + PIFile & operator >>(int & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%n", &v); return *this;} + PIFile & operator >>(long & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%ln", &v); return *this;} + PIFile & operator >>(llong & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%lln", &v); return *this;} + PIFile & operator >>(uchar & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%hhn", &v); return *this;} + PIFile & operator >>(ushort & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%hn", &v); return *this;} + PIFile & operator >>(uint & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%n", &v); return *this;} + PIFile & operator >>(ulong & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%ln", &v); return *this;} + PIFile & operator >>(ullong & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%lln", &v); return *this;} + PIFile & operator >>(float & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%f", &v); return *this;} + PIFile & operator >>(double & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%lf", &v); return *this;} static PIFile openTemporary(PIIODevice::DeviceMode mode = PIIODevice::ReadWrite) {return PIFile(PIString(tmpnam(0)), mode);} static bool isExists(const PIString & path); @@ -103,6 +116,8 @@ private: PIString strType(const PIIODevice::DeviceMode type) {switch (type) {case PIIODevice::ReadOnly: return "rb"; case WriteOnly: return "ab"; case ReadWrite: return "a+b";} return "rb";} FILE * fd; + int ret, prec; + string prec_str; }; diff --git a/pigeometry.h b/pigeometry.h old mode 100755 new mode 100644 index 642b559d..1536f7b0 --- a/pigeometry.h +++ b/pigeometry.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Geometry - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/piincludes.cpp b/piincludes.cpp index 35736881..eba50cb5 100644 --- a/piincludes.cpp +++ b/piincludes.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Global includes - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,3 +21,7 @@ bool isPIInit = false; bool piDebug = true; +string ifconfigPath; + +PIInit piInit; +lconv * currentLocale = std::localeconv(); diff --git a/piincludes.h b/piincludes.h old mode 100755 new mode 100644 index bede5cb1..ecd8ad4d --- a/piincludes.h +++ b/piincludes.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Global includes - Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,11 +20,11 @@ #ifndef PIINCLUDES_H #define PIINCLUDES_H -#define PIP_VERSION 0x000200 +#define PIP_VERSION 0x000206 #define PIP_VERSION_MAJOR (PIP_VERSION & 0xFF0000) >> 16 #define PIP_VERSION_MINOR (PIP_VERSION & 0xFF00) >> 8 #define PIP_VERSION_REVISION PIP_VERSION & 0xFF -#define PIP_VERSION_SUFFIX "" +#define PIP_VERSION_SUFFIX "_beta" #if WIN32 || WIN64 || _WIN32 || _WIN64 || __WIN32__ || __WIN64__ # define WINDOWS @@ -32,15 +32,33 @@ #if __QNX__ || __QNXNTO__ # define QNX #endif +#if __FreeBSD__ +# define FREE_BSD +#endif +#if __APPLE__ || __MACH__ +# define MAC_OS +#endif #ifndef WINDOWS # ifndef QNX -# define LINUX +# ifndef FREE_BSD +# ifndef MAC_OS +# define LINUX +# endif +# endif # endif #endif #if __GNUC__ # define CC_GCC +# define CC_GCC_VERSION ((__GNUC__ << 8) | __GNUC_MINOR__) +# if CC_GCC_VERSION > 0x025F // > 2.95 +# ifdef LINUX +# define HAS_LOCALE +# endif +# endif #elif _MSC_VER # define CC_VC +#else +# define CC_OTHER #endif #ifdef WINDOWS @@ -70,6 +88,9 @@ #include #include #include +#include +#include +//#include #include #include #include @@ -80,10 +101,46 @@ #include #include #include +#include #ifdef WINDOWS +typedef int socklen_t; # include +# include +# include +# ifdef CC_VC +# define SHUT_RDWR 2 +# pragma comment(lib, "Ws2_32.lib") +# pragma comment(lib, "Iphlpapi.lib") +# else +# define SHUT_RDWR SD_BOTH +# endif # include # include +# include +#else +# include +# include +# include +# include +# include +# include +#endif +#ifndef QNX +# ifndef WINDOWS +# ifndef FREE_BSD +# define environ __environ +# endif +# endif +#endif +#if !defined(WINDOWS) && !defined(MAC_OS) +# define PIP_TIMER_RT +#endif +#ifdef FREE_BSD +extern char ** environ; +#endif +#ifdef MAC_OS +typedef long time_t; +clock_serv_t __pi_mac_clock; #endif #include "pimonitor.h" @@ -110,18 +167,65 @@ using std::queue; using std::deque; using std::stack; using std::set; +using std::map; using std::string; #ifndef QNX using std::wstring; -# ifndef WINDOWS -static locale_t currentLocale_t = 0; -# endif +//# ifndef WINDOWS +//static locale_t currentLocale_t = 0; +//# endif #else typedef std::basic_string wstring; #endif +#ifdef HAS_LOCALE +static locale_t currentLocale_t = 0; +#endif + +template inline void piSwap(T & f, T & s) {T t = f; f = s; s = t;} +template inline int piRound(const T & v) {return int(v >= T(0.) ? v + T(0.5) : v - T(0.5));} +template inline int piFloor(const T & v) {return v < T(0) ? int(v) - 1 : int(v);} +template inline int piCeil(const T & v) {return v < T(0) ? int(v) : int(v) + 1;} +template inline T piAbs(const T & v) {return (v >= T(0) ? v : -v);} +template inline T piMin(const T & f, const T & s) {return (f > s) ? s : f;} +template inline T piMin(const T & f, const T & s, const T & t) {return (f < s && f < t) ? f : ((s < t) ? s : t);} +template inline T piMax(const T & f, const T & s) {return (f < s) ? s : f;} +template inline T piMax(const T & f, const T & s, const T & t) {return (f > s && f > t) ? f : ((s > t) ? s : t);} +template inline T piClamp(const T & v, const T & min, const T & max) {return (v > max ? max : (v < min ? min : v));} + +#define piRoundf piRound +#define piRoundd piRound +#define piFloorf piFloor +#define piFloord piFloor +#define piCeilf piCeil +#define piCeild piCeil +#define piAbss piAbs +#define piAbsi piAbs +#define piAbsl piAbs +#define piAbsll piAbs +#define piAbsf piAbs +#define piAbsd piAbs +#define piMins piMin +#define piMini piMin +#define piMinl piMin +#define piMinll piMin +#define piMinf piMin +#define piMind piMin +#define piMaxs piMax +#define piMaxi piMax +#define piMaxl piMax +#define piMaxll piMax +#define piMaxf piMax +#define piMaxd piMax +#define piClamps piClamp +#define piClampi piClamp +#define piClampl piClamp +#define piClampll piClamp +#define piClampf piClamp +#define piClampd piClamp extern bool isPIInit; extern bool piDebug; +extern string ifconfigPath; #define piCout if (piDebug) cout @@ -130,8 +234,34 @@ public: PIInit() { if (isPIInit) return; isPIInit = true; +#ifndef WINDOWS + sigset_t ss; + sigemptyset(&ss); + sigaddset(&ss, SIGALRM); + if (pthread_sigmask(SIG_BLOCK, &ss, 0) == -1) { + //cout << "[PITimer] sigaction error: " << errorString() << endl; + //return 0; + } + ifconfigPath = "/bin/ifconfig"; + if (!fileExists(ifconfigPath)) { + ifconfigPath = "/sbin/ifconfig"; + if (!fileExists(ifconfigPath)) { + ifconfigPath = "/usr/bin/ifconfig"; + if (!fileExists(ifconfigPath)) { + ifconfigPath = "/usr/sbin/ifconfig"; + if (!fileExists(ifconfigPath)) { + ifconfigPath = ""; + } + } + } + } +#else + WSADATA wsaData; + WSAStartup(MAKEWORD(2, 2), &wsaData); +#endif //piDebug = true; -#ifdef LINUX +#ifdef HAS_LOCALE + //cout << "has locale" << endl; if (currentLocale_t != 0) { freelocale(currentLocale_t); currentLocale_t = 0; @@ -139,21 +269,26 @@ public: currentLocale_t = newlocale(LC_ALL, setlocale(LC_ALL, ""), 0); #else setlocale(LC_ALL, ""); +#endif +#ifdef MAC_OS + host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &__pi_mac_clock); #endif } ~PIInit() { +#ifdef WINDOWS + WSACleanup(); +#endif +#ifdef MAC_OS + mach_port_deallocate(mach_task_self(), __pi_mac_clock); +#endif //if (currentLocale_t != 0) freelocale(currentLocale_t); } +private: + bool fileExists(const string & p) {FILE * f = fopen(p.c_str(), "r"); if (f == 0) return false; fclose(f); return true;} }; -static PIInit piInit; -static lconv * currentLocale = std::localeconv(); - -#ifdef CC_VC -inline string errorString() {char buff[1024]; strerror_s(buff, 1024, GetLastError()); return string(buff);} -#else -inline string errorString() {return string(strerror(errno));} -#endif +extern PIInit piInit; +extern lconv * currentLocale; #ifdef WINDOWS inline int random() {return rand();} @@ -162,12 +297,6 @@ inline double round(const double & v) {return floor(v + 0.5);} # endif #endif -template inline void piSwap(Type & f, Type & s) {Type t = f; f = s; s = t;} -template inline Type piMin(const Type & f, const Type & s) {return (f > s) ? s : f;} -template inline Type piMin(const Type & f, const Type & s, const Type & t) {return (f < s && f < t) ? f : ((s < t) ? s : t);} -template inline Type piMax(const Type & f, const Type & s) {return (f < s) ? s : f;} -template inline Type piMax(const Type & f, const Type & s, const Type & t) {return (f > s && f > t) ? f : ((s > t) ? s : t);} -template inline Type piClamp(const Type & v, const Type & min, const Type & max) {return (v > max ? max : (v < min ? min : v));} 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";}; @@ -220,6 +349,18 @@ inline string dtos(const double num) { #endif return string(ch); }; +#ifdef CC_VC +inline string errorString() { + char * msg; + int err = GetLastError(); + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msg, 0, NULL); + return "code " + itos(err) + " - " + string(msg); +} +#else +inline void errorClear() {errno = 0;} +inline string errorString() {int e = errno; return "code " + itos(e) + " - " + string(strerror(e));} +#endif + inline string PIPVersion() {return itos(PIP_VERSION_MAJOR) + "." + itos(PIP_VERSION_MINOR) + "." + itos(PIP_VERSION_REVISION) + PIP_VERSION_SUFFIX;} #endif // PIINCLUDES_H diff --git a/piiodevice.cpp b/piiodevice.cpp old mode 100755 new mode 100644 index 27a78afe..41912d9b --- a/piiodevice.cpp +++ b/piiodevice.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Abstract input/output device - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -96,7 +96,6 @@ void PIIODevice::run() { //cout << "not started\n"; return; } - readed_ = read(buffer_tr.data(), buffer_tr.size_s()); if (readed_ <= 0) { msleep(10); diff --git a/piiodevice.h b/piiodevice.h old mode 100755 new mode 100644 index 8fee6051..bc8b7181 --- a/piiodevice.h +++ b/piiodevice.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Abstract input/output device - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,6 +25,18 @@ // 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 { public: PIIODevice(); @@ -32,7 +44,7 @@ public: enum DeviceMode {ReadOnly = 0x01, WriteOnly = 0x02, ReadWrite = 0x03}; PIIODevice(const PIString & path, DeviceMode type = ReadWrite, bool initNow = true); - ~PIIODevice() {if (opened_) closeDevice();} + virtual ~PIIODevice() {if (opened_) {closeDevice(); if (!opened_) closed();}} DeviceMode mode() const {return mode_;} @@ -66,15 +78,19 @@ public: void startThreadedRead(ReadRetFunc func) {ret_func_ = func; if (!isRunning()) start();} - EVENT_HANDLER(PIIODevice, bool, open) {if (!init_) init(); opened_ = openDevice(); return opened_;} - EVENT_HANDLER1(PIIODevice, bool, open, const PIString &, _path) {path_ = _path; if (!init_) init(); opened_ = openDevice(); return opened_;} - EVENT_HANDLER1(PIIODevice, bool, open, const DeviceMode &, _type) {mode_ = _type; if (!init_) init(); opened_ = openDevice(); return opened_;} - EVENT_HANDLER2(PIIODevice, bool, open, const PIString &, _path, const DeviceMode &, _type) {path_ = _path; mode_ = _type; if (!init_) init(); opened_ = openDevice(); return opened_;} - EVENT_HANDLER(PIIODevice, bool, close) {opened_ = !closeDevice(); return !opened_;} + 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) + // 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;} @@ -84,6 +100,7 @@ public: // 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());} protected: @@ -97,6 +114,8 @@ protected: // Function executed when thread read some data, default implementation execute external slot "ret_func_" virtual bool threadedRead(uchar * readed, int size) {if (ret_func_ != 0) return ret_func_(ret_data_, readed, size); return true;} + void terminate(); + PIString path_; DeviceMode mode_; ReadRetFunc ret_func_; @@ -106,7 +125,6 @@ protected: private: EVENT_HANDLER2(PIIODevice, void, check_start, void * , data, int, delim); - void terminate(); void begin(); void run(); diff --git a/pikbdlistener.cpp b/pikbdlistener.cpp old mode 100755 new mode 100644 index e505eb45..3fc84153 --- a/pikbdlistener.cpp +++ b/pikbdlistener.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Keyboard grabber for console - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -64,6 +64,7 @@ void PIKbdListener::run() { PIKbdListener::exiting = true; return; } + keyPressed(rc, data); if (ret_func != 0 && ret > 0) ret_func(rc, data); } diff --git a/pikbdlistener.h b/pikbdlistener.h old mode 100755 new mode 100644 index c8ed6b87..9d122477 --- a/pikbdlistener.h +++ b/pikbdlistener.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Keyboard grabber for console - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,29 +29,39 @@ typedef void (*KBFunc)(char, void * ); +/// events: +/// keyPressed(char key, void * data) +/// +/// handlers: +/// void enableExitCapture(char key = 'Q') +/// void setActive(bool yes = true) class PIKbdListener: public PIThread { friend class PIConsole; public: // 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_;} - void enableExitCapture(char key = 'Q') {exit_enabled = true; exit_key = key;} + EVENT_HANDLER(PIKbdListener, void, enableExitCapture) {enableExitCapture('Q');} + EVENT_HANDLER1(PIKbdListener, 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;} - void setActive(bool yes = true); + EVENT_HANDLER(PIKbdListener, void, setActive) {setActive(true);} + EVENT_HANDLER1(PIKbdListener, void, setActive, bool, yes); + EVENT2(PIKbdListener, keyPressed, char, key, void * , data) + static bool exiting; - + private: void begin(); void run(); void end(); - + KBFunc ret_func; char exit_key; bool exit_enabled, is_active; @@ -65,7 +75,7 @@ private: int ret; struct termios sterm, tterm; #endif - + }; #endif // PIKBDLISTENER_H diff --git a/pimath.cpp b/pimath.cpp old mode 100755 new mode 100644 index b0107e67..c7cff361 --- a/pimath.cpp +++ b/pimath.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Math - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,160 +19,6 @@ #include "pimath.h" -/* -* Fast Fourier Transformation -* ==================================================== -* Coded by Miroslav Voinarovsky, 2002 -* This source is freeware. -*/ - -// This array contains values from 0 to 255 with reverse bit order -static uchar reverse256[]= { - 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, - 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, - 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, - 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, - 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, - 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, - 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, - 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, - 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, - 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, - 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, - 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, - 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, - 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, - 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, - 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, - 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, - 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, - 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, - 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, - 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, - 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, - 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, - 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, - 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, - 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, - 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, - 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, - 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, - 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, - 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, - 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF, -}; - -//This is array exp(-2*pi*j/2^n) for n= 1,...,32 -//exp(-2*pi*j/2^n) = complexd( cos(2*pi/2^n), -sin(2*pi/2^n) ) -static complexd W2n[32] = { - complexd(-1.00000000000000000000000000000000, 0.00000000000000000000000000000000), // W2 calculator (copy/paste) : po, ps - complexd( 0.00000000000000000000000000000000, -1.00000000000000000000000000000000), // W4: p/2=o, p/2=s - complexd( 0.70710678118654752440084436210485, -0.70710678118654752440084436210485), // W8: p/4=o, p/4=s - complexd( 0.92387953251128675612818318939679, -0.38268343236508977172845998403040), // p/8=o, p/8=s - complexd( 0.98078528040323044912618223613424, -0.19509032201612826784828486847702), // p/16= - complexd( 0.99518472667219688624483695310948, -9.80171403295606019941955638886e-2), // p/32= - complexd( 0.99879545620517239271477160475910, -4.90676743274180142549549769426e-2), // p/64= - complexd( 0.99969881869620422011576564966617, -2.45412285229122880317345294592e-2), // p/128= - complexd( 0.99992470183914454092164649119638, -1.22715382857199260794082619510e-2), // p/256= - complexd( 0.99998117528260114265699043772857, -6.13588464915447535964023459037e-3), // p/(2y9)= - complexd( 0.99999529380957617151158012570012, -3.06795676296597627014536549091e-3), // p/(2y10)= - complexd( 0.99999882345170190992902571017153, -1.53398018628476561230369715026e-3), // p/(2y11)= - complexd( 0.99999970586288221916022821773877, -7.66990318742704526938568357948e-4), // p/(2y12)= - complexd( 0.99999992646571785114473148070739, -3.83495187571395589072461681181e-4), // p/(2y13)= - complexd( 0.99999998161642929380834691540291, -1.91747597310703307439909561989e-4), // p/(2y14)= - complexd( 0.99999999540410731289097193313961, -9.58737990959773458705172109764e-5), // p/(2y15)= - complexd( 0.99999999885102682756267330779455, -4.79368996030668845490039904946e-5), // p/(2y16)= - complexd( 0.99999999971275670684941397221864, -2.39684498084182187291865771650e-5), // p/(2y17)= - complexd( 0.99999999992818917670977509588385, -1.19842249050697064215215615969e-5), // p/(2y18)= - complexd( 0.99999999998204729417728262414778, -5.99211245264242784287971180889e-6), // p/(2y19)= - complexd( 0.99999999999551182354431058417300, -2.99605622633466075045481280835e-6), // p/(2y20)= - complexd( 0.99999999999887795588607701655175, -1.49802811316901122885427884615e-6), // p/(2y21)= - complexd( 0.99999999999971948897151921479472, -7.49014056584715721130498566730e-7), // p/(2y22)= - complexd( 0.99999999999992987224287980123973, -3.74507028292384123903169179084e-7), // p/(2y23)= - complexd( 0.99999999999998246806071995015625, -1.87253514146195344868824576593e-7), // p/(2y24)= - complexd( 0.99999999999999561701517998752946, -9.36267570730980827990672866808e-8), // p/(2y25)= - complexd( 0.99999999999999890425379499688176, -4.68133785365490926951155181385e-8), // p/(2y26)= - complexd( 0.99999999999999972606344874922040, -2.34066892682745527595054934190e-8), // p/(2y27)= - complexd( 0.99999999999999993151586218730510, -1.17033446341372771812462135032e-8), // p/(2y28)= - complexd( 0.99999999999999998287896554682627, -5.85167231706863869080979010083e-9), // p/(2y29)= - complexd( 0.99999999999999999571974138670657, -2.92583615853431935792823046906e-9), // p/(2y30)= - complexd( 0.99999999999999999892993534667664, -1.46291807926715968052953216186e-9), // p/(2y31)= -}; - -/* - * x: x - array of items - * T: 1 << T = 2 power T - number of items in array - * complement: false - normal (direct) transformation, true - reverse transformation - */ -void fft(complexd * x, int T, bool complement) -{ - uint I, J, Nmax, N, Nd2, k, m, mpNd2, Skew; - uchar *Ic = (uchar*) &I; - uchar *Jc = (uchar*) &J; - complexd S; - complexd * Wstore, * Warray; - complexd WN, W, Temp, *pWN; - - Nmax = 1 << T; - - //first interchanging - for(I = 1; I < Nmax - 1; I++) - { - Jc[0] = reverse256[Ic[3]]; - Jc[1] = reverse256[Ic[2]]; - Jc[2] = reverse256[Ic[1]]; - Jc[3] = reverse256[Ic[0]]; - J >>= (32 - T); - if (I < J) - { - S = x[I]; - x[I] = x[J]; - x[J] = S; - } - } - - //rotation multiplier array allocation - Wstore = new complexd[Nmax / 2]; - Wstore[0] = complexd(1., 0.); - - //main loop - for(N = 2, Nd2 = 1, pWN = W2n, Skew = Nmax >> 1; N <= Nmax; Nd2 = N, N += N, pWN++, Skew >>= 1) - { - //WN = W(1, N) = exp(-2*pi*j/N) - WN= *pWN; - if (complement) - WN = complexd(WN.real(), -WN.imag()); - for(Warray = Wstore, k = 0; k < Nd2; k++, Warray += Skew) - { - if (k & 1) - { - W *= WN; - *Warray = W; - } - else - W = *Warray; - - for(m = k; m < Nmax; m += N) - { - mpNd2 = m + Nd2; - Temp = W; - Temp *= x[mpNd2]; - x[mpNd2] = x[m]; - x[mpNd2] -= Temp; - x[m] += Temp; - } - } - } - - delete[] Wstore; - - if (complement) - { - for( I = 0; I < Nmax; I++ ) - x[I] /= Nmax; - } -} - const char Solver::methods_desc[] = "b{Methods:}\ \n -1 - Global settings\ @@ -401,3 +247,981 @@ void Solver::solvePA(double u, double h, uint deg) { } moveF(); } + + + +PIFFT::PIFFT() { + prepared = false; +} + + +PIVector * PIFFT::calcFFT(const PIVector & val) { +// for (uint i=0; i *PIFFT::calcFFTinverse(const PIVector &val) +{ + result.clear(); + if (val.size_s() < 4) return &result; + fftc1dinv(val, val.size()); + return &result; +} + + +PIVector *PIFFT::calcHilbert(const PIVector &val) +{ + result.clear(); + if (val.size_s() < 4) return &result; + fftc1r(val, val.size()); + for (uint i=0; i* PIFFT::calcFFT(const PIVector & val) { + result.clear(); + if (val.size_s() < 4) return &result; + fftc1r(val, val.size()); + return &result; +} + + +PIVector PIFFT::getAmplitude() { + PIVector a; + double tmp; + for (uint i=0; i &a, uint n) { + createPlan(n); + uint i; + PIVector buf; + buf.resize(2*n); + for(i=0; iptr.p_complex[i].x; + buf[2*i+1] = a.at(i).imag();//a->ptr.p_complex[i].y; + } + ftbaseexecuteplan(&buf, 0, n, &curplan); + result.resize(n); + for(i=0; i & a, uint n) { + uint i; + if( n%2==0 ) { + PIVector buf; + uint n2 = n/2; + //buf.resize(n); + buf = a; + createPlan(n2); + //cout << "fftr " << n2 << endl; + ftbaseexecuteplan(&buf, 0, n2, &curplan); + result.resize(n); + uint idx; + complexd hn, hmnc, v; + for(i=0; i<=n2; i++) { + idx = 2*(i%n2); + hn = complexd(buf[idx+0], buf[idx+1]); + idx = 2*((n2-i)%n2); + hmnc = complexd(buf[idx+0], -buf[idx+1]); + v = complexd(sin(M_PI*i/n2), cos(M_PI*i/n2)); + result[i] = ((hn + hmnc) - (v * (hn - hmnc))); + result[i] *= 0.5; + } + for(i=n2+1; i cbuf; + cbuf.resize(n); + for(i=0; i &a, uint n) +{ + PIVector cbuf; + cbuf.resize(n); + uint i; + for(i=0; i(*planarraysize) ) { + curplan.plan.resize(8*(*planarraysize)); + *planarraysize = 8*(*planarraysize); + } + entryoffset = *plansize; + esize = ftbase_ftbaseplanentrysize; + *plansize = *plansize+esize; + if( n==1 ) { + curplan.plan[entryoffset+0] = esize; + curplan.plan[entryoffset+1] = -1; + curplan.plan[entryoffset+2] = -1; + curplan.plan[entryoffset+3] = ftbase_fftemptyplan; + curplan.plan[entryoffset+4] = -1; + curplan.plan[entryoffset+5] = -1; + curplan.plan[entryoffset+6] = -1; + curplan.plan[entryoffset+7] = -1; + return; + } + ftbasefactorize(n, &n1, &n2); + if( n1!=1 ) { + *tmpmemsize = piMax(*tmpmemsize, 2*n1*n2); + curplan.plan[entryoffset+0] = esize; + curplan.plan[entryoffset+1] = n1; + curplan.plan[entryoffset+2] = n2; + if( tasktype==ftbase_ftbasecffttask ) + curplan.plan[entryoffset+3] = ftbase_fftcooleytukeyplan; + else + curplan.plan[entryoffset+3] = ftbase_fftrealcooleytukeyplan; + curplan.plan[entryoffset+4] = 0; + curplan.plan[entryoffset+5] = *plansize; + debugi++; + ftbase_ftbasegenerateplanrec(n1, ftbase_ftbasecffttask, plan, plansize, precomputedsize, planarraysize, tmpmemsize, stackmemsize, stackptr,debugi); + curplan.plan[entryoffset+6] = *plansize; + ftbase_ftbasegenerateplanrec(n2, ftbase_ftbasecffttask, plan, plansize, precomputedsize, planarraysize, tmpmemsize, stackmemsize, stackptr,debugi); + curplan.plan[entryoffset+7] = -1; + return; + } else { + if (n>=2 && n<=5) { + curplan.plan[entryoffset+0] = esize; + curplan.plan[entryoffset+1] = n1; + curplan.plan[entryoffset+2] = n2; + curplan.plan[entryoffset+3] = ftbase_fftcodeletplan; + curplan.plan[entryoffset+4] = 0; + curplan.plan[entryoffset+5] = -1; + curplan.plan[entryoffset+6] = -1; + curplan.plan[entryoffset+7] = *precomputedsize; + if( n==3 ) + *precomputedsize = *precomputedsize+2; + if( n==5 ) + *precomputedsize = *precomputedsize+5; + return; + } else { + k = 2*n2-1; + m = ftbasefindsmooth(k); + *tmpmemsize = piMax(*tmpmemsize, 2*m); + curplan.plan[entryoffset+0] = esize; + curplan.plan[entryoffset+1] = n2; + curplan.plan[entryoffset+2] = -1; + curplan.plan[entryoffset+3] = ftbase_fftbluesteinplan; + curplan.plan[entryoffset+4] = m; + curplan.plan[entryoffset+5] = *plansize; + stackptr = stackptr+2*2*m; + *stackmemsize = piMax(*stackmemsize, stackptr); + ftbase_ftbasegenerateplanrec(m, ftbase_ftbasecffttask, plan, plansize, precomputedsize, planarraysize, tmpmemsize, stackmemsize, stackptr); + stackptr = stackptr-2*2*m; + curplan.plan[entryoffset+6] = -1; + curplan.plan[entryoffset+7] = *precomputedsize; + *precomputedsize = *precomputedsize+2*m+2*n; + return; + } + } +} + + +/************************************************************************* +Recurrent subroutine for precomputing FFT plans + +-- ALGLIB -- + Copyright 01.05.2009 by Bochkanov Sergey +*************************************************************************/ +void PIFFT::ftbase_ftbaseprecomputeplanrec(ftplan* plan, + int entryoffset, + ae_int_t stackptr) +{ + int n1, n2, n, m, offs; + double v, bx, by; + int ftbase_fftcooleytukeyplan = 0; + int ftbase_fftbluesteinplan = 1; + int ftbase_fftcodeletplan = 2; + int ftbase_fhtcooleytukeyplan = 3; + int ftbase_fhtcodeletplan = 4; + int ftbase_fftrealcooleytukeyplan = 5; + if( (curplan.plan[entryoffset+3]==ftbase_fftcooleytukeyplan||curplan.plan[entryoffset+3]==ftbase_fftrealcooleytukeyplan)||curplan.plan[entryoffset+3]==ftbase_fhtcooleytukeyplan ) { + ftbase_ftbaseprecomputeplanrec(plan, curplan.plan[entryoffset+5], stackptr); + ftbase_ftbaseprecomputeplanrec(plan, curplan.plan[entryoffset+6], stackptr); + return; + } + if( curplan.plan[entryoffset+3]==ftbase_fftcodeletplan||curplan.plan[entryoffset+3]==ftbase_fhtcodeletplan ) { + n1 = curplan.plan[entryoffset+1]; + n2 = curplan.plan[entryoffset+2]; + n = n1*n2; + if( n==3 ) { + offs = curplan.plan[entryoffset+7]; + curplan.precomputed[offs+0] = cos(2*M_PI/3)-1; + curplan.precomputed[offs+1] = sin(2*M_PI/3); + return; + } + if( n==5 ) { + offs = curplan.plan[entryoffset+7]; + v = 2*M_PI/5; + curplan.precomputed[offs+0] = (cos(v)+cos(2*v))/2-1; + curplan.precomputed[offs+1] = (cos(v)-cos(2*v))/2; + curplan.precomputed[offs+2] = -sin(v); + curplan.precomputed[offs+3] = -(sin(v)+sin(2*v)); + curplan.precomputed[offs+4] = sin(v)-sin(2*v); + return; + } + } + if( curplan.plan[entryoffset+3]==ftbase_fftbluesteinplan ) { + ftbase_ftbaseprecomputeplanrec(plan, curplan.plan[entryoffset+5], stackptr); + n = curplan.plan[entryoffset+1]; + m = curplan.plan[entryoffset+4]; + offs = curplan.plan[entryoffset+7]; + for(int i=0; i<=2*m-1; i++) + curplan.precomputed[offs+i] = 0; + for(int i=0; i0 ) { + curplan.precomputed[offs+2*(m-i)+0] = bx; + curplan.precomputed[offs+2*(m-i)+1] = by; + } + } + ftbaseexecuteplanrec(&curplan.precomputed, offs, plan, curplan.plan[entryoffset+5], stackptr); + return; + } +} + + +void PIFFT::ftbasefactorize(int n, int* n1, int* n2) { + *n1 = *n2 = 0; + int ftbase_ftbasecodeletrecommended = 5; + if( (*n1)*(*n2)!=n ) { + for(int j=ftbase_ftbasecodeletrecommended; j>=2; j--) { + if( n%j==0 ) { + *n1 = j; + *n2 = n/j; + break; + } + } + } + if( (*n1)*(*n2)!=n ) { + for(int j=ftbase_ftbasecodeletrecommended+1; j<=n-1; j++) { + if( n%j==0 ) { + *n1 = j; + *n2 = n/j; + break; + } + } + } + if( (*n1)*(*n2)!=n ) { + *n1 = 1; + *n2 = n; + } + if( (*n2)==1 && (*n1)!=1 ) { + *n2 = *n1; + *n1 = 1; + } +} + + +/************************************************************************* +Is number smooth? + +-- ALGLIB -- + Copyright 01.05.2009 by Bochkanov Sergey +*************************************************************************/ +void PIFFT::ftbase_ftbasefindsmoothrec(int n, int seed, int leastfactor, int* best) { + if( seed>=n ) { + *best = piMin(*best, seed); + return; + } + if( leastfactor<=2 ) + ftbase_ftbasefindsmoothrec(n, seed*2, 2, best); + if( leastfactor<=3 ) + ftbase_ftbasefindsmoothrec(n, seed*3, 3, best); + if( leastfactor<=5 ) + ftbase_ftbasefindsmoothrec(n, seed*5, 5, best); +} + + +int PIFFT::ftbasefindsmooth(int n) { + int best, result; + best = 2; + while(best* a, int m, int n, int astart, PIVector* buf) { + ftbase_fftirltrec(a, astart, n, buf, 0, m, m, n); + for (int i=0; i<2*m*n; i++) (*a)[astart+i] = (*buf)[i]; +} + + +void PIFFT::ftbase_fftirltrec(PIVector* a, int astart, int astride, PIVector* b, int bstart, int bstride, int m, int n) { + int idx1, idx2; + int m1, n1; + if( m==0||n==0 ) + return; + if( piMax(m, n)<=8 ) { + for(int i=0; i<=m-1; i++) { + idx1 = bstart+i; + idx2 = astart+i*astride; + for(int j=0; j<=n-1; j++) { + (*b)[idx1] = a->at(idx2); + idx1 = idx1+bstride; + idx2 = idx2+1; + } + } + return; + } + if( n>m ) { + n1 = n/2; + if( n-n1>=8&&n1%8!=0 ) + n1 = n1+(8-n1%8); + ftbase_fftirltrec(a, astart, astride, b, bstart, bstride, m, n1); + ftbase_fftirltrec(a, astart+n1, astride, b, bstart+n1*bstride, bstride, m, n-n1); + } else { + m1 = m/2; + if( m-m1>=8&&m1%8!=0 ) + m1 = m1+(8-m1%8); + ftbase_fftirltrec(a, astart, astride, b, bstart, bstride, m1, n); + ftbase_fftirltrec(a, astart+m1*astride, astride, b, bstart+m1, bstride, m-m1, n); + } +} + + +void PIFFT::ftbase_internalcomplexlintranspose(PIVector* a, int m, int n, int astart, PIVector* buf) { + ftbase_ffticltrec(a, astart, n, buf, 0, m, m, n); + for (int i=0; i<2*m*n; i++) + (*a)[astart+i] = (*buf)[i]; +} + + +void PIFFT::ftbase_ffticltrec(PIVector* a, int astart, int astride, PIVector* b, int bstart, int bstride, int m, int n) { + int idx1, idx2, m2, m1, n1; + if( m==0||n==0 ) + return; + if( piMax(m, n)<=8 ) { + m2 = 2*bstride; + for(int i=0; i<=m-1; i++) { + idx1 = bstart+2*i; + idx2 = astart+2*i*astride; + for(int j=0; j<=n-1; j++) { + (*b)[idx1+0] = a->at(idx2+0); + (*b)[idx1+1] = a->at(idx2+1); + idx1 = idx1+m2; + idx2 = idx2+2; + } + } + return; + } + if( n>m ) { + n1 = n/2; + if( n-n1>=8&&n1%8!=0 ) + n1 = n1+(8-n1%8); + ftbase_ffticltrec(a, astart, astride, b, bstart, bstride, m, n1); + ftbase_ffticltrec(a, astart+2*n1, astride, b, bstart+2*n1*bstride, bstride, m, n-n1); + } else { + m1 = m/2; + if( m-m1>=8&&m1%8!=0 ) + m1 = m1+(8-m1%8); + ftbase_ffticltrec(a, astart, astride, b, bstart, bstride, m1, n); + ftbase_ffticltrec(a, astart+2*m1*astride, astride, b, bstart+2*m1, bstride, m-m1, n); + } +} + + +void PIFFT::ftbaseexecuteplan(PIVector* a, int aoffset, int n, ftplan* plan) { + ae_int_t stackptr; + stackptr = 0; + ftbaseexecuteplanrec(a, aoffset, plan, 0, stackptr); +} + + +/************************************************************************* +Recurrent subroutine for the FTBaseExecutePlan + +Parameters: + A FFT'ed array + AOffset offset of the FFT'ed part (distance is measured in doubles) + +-- ALGLIB -- + Copyright 01.05.2009 by Bochkanov Sergey +*************************************************************************/ +void PIFFT::ftbaseexecuteplanrec(PIVector* a, int aoffset, ftplan* plan, int entryoffset, ae_int_t stackptr) { + int n1, n2, n, m, offs, offs1, offs2, offsa, offsb, offsp; + double hk, hnk, x, y, bx, by, v0, v1, v2, v3; + double a0x, a0y, a1x, a1y, a2x, a2y, a3x, a3y; + double t1x, t1y, t2x, t2y, t3x, t3y, t4x, t4y, t5x, t5y; + double m1x, m1y, m2x, m2y, m3x, m3y, m4x, m4y, m5x, m5y; + double s1x, s1y, s2x, s2y, s3x, s3y, s4x, s4y, s5x, s5y; + double c1, c2, c3, c4, c5; + int ftbase_fftcooleytukeyplan = 0; + int ftbase_fftbluesteinplan = 1; + int ftbase_fftcodeletplan = 2; + int ftbase_fhtcooleytukeyplan = 3; + int ftbase_fhtcodeletplan = 4; + int ftbase_fftrealcooleytukeyplan = 5; + int ftbase_fftemptyplan = 6; + PIVector & tmpb(curplan.tmpbuf); + + if( curplan.plan[entryoffset+3]==ftbase_fftemptyplan ) + return; + if( curplan.plan[entryoffset+3]==ftbase_fftcooleytukeyplan ) { + n1 = curplan.plan[entryoffset+1]; + n2 = curplan.plan[entryoffset+2]; + ftbase_internalcomplexlintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf)); + for(int i=0; i<=n2-1; i++) + ftbaseexecuteplanrec(a, aoffset+i*n1*2, plan, curplan.plan[entryoffset+5], stackptr); + ftbase_ffttwcalc(a, aoffset, n1, n2); + ftbase_internalcomplexlintranspose(a, n2, n1, aoffset, &(curplan.tmpbuf)); + for(int i=0; i<=n1-1; i++) + ftbaseexecuteplanrec(a, aoffset+i*n2*2, plan, curplan.plan[entryoffset+6], stackptr); + ftbase_internalcomplexlintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf)); + return; + } + if( curplan.plan[entryoffset+3]==ftbase_fftrealcooleytukeyplan ) { + n1 = curplan.plan[entryoffset+1]; + n2 = curplan.plan[entryoffset+2]; + ftbase_internalcomplexlintranspose(a, n2, n1, aoffset, &(curplan.tmpbuf)); + for(int i=0; i<=n1/2-1; i++) { + offs = aoffset+2*i*n2*2; + for(int k=0; k<=n2-1; k++) + (*a)[offs+2*k+1] = (*a)[offs+2*n2+2*k+0]; + ftbaseexecuteplanrec(a, offs, plan, curplan.plan[entryoffset+6], stackptr); + tmpb[0] = (*a)[offs+0]; + tmpb[1] = 0; + tmpb[2*n2+0] = (*a)[offs+1]; + tmpb[2*n2+1] = 0; + for(int k=1; k<=n2-1; k++) { + offs1 = 2*k; + offs2 = 2*n2+2*k; + hk = (*a)[offs+2*k+0]; + hnk = (*a)[offs+2*(n2-k)+0]; + tmpb[offs1+0] = 0.5*(hk+hnk); + tmpb[offs2+1] = -0.5*(hk-hnk); + hk = (*a)[offs+2*k+1]; + hnk = (*a)[offs+2*(n2-k)+1]; + tmpb[offs2+0] = 0.5*(hk+hnk); + tmpb[offs1+1] = 0.5*(hk-hnk); + } + for (int i=0; i<2*n2*2; i++) (*a)[offs+i] = tmpb[i]; + } + if( n1%2!=0 ) + ftbaseexecuteplanrec(a, aoffset+(n1-1)*n2*2, plan, curplan.plan[entryoffset+6], stackptr); + ftbase_ffttwcalc(a, aoffset, n2, n1); + ftbase_internalcomplexlintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf)); + for(int i=0; i<=n2-1; i++) + ftbaseexecuteplanrec(a, aoffset+i*n1*2, plan, curplan.plan[entryoffset+5], stackptr); + ftbase_internalcomplexlintranspose(a, n2, n1, aoffset, &(curplan.tmpbuf)); + return; + } + if( curplan.plan[entryoffset+3]==ftbase_fhtcooleytukeyplan ) { + n1 = curplan.plan[entryoffset+1]; + n2 = curplan.plan[entryoffset+2]; + n = n1*n2; + ftbase_internalreallintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf)); + for(int i=0; i<=n2-1; i++) + ftbaseexecuteplanrec(a, aoffset+i*n1, plan, curplan.plan[entryoffset+5], stackptr); + for(int i=0; i<=n2-1; i++) { + for(int j=0; j<=n1-1; j++) { + offsa = aoffset+i*n1; + hk = (*a)[offsa+j]; + hnk = (*a)[offsa+(n1-j)%n1]; + offs = 2*(i*n1+j); + tmpb[offs+0] = -0.5*(hnk-hk); + tmpb[offs+1] = 0.5*(hk+hnk); + } + } + ftbase_ffttwcalc(&(curplan.tmpbuf), 0, n1, n2); + for(int j=0; j<=n1-1; j++) + (*a)[aoffset+j] = tmpb[2*j+0]+tmpb[2*j+1]; + if( n2%2==0 ) { + offs = 2*(n2/2)*n1; + offsa = aoffset+n2/2*n1; + for(int j=0; j<=n1-1; j++) + (*a)[offsa+j] = tmpb[offs+2*j+0]+tmpb[offs+2*j+1]; + } + for(int i=1; i<=(n2+1)/2-1; i++) { + offs = 2*i*n1; + offs2 = 2*(n2-i)*n1; + offsa = aoffset+i*n1; + for(int j=0; j<=n1-1; j++) + (*a)[offsa+j] = tmpb[offs+2*j+1]+tmpb[offs2+2*j+0]; + offsa = aoffset+(n2-i)*n1; + for(int j=0; j<=n1-1; j++) + (*a)[offsa+j] = tmpb[offs+2*j+0]+tmpb[offs2+2*j+1]; + } + ftbase_internalreallintranspose(a, n2, n1, aoffset, &(curplan.tmpbuf)); + for(int i=0; i<=n1-1; i++) + ftbaseexecuteplanrec(a, aoffset+i*n2, plan, curplan.plan[entryoffset+6], stackptr); + ftbase_internalreallintranspose(a, n1, n2, aoffset, &(curplan.tmpbuf)); + return; + } + if( curplan.plan[entryoffset+3]==ftbase_fftcodeletplan ) { + n1 = curplan.plan[entryoffset+1]; + n2 = curplan.plan[entryoffset+2]; + n = n1*n2; + if( n==2 ) { + a0x = (*a)[aoffset+0]; + a0y = (*a)[aoffset+1]; + a1x = (*a)[aoffset+2]; + a1y = (*a)[aoffset+3]; + v0 = a0x+a1x; + v1 = a0y+a1y; + v2 = a0x-a1x; + v3 = a0y-a1y; + (*a)[aoffset+0] = v0; + (*a)[aoffset+1] = v1; + (*a)[aoffset+2] = v2; + (*a)[aoffset+3] = v3; + return; + } + if( n==3 ) { + offs = curplan.plan[entryoffset+7]; + c1 = curplan.precomputed[offs+0]; + c2 = curplan.precomputed[offs+1]; + a0x = (*a)[aoffset+0]; + a0y = (*a)[aoffset+1]; + a1x = (*a)[aoffset+2]; + a1y = (*a)[aoffset+3]; + a2x = (*a)[aoffset+4]; + a2y = (*a)[aoffset+5]; + t1x = a1x+a2x; + t1y = a1y+a2y; + a0x = a0x+t1x; + a0y = a0y+t1y; + m1x = c1*t1x; + m1y = c1*t1y; + m2x = c2*(a1y-a2y); + m2y = c2*(a2x-a1x); + s1x = a0x+m1x; + s1y = a0y+m1y; + a1x = s1x+m2x; + a1y = s1y+m2y; + a2x = s1x-m2x; + a2y = s1y-m2y; + (*a)[aoffset+0] = a0x; + (*a)[aoffset+1] = a0y; + (*a)[aoffset+2] = a1x; + (*a)[aoffset+3] = a1y; + (*a)[aoffset+4] = a2x; + (*a)[aoffset+5] = a2y; + return; + } + if( n==4 ) { + a0x = (*a)[aoffset+0]; + a0y = (*a)[aoffset+1]; + a1x = (*a)[aoffset+2]; + a1y = (*a)[aoffset+3]; + a2x = (*a)[aoffset+4]; + a2y = (*a)[aoffset+5]; + a3x = (*a)[aoffset+6]; + a3y = (*a)[aoffset+7]; + t1x = a0x+a2x; + t1y = a0y+a2y; + t2x = a1x+a3x; + t2y = a1y+a3y; + m2x = a0x-a2x; + m2y = a0y-a2y; + m3x = a1y-a3y; + m3y = a3x-a1x; + (*a)[aoffset+0] = t1x+t2x; + (*a)[aoffset+1] = t1y+t2y; + (*a)[aoffset+4] = t1x-t2x; + (*a)[aoffset+5] = t1y-t2y; + (*a)[aoffset+2] = m2x+m3x; + (*a)[aoffset+3] = m2y+m3y; + (*a)[aoffset+6] = m2x-m3x; + (*a)[aoffset+7] = m2y-m3y; + return; + } + if( n==5 ) { + offs = curplan.plan[entryoffset+7]; + c1 = curplan.precomputed[offs+0]; + c2 = curplan.precomputed[offs+1]; + c3 = curplan.precomputed[offs+2]; + c4 = curplan.precomputed[offs+3]; + c5 = curplan.precomputed[offs+4]; + t1x = (*a)[aoffset+2]+(*a)[aoffset+8]; + t1y = (*a)[aoffset+3]+(*a)[aoffset+9]; + t2x = (*a)[aoffset+4]+(*a)[aoffset+6]; + t2y = (*a)[aoffset+5]+(*a)[aoffset+7]; + t3x = (*a)[aoffset+2]-(*a)[aoffset+8]; + t3y = (*a)[aoffset+3]-(*a)[aoffset+9]; + t4x = (*a)[aoffset+6]-(*a)[aoffset+4]; + t4y = (*a)[aoffset+7]-(*a)[aoffset+5]; + t5x = t1x+t2x; + t5y = t1y+t2y; + (*a)[aoffset+0] = (*a)[aoffset+0]+t5x; + (*a)[aoffset+1] = (*a)[aoffset+1]+t5y; + m1x = c1*t5x; + m1y = c1*t5y; + m2x = c2*(t1x-t2x); + m2y = c2*(t1y-t2y); + m3x = -c3*(t3y+t4y); + m3y = c3*(t3x+t4x); + m4x = -c4*t4y; + m4y = c4*t4x; + m5x = -c5*t3y; + m5y = c5*t3x; + s3x = m3x-m4x; + s3y = m3y-m4y; + s5x = m3x+m5x; + s5y = m3y+m5y; + s1x = (*a)[aoffset+0]+m1x; + s1y = (*a)[aoffset+1]+m1y; + s2x = s1x+m2x; + s2y = s1y+m2y; + s4x = s1x-m2x; + s4y = s1y-m2y; + (*a)[aoffset+2] = s2x+s3x; + (*a)[aoffset+3] = s2y+s3y; + (*a)[aoffset+4] = s4x+s5x; + (*a)[aoffset+5] = s4y+s5y; + (*a)[aoffset+6] = s4x-s5x; + (*a)[aoffset+7] = s4y-s5y; + (*a)[aoffset+8] = s2x-s3x; + (*a)[aoffset+9] = s2y-s3y; + return; + } + } + if( curplan.plan[entryoffset+3]==ftbase_fhtcodeletplan ) { + n1 = curplan.plan[entryoffset+1]; + n2 = curplan.plan[entryoffset+2]; + n = n1*n2; + if( n==2 ) { + a0x = (*a)[aoffset+0]; + a1x = (*a)[aoffset+1]; + (*a)[aoffset+0] = a0x+a1x; + (*a)[aoffset+1] = a0x-a1x; + return; + } + if( n==3 ) { + offs = curplan.plan[entryoffset+7]; + c1 = curplan.precomputed[offs+0]; + c2 = curplan.precomputed[offs+1]; + a0x = (*a)[aoffset+0]; + a1x = (*a)[aoffset+1]; + a2x = (*a)[aoffset+2]; + t1x = a1x+a2x; + a0x = a0x+t1x; + m1x = c1*t1x; + m2y = c2*(a2x-a1x); + s1x = a0x+m1x; + (*a)[aoffset+0] = a0x; + (*a)[aoffset+1] = s1x-m2y; + (*a)[aoffset+2] = s1x+m2y; + return; + } + if( n==4 ) { + a0x = (*a)[aoffset+0]; + a1x = (*a)[aoffset+1]; + a2x = (*a)[aoffset+2]; + a3x = (*a)[aoffset+3]; + t1x = a0x+a2x; + t2x = a1x+a3x; + m2x = a0x-a2x; + m3y = a3x-a1x; + (*a)[aoffset+0] = t1x+t2x; + (*a)[aoffset+1] = m2x-m3y; + (*a)[aoffset+2] = t1x-t2x; + (*a)[aoffset+3] = m2x+m3y; + return; + } + if( n==5 ) { + offs = curplan.plan[entryoffset+7]; + c1 = curplan.precomputed[offs+0]; + c2 = curplan.precomputed[offs+1]; + c3 = curplan.precomputed[offs+2]; + c4 = curplan.precomputed[offs+3]; + c5 = curplan.precomputed[offs+4]; + t1x = (*a)[aoffset+1]+(*a)[aoffset+4]; + t2x = (*a)[aoffset+2]+(*a)[aoffset+3]; + t3x = (*a)[aoffset+1]-(*a)[aoffset+4]; + t4x = (*a)[aoffset+3]-(*a)[aoffset+2]; + t5x = t1x+t2x; + v0 = (*a)[aoffset+0]+t5x; + (*a)[aoffset+0] = v0; + m2x = c2*(t1x-t2x); + m3y = c3*(t3x+t4x); + s3y = m3y-c4*t4x; + s5y = m3y+c5*t3x; + s1x = v0+c1*t5x; + s2x = s1x+m2x; + s4x = s1x-m2x; + (*a)[aoffset+1] = s2x-s3y; + (*a)[aoffset+2] = s4x-s5y; + (*a)[aoffset+3] = s4x+s5y; + (*a)[aoffset+4] = s2x+s3y; + return; + } + } + if( curplan.plan[entryoffset+3]==ftbase_fftbluesteinplan ) { + n = curplan.plan[entryoffset+1]; + m = curplan.plan[entryoffset+4]; + offs = curplan.plan[entryoffset+7]; + for(int i=stackptr+2*n; i<=stackptr+2*m-1; i++) + curplan.stackbuf[i] = 0; + offsp = offs+2*m; + offsa = aoffset; + offsb = stackptr; + for(int i=0; i * a, int aoffset, int n1, int n2) { + int n, idx, offs; + double x, y, twxm1, twy, twbasexm1, twbasey, twrowxm1, twrowy, tmpx, tmpy, v; + int ftbase_ftbaseupdatetw = 4; + n = n1*n2; + v = -2*M_PI/n; + twbasexm1 = -2*sqr(sin(0.5*v)); + twbasey = sin(v); + twrowxm1 = 0; + twrowy = 0; + for(int i=0, j = 0; i<=n2-1; i++) { + twxm1 = 0; + twy = 0; + for(j=0; j<=n1-1; j++) { + idx = i*n1+j; + offs = aoffset+2*idx; + x = (*a)[offs+0]; + y = (*a)[offs+1]; + tmpx = x*twxm1-y*twy; + tmpy = x*twy+y*twxm1; + (*a)[offs+0] = x+tmpx; + (*a)[offs+1] = y+tmpy; + if( j & val) { + double v = 0., v1 = 0., v2 = 0., stddev = 0.; + int i, n = val.size(); + if (n < 2) + return false; + /* + * Mean + */ + for (i = 0; i < n; i++) + mean += val[i]; + mean /= n; + /* + * Variance (using corrected two-pass algorithm) + */ + for (i = 0; i < n; i++) + v1 += sqr(val[i] - mean); + for (i = 0; i < n; i++) + v2 += val[i] - mean; + v2 = sqr(v2) / n; + variance = (v1 - v2) / (n - 1); + if(variance < 0) + variance = 0.; + stddev = sqrt(variance); + /* + * Skewness and kurtosis + */ + if (stddev != 0) { + for (i = 0; i < n; i++) { + v = (val[i] - mean) / stddev; + v2 = sqr(v); + skewness = skewness + v2 * v; + kurtosis = kurtosis + sqr(v2); + } + skewness /= n; + kurtosis = kurtosis / n - 3.; + } + return true; +} diff --git a/pimath.h b/pimath.h old mode 100755 new mode 100644 index 45e11f83..94838ddd --- a/pimath.h +++ b/pimath.h @@ -1,20 +1,20 @@ /* - PIP - Platform Independent Primitives - Math - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + PIP - Platform Independent Primitives + Math + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program. If not, see . + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ #ifndef PIMATH_H @@ -22,18 +22,37 @@ #include "picontainers.h" #ifndef QNX -# include -# include +# include +# include #else -# include -# include -#endif -#ifdef CC_VC -#define M_PI 3.14159265358979323846 +# include +# include #endif -#define M_2PI 6.28318530717958647692 -#define M_PI_3 1.04719755119659774615 +#ifndef M_LN2 +# define M_LN2 0.69314718055994530942 +#endif +#ifndef M_LN10 +# define M_LN10 2.30258509299404568402 +#endif +#ifndef M_PI +# define M_PI 3.14159265358979323846 +#endif +#ifndef M_2PI +# define M_2PI 6.28318530717958647692 +#endif +#ifndef M_PI_3 +# define M_PI_3 1.04719755119659774615 +#endif +#ifndef M_2PI_3 +# define M_2PI_3 2.0943951023931954923 +#endif +#ifndef M_180_PI +# define M_180_PI 57.2957795130823208768 +#endif +#ifndef M_PI_180 +# define M_PI_180 1.74532925199432957692e-2 +#endif using std::complex; @@ -48,30 +67,47 @@ const complexd complexd_i(0., 1.); const complexd complexd_0(0.); const complexd complexd_1(1.); -const double deg2rad = atan(1.) / 45.; -const double rad2deg = 45. / atan(1.); +const double deg2rad = M_PI_180; +const double rad2deg = M_180_PI; inline int pow2(const int p) {return 1 << p;} inline double sqr(const double & v) {return v * v;} -inline double sinc(const double & v) {double t = M_PI * v; return sin(t) / t;} -inline complexd round(const complexd & c) {return complexd(round(c.real()), round(c.imag()));} +inline double sinc(const double & v) {if (v == 0.) return 1.; double t = M_PI * v; return sin(t) / t;} +inline complexd round(const complexd & c) {return complexd(piRound(c.real()), piRound(c.imag()));} inline complexd floor(const complexd & c) {return complexd(floor(c.real()), floor(c.imag()));} inline complexd ceil(const complexd & c) {return complexd(ceil(c.real()), ceil(c.imag()));} inline complexd atanc(const complexd & c) {return -complexd(-0.5, 1.) * log((complexd_1 + complexd_i * c) / (complexd_1 - complexd_i * c));} inline complexd asinc(const complexd & c) {return -complexd_i * log(complexd_i * c + sqrt(complexd_1 - c * c));} inline complexd acosc(const complexd & c) {return -complexd_i * log(c + complexd_i * sqrt(complexd_1 - c * c));} -#ifdef QNX +#if CC_GCC_VERSION <= 0x025F inline complexd tan(const complexd & c) {return sin(c) / cos(c);} inline complexd tanh(const complexd & c) {return sinh(c) / cosh(c);} inline complexd log2(const complexd & c) {return log(c) / M_LN2;} inline complexd log10(const complexd & c) {return log(c) / M_LN10;} -inline double j0(const double & v) {v;} +inline double j0(const double & v) {return v;} inline double j1(const double & v) {v;} -inline double jn(const int & n, const double & v) {v;} -inline double y0(const double & v) {v;} -inline double y1(const double & v) {v;} -inline double yn(const int & n, const double & v) {v;} +inline double jn(const int & n, const double & v) {return v;} +inline double y0(const double & v) {return v;} +inline double y1(const double & v) {return v;} +inline double yn(const int & n, const double & v) {return v;} #endif +inline double toDb(double val) {return 10. * log10(val);} +inline double fromDb(double val) {return pow(10., val / 10.);} +inline double toRad(double deg) {return deg * M_PI_180;} +inline double toDeg(double rad) {return rad * M_180_PI;} + +inline PIVector abs(const PIVector &v) { + PIVector result; + result.resize(v.size()); + for(uint i=0; i abs(const PIVector &v) { + PIVector result; + result.resize(v.size()); + for(uint i=0; i class PIMathMatrixT; @@ -103,7 +139,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 acos(angleCos(v)) * rad2deg;} + Type angleDeg(const _CVector & v) const {return toGrad(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;} @@ -404,7 +440,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 acos(angleCos(v)) * rad2deg;} + Type angleDeg(const _CVector & v) const {return toGrad(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;} @@ -624,7 +660,7 @@ inline std::ostream & operator <<(std::ostream & s, const PIMathMatrix & m /// Multiply matrices {CR x Rows0} on {Cols1 x CR}, result is {Cols1 x Rows0} template inline PIMathMatrix operator *(const PIMathMatrix & fm, - const PIMathMatrix & sm) { + const PIMathMatrix & sm) { uint cr = fm.cols(), rows0 = fm.rows(), cols1 = sm.cols(); PIMathMatrix tm(cols1, rows0); if (fm.cols() != sm.rows()) return tm; @@ -643,7 +679,7 @@ inline PIMathMatrix operator *(const PIMathMatrix & fm, /// Multiply matrix {Cols x Rows} on vector {Cols}, result is vector {Rows} template inline PIMathVector operator *(const PIMathMatrix & fm, - const PIMathVector & sv) { + const PIMathVector & sv) { uint c = fm.cols(), r = fm.rows(); PIMathVector tv(r); if (c != sv.size()) return tv; @@ -669,13 +705,6 @@ typedef PIMathMatrix PIMathMatrixd; #undef PIMM_FOR_R -/* - Fast Fourier Transformation: direct (complement= false) - and complement (complement = true). 'x' is data source. - 'x' contains 2^T items. -*/ -void fft(complexd * x, int T, bool complement); - /// Differential evaluations struct TransferFunction { // Для задания передаточной функции @@ -691,18 +720,18 @@ class Solver { public: enum Method {Global = -1, - Eyler_1 = 01, - Eyler_2 = 02, - EylerKoshi = 03, - RungeKutta_4 = 14, - AdamsBashfortMoulton_2 = 22, - AdamsBashfortMoulton_3 = 23, - AdamsBashfortMoulton_4 = 24, - PolynomialApproximation_2 = 32, - PolynomialApproximation_3 = 33, - PolynomialApproximation_4 = 34, - PolynomialApproximation_5 = 35 - }; + Eyler_1 = 01, + Eyler_2 = 02, + EylerKoshi = 03, + RungeKutta_4 = 14, + AdamsBashfortMoulton_2 = 22, + AdamsBashfortMoulton_3 = 23, + AdamsBashfortMoulton_4 = 24, + PolynomialApproximation_2 = 32, + PolynomialApproximation_3 = 33, + PolynomialApproximation_4 = 34, + PolynomialApproximation_5 = 35 + }; Solver() {times.resize(4); step = 0;} @@ -744,4 +773,68 @@ private: }; + +class PIFFT +{ +public: + PIFFT(); + // const PIVector & getIndexes() {return indexes;} + // const PIVector & getCoefs() {return coefs;} + PIVector * calcFFT(const PIVector &val); + PIVector * calcFFT(const PIVector &val); + PIVector * calcFFTinverse(const PIVector &val); + PIVector * calcHilbert(const PIVector &val); + PIVector getAmplitude(); +private: + // PIVector indexes; + // PIVector coefs; + PIVector result; + // uint iterations; + bool prepared; + // uint out_size; + typedef ptrdiff_t ae_int_t; + void calc_coefs(uint cnt2); + void calc_indexes(uint cnt2, uint deep2); + complexd coef(uint n, uint k); + + struct ftplan { + PIVector plan; + PIVector precomputed; + PIVector tmpbuf; + PIVector stackbuf; + }; + + ftplan curplan; + + void fftc1d(const PIVector &a, uint n); + void fftc1r(const PIVector &a, uint n); + void fftc1dinv(const PIVector &a, uint n); + + void createPlan(uint n); + void ftbasegeneratecomplexfftplan(uint n, ftplan *plan); + void ftbase_ftbasegenerateplanrec(int n, int tasktype, ftplan *plan, int *plansize, int *precomputedsize, int *planarraysize, int *tmpmemsize, int *stackmemsize, ae_int_t stackptr, int debugi=0); + void ftbase_ftbaseprecomputeplanrec(ftplan *plan, int entryoffset, ae_int_t stackptr); + void ftbasefactorize(int n, int *n1, int *n2); + void ftbase_ftbasefindsmoothrec(int n, int seed, int leastfactor, int *best); + int ftbasefindsmooth(int n); + void ftbaseexecuteplan(PIVector *a, int aoffset, int n, ftplan *plan); + void ftbaseexecuteplanrec(PIVector *a, int aoffset, ftplan *plan, int entryoffset, ae_int_t stackptr); + void ftbase_internalcomplexlintranspose(PIVector *a, int m, int n, int astart, PIVector *buf); + void ftbase_ffticltrec(PIVector *a, int astart, int astride, PIVector *b, int bstart, int bstride, int m, int n); + void ftbase_internalreallintranspose(PIVector *a, int m, int n, int astart, PIVector *buf); + void ftbase_fftirltrec(PIVector *a, int astart, int astride, PIVector *b, int bstart, int bstride, int m, int n); + void ftbase_ffttwcalc(PIVector *a, int aoffset, int n1, int n2); +}; + + +class PIStatistic { +public: + PIStatistic(); + bool calculate(const PIVector &val); + double mean; + double variance; + double skewness; + double kurtosis; +}; + #endif // PIMATH_H diff --git a/pimonitor.cpp b/pimonitor.cpp old mode 100755 new mode 100644 index 9ded81ad..f4a666b3 --- a/pimonitor.cpp +++ b/pimonitor.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Counter of some PIP types - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pimonitor.h b/pimonitor.h old mode 100755 new mode 100644 index 486f86b9..34aab13a --- a/pimonitor.h +++ b/pimonitor.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Counter of some PIP types - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pimultiprotocol.h b/pimultiprotocol.h old mode 100755 new mode 100644 index 7fe7d6e7..c045de1b --- a/pimultiprotocol.h +++ b/pimultiprotocol.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Multiprotocol - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -81,9 +81,9 @@ public: PIString secondChannelName() {if (count() == 2) return protocol(1)->receiverDeviceName() + " -> " + protocol(0)->senderDeviceName(); return "Config error";} ullong receiveCount() {if (count() == 2) return protocol(0)->receiveCount(); return 0;} - ullong * receiveCount_ptr() {if (count() == 2) return protocol(0)->receiveCount_ptr(); return 0;} + const ullong * receiveCount_ptr() {if (count() == 2) return protocol(0)->receiveCount_ptr(); return 0;} ullong sendCount() {if (count() == 2) return protocol(0)->sendCount(); return 0;} - ullong * sendCount_ptr() {if (count() == 2) return protocol(0)->sendCount_ptr(); return 0;} + const ullong * sendCount_ptr() {if (count() == 2) return protocol(0)->sendCount_ptr(); return 0;} private: void received(PIProtocol * prot, bool , uchar * data, int size) {if (prot == protocol(0)) protocol(1)->send(data, size); else protocol(0)->send(data, size);} diff --git a/pimutex.h b/pimutex.h old mode 100755 new mode 100644 index dba34ec0..43d5930e --- a/pimutex.h +++ b/pimutex.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Mutex - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/piobject.cpp b/piobject.cpp old mode 100755 new mode 100644 index 3674cdc2..fb0d61d5 --- a/piobject.cpp +++ b/piobject.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -36,4 +36,4 @@ PIStringList PIObject::eventHandlers() { l << (*i).first; return l; } -*/ \ No newline at end of file +*/ diff --git a/piobject.h b/piobject.h old mode 100755 new mode 100644 index 826e9732..8005898f --- a/piobject.h +++ b/piobject.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,37 +22,62 @@ #include "pistring.h" -//#ifdef CC_VC -//#define HANDLER(c,s) #s,PIObject::handlerPtr((void(c::*)())&c::s) -//#else -//#define HANDLER(c,s) #s,(void*)&c::s -//#endif - -//#define EVENT_HANDLER0(obj, name) static void __stat_##name##__(obj * o) {o->name();} void name() -//#define EVENT_HANDLER1(obj, name, a0, n0) static void __stat_##name##__(obj * o, a0 n0) {o->name(n0);} void name(a0 n0) -//#define EVENT_HANDLER2(obj, name, a0, n0, a1, n1) static void __stat_##name##__(obj * o, a0 n0, a1 n1) {o->name(n0, n1);} void name(a0 n0, a1 n1) - -#define EVENT_HANDLER0(obj, ret, name) static ret __stat_##name##__(void * o) {return ((obj*)o)->name();} ret name() -#define EVENT_HANDLER1(obj, ret, name, a0, n0) static ret __stat_##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_##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_##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_##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) +/// 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) #define EVENT_HANDLER EVENT_HANDLER0 -#define EVENT_VHANDLER0(obj, ret, name) static ret __stat_##name##__(void * o) {return ((obj*)o)->name();} virtual ret name() -#define EVENT_VHANDLER1(obj, ret, name, a0, n0) static ret __stat_##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_##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_##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_##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) +/// 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) #define EVENT_VHANDLER EVENT_VHANDLER0 -#define CONNECT0(ret, src, event, dst, handler) PIObject::connect(src, #event, dst, (void*)(ret(*)(void*))(&(dst)->__stat_##handler##__)); -#define CONNECT1(ret, a0, src, event, dst, handler) PIObject::connect(src, #event, dst, (void*)(ret(*)(void*, a0))(&(dst)->__stat_##handler##__)); -#define CONNECT2(ret, a0, a1, src, event, dst, handler) PIObject::connect(src, #event, dst, (void*)(ret(*)(void*, a0, a1))(&(dst)->__stat_##handler##__)); -#define CONNECT3(ret, a0, a1, a2, src, event, dst, handler) PIObject::connect(src, #event, dst, (void*)(ret(*)(void*, a0, a1, a2))(&(dst)->__stat_##handler##__)); -#define CONNECT4(ret, a0, a1, a2, a3, src, event, dst, handler) PIObject::connect(src, #event, dst, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dst)->__stat_##handler##__)); +/// 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);} +#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); +#define RAISE_EVENT3(src, event, v0, v1, v2) (src)->event(v0, v1, v2); +#define RAISE_EVENT4(src, event, v0, v1, v2, v3) (src)->event(v0, v1, v2, v3); +#define RAISE_EVENT RAISE_EVENT0 + +/// 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 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_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 DISCONNECT DISCONNECT0 + class PIObject { friend class PIObjectManager; @@ -109,24 +134,34 @@ public: } */ /// Direct connect - static void connect(PIObject * src, const PIString & sig, void * dest, void * ev_h) {src->connections << Connection(ev_h, sig, dest);} - //static void connect(PIObject & src, const PIString & sig, PIObject * dest, void * ev_h) {src.connections << Connection(ev_h, sig, dest);} - //static void connect(PIObject * src, const PIString & sig, PIObject & dest, void * ev_h) {src->connections << Connection(ev_h, sig, &dest);} - //static void connect(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, 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) { + for (int i = 0; i < src->connections.size_s(); ++i) { + Connection & cc(src->connections[i]); + if (cc.event == sig && cc.dest == dest && cc.slot == ev_h) { + src->connections.remove(i); + i--; + } + } + } + //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);} /*/// Connect through manager - static bool connect(const PIString & srcObject, const PIString & event, const PIString & destObject, const PIString & handler, bool force = false) { + static bool piConnect(const PIString & srcObject, const PIString & event, const PIString & destObject, const PIString & handler, bool force = false) { PIObject * src = findByName(srcObject); if (src == 0) { - cout << "PIObject::connect: can`t find PIObject with \"" << srcObject << "\" name!" << endl; + cout << "PIObject::piConnect: can`t find PIObject with \"" << srcObject << "\" name!" << endl; return false; } PIObject * dest = findByName(destObject); if (dest == 0) { - cout << "PIObject::connect: can`t find PIObject with \"" << destObject << "\" name!" << endl; + cout << "PIObject::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl; return false; } - return PIObject::connect(src, event, dest, handler, force); + return PIObject::piConnect(src, event, dest, handler, force); }*/ /// Raise events @@ -195,7 +230,7 @@ public: static void raiseEvent(const PIString & destObject, const PIString & name) { PIObject * dest = findByName(destObject); if (dest == 0) { - cout << "PIObject::connect: can`t find PIObject with \"" << destObject << "\" name!" << endl; + cout << "PIObject::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl; return; } raiseEvent(dest, name); @@ -204,7 +239,7 @@ public: static void raiseEvent(const PIString & destObject, const PIString & name, const T0 & v0 = T0()) { PIObject * dest = findByName(destObject); if (dest == 0) { - cout << "PIObject::connect: can`t find PIObject with \"" << destObject << "\" name!" << endl; + cout << "PIObject::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl; return; } raiseEvent(dest, name, v0); @@ -213,7 +248,7 @@ public: static void raiseEvent(const PIString & destObject, const PIString & name, const T0 & v0 = T0(), const T1 & v1 = T1()) { PIObject * dest = findByName(destObject); if (dest == 0) { - cout << "PIObject::connect: can`t find PIObject with \"" << destObject << "\" name!" << endl; + cout << "PIObject::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl; return; } raiseEvent(dest, name, v0, v1); @@ -222,7 +257,7 @@ public: static void raiseEvent(const PIString & destObject, const PIString & name, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2()) { PIObject * dest = findByName(destObject); if (dest == 0) { - cout << "PIObject::connect: can`t find PIObject with \"" << destObject << "\" name!" << endl; + cout << "PIObject::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl; return; } raiseEvent(name, dest, v0, v1, v2); @@ -231,21 +266,24 @@ public: static void raiseEvent(const PIString & destObject, const PIString & name, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2(), const T3 & v3 = T3()) { PIObject * dest = findByName(destObject); if (dest == 0) { - cout << "PIObject::connect: can`t find PIObject with \"" << destObject << "\" name!" << endl; + cout << "PIObject::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl; return; } raiseEvent(name,dest , v0, v1, v2, v3); } +protected: + PIString name_; + private: struct Connection { - Connection(void * s = 0, const PIString & e = PIString(), void * o = 0) {slot = s; event = e; dest = o;} + Connection(void * sl = 0, void * si = 0, const PIString & e = PIString(), void * o = 0) {slot = sl; signal = si; event = e; dest = o;} void * slot; + void * signal; PIString event; void * dest; }; - PIString name_; PIVector connections; static PIVector objects; diff --git a/pip.h b/pip.h old mode 100755 new mode 100644 index eba95202..bd1fb55b --- a/pip.h +++ b/pip.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives All includes - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,3 +27,5 @@ #include "pisignals.h" #include "piobject.h" #include "pisystemmonitor.h" +#include "pipeer.h" +#include "picrc.h" diff --git a/pipacketextractor.cpp b/pipacketextractor.cpp index a68c2883..a24738da 100644 --- a/pipacketextractor.cpp +++ b/pipacketextractor.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Packets extractor - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,9 +23,10 @@ PIPacketExtractor::PIPacketExtractor(PIIODevice * device_, void * recHeaderPtr, int recHeaderSize, int recDataSize) { ret_func_header = 0; setPacketData(recHeaderPtr, recHeaderSize, recDataSize); - setBufferSize(4096); + setThreadedReadBufferSize(65536); + setBufferSize(65536); setDevice(device_); - allReaded = addSize = curInd = 0; + allReaded = addSize = curInd = missed = 0; } @@ -55,7 +56,8 @@ bool PIPacketExtractor::threadedRead(uchar * readed, int size_) { return true; } } - memcpy(mheader.data(), buffer.data(curInd + headerSize), headerSize); + memcpy(mheader.data(), buffer.data(curInd), headerSize); + if (headerPtr != 0) memcpy(headerPtr, buffer.data(curInd), headerSize); if (!packetValidate(buffer.data(curInd + headerSize), dataSize)) { curInd++; missed++; if (packetSize > 0) missed_packets = missed / packetSize; @@ -66,10 +68,17 @@ bool PIPacketExtractor::threadedRead(uchar * readed, int size_) { allReaded -= packetSize + curInd; curInd = addSize = 0; } else { - packetValidate(buffer.data(), dataSize); - memcpy(sbuffer.data(), buffer.data(), allReaded); - memcpy(buffer.data(), sbuffer.data(packetSize), allReaded); - allReaded -= packetSize; + if (dataSize == 0) { + packetValidate(buffer.data(), size_); + memcpy(sbuffer.data(), buffer.data(), allReaded); + memcpy(buffer.data(), sbuffer.data(size_), allReaded); + allReaded -= size_; + } else { + packetValidate(buffer.data(), dataSize); + memcpy(sbuffer.data(), buffer.data(), allReaded); + memcpy(buffer.data(), sbuffer.data(packetSize), allReaded); + allReaded -= packetSize; + } } return true; } diff --git a/pipacketextractor.h b/pipacketextractor.h index 38bdb2cb..a293caa6 100644 --- a/pipacketextractor.h +++ b/pipacketextractor.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Packets extractor - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,18 +30,19 @@ class PIPacketExtractor: public PIIODevice { public: PIPacketExtractor(PIIODevice * device_ = 0, void * recHeaderPtr = 0, int recHeaderSize = 0, int recDataSize = 0); + virtual ~PIPacketExtractor() {} PIIODevice * device() {return dev;} void setDevice(PIIODevice * device_); int bufferSize() const {return buffer_size;} - void setBufferSize(int new_size) {buffer_size = new_size; buffer.resize(buffer_size); sbuffer.resize(buffer_size);} + void setBufferSize(int new_size) {buffer_size = new_size; buffer.resize(buffer_size); sbuffer.resize(buffer_size); memset(buffer.data(), 0, buffer.size()); memset(sbuffer.data(), 0, sbuffer.size());} void setHeaderCheckSlot(HeaderCheckFunc f) {ret_func_header = f;} void setPacketData(void * recHeaderPtr, int recHeaderSize, int recDataSize) {headerPtr = recHeaderPtr; headerSize = recHeaderSize; dataSize = recDataSize; packetSize = headerSize + dataSize; if (headerSize > 0) mheader.resize(headerSize);} ullong missedBytes() const {return missed;} - ullong missedPackets() const {return missed / packetSize;} + ullong missedPackets() const {if (packetSize == 0) return missed; return missed / packetSize;} const ullong * missedBytes_ptr() const {return &missed;} const ullong * missedPackets_ptr() const {return &missed_packets;} @@ -56,7 +57,7 @@ protected: private: bool threadedRead(uchar * readed, int size); - bool openDevice() {if (dev == 0) return false; return dev->isOpened();} + bool openDevice() {if (dev == 0) return false; return dev->open();} PIIODevice * dev; PIByteArray mheader, buffer, sbuffer; diff --git a/pipeer.cpp b/pipeer.cpp new file mode 100644 index 00000000..d48de099 --- /dev/null +++ b/pipeer.cpp @@ -0,0 +1,186 @@ +/* + PIP - Platform Independent Primitives + Peer - named I/O ethernet node + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pipeer.h" + + +PIPeer::PIPeer(const PIString & name): PIEthernet() { + setName(name); + setParameter(PIEthernet::Broadcast); + setReadPort(13312); + setSendPort(13312); + srand(uint(PITimer::elapsed_system_m())); + //id_ = name() + "_" + PIString::fromNumber(rand()); + CONNECT2(void, void * , int, &timer, timeout, this, timerEvent); + + PIEthernet * ce; + PIStringList sl = PIEthernet::allAddresses(); + PIString ta; + self_info.name = name_; + self_info.dist = 0; + piForeachC (PIString & i, sl) { + ce = new PIEthernet(this, func_readed); + ce->setReadAddress(i, 13313); + eths << ce; + ce->startThreadedRead(); + self_info.addresses << i; + //cout << i << ": " << ta << endl; + } + eth_send = new PIEthernet(); + eth_send->initialize(); + + startThreadedRead(); + //joinMulticastGroup("239.13.3.12"); + //timer.addDelimiter(5); + timer.start(1000); + sendSelfInfo(); +} + + +PIPeer::~PIPeer() { + terminate(); + sendSelfRemove(); + //leaveMulticastGroup("239.13.3.12"); + delete eth_send; + piForeach (PIEthernet * i, eths) + delete i; + eths.clear(); +} + + +void PIPeer::timerEvent(void * data, int delim) { + switch (delim) { + case 1: // 5 s + syncPeers(); + break; + } + //send("broadcast", 9); +} + + +bool PIPeer::threadedRead(uchar * data, int size) { + int header; + PeerInfo pi; + PIByteArray ba(data, size); + PIVector rpeers; + ba >> header >> pi.name; + if (pi.name == name_) return true; + switch (header) { + case 1: // new peer accepted + if (hasPeer(pi.name)) break; + ba >> pi.dist >> pi.addresses; + pi.sync = 0; + peers << pi; + cout << "[PIPeer \"" + name_ + "\"] new peer \"" << pi.name << "\"" << " dist " << pi.dist << endl; + pi.dist++; + sendSelfInfo(); + sendPeerInfo(pi); + findNearestAddresses(); + break; + case 2: // remove peer accepted + if (removePeer(pi.name)) { + cout << "[PIPeer \"" + name_ + "\"] remove peer \"" << pi.name << "\"" << endl; + sendPeerRemove(pi.name); + findNearestAddresses(); + } + break; + case 3: // sync peers + ba >> pi.addresses >> rpeers; + rpeers << pi; + //cout << "[PIPeer \"" + name_ + "\"] rec sync " << rpeers.size_s() << " peers" << endl; + for (uint i = 0; i < rpeers.size(); ++i) { + PeerInfo & rpeer(rpeers[i]); + //cout << " to sync " << rpeer.name << endl; + if (rpeer.name == name_) continue; + bool exist = false; + for (uint j = 0; j < peers.size(); ++j) { + PeerInfo & peer(peers[j]); + if (peer.name == rpeer.name) { + //cout << "synced " << peer.name << endl; + peer.addresses == rpeer.addresses; + if (peer.name == pi.name) peer.sync = 0; + exist = true; + break; + } + } + if (exist) continue; + peers << rpeer; + peers.back().dist++; + findNearestAddresses(); + } + break; + } + return true; +} + + +bool PIPeer::func_readed(void * peer, uchar * data, int size) { + PIPeer * p = (PIPeer * )peer; + cout << "[PIPeer \"" + p->name_ + "\"] received " << data << endl; + return true; +} + + +void PIPeer::sendPeerInfo(const PeerInfo & info) { + PIByteArray ba; + ba << int(1) << info.name << info.dist << info.addresses; + write(ba); +} + + +void PIPeer::sendPeerRemove(const PIString & peer) { + PIByteArray ba; + ba << int(2) << peer; + write(ba); +} + + +void PIPeer::syncPeers() { + //cout << "[PIPeer \"" + name_ + "\"] sync " << peers.size_s() << " peers" << endl; + PIString pn; + for (uint i = 0; i < peers.size(); ++i) { + PeerInfo & cp(peers[i]); + if (cp.sync > 1 && cp.dist == 0) { + pn = cp.name; + cout << "[PIPeer \"" + name_ + "\"] sync: remove " << pn << endl; + peers.remove(i); + sendPeerRemove(pn); + --i; + findNearestAddresses(); + continue; + } + cp.sync++; + } + PIByteArray ba; + ba << int(3) << self_info.name << self_info.addresses << peers; + write(ba); +} + + +void PIPeer::findNearestAddresses() { + cout << "[PIPeer \"" + name_ + "\"] findNearestAddresses" << endl; + int max_dist = -1; + piForeach (PeerInfo & i, peers) + if (max_dist < i.dist) + max_dist = i.dist; + PIVector cwave; + for (int d = 0; d <= max_dist; ++d) { + //if () + } +} diff --git a/pipeer.h b/pipeer.h new file mode 100644 index 00000000..db39a9b1 --- /dev/null +++ b/pipeer.h @@ -0,0 +1,81 @@ +/* + PIP - Platform Independent Primitives + Peer - named I/O ethernet node + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIPEER_H +#define PIPEER_H + +#include "piethernet.h" + +class PIPeer: public PIEthernet +{ + struct PeerInfo; + friend PIByteArray & operator <<(PIByteArray & s, const PIPeer::PeerInfo & v); + friend PIByteArray & operator >>(PIByteArray & s, PIPeer::PeerInfo & v); +public: + PIPeer(const PIString & name); + ~PIPeer(); + + //const PIString & id() const {return id_;} + +protected: + bool threadedRead(uchar * readed, int size); + +private: + EVENT_HANDLER2(PIPeer, void, timerEvent, void * , data, int, delim); + static bool func_readed(void * peer, uchar * data, int size); + + struct PeerInfo { + PIString name; + PIString nearest_address; + PIStringList addresses; + int dist; + int sync; + int _wave; + }; + + + bool hasPeer(const PIString & name) {piForeachC (PeerInfo & i, peers) if (i.name == name) return true; return false;} + bool removePeer(const PIString & name) {for (uint i = 0; i < peers.size(); ++i) if (peers[i].name == name) {peers.remove(i); return true;} return false;} + + void sendPeerInfo(const PeerInfo & info); + void sendPeerRemove(const PIString & peer); + void sendSelfInfo() {sendPeerInfo(self_info);} + void sendSelfRemove() {sendPeerRemove(name_);} + void syncPeers(); + void findNearestAddresses(); + + struct PeerPacket { + int header; // 1 - new peer, 2 - remove peer, 3 - sync peers + + }; + + PIList eths; + PIEthernet * eth_send; + PITimer timer; + + PeerInfo self_info; + PIVector peers; + //PIString id_; + +}; + +inline PIByteArray & operator <<(PIByteArray & s, const PIPeer::PeerInfo & v) {s << v.name << v.addresses << v.dist; return s;} +inline PIByteArray & operator >>(PIByteArray & s, PIPeer::PeerInfo & v) {s >> v.name >> v.addresses >> v.dist; return s;} + +#endif // PIPEER_H diff --git a/piprocess.cpp b/piprocess.cpp old mode 100755 new mode 100644 index 1971858b..4d944be6 --- a/piprocess.cpp +++ b/piprocess.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Process - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -55,7 +55,7 @@ void PIProcess::run() { //cout << "run" << endl; string str; /// arguments convertion - int as = 0; + as = 0; #ifdef WINDOWS //args.pop_front(); piForeachC (PIString & i, args) @@ -96,30 +96,31 @@ void PIProcess::run() { f_in = PIFile::openTemporary(PIIODevice::ReadWrite); t_in = true; } - f_in.open(PIIODevice::ReadWrite); f_in.close(); + //f_in.open(PIIODevice::ReadWrite); f_in.close(); if (f_out.path().isEmpty()) { f_out = PIFile::openTemporary(PIIODevice::ReadWrite); t_out = true; } - f_out.open(PIIODevice::WriteOnly); f_out.close(); + //f_out.open(PIIODevice::WriteOnly); f_out.close(); if (f_err.path().isEmpty()) { f_err = PIFile::openTemporary(PIIODevice::ReadWrite); t_err = true; } - f_err.open(PIIODevice::WriteOnly); f_err.close(); + //f_err.open(PIIODevice::WriteOnly); f_err.close(); str = args.front().stdString(); is_exec = true; + execStarted(PIString(str)); #ifndef WINDOWS pid = fork(); if (pid == 0) { #endif - FILE * tf = 0; - //cout << "exec" << endl; + tf_in = tf_out = tf_err = 0; + //cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl; //cout << f_out.path() << endl; - if (g_in) tf = freopen(f_in.path().data(), "r", stdin); - if (g_out) tf = freopen(f_out.path().data(), "w", stdout); - if (g_err) tf = freopen(f_err.path().data(), "w", stderr); + if (g_in) tf_in = freopen(f_in.path().data(), "r", stdin); + if (g_out) tf_out = freopen(f_out.path().data(), "w", stdout); + if (g_err) tf_err = freopen(f_err.path().data(), "w", stderr); #ifndef WINDOWS if (!wd.isEmpty()) as = chdir(wd.data()); #endif @@ -142,16 +143,22 @@ void PIProcess::run() { } else piCout << "[PIProcess] \"CreateProcess\" error, " << errorString() << endl; #else + + //cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl; if (execve(str.c_str(), a, e) < 0) piCout << "[PIProcess] \"execve\" error, " << errorString() << endl; } else { msleep(1); //cout << "wait" << endl; wait(&exit_code); + /*if (tf_in != 0) fclose(tf_in); + if (tf_out != 0) fclose(tf_out); + if (tf_err != 0) fclose(tf_err);*/ pid = 0; //cout << "wait done" << endl; } #endif + execFinished(PIString(str), exit_code); is_exec = false; for (int i = 0; i < env.size_s(); ++i) delete e[i]; @@ -162,7 +169,7 @@ void PIProcess::run() { for (int i = 0; i < args.size_s(); ++i) delete a[i]; #endif - //cout << "end" << endl; + //cout << "end " << tf_in << ", " << tf_out << ", " << tf_err << endl; } diff --git a/piprocess.h b/piprocess.h old mode 100755 new mode 100644 index 0dd951e8..aa1ea544 --- a/piprocess.h +++ b/piprocess.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Process - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,6 +28,18 @@ # include #endif +/// events: +/// execStarted(PIString program) +/// execFinished(PIString program, int exit_code) +/// +/// handlers: +/// bool exec(const PIString & program) +/// bool exec(const PIString & program, const PIString & arg1) +/// bool exec(const PIString & program, const PIString & arg1, const PIString & arg2) +/// bool exec(const PIString & program, const PIString & arg1, const PIString & arg2, const PIString & arg3) +/// bool exec(const PIString & program, const PIStringList & args) +/// void terminate() +/// bool waitForFinish(int timeout_msecs = 60000) class PIProcess: private PIThread { public: @@ -53,17 +65,18 @@ public: PIString workingDirectory() const {return wd;} void setWorkingDirectory(const PIString & path) {wd = path;} void resetWorkingDirectory() {wd.clear();} - void exec(const PIString & program) {args.clear(); args << program; exec_();} - void exec(const PIString & program, const PIString & arg) {args.clear(); args << program << arg; exec_();} - void exec(const PIString & program, const PIString & arg1, const PIString & arg2) {args.clear(); args << program << arg1 << arg2; exec_();} - void exec(const PIString & program, const PIString & arg1, const PIString & arg2, const PIString & arg3) {args.clear(); args << program << arg1 << arg2 << arg3; exec_();} - void exec(const PIString & program, const PIStringList & args_) {args << program << args_; exec_();} + 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_();} #ifdef WINDOWS - void terminate() {if (is_exec) if (!TerminateProcess(pi.hProcess, 0)) return; pi.dwProcessId = 0;} + EVENT_HANDLER(PIProcess, void, terminate) {if (is_exec) if (!TerminateProcess(pi.hProcess, 0)) return; pi.dwProcessId = 0;} #else - void terminate() {if (is_exec) kill(pid, SIGKILL); pid = 0;} + EVENT_HANDLER(PIProcess, void, terminate) {if (is_exec) kill(pid, SIGKILL); pid = 0;} #endif - bool waitForFinish(int timeout_msecs = 60000) {return PIThread::waitForFinish(timeout_msecs);} + EVENT_HANDLER(PIProcess, bool, waitForFinish) {return waitForFinish(60000);} + EVENT_HANDLER1(PIProcess, 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();} @@ -79,6 +92,9 @@ public: static int currentPID() {return getpid();} #endif + EVENT1(PIProcess, execStarted, PIString, program) + EVENT2(PIProcess, execFinished, PIString, program, int, exit_code) + private: virtual void run(); void exec_(); @@ -94,7 +110,8 @@ private: #else pid_t pid; #endif - int exit_code, sz; + FILE * tf_in, * tf_out, * tf_err; + int exit_code, sz, as; bool is_exec; }; diff --git a/piprotocol.cpp b/piprotocol.cpp old mode 100755 new mode 100644 index 357ad9c1..5889313e --- a/piprotocol.cpp +++ b/piprotocol.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Protocol, input/output channel (COM, UDP) - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -33,7 +33,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re int ps, gps; bool ok, gok, flag, gflag, has_dev = false; float freq, gfreq; - PIFlags pp; + PIFlags pp(0); PIConfig::Entry & b(conf.getValue(name)), & rb(b.getValue("receiver")), & sb(b.getValue("sender")); @@ -65,7 +65,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re } type_rec = PIProtocol::Ethernet; eth = new PIEthernet(); - packet_ext.setDevice(eth); + packet_ext->setDevice(eth); //setSenderAddress(dev, ps); setReceiverAddress(dev, ps); has_dev = true; @@ -128,7 +128,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re devReceiverState = "Config error"; return; } - pp |= PISerial::ParityControl; + pp.setFlag(PISerial::ParityControl, flag); } flag = rb.getValue("twoStopBits", false, &ok); gflag = b.getValue("twoStopBits", false, &gok); @@ -139,12 +139,12 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re devReceiverState = "Config error"; return; } - pp |= PISerial::TwoStopBits; + pp.setFlag(PISerial::TwoStopBits, flag); } type_rec = PIProtocol::Serial; type_send = PIProtocol::Serial; ser = new PISerial(dev); - packet_ext.setDevice(ser); + packet_ext->setDevice(ser); //setSenderDevice(dev, (PISerial::Speed)ps); setReceiverDevice(dev, (PISerial::Speed)ps); ser->setInSpeed((PISerial::Speed)ps); @@ -297,7 +297,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re devSenderState = "Config error"; return; } - pp |= PISerial::ParityControl; + pp.setFlag(PISerial::ParityControl, flag); } flag = sb.getValue("twoStopBits", false, &ok); gflag = b.getValue("twoStopBits", false, &gok); @@ -308,7 +308,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re devSenderState = "Config error"; return; } - pp |= PISerial::TwoStopBits; + pp.setFlag(PISerial::TwoStopBits, flag); } } else { piCout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".sender.speed\" or \"" << name << ".speed\" in \"" << config << "\"!" << endl; @@ -365,14 +365,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re dataSize = recDataSize; sendDataPtr = (uchar * )sendDataPtr_; sendDataSize = sendDataSize_; - packet_ext.setPacketData(recHeaderPtr, recHeaderSize, recDataSize); - if (type_rec == PIProtocol::Ethernet) { - if (recHeaderPtr != 0) { - dataPtr = (uchar * )recHeaderPtr; - dataSize = recHeaderSize + recDataSize; - if (dataSize > 0) packet = new char[dataSize]; - } else if (recDataSize > 0) packet = new char[recDataSize]; - } else if (recHeaderSize + recDataSize > 0) packet = new char[recHeaderSize + recDataSize]; + packet_ext->setPacketData(recHeaderPtr, recHeaderSize, recDataSize); } @@ -394,16 +387,18 @@ PIProtocol::~PIProtocol() { } delete diagTimer; delete sendTimer; - if (packet != 0) delete packet; + delete secTimer; if (eth != 0) delete eth; if (ser != 0) delete ser; + delete packet_ext; } void PIProtocol::init() { - packet_ext.setThreadedReadData(this); - packet_ext.setThreadedReadSlot(receiveEvent); - packet_ext.setHeaderCheckSlot(headerValidateEvent); + packet_ext = new PIPacketExtractor(); + packet_ext->setThreadedReadData(this); + packet_ext->setThreadedReadSlot(receiveEvent); + packet_ext->setHeaderCheckSlot(headerValidateEvent); work = new_mp_prot = history_write_rec = history_write_send = false; eth = 0; ser = 0; @@ -412,18 +407,20 @@ void PIProtocol::init() { net_diag = PIProtocol::Unknown; cur_pckt = 0; diagTimer = 0; - packet = 0; timeout_ = 3.f; sendTimer = new PITimer(sendEvent, this); diagTimer = new PITimer(diagEvent, this); + secTimer = new PITimer(secEvent, this); wrong_count = receive_count = send_count = missed_count = 0; - immediate_freq = integral_freq = 0.f; + packets_in_sec = packets_out_sec = bytes_in_sec = bytes_out_sec = 0; + immediate_freq = integral_freq = ifreq = 0.f; headerPtr = dataPtr = sendDataPtr = 0; headerSize = dataSize = sendDataSize = 0; type_rec = type_send = PIProtocol::None; devSenderState = devReceiverState = "Unknown"; devSenderName = devReceiverName = "no device"; history_rsize_rec = history_rsize_send = "no file"; + secTimer->start(1000.); /*addEvent("receiver started"); addEvent("receiver stopped"); addEvent("sender started"); @@ -444,7 +441,7 @@ void PIProtocol::setReceiverDevice(const PIString & device, PISerial::Speed spee type_send = type_rec = PIProtocol::Serial; if (ser == 0) { ser = new PISerial(); - packet_ext.setDevice(ser); + packet_ext->setDevice(ser); } } if (type_rec == PIProtocol::Serial && ser != 0) { @@ -461,7 +458,7 @@ void PIProtocol::setReceiverAddress(const PIString & ip, int port, bool force) { type_rec = PIProtocol::Ethernet; if (eth == 0) { eth = new PIEthernet(); - packet_ext.setDevice(eth); + packet_ext->setDevice(eth); } } if (type_rec == PIProtocol::Ethernet && eth != 0) { @@ -493,13 +490,38 @@ void PIProtocol::setSenderAddress(const PIString & ip, int port, bool force) { } if (type_send == PIProtocol::Ethernet && eth != 0) { eth->setSendAddress(ip, port); - eth->open(); if (ip.isEmpty()) devSenderName = "no ip"; else devSenderName = ip + ":" + PIString::fromNumber(port); } } +void PIProtocol::setSenderIP(const PIString & ip, bool force) { + if (force) { + type_send = PIProtocol::Ethernet; + if (eth == 0) eth = new PIEthernet(); + } + if (type_send == PIProtocol::Ethernet && eth != 0) { + eth->setSendIP(ip); + if (ip.isEmpty()) devSenderName = "no ip"; + else devSenderName = ip + ":" + PIString::fromNumber(eth->sendPort()); + } +} + + +void PIProtocol::setSenderPort(int port, bool force) { + if (force) { + type_send = PIProtocol::Ethernet; + if (eth == 0) eth = new PIEthernet(); + } + if (type_send == PIProtocol::Ethernet && eth != 0) { + eth->setSendPort(port); + if (eth->sendIP().isEmpty()) devSenderName = "no ip"; + else devSenderName = eth->sendIP() + ":" + PIString::fromNumber(port); + } +} + + void PIProtocol::setExpectedFrequency(float frequency) { exp_freq = frequency; changeDisconnectTimeout(); @@ -517,29 +539,35 @@ void PIProtocol::startReceive(float exp_frequency) { if (exp_frequency > 0.f) exp_freq = exp_frequency; //if (type_rec == PIProtocol::Serial) ser->start(); //if (type_rec == PIProtocol::Ethernet) eth->start(); + packet_ext->startThreadedRead(); + msleep(1); + check_state(); if (exp_freq <= 0.f) return; - packet_ext.startThreadedRead(); setExpectedFrequency(exp_freq); diagTimer->start(1000. / exp_freq); diagTimer->reset(); - raiseEvent(this, "receiver started"); + receiverStarted(); } void PIProtocol::startSend(float frequency) { + //cout << "** start send " << send_freq << ", " << frequency << endl; if (frequency > 0.f) send_freq = frequency; + msleep(1); + check_state(); if (send_freq <= 0.f) return; sendTimer->start(1000. / send_freq); - raiseEvent(this, "sender started"); + diagTimer->reset(); + senderStarted(); } void PIProtocol::stopReceive() { //if (type_rec == PIProtocol::Serial) ser->stop(); //if (type_rec == PIProtocol::Ethernet) eth->stop(); - packet_ext.stop(); + packet_ext->stop(); diagTimer->stop(); - raiseEvent(this, "receiver stopped"); + receiverStopped(); } @@ -553,15 +581,20 @@ bool PIProtocol::receiveEvent(void * t, uchar * data, int size) { p->history_file_rec.writeToBinLog(p->history_id_rec, data, size); p->history_rsize_rec.setReadableSize(p->history_file_rec.pos()); } - raiseEvent(p, "received", true); + p->received(true); //p->unlock(); + p->ifreq = p->diagTimer->elapsed_m(); + if (p->ifreq > 0.) p->ifreq = 1000. / p->ifreq; + p->diagTimer->reset(); p->receive_count++; + p->packets_in_sec++; + p->bytes_in_sec += size; p->cur_pckt = 1; if (p->ret_func != 0) p->ret_func(p); if (p->mp_owner != 0) PIMultiProtocolBase::receiveEvent(p->mp_owner, p, true, data, size); return true; } - raiseEvent(p, "received", false); + p->received(false); //p->unlock(); p->wrong_count++; if (p->mp_owner != 0) PIMultiProtocolBase::receiveEvent(p->mp_owner, p, false, data, size); @@ -569,19 +602,21 @@ bool PIProtocol::receiveEvent(void * t, uchar * data, int size) { } -bool PIProtocol::headerValidateEvent(void * t, uchar * src, uchar * rec, int size) { - PIProtocol * p = (PIProtocol * )t; - //cout << "validate\n"; - return p->headerValidate(src, rec, size); -} - - void PIProtocol::diagEvent(void * t, int) { PIProtocol * p = (PIProtocol * )t; p->calc_freq(); p->calc_diag(); p->check_state(); - if (p->ser != 0) p->missed_count = p->packet_ext.missedPackets(); + if (p->ser != 0) p->missed_count = p->packet_ext->missedPackets(); +} + + +void PIProtocol::secEvent(void * t, int ) { + PIProtocol * p = (PIProtocol * )t; + p->speedIn = PIString::readableSize(p->bytes_in_sec) + "/s"; + p->speedOut = PIString::readableSize(p->bytes_out_sec) + "/s"; + p->bytes_in_sec = p->bytes_out_sec = p->packets_in_sec = p->packets_out_sec = 0; + if (p->ser != 0) p->missed_count = p->packet_ext->missedPackets(); } @@ -608,17 +643,16 @@ 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); net_diag = diag; - raiseEvent(this, "quality changed", diag); } } void PIProtocol::calc_freq() { - float tf = float(1000.f / diagTimer->elapsed_m()); - diagTimer->reset(); - if (cur_pckt != 1) tf = 0.f; - immediate_freq = tf; + float tf;// = float(1000.f / diagTimer->elapsed_m()); + tf = immediate_freq = ifreq; + ifreq = 0.f; if (last_freq.size_s() >= pckt_cnt_max && last_freq.size_s() > 0) last_freq.pop_front(); last_freq.push_back(tf); tf = last_freq[0]; @@ -670,11 +704,17 @@ void PIProtocol::send(const void * data, int size, bool direct) { history_rsize_send.setReadableSize(history_file_send.pos()); } if (type_send == PIProtocol::Serial) - if (ser->send(data, size)) + if (ser->send(data, size)) { send_count++; + packets_out_sec++; + bytes_out_sec += size; + } if (type_send == PIProtocol::Ethernet) - if (eth->send(data, size)) + if (eth->send(data, size)) { send_count++; + packets_out_sec++; + bytes_out_sec += size; + } } @@ -682,6 +722,7 @@ void PIProtocol::send() { //lock(); //memcpy(packet, sendDataPtr, sendDataSize); //unlock(); + //cout << "**send" << endl; if (!aboutSend()) return; if (sendDataPtr == 0 || sendDataSize == 0) return; if (history_write_send) { @@ -689,9 +730,15 @@ void PIProtocol::send() { history_rsize_send.setReadableSize(history_file_send.pos()); } if (type_send == PIProtocol::Serial) - if (ser->send(sendDataPtr, sendDataSize)) + if (ser->send(sendDataPtr, sendDataSize)) { send_count++; + packets_out_sec++; + bytes_out_sec += sendDataSize; + } if (type_send == PIProtocol::Ethernet) - if (eth->send(sendDataPtr, sendDataSize)) + if (eth->send(sendDataPtr, sendDataSize)) { send_count++; + packets_out_sec++; + bytes_out_sec += sendDataSize; + } } diff --git a/piprotocol.h b/piprotocol.h old mode 100755 new mode 100644 index 1f512a62..9bd60ad9 --- a/piprotocol.h +++ b/piprotocol.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Protocol, input/output channel (COM, UDP) - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -34,7 +34,7 @@ class PIMultiProtocolBase friend class PIProtocol; public: PIMultiProtocolBase() {;} - ~PIMultiProtocolBase() {;} + virtual ~PIMultiProtocolBase() {;} protected: virtual void received(PIProtocol * prot, bool corrected, uchar * data, int size) {;} @@ -48,6 +48,23 @@ private: typedef void (*ReceiveFunc)(void * ); +/// events: +/// void receiverStarted() +/// void receiverStopped() +/// void senderStarted() +/// void senderStopped() +/// void received(bool validate_is_ok) +/// void qualityChanged(PIProtocol::Quality old_quality, PIProtocol::Quality new_quality) +/// +/// handlers: +/// void startReceive(float exp_frequency = -1.f) +/// void stopReceive() +/// void startSend(float frequency = -1.f) +/// void stopSend() +/// void start() +/// void stop() +/// void send() +/// void send(const void * data, int size, bool direct = false) class PIProtocol: public PIObject { friend class PIMultiProtocolBase; @@ -58,7 +75,7 @@ public: PIProtocol(): PIObject() {init();} PIProtocol(const PIString & config, const PIString & name, void * recHeaderPtr = 0, int recHeaderSize = 0, void * recDataPtr = 0, int recDataSize = 0, void * sendDataPtr = 0, int sendDataSize = 0); // from config - ~PIProtocol(); + virtual ~PIProtocol(); enum Quality {Unknown = 1, Failure = 2, Bad = 3, Average = 4, Good = 5}; @@ -67,8 +84,8 @@ public: EVENT_HANDLER0(PIProtocol, 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);} - void setReceiverDataHeader(void * headerPtr, int headerSize) {this->headerPtr = (uchar * )headerPtr; this->headerSize = headerSize; packet_ext.setPacketData(headerPtr, headerSize, dataSize);} + void setReceiverData(void * dataPtr, int dataSize) {this->dataPtr = (uchar * )dataPtr; this->dataSize = dataSize; packet_ext->setPacketData(headerPtr, headerSize, dataSize);} + void setReceiverDataHeader(void * headerPtr, int headerSize) {this->headerPtr = (uchar * )headerPtr; this->headerSize = headerSize; packet_ext->setPacketData(headerPtr, headerSize, dataSize);} void setReceiverAddress(const PIString & ip, int port, bool force = false); // for Ethernet void setReceiverParameters(PIFlags parameters) {if (type_rec == PIProtocol::Serial || type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial void setReceiveSlot(ReceiveFunc slot) {ret_func = slot;} @@ -76,11 +93,13 @@ public: 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(); raiseEvent(this, "sender stopped");} + EVENT_HANDLER0(PIProtocol, void, stopSend) {sendTimer->stop(); senderStopped();} void setSenderFrequency(float frequency) {send_freq = frequency;} void setSenderDevice(const PIString & device, PISerial::Speed speed, bool force = false); // for Serial void setSenderData(void * dataPtr, int dataSize) {sendDataPtr = (uchar * )dataPtr; sendDataSize = dataSize;} void setSenderAddress(const PIString & ip, int port, bool force = false); // for Ethernet + void setSenderIP(const PIString & ip, bool force = false); // for Ethernet + void setSenderPort(int port, bool force = false); // for Ethernet void setSenderParameters(PIFlags parameters) {if (type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial float senderFrequency() const {return send_freq;} @@ -94,40 +113,60 @@ public: PIString name() const {return protName;} void setDisconnectTimeout(float timeout) {timeout_ = timeout; changeDisconnectTimeout();} float disconnectTimeout() const {return timeout_;} - float * disconnectTimeout_ptr() {return &timeout_;} + const float * disconnectTimeout_ptr() const {return &timeout_;} float immediateFrequency() const {return immediate_freq;} float integralFrequency() const {return integral_freq;} - float * immediateFrequency_ptr() {return &immediate_freq;} - float * integralFrequency_ptr() {return &integral_freq;} + const float * immediateFrequency_ptr() const {return &immediate_freq;} + const float * integralFrequency_ptr() const {return &integral_freq;} + ullong receiveCountPerSec() const {return packets_in_sec;} + const ullong * receiveCountPerSec_ptr() const {return &packets_in_sec;} + ullong sendCountPerSec() const {return packets_out_sec;} + const ullong * sendCountPerSec_ptr() const {return &packets_out_sec;} + ullong receiveBytesPerSec() const {return bytes_in_sec;} + const ullong * receiveBytesPerSec_ptr() const {return &bytes_in_sec;} + ullong sendBytesPerSec() const {return bytes_out_sec;} + const ullong * sendBytesPerSec_ptr() const {return &bytes_out_sec;} ullong receiveCount() const {return receive_count;} - ullong * receiveCount_ptr() {return &receive_count;} + const ullong * receiveCount_ptr() const {return &receive_count;} ullong wrongCount() const {return wrong_count;} - ullong * wrongCount_ptr() {return &wrong_count;} + const ullong * wrongCount_ptr() const {return &wrong_count;} ullong sendCount() const {return send_count;} - ullong * sendCount_ptr() {return &send_count;} + const ullong * sendCount_ptr() const {return &send_count;} ullong missedCount() const {return missed_count;} - ullong * missedCount_ptr() {return &missed_count;} + const ullong * missedCount_ptr() const {return &missed_count;} PIProtocol::Quality quality() const {return net_diag;} // receive quality - int * quality_ptr() {return (int * )&net_diag;} // receive quality pointer + const int * quality_ptr() const {return (int * )&net_diag;} // receive quality pointer PIString receiverDeviceName() const {return devReceiverName;} PIString senderDeviceName() const {return devSenderName;} PIString receiverDeviceState() const {return devReceiverState;} - PIString * receiverDeviceState_ptr() {return &devReceiverState;} + const PIString * receiverDeviceState_ptr() const {return &devReceiverState;} PIString senderDeviceState() const {return devSenderState;} - PIString * senderDeviceState_ptr() {return &devSenderState;} + const PIString * senderDeviceState_ptr() const {return &devSenderState;} + PIString receiveSpeed() const {return speedIn;} + const PIString * receiveSpeed_ptr() const {return &speedIn;} + PIString sendSpeed() const {return speedOut;} + const PIString * sendSpeed_ptr() const {return &speedOut;} PIString receiverHistorySize() const {return history_rsize_rec;} - PIString * receiverHistorySize_ptr() {return &history_rsize_rec;} + const PIString * receiverHistorySize_ptr() const {return &history_rsize_rec;} PIString senderHistorySize() const {return history_rsize_send;} - PIString * senderHistorySize_ptr() {return &history_rsize_send;} + const PIString * senderHistorySize_ptr() const {return &history_rsize_send;} bool writeReceiverHistory() const {return history_write_rec;} - bool * writeReceiverHistory_ptr() {return &history_write_rec;} + const bool * writeReceiverHistory_ptr() const {return &history_write_rec;} bool writeSenderHistory() const {return history_write_send;} - bool * writeSenderHistory_ptr() {return &history_write_send;} + const bool * writeSenderHistory_ptr() const {return &history_write_send;} void * receiveData() {return dataPtr;} void * sendData() {return sendDataPtr;} - PIByteArray lastHeader() {return packet_ext.lastHeader();} + 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) 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 @@ -137,15 +176,13 @@ protected: uint c = 0; for (int i = 0; i < size; ++i) c += ((uchar*)data)[i]; - c = ~(c + 1); - return c; + return ~(c + 1); } virtual uchar checksum_c(void * data, int size) { // function for checksum (uchar) uchar c = 0; for (int i = 0; i < size; ++i) c += ((uchar*)data)[i]; - c = ~(c + 1); - return c; + return ~(c + 1); } virtual bool aboutSend() {return true;} // executed before send data, if return 'false' then data is not sending @@ -162,30 +199,31 @@ protected: private: static void sendEvent(void * e, int) {((PIProtocol * )e)->send();} static bool receiveEvent(void * t, uchar * data, int size); - static bool headerValidateEvent(void * t, uchar * src, uchar * rec, int size); + static bool headerValidateEvent(void * t, uchar * src, uchar * rec, int size) {return ((PIProtocol * )t)->headerValidate(src, rec, size);} static void diagEvent(void * t, int); + static void secEvent(void * t, int); void setMultiProtocolOwner(PIMultiProtocolBase * mp) {mp_owner = mp;} PIMultiProtocolBase * multiProtocolOwner() const {return mp_owner;} void changeDisconnectTimeout(); ReceiveFunc ret_func; - PIPacketExtractor packet_ext; - PITimer * diagTimer, * sendTimer; + PIPacketExtractor * packet_ext; + PITimer * diagTimer, * sendTimer, * secTimer; PIMultiProtocolBase * mp_owner; PIProtocol::Type type_send, type_rec; PIProtocol::Quality net_diag; PIDeque last_freq; PIDeque last_packets; - PIString protName, devReceiverName, devReceiverState, devSenderName, devSenderState; + PIString protName, devReceiverName, devReceiverState, devSenderName, devSenderState, speedIn, speedOut; PIString history_path_rec, history_path_send, history_rsize_rec, history_rsize_send; PIFile history_file_rec, history_file_send; ushort history_id_rec, history_id_send; bool work, new_mp_prot, history_write_rec, history_write_send; - float exp_freq, send_freq, immediate_freq, integral_freq, timeout_; + float exp_freq, send_freq, ifreq, immediate_freq, integral_freq, timeout_; int packets[2], pckt_cnt, pckt_cnt_max; - char * packet, cur_pckt; - ullong wrong_count, receive_count, send_count, missed_count; + char cur_pckt; + ullong wrong_count, receive_count, send_count, missed_count, packets_in_sec, packets_out_sec, bytes_in_sec, bytes_out_sec; }; diff --git a/piserial.cpp b/piserial.cpp old mode 100755 new mode 100644 index a5f90322..2370c5e1 --- a/piserial.cpp +++ b/piserial.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives COM - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -60,6 +60,81 @@ PISerial::~PISerial() { } +bool PISerial::setPin(int number, bool on) { + switch (number) { + case 1: return setCAR(on); break; + case 2: return setSR(on); break; + case 3: return setST(on); break; + case 4: return setDTR(on); break; + case 5: + piCout << "[PISerial] Pin number 5 is ground" << endl; + 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; + return false; + } + return false; +} + + +bool PISerial::isPin(int number) const { + switch (number) { + case 1: return isCAR(); break; + case 2: return isSR(); break; + case 3: return isST(); break; + case 4: return isDTR(); break; + case 5: return false; + case 6: return isDSR(); break; + case 7: return isRTS(); break; + case 8: return isCTS(); break; + case 9: return isRNG(); break; + default: + piCout << "[PISerial] Pin number " << number << " doesn`t exists!" << endl; + return false; + } + return false; +} + + +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; + return false; + } + if (ioctl(fd, on ? TIOCMBIS : TIOCMBIC, &bit) < 0) { + piCout << "[PISerial] set" << bname << " error: " << errorString(); + return false; + } + return true; +#else + piCout << "[PISerial] set" << bname << " doesn`t implemented on Windows, sorry :-(" << endl; + return false; +#endif +} + + +bool PISerial::isBit(int bit, const PIString & bname) const { +#ifndef WINDOWS + if (fd < 0) { + piCout << "[PISerial] is" << bname << " error: \"" << path_ << "\" is not opened!" << endl; + return false; + } + int ret = 0; + if (ioctl(fd, TIOCMGET, &ret) < 0) + piCout << "[PISerial] is" << bname << " error: " << errorString(); + return ret & bit; +#else + piCout << "[PISerial] set" << bname << " doesn`t implemented on Windows, sorry :-(" << endl; + return false; +#endif +} + + bool PISerial::closeDevice() { if (!isInitialized()) return true; if (isRunning()) { @@ -86,6 +161,8 @@ bool PISerial::closeDevice() { int PISerial::convertSpeed(PISerial::Speed speed) { switch (speed) { + case S50: return B50; + case S75: return B75; case S110: return B110; case S300: return B300; case S600: return B600; @@ -97,6 +174,13 @@ int PISerial::convertSpeed(PISerial::Speed speed) { case S38400: return B38400; case S57600: return B57600; case S115200: return B115200; + case S1500000: return B1500000; + case S2000000: return B2000000; + case S2500000: return B2500000; + case S3000000: return B3000000; + case S3500000: return B3500000; + case S4000000: return B4000000; + default: break; } return B115200; } @@ -114,6 +198,7 @@ bool PISerial::read(void * data, int size, double timeout_ms) { if (ret > 0) all += ret; else msleep(1); } + received(data, all); return (all == size); } else { setReadIsBlocking(true); @@ -122,15 +207,96 @@ bool PISerial::read(void * data, int size, double timeout_ms) { ret = ::read(fd, &((uchar * )data)[all], size - all); if (ret > 0) all += ret; } + received(data, all); return (all == size); } return false; } +PIByteArray PISerial::readData(int size, double timeout_ms) { + int ret, all = 0; + uchar td[1024]; + PIByteArray str; + if (timeout_ms > 0.) { + setReadIsBlocking(false); + timer.reset(); + if (size <= 0) { + while (timer.elapsed_m() < timeout_ms) { + ret = ::read(fd, td, 1024); + if (ret <= 0) msleep(1); + else str << PIByteArray(td, ret); + } + } else { + while (all < size && timer.elapsed_m() < timeout_ms) { + ret = ::read(fd, td, size - all); + if (ret <= 0) msleep(1); + else { + str << PIByteArray(td, ret); + all += ret; + } + } + } + } else { + setReadIsBlocking(true); + all = ::read(fd, td, 1); + str << PIByteArray(td, all); + while (all < size) { + ret = ::read(fd, td, size - all); + if (ret <= 0) msleep(1); + else { + str << PIByteArray(td, ret); + all += ret; + } + } + } + return str; +} + + +PIString PISerial::read(int size, double timeout_ms) { + int ret, all = 0; + uchar td[1024]; + PIString str; + if (timeout_ms > 0.) { + setReadIsBlocking(false); + timer.reset(); + if (size <= 0) { + while (timer.elapsed_m() < timeout_ms) { + ret = ::read(fd, td, 1024); + if (ret <= 0) msleep(1); + else str << PIString((char*)td, ret); + } + } else { + while (all < size && timer.elapsed_m() < timeout_ms) { + ret = ::read(fd, td, size - all); + if (ret <= 0) msleep(1); + else { + str << PIString((char*)td, ret); + all += ret; + } + } + } + } else { + setReadIsBlocking(true); + all = ::read(fd, td, 1); + str << PIString((char*)td, all); + while (all < size) { + ret = ::read(fd, td, size - all); + if (ret <= 0) msleep(1); + else { + str << PIString((char*)td, ret); + all += ret; + } + } + } + return str; +} + + bool PISerial::openDevice() { #ifdef WINDOWS - DWORD da = 0, sm = 0; + DWORD ds = 0, sm = 0; if (isReadable()) {ds |= GENERIC_READ; sm |= FILE_SHARE_READ;} if (isWriteable()) {ds |= GENERIC_WRITE; sm |= FILE_SHARE_WRITE;} hCom = CreateFileA(path_.data(), ds, sm, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0); @@ -176,19 +342,19 @@ bool PISerial::openDevice() { case PIIODevice::WriteOnly: om = O_WRONLY; break; case PIIODevice::ReadWrite: om = O_RDWR; break; } - //cout << "init ser " << path_ << " mode " << om << endl; + //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; return false; } - fcntl(fd, F_SETFL, 0); tcgetattr(fd, &desc); sdesc = desc; - desc.c_iflag = desc.c_oflag = desc.c_lflag = 0; + desc.c_iflag = desc.c_oflag = desc.c_lflag = desc.c_cflag = 0; desc.c_cflag = CLOCAL | CSIZE | CS8; if (isReadable()) desc.c_cflag |= CREAD; + if (params[PISerial::HardwareFlowControl]) desc.c_cflag |= CRTSCTS; if (params[PISerial::TwoStopBits]) desc.c_cflag |= CSTOPB; if (params[PISerial::ParityControl]) { desc.c_iflag |= INPCK; @@ -201,12 +367,14 @@ bool PISerial::openDevice() { cfsetispeed(&desc, convertSpeed(ispeed)); cfsetospeed(&desc, convertSpeed(ospeed)); + tcflush(fd, TCIOFLUSH); + fcntl(fd, F_SETFL, 0); + if(tcsetattr(fd, TCSANOW, &desc) < 0) { piCout << "[PISerial] Can`t set attributes for \"" << path_ << "\"" << endl; ::close(fd); return false; } - tcflush(fd, TCIOFLUSH); //piCout << "[PISerial] Initialized " << path_ << endl; #endif return true; @@ -214,7 +382,7 @@ bool PISerial::openDevice() { int PISerial::write(const void * data, int max_size, bool wait) { - //piCout << "[PISerial] send size: " << sizeof(data) << endl; + //piCout << "[PISerial] send " << max_size << ": " << PIString((char*)data, max_size) << endl; if (fd == -1 || !canWrite()) { //piCout << "[PISerial] Can`t write to uninitialized COM" << endl; return -1; @@ -222,12 +390,18 @@ int PISerial::write(const void * data, int max_size, bool wait) { #ifdef WINDOWS DWORD wrote; WriteFile(hCom, data, max_size, &wrote, 0); + if (wait) { + DWORD event; + SetCommMask(hCom, EV_TXEMPTY); + WaitCommEvent(hCom, &event, NULL); + SetCommMask(hCom, EV_RXCHAR); + } #else int wrote; wrote = ::write(fd, data, max_size); if (wait) tcdrain(fd); #endif return (int)wrote; - //piCout << "[PISerial] Error while sending" << endl; + //piCout << "[PISerial] Error while sending" << endl; //piCout << "[PISerial] Wrote " << wrote << " bytes in " << path_ << endl; } diff --git a/piserial.h b/piserial.h old mode 100755 new mode 100644 index 1b823831..4e00e2d8 --- a/piserial.h +++ b/piserial.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives COM - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,21 +25,63 @@ #ifndef WINDOWS # include # include +# include +# ifndef B50 +# define B50 0000001 +# endif +# ifndef B50 +# define B75 0000002 +# endif +# ifndef B1500000 +# define B1500000 0010012 +# endif +# ifndef B2000000 +# define B2000000 0010013 +# endif +# ifndef B2500000 +# define B2500000 0010014 +# endif +# ifndef B3000000 +# define B3000000 0010015 +# endif +# ifndef B3500000 +# define B3500000 0010016 +# endif +# ifndef B4000000 +# define B4000000 0010017 +# endif #else -# define B110 110 -# define B300 300 -# define B600 600 -# define B1200 1200 -# define B2400 2400 -# define B4800 4800 -# define B9600 9600 -# define B14400 14400 -# define B19200 19200 -# define B38400 38400 -# define B57600 57600 -# define B115200 115200 -# define B128000 128000 -# define B256000 256000 +# define TIOCM_LE 1 +# define TIOCM_DTR 4 +# define TIOCM_RTS 7 +# define TIOCM_CTS 8 +# define TIOCM_ST 3 +# define TIOCM_SR 2 +# define TIOCM_CAR 1 +# define TIOCM_RNG 9 +# define TIOCM_DSR 6 +# define B50 50 +# define B75 75 +# define B110 110 +# define B300 300 +# define B600 600 +# define B1200 1200 +# define B2400 2400 +# define B4800 4800 +# define B9600 9600 +# define B14400 14400 +# define B19200 19200 +# define B38400 38400 +# define B57600 57600 +# define B115200 115200 +# define B128000 128000 +# define B256000 256000 +# define B1500000 1500000 +# define B2000000 2000000 +# define B2500000 2500000 +# define B3000000 3000000 +# define B3500000 3500000 +# define B4000000 4000000 #endif class PISerial: public PIIODevice { @@ -50,8 +92,10 @@ public: PISerial(void * data = 0, ReadRetFunc slot = 0); ~PISerial(); - enum Parameters {ParityControl = 0x01, ParityOdd = 0x02, TwoStopBits = 0x04}; + enum Parameters {ParityControl = 0x1, ParityOdd = 0x2, TwoStopBits = 0x4, HardwareFlowControl = 0x8}; enum Speed { + S50 = 50, + S75 = 75, S110 = 110, S300 = 300, S600 = 600, @@ -62,7 +106,13 @@ public: S19200 = 19200, S38400 = 38400, S57600 = 57600, - S115200 = 115200 + S115200 = 115200, + S1500000 = 1500000, // Linux only + S2000000 = 2000000, // Linux only + S2500000 = 2500000, // Linux only + S3000000 = 3000000, // Linux only + S3500000 = 3500000, // Linux only + S4000000 = 4000000 // Linux only }; void setData(void * d) {data = d;} @@ -72,12 +122,39 @@ public: void setOutSpeed(PISerial::Speed speed) {ospeed = speed;} void setInSpeed(PISerial::Speed speed) {ispeed = speed;} void setDevice(const PIString & dev) {path_ = dev;} - void setParameters(PIFlags parameters) {params = parameters;} + + void setParameters(PIFlags parameters_) {params = parameters_;} void setParameter(PISerial::Parameters parameter, bool on = true) {params.setFlag(parameter, on);} + bool isParameterSet(PISerial::Parameters parameter) const {return params[parameter];} + PIFlags parameters() const {return params;} + + bool setPin(int number, bool on); + bool isPin(int number) const; + + bool setLE(bool on) {return setBit(TIOCM_LE, on, "LE");} // useless function, just formally + bool setDTR(bool on) {return setBit(TIOCM_DTR, on, "DTR");} + bool setRTS(bool on) {return setBit(TIOCM_RTS, on, "RTS");} + bool setCTS(bool on) {return setBit(TIOCM_CTS, on, "CTS");} // useless function, just formally + bool setST(bool on) {return setBit(TIOCM_ST, on, "ST");} // useless function, just formally + bool setSR(bool on) {return setBit(TIOCM_SR, on, "SR");} // useless function, just formally + bool setCAR(bool on) {return setBit(TIOCM_CAR, on, "CAR");} // useless function, just formally + bool setRNG(bool on) {return setBit(TIOCM_RNG, on, "RNG");} // useless function, just formally + bool setDSR(bool on) {return setBit(TIOCM_DSR, on, "DSR");} // useless function, just formally + + bool isLE() const {return isBit(TIOCM_LE, "LE");} + bool isDTR() const {return isBit(TIOCM_DTR, "DTR");} + bool isRTS() const {return isBit(TIOCM_RTS, "RTS");} + bool isCTS() const {return isBit(TIOCM_CTS, "CTS");} + bool isST() const {return isBit(TIOCM_ST, "ST");} + bool isSR() const {return isBit(TIOCM_SR, "SR");} + bool isCAR() const {return isBit(TIOCM_CAR, "CAR");} + bool isRNG() const {return isBit(TIOCM_RNG, "RNG");} + bool isDSR() const {return isBit(TIOCM_DSR, "DSR");} + void setVTime(int t) {vtime = t;} -#ifdef WINDOWS void setReadIsBlocking(bool yes) { +#ifdef WINDOWS COMMTIMEOUTS times; times.ReadIntervalTimeout = yes ? vtime : MAXDWORD; times.ReadTotalTimeoutConstant = yes ? 1 : 0; @@ -85,35 +162,48 @@ public: times.WriteTotalTimeoutConstant = 1; times.WriteTotalTimeoutMultiplier = 0; if (isOpened()) SetCommTimeouts(hCom, ×); - } #else - void setReadIsBlocking(bool yes) {if (isOpened()) fcntl(fd, F_SETFL, yes ? 0 : O_NONBLOCK);} + if (isOpened()) fcntl(fd, F_SETFL, yes ? 0 : O_NONBLOCK); #endif + } const PIString & device() const {return path_;} PISerial::Speed outSpeed() const {return ospeed;} PISerial::Speed inSpeed() const {return ispeed;} int VTime() const {return vtime;} -#ifdef WINDOWS +#ifndef WINDOWS + void flush() {if (fd != -1) tcflush(fd, TCIOFLUSH);} +#endif + int read(void * read_to, int max_size) { +#ifdef WINDOWS if (!canRead()) return -1; WaitCommEvent(hCom, 0, 0); ReadFile(hCom, read_to, max_size, &readed, 0); return readed; - } #else - int read(void * read_to, int max_size) {if (!canRead()) return -1; return ::read(fd, read_to, max_size);} + if (!canRead()) return -1; + return ::read(fd, read_to, max_size); #endif + } bool read(void * data, int size, double timeout_ms); + PIString read(int size = -1, double timeout_ms = 1000.); + PIByteArray readData(int size = -1, double timeout_ms = 1000.); int write(const void * data, int max_size, bool wait); int write(const void * data, int max_size) {return write(data, max_size, false);} bool send(const void * data, int size, bool wait = false) {return (write(data, size, wait) == size);} + bool send(const PIString & data, bool wait = false) {return (write(data.data(), data.lengthAscii(), wait) == data.size_s());} + bool send(const PIByteArray & data, bool wait = false) {return (write(data.data(), data.size_s(), wait) == data.size_s());} protected: + virtual void received(void * data, int size) {;} + int convertSpeed(PISerial::Speed speed); + bool setBit(int bit, bool on, const PIString & bname); + bool isBit(int bit, const PIString & bname) const; static bool headerValidate(void * d, uchar * src, uchar * rec, int size) {for (int i = 0; i < size; ++i) if (src[i] != rec[i]) return false; return true;} bool openDevice(); diff --git a/pisignals.cpp b/pisignals.cpp old mode 100755 new mode 100644 index 12f4705c..1336baab --- a/pisignals.cpp +++ b/pisignals.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Signals - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pisignals.h b/pisignals.h old mode 100755 new mode 100644 index 43b58119..b1e9ec3d --- a/pisignals.h +++ b/pisignals.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Signals - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pistring.cpp b/pistring.cpp old mode 100755 new mode 100644 index cb1329a9..bbd1721e --- a/pistring.cpp +++ b/pistring.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives String - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,6 +20,28 @@ #include "pistring.h" +const char PIString::toBaseN[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^'}; +const int PIString::fromBaseN[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -1, + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; + + void PIString::appendFromChars(const char * c, int s) { int sz; wchar_t wc; @@ -88,11 +110,13 @@ PIString & PIString::operator +=(const wchar_t * str) { } +#ifdef HAS_LOCALE PIString & PIString::operator +=(const wstring & str) { uint l = str.size(); for (uint i = 0; i < l; ++i) push_back(str[i]); return *this; } +#endif PIString & PIString::operator +=(const PIString & str) { @@ -324,13 +348,20 @@ int PIString::lengthAscii() const { const char * PIString::data() const { PIByteArray & d_(*(const_cast(&data_))); d_.clear(); - for (int i = 0, j = 0; i < size_s(); ++i, ++j) { - if (at(i).isAscii()) + 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; + wc >>= 8; + } + /*if (at(i).isAscii()) d_.push_back(uchar(at(i).toAscii())); else { d_.push_back((at(i).toCharPtr()[0])); ++j; d_.push_back((at(i).toCharPtr()[1])); - } + }*/ } d_.push_back(uchar('\0')); return (const char * )d_.data(); @@ -339,14 +370,21 @@ const char * PIString::data() const { string PIString::convertToStd() const { string s; + int wc; + uchar tc; if (size() > 0) { for (int i = 0; i < length(); ++i) { - if (at(i).isAscii()) + wc = at(i).toInt(); + while (tc = wc & 0xFF, tc) { + s.push_back(char(tc)); + wc >>= 8; + } + /*if (at(i).isAscii()) s.push_back(at(i).toAscii()); else { s.push_back(at(i).toCharPtr()[0]); s.push_back(at(i).toCharPtr()[1]); - } + }*/ } } return s; @@ -360,7 +398,7 @@ char PIString::toChar() const { return v; } - +/* short PIString::toShort() const { PIString s(trimmed().toLowerCase().toNativeDecimalPoints()); short v; @@ -399,7 +437,7 @@ llong PIString::toLLong() const { sscanf(s.data(), "%lld", &v); return v; } - +*/ PIString & PIString::setReadableSize(long bytes) { clear(); @@ -424,14 +462,14 @@ PIString & PIString::setReadableSize(long bytes) { } -char chrUpr(char c) { +inline char chrUpr(char c) { if (c >= 'a' && c <= 'z') return c + 'A' - 'a'; //if (c >= 'а' && c <= 'я') return c + 'А' - 'а'; return c; } -char chrLwr(char c) { +inline char chrLwr(char c) { if (c >= 'A' && c <= 'Z') return c + 'a' - 'A'; //if (c >= 'А' && c <= 'Я') return c + 'а' - 'А'; return c; diff --git a/pistring.h b/pistring.h old mode 100755 new mode 100644 index 7f1d784f..35e12a7b --- a/pistring.h +++ b/pistring.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives String - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -38,19 +38,23 @@ public: PIString & operator +=(const string & str) {appendFromChars(str.c_str(), str.length()); return *this;} PIString & operator +=(const PIByteArray & ba) {appendFromChars((const char * )ba.data(), ba.size_s()); return *this;} PIString & operator +=(const PIString & str); +#ifdef HAS_LOCALE PIString & operator +=(const wstring & str); +#endif //PIString(const char c) {*this += c;} - PIString(const PIChar c) {piMonitor.strings++; piMonitor.containers--;*this += c;} - PIString(const char * str) {piMonitor.strings++; piMonitor.containers--;*this += str;} - PIString(const wchar_t * str) {piMonitor.strings++; piMonitor.containers--;*this += str;} - PIString(const string & str) {piMonitor.strings++; piMonitor.containers--;*this += str;} - PIString(const wstring & str) {piMonitor.strings++; piMonitor.containers--;*this += str;} - PIString(const PIByteArray & ba) {piMonitor.strings++; piMonitor.containers--;*this += ba;} - PIString(const char * str, const int len) {piMonitor.strings++; piMonitor.containers--;*this += string(str, len);} - PIString(const int len, const char c) {piMonitor.strings++; piMonitor.containers--;for (int i = 0; i < len; ++i) push_back(c);} - PIString(const int len, const PIChar & c) {piMonitor.strings++; piMonitor.containers--;for (int i = 0; i < len; ++i) push_back(c);} - PIString(const PIString & str) {piMonitor.strings++; piMonitor.containers--;*this += str;} + PIString(const PIChar c) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += c;} + PIString(const char * str) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;} + PIString(const wchar_t * str) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;} + PIString(const string & str) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;} +#ifdef HAS_LOCALE + PIString(const wstring & str) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;} +#endif + PIString(const PIByteArray & ba) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += ba;} + PIString(const char * str, const int len) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += string(str, len);} + PIString(const int len, const char c) {reserve(256); piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);} + PIString(const int len, const PIChar & c) {reserve(256); piMonitor.strings++; piMonitor.containers--; for (int i = 0; i < len; ++i) push_back(c);} + PIString(const PIString & str) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;} ~PIString() {piMonitor.strings--; piMonitor.containers++;} operator const char*() {return data();} @@ -133,16 +137,18 @@ public: int lengthAscii() const; const char * data() const; const string stdString() const {return convertToStd();} +#ifdef HAS_LOCALE wstring stdWString() const {return convertToWString();} - PIByteArray toByteArray() {string s(convertToStd()); return PIByteArray(s.c_str(), s.length());} +#endif + PIByteArray toByteArray() const {const char * d = data(); return PIByteArray(d, lengthAscii());} PIStringList split(const PIString & delim) const; PIString toUpperCase() const; PIString toLowerCase() const; -#ifdef QNX - PIString toNativeDecimalPoints() const {PIString s(*this); return s;} -#else +#ifdef HAS_LOCALE PIString toNativeDecimalPoints() const {PIString s(*this); if (currentLocale == 0) return s; return s.replaceAll(".", currentLocale->decimal_point);} +#else + PIString toNativeDecimalPoints() const {PIString s(*this); return s;} #endif int find(const char str, const int start = 0) const; @@ -157,30 +163,43 @@ public: int length() const {return size();} bool isEmpty() const {return (size() == 0 || *this == "");} - bool toBool() const {PIString s(*this); if (atof(s.toNativeDecimalPoints().data()) > 0. || s.trimmed().toLowerCase() == "true") return true; return false;} + bool toBool() const {PIString s(*this); if (atof(s.toNativeDecimalPoints().data()) > 0. || s.trimmed().toLowerCase() == "true" || s.trimmed().toLowerCase() == "on") return true; return false;} char toChar() const; - short toShort() const; - int toInt() const; - long toLong() const; - llong toLLong() const; + short toShort(int base = -1, bool * ok = 0) const {return short(toNumberBase(*this, base, ok));} + ushort toUShort(int base = -1, bool * ok = 0) const {return ushort(toNumberBase(*this, base, ok));} + int toInt(int base = -1, bool * ok = 0) const {return int(toNumberBase(*this, base, ok));} + uint toUInt(int base = -1, bool * ok = 0) const {return uint(toNumberBase(*this, base, ok));} + long toLong(int base = -1, bool * ok = 0) const {return long(toNumberBase(*this, base, ok));} + ulong toULong(int base = -1, bool * ok = 0) const {return ulong(toNumberBase(*this, base, ok));} + llong toLLong(int base = -1, bool * ok = 0) const {return toNumberBase(*this, base, ok);} + ullong toULLong(int base = -1, bool * ok = 0) const {return ullong(toNumberBase(*this, base, ok));} float toFloat() const {PIString s(*this); return (float)atof(s.toNativeDecimalPoints().data());} double toDouble() const {PIString s(*this); return atof(s.toNativeDecimalPoints().data());} ldouble toLDouble() const {PIString s(*this); return atof(s.toNativeDecimalPoints().data());} //inline PIString & setNumber(const char value) {clear(); *this += itos(value); return *this;} - PIString & setNumber(const int value) {clear(); *this += itos(value); return *this;} - PIString & setNumber(const short value) {clear(); *this += itos(value); return *this;} - PIString & setNumber(const long value) {clear(); *this += ltos(value); return *this;} + PIString & setNumber(const short value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} + PIString & setNumber(const ushort value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} + PIString & setNumber(const int value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} + PIString & setNumber(const uint value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} + PIString & setNumber(const long value, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;} + 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;} 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); //inline static PIString fromNumber(const char value) {return PIString(itos(value));} - static PIString fromNumber(const int value) {return PIString(itos(value));} - static PIString fromNumber(const uint value) {return PIString(itos(value));} - static PIString fromNumber(const short value) {return PIString(itos(value));} - static PIString fromNumber(const long value) {return PIString(ltos(value));} + static PIString fromNumber(const short value, int base = 10, bool * ok = 0) {return fromNumberBase(llong(value), base, ok);} + static PIString fromNumber(const ushort value, int base = 10, bool * ok = 0) {return fromNumberBase(llong(value), base, ok);} + static PIString fromNumber(const int value, int base = 10, bool * ok = 0) {return fromNumberBase(llong(value), base, ok);} + static PIString fromNumber(const uint value, int base = 10, bool * ok = 0) {return fromNumberBase(llong(value), base, ok);} + static PIString fromNumber(const long value, int base = 10, bool * ok = 0) {return fromNumberBase(llong(value), base, ok);} + 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);} 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));} @@ -188,9 +207,52 @@ public: static PIString readableSize(long bytes) {PIString s; s.setReadableSize(bytes); return s;} private: + static const char toBaseN[]; + static const int fromBaseN[]; + + static PIString fromNumberBase(const llong value, int base = 10, bool * ok = 0) { + if (base < 2 || base > 40) {if (ok != 0) *ok = false; return PIString();} + if (ok != 0) *ok = true; + if (base == 10) return itos(value); + PIString ret; + llong v = value < 0 ? -value : value, cn, b = base; + while (v >= base) { + cn = v % b; + v /= b; + //cout << int(cn) << ", " << int(v) << endl; + ret.push_front(PIChar(toBaseN[cn])); + } + if (v > 0) ret.push_front(PIChar(toBaseN[v])); + if (value < 0) ret.push_front('-'); + return ret; + } + static llong toNumberBase(const PIString & value, int base = -1, bool * ok = 0) { + PIString v = value.trimmed(); + if (base < 0) { + int ind = v.find("0x"); + if (ind == 0 || ind == 1) {v.remove(ind, 2); base = 16;} + else base = 10; + } else + if (base < 2 || base > 40) {if (ok != 0) *ok = false; return 0;} + v.reverse(); + if (ok != 0) *ok = true; + llong ret = 0, m = 1; + int cs; + piForeachC (PIChar & i, v) { + if (i == PIChar('-')) {ret = -ret; continue;} + //cout << i << ", " << fromBaseN[int(i.toAscii())] << ", " << m << endl; + cs = fromBaseN[int(i.toAscii())]; + if (cs < 0 || cs >= base) break; + ret += cs * m; + m *= base; + } + return ret; + } void appendFromChars(const char * c, int s); string convertToStd() const; +#ifdef HAS_LOCALE wstring convertToWString() const {wstring s; for (int i = 0; i < length(); ++i) s.push_back(at(i).toWChar()); return s;} +#endif PIByteArray data_; //string std_string; @@ -201,6 +263,9 @@ private: inline std::ostream & operator <<(std::ostream & s, const PIString & v) {for (int i = 0; i < v.length(); ++i) s << v[i]; return s;} inline std::istream & operator >>(std::istream & s, PIString & v) {string ss; s >> ss; v << PIString(ss); return s;} +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;} +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;} + 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;} @@ -211,8 +276,8 @@ inline PIString operator +(const PIString & f, const string & str) {PIString s(f inline PIString operator +(const char * str, const PIString & f) {return PIString(str) + f;} inline PIString operator +(const string & str, const PIString & f) {return PIString(str) + f;} -char chrUpr(char c); -char chrLwr(char c); +inline char chrUpr(char c); +inline char chrLwr(char c); class PIStringList: public PIVector { diff --git a/pisystemmonitor.cpp b/pisystemmonitor.cpp old mode 100755 new mode 100644 index 661ed91d..b880ac0c --- a/pisystemmonitor.cpp +++ b/pisystemmonitor.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Process resource monitor - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -53,6 +53,7 @@ bool PISystemMonitor::startOnProcess(int pID) { void PISystemMonitor::run() { #ifndef WINDOWS + file.seekToBegin(); PIString str(file.readAll(true)); int si = str.find('(') + 1, fi = 0, cc = 1; for (int i = si; i < str.size_s(); ++i) { @@ -93,6 +94,7 @@ void PISystemMonitor::run() { stat.priority = sl[16].toInt(); stat.threads = sl[18].toInt(); + filem.seekToBegin(); str = filem.readAll(true); sl = str.split(" "); if (sl.size_s() < 5) return; diff --git a/pisystemmonitor.h b/pisystemmonitor.h old mode 100755 new mode 100644 index d721646d..2f013092 --- a/pisystemmonitor.h +++ b/pisystemmonitor.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Process resource monitor - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,7 +27,7 @@ class PISystemMonitor: public PIThread { public: PISystemMonitor(); - + struct ProcessStats { PIString exec_name; PIString state; @@ -50,21 +50,21 @@ public: float cpu_load_system; float cpu_load_user; }; - + bool startOnProcess(int pID); bool startOnSelf() {return startOnProcess(PIProcess::currentPID());} - ProcessStats & statistic() {return stat;} - + const ProcessStats & statistic() const {return stat;} + private: void run(); - + PIFile file, filem; ProcessStats stat; int pID_, page_size, cpu_count, cycle; #ifndef WINDOWS llong cpu_u_cur, cpu_u_prev, cpu_s_cur, cpu_s_prev; #endif - + }; #endif // PISYSTEMMONITOR_H diff --git a/pisystemtests.cpp b/pisystemtests.cpp new file mode 100644 index 00000000..8dc565f7 --- /dev/null +++ b/pisystemtests.cpp @@ -0,0 +1,44 @@ +/* + PIP - Platform Independent Primitives + System tests results (see system_test folder) + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pisystemtests.h" + + +namespace PISystemTests { + long time_resolution_ns = 1; + long time_elapsed_ns = 0; + long usleep_offset_us = 60; + + PISystemTestReader pisystestreader; + +}; + + +PISystemTests::PISystemTestReader::PISystemTestReader() { + PIConfig conf( +#ifndef WINDOWS + "/etc/pip.conf" +#else + "pip.conf" +#endif + , PIIODevice::ReadOnly); + time_resolution_ns = conf.getValue("time_resolution_ns", 1); + time_elapsed_ns = conf.getValue("time_elapsed_ns", 0); + usleep_offset_us = conf.getValue("usleep_offset_us", 60); +} diff --git a/pimultiprotocol.cpp b/pisystemtests.h old mode 100755 new mode 100644 similarity index 61% rename from pimultiprotocol.cpp rename to pisystemtests.h index 422263cf..1c8e4539 --- a/pimultiprotocol.cpp +++ b/pisystemtests.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives - Multiprotocol - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + System tests results (see system_test folder) + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,5 +17,23 @@ along with this program. If not, see . */ -#include "pimultiprotocol.h" +#ifndef PISYSTEMTESTS_H +#define PISYSTEMTESTS_H +#include "piconfig.h" + +namespace PISystemTests { + extern long time_resolution_ns; + extern long time_elapsed_ns; + extern long usleep_offset_us; + + class PISystemTestReader { + public: + PISystemTestReader(); + }; + + extern PISystemTestReader pisystestreader; + +}; + +#endif // PISYSTEMTESTS_H diff --git a/pithread.cpp b/pithread.cpp old mode 100755 new mode 100644 index f9d796df..b9e97860 --- a/pithread.cpp +++ b/pithread.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Thread - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,6 +18,17 @@ */ #include "pithread.h" +#include "pisystemtests.h" + + +void piUSleep(int usecs) { +#ifdef WINDOWS + if (usecs > 0) Sleep(usecs / 1000); +#else + usecs -= PISystemTests::usleep_offset_us; + if (usecs > 0) usleep(usecs); +#endif +} PIThread::PIThread(void * data, ThreadFunc func, bool startNow, int timer_delay): PIObject() { @@ -103,7 +114,7 @@ void PIThread::terminate(bool hard) { if (thread == 0) return; running = false; #ifndef WINDOWS - if (hard) kill(thread, SIGKILL); + if (hard) kill((ullong)thread, SIGKILL); else pthread_cancel(thread); #else CloseHandle(thread); @@ -114,20 +125,20 @@ void PIThread::terminate(bool hard) { void * PIThread::thread_function(void * t) { - PIThread * ct = (PIThread * )t; - ct->running = true; - ct->begin(); - raiseEvent(ct, "started"); - while (!ct->terminating) { - if (ct->lockRun) ct->mutex_.lock(); - ct->run(); - if (ct->ret_func != 0) ct->ret_func(ct->data_); - if (ct->lockRun) ct->mutex_.unlock(); - if (ct->timer > 0) msleep(ct->timer); + PIThread & ct = *((PIThread * )t); + ct.running = true; + ct.begin(); + ct.started(); + while (!ct.terminating) { + if (ct.lockRun) ct.mutex_.lock(); + ct.run(); + if (ct.ret_func != 0) ct.ret_func(ct.data_); + if (ct.lockRun) ct.mutex_.unlock(); + if (ct.timer > 0) msleep(ct.timer); } - raiseEvent(ct, "stopped"); - ct->end(); - ct->running = false; + ct.stopped(); + ct.end(); + ct.running = false; //cout << "thread " << t << " exiting ... " << endl; #ifndef WINDOWS pthread_exit(0); @@ -139,17 +150,17 @@ void * PIThread::thread_function(void * t) { void * PIThread::thread_function_once(void * t) { - PIThread * ct = (PIThread * )t; - ct->running = true; - ct->begin(); - raiseEvent(ct, "started"); - if (ct->lockRun) ct->mutex_.lock(); - ct->run(); - if (ct->ret_func != 0) ct->ret_func(ct->data_); - if (ct->lockRun) ct->mutex_.unlock(); - raiseEvent(ct, "stopped"); - ct->end(); - ct->running = false; + PIThread & ct = *((PIThread * )t); + ct.running = true; + ct.begin(); + ct.started(); + if (ct.lockRun) ct.mutex_.lock(); + ct.run(); + if (ct.ret_func != 0) ct.ret_func(ct.data_); + if (ct.lockRun) ct.mutex_.unlock(); + ct.stopped(); + ct.end(); + ct.running = false; //cout << "thread " << t << " exiting ... " << endl; #ifndef WINDOWS pthread_exit(0); diff --git a/pithread.h b/pithread.h old mode 100755 new mode 100644 index b01d4a02..d9f109e0 --- a/pithread.h +++ b/pithread.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Thread - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,14 +29,31 @@ inline void msleep(int msecs) {Sleep(msecs);} #else inline void msleep(int msecs) {usleep(msecs * 1000);} #endif +void piUSleep(int usecs); // on !Windows consider constant "usleep" offset +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 { public: PIThread(void * data, ThreadFunc func, bool startNow = false, int timer_delay = -1); PIThread(bool startNow = false, int timer_delay = -1); - ~PIThread(); + virtual ~PIThread(); #ifdef QNX enum Priority {piHighest = 12, @@ -76,6 +93,9 @@ public: EVENT_HANDLER0(PIThread, void, lock) {mutex_.lock();} EVENT_HANDLER0(PIThread, void, unlock) {mutex_.unlock();} PIMutex & mutex() {return mutex_;} + + EVENT(PIThread, started) + EVENT(PIThread, stopped) protected: static void * thread_function(void * t); diff --git a/pitimer.cpp b/pitimer.cpp index 802df41d..da90d0c2 100644 --- a/pitimer.cpp +++ b/pitimer.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Timer - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,49 +18,87 @@ */ #include "pitimer.h" +#include "pisystemtests.h" -PITimer::PITimer(TimerEvent slot, void * data_) -#ifdef WINDOWS +#ifdef PIP_TIMER_RT +PITimer::TimerPool * pool = 0; +#endif + + +PITimer::PITimer(TimerEvent slot, void * data_, bool threaded_) +#ifndef PIP_TIMER_RT : PIThread() { #else : PIObject() { #endif ret_func = slot; data = data_; -#ifndef WINDOWS +#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 = timer_event; + se.sigev_notify_function = PITimer::timer_event; + se.sigev_notify_attributes = 0; + lockRun = false; +#endif + reset(); +} + + +PITimer::PITimer(bool threaded_) +#ifndef PIP_TIMER_RT +: PIThread() { +#else +: PIObject() { +#endif + ret_func = 0; + data = 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; #endif reset(); - /*addEvent("timeout"); - addEventHandler(HANDLER(PITimer, start)); - addEventHandler(HANDLER(PITimer, stop)); - addEventHandler(HANDLER(PITimer, reset));*/ } PITimer::~PITimer() { -#ifndef WINDOWS +#ifdef PIP_TIMER_RT piMonitor.timers--; #endif stop(); } -#ifndef WINDOWS +#ifdef PIP_TIMER_RT void PITimer::start(double msecs) { - if (ti == 0 || msecs < 0) return; + if (ti != -1 || msecs < 0 || running) return; + 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; + return; + } spec.it_interval.tv_nsec = ((int)(msecs * 1000) % 1000000) * 1000; spec.it_interval.tv_sec = (time_t)(msecs / 1000); spec.it_value = spec.it_interval; 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; return; @@ -70,18 +108,146 @@ void PITimer::start(double msecs) { } +void PITimer::deferredStart(double interval_msecs, double delay_msecs) { + if (ti != -1 || interval_msecs < 0 || running) return; + 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; + spec.it_value.tv_sec = (time_t)(delay_msecs / 1000); + 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; + return; + } + timer_settime(timer, 0, &spec, 0); + running = true; +} + + +void PITimer::deferredStart(double interval_msecs, const PIDateTime & start_datetime) { + if (ti != -1 || interval_msecs < 0 || running) return; + spec.it_interval.tv_nsec = ((int)(interval_msecs * 1000) % 1000000) * 1000; + spec.it_interval.tv_sec = (time_t)(interval_msecs / 1000); + struct tm dtm; + memset(&dtm, 0, sizeof(dtm)); + dtm.tm_sec = start_datetime.seconds; + dtm.tm_min = start_datetime.minutes; + dtm.tm_hour = start_datetime.hours; + dtm.tm_mday = start_datetime.day; + dtm.tm_mon = start_datetime.month - 1; + dtm.tm_year = start_datetime.year - 1900; + spec.it_value.tv_nsec = 0; + spec.it_value.tv_sec = mktime(&dtm); + 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; + return; + } + timer_settime(timer, TIMER_ABSTIME, &spec, 0); + running = true; +} + + + +void PITimer::TimerPool::remove(PITimer * t) { + mutex.lock(); + for (int i = 0; i < timers.size_s(); ++i) + if (timers[i].first == t) { + timers.remove(i); + mutex.unlock(); + return; + } + mutex.unlock(); +} + + +void PITimer::TimerPool::begin() { + //cout << "pool begin\n"; + /*struct sigaction sa; + sa.sa_flags = 0; + sa.sa_handler = empty_handler; + sigemptyset(&sa.sa_mask); + if (sigaction(SIGALRM, &sa, 0) == -1) { + piCout << "[PITimer] sigaction error: " << errorString() << endl; + stop(); + return; + }*/ + sigemptyset(&ss); + sigaddset(&ss, SIGALRM); + memset(&se, 0, sizeof(se)); + se.sigev_notify = SIGEV_SIGNAL; + se.sigev_signo = SIGALRM; + spec.it_interval.tv_nsec = 1000000; + spec.it_interval.tv_sec = 0; + 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; + stop(); + return; + } + if (timer_settime(timer, 0, &spec, 0) == -1) { + piCout << "[PITimer] Can`t set timer for pool: " << errorString() << endl; + stop(); + return; + } + ti = 1; +} + + +void PITimer::TimerPool::run() { + //cout << "wait ...\n"; + sigwait(&ss, &si); + //cout << "ok\n"; + mutex.lock(); + //cout << "* pool tick , pool = " << this <<", timers = " << timers.size()<<"\n"; + for (int i = 0; i < timers.size_s(); ++i) { + TimerPair & ct(timers[i]); + sv.sival_ptr = ct.first; + ct.second++; + //cout << "** pool tick for " << ct.first << ", cnt " << ct.second << ", " << ct.first->ticks << "\n"; + if (ct.second >= ct.first->ticks) { + //cout << "*** timer "<remove(this); + if (pool->isEmpty()) pool->terminate(); + } + } + if (ti != -1) timer_delete(timer); + ti = -1; +} + + void PITimer::timer_event(sigval e) { PITimer * ct = (PITimer * )e.sival_ptr; if (!ct->running) return; if (ct->lockRun) ct->lock(); if (ct->ret_func != 0) ct->ret_func(ct->data, 1); - raiseEvent(ct, "timeout", ct->data, 1); + ct->timeout(ct->data, 1); + ct->tick(ct->data, 1); piForeach (TimerSlot & i, ct->ret_funcs) { if (i.delim > ++(i.tick)) continue; i.tick = 0; if (i.slot != 0) i.slot(ct->data, i.delim); else if (ct->ret_func != 0) ct->ret_func(ct->data, i.delim); - raiseEvent(ct, "timeout", ct->data, i.delim); + ct->timeout(ct->data, i.delim); + ct->tick(ct->data, i.delim); } if (ct->lockRun) ct->unlock(); } @@ -101,32 +267,48 @@ bool PITimer::waitForFinish(int timeout_msecs) { return cnt < timeout_msecs; } - #else + +void PITimer::start(double msecs) { + if (msecs < 0 || running) return; + inc_time = PISystemTime::fromMilliseconds(msecs); + st_time = currentSystemTime() + inc_time; + PIThread::start(); +} + + void PITimer::run() { if (!running) return; + (st_time - currentSystemTime()).sleep(); + st_time += inc_time; if (lockRun) lock(); if (ret_func != 0) ret_func(data, 1); - raiseEvent(this, "timeout", data, 1); + timeout(data, 1); + tick(data, 1); piForeach (TimerSlot & i, ret_funcs) { if (i.delim > ++(i.tick)) continue; i.tick = 0; if (i.slot != 0) i.slot(data, i.delim); else if (ret_func != 0) ret_func(data, i.delim); - raiseEvent(this, "timeout", data, i.delim); + timeout(data, i.delim); + tick(data, i.delim); } if (lockRun) unlock(); } -#endif +#endif double PITimer::elapsed_n() { #ifdef WINDOWS t_cur = GetCurrentTime(); return (t_cur - t_st) * 1000000.; #else +# ifdef MAC_OS + clock_get_time(__pi_mac_clock, &t_cur); +# else clock_gettime(0, &t_cur); - return (t_cur.tv_sec - t_st.tv_sec) * 1.e+9 + (t_cur.tv_nsec - t_st.tv_nsec); +# endif + return (t_cur.tv_sec - t_st.tv_sec) * 1.e+9 + (t_cur.tv_nsec - t_st.tv_nsec - PISystemTests::time_elapsed_ns); #endif } @@ -136,8 +318,12 @@ double PITimer::elapsed_u() { t_cur = GetCurrentTime(); return (t_cur - t_st) * 1000.; #else +# ifdef MAC_OS + clock_get_time(__pi_mac_clock, &t_cur); +# else clock_gettime(0, &t_cur); - return (t_cur.tv_sec - t_st.tv_sec) * 1.e+6 + (t_cur.tv_nsec - t_st.tv_nsec) / 1.e+3; +# endif + return (t_cur.tv_sec - t_st.tv_sec) * 1.e+6 + (t_cur.tv_nsec - t_st.tv_nsec - PISystemTests::time_elapsed_ns) / 1.e+3; #endif } @@ -147,8 +333,12 @@ double PITimer::elapsed_m() { t_cur = GetCurrentTime(); return (double)(t_cur - t_st); #else +# ifdef MAC_OS + clock_get_time(__pi_mac_clock, &t_cur); +# else clock_gettime(0, &t_cur); - return (t_cur.tv_sec - t_st.tv_sec) * 1.e+3 + (t_cur.tv_nsec - t_st.tv_nsec) / 1.e+6; +# endif + return (t_cur.tv_sec - t_st.tv_sec) * 1.e+3 + (t_cur.tv_nsec - t_st.tv_nsec - PISystemTests::time_elapsed_ns) / 1.e+6; #endif } @@ -158,18 +348,20 @@ double PITimer::elapsed_s() { t_cur = GetCurrentTime(); return (t_cur - t_st) / 1000.; #else +# ifdef MAC_OS + clock_get_time(__pi_mac_clock, &t_cur); +# else clock_gettime(0, &t_cur); - return (t_cur.tv_sec - t_st.tv_sec) + (t_cur.tv_nsec - t_st.tv_nsec) / 1.e+9; +# endif + return (t_cur.tv_sec - t_st.tv_sec) + (t_cur.tv_nsec - t_st.tv_nsec - PISystemTests::time_elapsed_ns) / 1.e+9; #endif } double PITimer::reset_time_n() { #ifdef WINDOWS - t_cur = GetCurrentTime(); - return t_st * 1000000.; + return t_st * 1.e+6; #else - clock_gettime(0, &t_cur); return t_st.tv_sec * 1.e+9 + t_st.tv_nsec; #endif } @@ -177,10 +369,8 @@ double PITimer::reset_time_n() { double PITimer::reset_time_u() { #ifdef WINDOWS - t_cur = GetCurrentTime(); - return (t_cur - t_st) * 1000.; + return t_st * 1.e+3; #else - clock_gettime(0, &t_cur); return t_st.tv_sec * 1.e+6 + t_st.tv_nsec / 1.e+3; #endif } @@ -188,10 +378,8 @@ double PITimer::reset_time_u() { double PITimer::reset_time_m() { #ifdef WINDOWS - t_cur = GetCurrentTime(); - return (double)(t_cur - t_st); + return (double)t_st; #else - clock_gettime(0, &t_cur); return t_st.tv_sec * 1.e+3 + t_st.tv_nsec / 1.e+6; #endif } @@ -199,22 +387,34 @@ double PITimer::reset_time_m() { double PITimer::reset_time_s() { #ifdef WINDOWS - t_cur = GetCurrentTime(); - return (t_cur - t_st) / 1000.; + return t_st / 1000.; #else - clock_gettime(0, &t_cur); return t_st.tv_sec + t_st.tv_nsec / 1.e+9; #endif } +PISystemTime PITimer::reset_time() { +#ifdef WINDOWS + return PISystemTime(t_st / 1000, (t_st % 1000) * 1000000); +#else + return PISystemTime(t_st.tv_sec, t_st.tv_nsec); +#endif +} + + double PITimer::elapsed_system_n() { #ifdef WINDOWS long t_cur = GetCurrentTime(); return (t_cur * 1000000.); #else +# ifdef MAC_OS + mach_timespec_t t_cur; + clock_get_time(__pi_mac_clock, &t_cur); +# else timespec t_cur; clock_gettime(0, &t_cur); +# endif return (t_cur.tv_sec * 1.e+9 + t_cur.tv_nsec); #endif } @@ -225,8 +425,13 @@ double PITimer::elapsed_system_u() { long t_cur = GetCurrentTime(); return (t_cur * 1000.); #else +# ifdef MAC_OS + mach_timespec_t t_cur; + clock_get_time(__pi_mac_clock, &t_cur); +# else timespec t_cur; clock_gettime(0, &t_cur); +# endif return (t_cur.tv_sec * 1.e+6 + (t_cur.tv_nsec / 1.e+3)); #endif } @@ -237,8 +442,13 @@ double PITimer::elapsed_system_m() { long t_cur = GetCurrentTime(); return (double)t_cur; #else +# ifdef MAC_OS + mach_timespec_t t_cur; + clock_get_time(__pi_mac_clock, &t_cur); +# else timespec t_cur; clock_gettime(0, &t_cur); +# endif return (t_cur.tv_sec * 1.e+3 + (t_cur.tv_nsec / 1.e+6)); #endif } @@ -249,8 +459,13 @@ double PITimer::elapsed_system_s() { long t_cur = GetCurrentTime(); return (t_cur / 1000.); #else +# ifdef MAC_OS + mach_timespec_t t_cur; + clock_get_time(__pi_mac_clock, &t_cur); +# else timespec t_cur; clock_gettime(0, &t_cur); +# endif return (t_cur.tv_sec + (t_cur.tv_nsec / 1.e+9)); #endif } @@ -278,6 +493,37 @@ PIDate currentDate() { } +PIDateTime currentDateTime() { + time_t rt = time(0); + tm * pt = localtime(&rt); + 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; +} + + +PISystemTime currentSystemTime() { +#ifdef WINDOWS + long t_cur = GetCurrentTime(); + return PISystemTime(t_cur / 1000, (t_cur % 1000) * 1000000); +#else +# ifdef MAC_OS + mach_timespec_t t_cur; + clock_get_time(__pi_mac_clock, &t_cur); +# else + timespec t_cur; + clock_gettime(0, &t_cur); +# endif + return PISystemTime(t_cur.tv_sec, t_cur.tv_nsec); +#endif +} + + PIString PITime::toString(const PIString & format) { PIString ts = format; ts.replace("hh", PIString::fromNumber(hours).expandLeftTo(2, '0')); @@ -293,10 +539,29 @@ PIString PITime::toString(const PIString & format) { PIString PIDate::toString(const PIString & format) { PIString ts = format; ts.replace("yyyy", PIString::fromNumber(year).expandLeftTo(4, '0')); - ts.replace("yy", PIString::fromNumber(year).expandLeftTo(2, '0')); - ts.replace("y", PIString::fromNumber(year)); - ts.replace("mm", PIString::fromNumber(month).expandLeftTo(2, '0')); - ts.replace("m", PIString::fromNumber(month)); + ts.replace("yy", PIString::fromNumber(year).right(2)); + ts.replace("y", PIString::fromNumber(year).right(1)); + ts.replace("MM", PIString::fromNumber(month).expandLeftTo(2, '0')); + ts.replace("M", PIString::fromNumber(month)); + ts.replace("dd", PIString::fromNumber(day).expandLeftTo(2, '0')); + ts.replace("d", PIString::fromNumber(day)); + return ts; +} + + +PIString PIDateTime::toString(const PIString & format) { + 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)); + ts.replace("MM", PIString::fromNumber(month).expandLeftTo(2, '0')); + ts.replace("M", PIString::fromNumber(month)); ts.replace("dd", PIString::fromNumber(day).expandLeftTo(2, '0')); ts.replace("d", PIString::fromNumber(day)); return ts; @@ -318,10 +583,29 @@ PIString time2string(const PITime & time, const PIString & format) { PIString date2string(const PIDate & date, const PIString & format) { PIString ts = format; ts.replace("yyyy", PIString::fromNumber(date.year).expandLeftTo(4, '0')); - ts.replace("yy", PIString::fromNumber(date.year).expandLeftTo(2, '0')); - ts.replace("y", PIString::fromNumber(date.year)); - ts.replace("mm", PIString::fromNumber(date.month).expandLeftTo(2, '0')); - ts.replace("m", PIString::fromNumber(date.month)); + ts.replace("yy", PIString::fromNumber(date.year).right(2)); + ts.replace("y", PIString::fromNumber(date.year).right(1)); + ts.replace("MM", PIString::fromNumber(date.month).expandLeftTo(2, '0')); + ts.replace("M", PIString::fromNumber(date.month)); + ts.replace("dd", PIString::fromNumber(date.day).expandLeftTo(2, '0')); + ts.replace("d", PIString::fromNumber(date.day)); + return ts; +} + + +PIString datetime2string(const PIDateTime & date, const PIString & format) { + PIString ts = format; + ts.replace("hh", PIString::fromNumber(date.hours).expandLeftTo(2, '0')); + ts.replace("h", PIString::fromNumber(date.hours)); + ts.replace("mm", PIString::fromNumber(date.minutes).expandLeftTo(2, '0')); + ts.replace("m", PIString::fromNumber(date.minutes)); + ts.replace("ss", PIString::fromNumber(date.seconds).expandLeftTo(2, '0')); + ts.replace("s", PIString::fromNumber(date.seconds)); + ts.replace("yyyy", PIString::fromNumber(date.year).expandLeftTo(4, '0')); + ts.replace("yy", PIString::fromNumber(date.year).right(2)); + ts.replace("y", PIString::fromNumber(date.year).right(1)); + ts.replace("MM", PIString::fromNumber(date.month).expandLeftTo(2, '0')); + ts.replace("M", PIString::fromNumber(date.month)); ts.replace("dd", PIString::fromNumber(date.day).expandLeftTo(2, '0')); ts.replace("d", PIString::fromNumber(date.day)); return ts; diff --git a/pitimer.h b/pitimer.h index 8dc21ac2..caa009f3 100644 --- a/pitimer.h +++ b/pitimer.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Timer - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,6 +28,45 @@ typedef void (*TimerEvent)(void * , int ); +class PISystemTime { +public: + PISystemTime() {seconds = nanoseconds = 0;} + PISystemTime(long s, long ns) {seconds = s; nanoseconds = ns; checkOverflows();} + PISystemTime(const PISystemTime & t) {seconds = t.seconds; nanoseconds = t.nanoseconds;} + + double toSeconds() const {return double(seconds) + nanoseconds / 1.e+9;} + double toMilliseconds() const {return seconds * 1.e+3 + nanoseconds / 1.e+6;} + double toMicroseconds() const {return seconds * 1.e+6 + nanoseconds / 1.e+3;} + double toNanoseconds() const {return seconds * 1.e+9 + double(nanoseconds);} + void sleep() {piUSleep(piFloord(toMicroseconds()));} // wait self value, useful to wait some dT = (t1 - t0) + PISystemTime abs() const {return PISystemTime(piAbsl(seconds), piAbsl(nanoseconds));} + PISystemTime operator +(const PISystemTime & t) {PISystemTime tt(*this); tt.seconds += t.seconds; tt.nanoseconds += t.nanoseconds; tt.checkOverflows(); return tt;} + PISystemTime operator -(const PISystemTime & t) {PISystemTime tt(*this); tt.seconds -= t.seconds; tt.nanoseconds -= t.nanoseconds; tt.checkOverflows(); return tt;} + PISystemTime & operator +=(const PISystemTime & t) {seconds += t.seconds; nanoseconds += t.nanoseconds; checkOverflows(); return *this;} + PISystemTime & operator -=(const PISystemTime & t) {seconds -= t.seconds; nanoseconds -= t.nanoseconds; checkOverflows(); return *this;} + bool operator ==(const PISystemTime & t) {return ((seconds == t.seconds) && (nanoseconds == t.nanoseconds));} + bool operator !=(const PISystemTime & t) {return ((seconds != t.seconds) || (nanoseconds != t.nanoseconds));} + bool operator >(const PISystemTime & t) {if (seconds == t.seconds) return nanoseconds > t.nanoseconds; return seconds > t.seconds;} + bool operator <(const PISystemTime & t) {if (seconds == t.seconds) return nanoseconds < t.nanoseconds; return seconds < t.seconds;} + bool operator >=(const PISystemTime & t) {if (seconds == t.seconds) return nanoseconds >= t.nanoseconds; return seconds >= t.seconds;} + bool operator <=(const PISystemTime & t) {if (seconds == t.seconds) return nanoseconds <= t.nanoseconds; return seconds <= t.seconds;} + + static PISystemTime fromSeconds(double v) {long s = piFloord(v); return PISystemTime(s, (v - s) * 1000000000);} + static PISystemTime fromMilliseconds(double v) {long s = piFloord(v / 1000.); return PISystemTime(s, (v / 1000. - s) * 1000000000);} + static PISystemTime fromMicroseconds(double v) {long s = piFloord(v / 1000000.); return PISystemTime(s, (v / 1000000. - s) * 1000000000);} + static PISystemTime fromNanoseconds(double v) {long s = piFloord(v / 1000000000.); return PISystemTime(s, (v / 1000000000. - s) * 1000000000);} + + long seconds; + long nanoseconds; + +private: + void checkOverflows() {while (nanoseconds >= 1000000000) {nanoseconds -= 1000000000; seconds++;} while (nanoseconds < 0) {nanoseconds += 1000000000; seconds--;}} + +}; + +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 { int seconds; int minutes; @@ -38,29 +77,67 @@ struct PITime { struct PIDate { int day; int month; - int year; // since 1900 - PIString toString(const PIString & format = "d.mm.yyyy"); + int year; + PIString toString(const PIString & format = "d.MM.yyyy"); }; +struct PIDateTime { + int seconds; + int minutes; + int hours; + int day; + int month; + int year; + PIString toString(const PIString & format = "h:mm:ss d.MM.yyyy"); +}; + +/// events: +/// void timeout(void * data, int delimiter) +/// +/// handlers: +/// void start(double msecs) +/// void deferredStart(double interval_msecs, double delay_msecs) +/// void deferredStart(double interval_msecs, const PIDateTime & start_datetime) +/// void stop() +/// bool waitForFinish(int timeout_msecs = -1) +/// void reset() +/// void clearDelimiters() +/// void lock() +/// void unlock() class PITimer -#ifdef WINDOWS +#ifndef PIP_TIMER_RT : public PIThread #else : public PIObject #endif { public: - PITimer(TimerEvent slot = 0, void * data = 0); - ~PITimer(); + PITimer(TimerEvent slot = 0, void * data = 0, bool threaded = true); + PITimer(bool threaded); + virtual ~PITimer(); void setData(void * data_) {data = data_;} void setSlot(TimerEvent slot) {ret_func = slot;} -#ifdef WINDOWS - void reset() {t_st = GetCurrentTime();} +#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); +# 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); +# 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); +# endif #else EVENT_HANDLER0(PITimer, void, reset) {clock_gettime(0, &t_st);} EVENT_HANDLER1(PITimer, void, start, double, msecs); - EVENT_HANDLER0(PITimer, void, stop) {if (ti == 0) timer_delete(timer); ti = -1; running = false;} + 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;} @@ -83,29 +160,71 @@ public: double reset_time_u(); // microseconds double reset_time_m(); // miliseconds 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_s(); // seconds -private: -#ifdef WINDOWS - void run(); - long t_st, t_cur; -#else +#ifdef PIP_TIMER_RT + class TimerPool: public PIThread { + public: + TimerPool(): PIThread() {/*cout << "+++++new pool\n"; */ti = -1;} + ~TimerPool() {stop();} + void add(PITimer * t) {mutex.lock(); timers << TimerPair(t, 0); mutex.unlock();} + void remove(PITimer * t); + bool isEmpty() const {return timers.isEmpty();} + typedef PIPair TimerPair; + private: + static void empty_handler(int) {} + void begin(); + void run(); + void end() {/*cout << "pool end\n"; */if (ti != -1) timer_delete(timer); ti = -1;} + int ti, si; + sigset_t ss; + sigevent se; + sigval sv; + itimerspec spec; + + timer_t timer; + PIVector timers; + PIMutex mutex; + }; static void timer_event(sigval e); + int ticks; +#endif + + EVENT2(PITimer, timeout, void * , data, int, delimiter) + +protected: + virtual void tick(void * data, int delimiter) {;} - bool running; +private: +#ifndef PIP_TIMER_RT + void run(); + + PISystemTime st_time, inc_time; +#else + bool running, threaded; volatile bool lockRun; PIMutex mutex_; int ti; itimerspec spec; - timespec t_st, t_cur; timer_t timer; sigevent se; #endif + +#ifdef WINDOWS + long +#elif defined(MAC_OS) + mach_timespec_t +#else + timespec +#endif + t_st, t_cur; + struct TimerSlot { TimerSlot(TimerEvent slot_ = 0, int delim_ = 1) {slot = slot_; delim = delim_; tick = 0;} TimerEvent slot; @@ -119,9 +238,16 @@ private: }; +#ifdef PIP_TIMER_RT +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 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 #endif // PITIMER_H diff --git a/pivariable.cpp b/pivariable.cpp old mode 100755 new mode 100644 index 5890ae1d..85393b79 --- a/pivariable.cpp +++ b/pivariable.cpp @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Variable, Struct (simple serialization) - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/pivariable.h b/pivariable.h old mode 100755 new mode 100644 index ba35da6b..6f20de90 --- a/pivariable.h +++ b/pivariable.h @@ -1,7 +1,7 @@ /* PIP - Platform Independent Primitives Variable, Struct (simple serialization) - Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/protocols.conf b/protocols.conf new file mode 100644 index 00000000..41fbffb5 --- /dev/null +++ b/protocols.conf @@ -0,0 +1,192 @@ +# Eth + +#gas.receiver.ip = 192.168.5.36 #i +#gas.receiver.ip = 192.168.0.190 #i +gas.receiver.ip = 192.168.6.36 #i +gas.receiver.port = 9217 #n +gas.receiver.frequency = 100 #f +#gas.sender.ip = 192.168.5.2 #i +#gas.sender.ip = 192.168.0.190 #i +gas.sender.ip = 192.168.6.133 #i +#gas.sender.port = 1 #n +gas.sender.port = 10000 #n +gas.sender.frequency = 10 #f +gas.writeHistory = false #b + +# Eth +mcp1_c.receiver.ip = 192.168.5.36 #i +#mcp1.receiver.ip = 127.0.0.1 #i +mcp1_c.receiver.port = 4012 #n +mcp1_c.receiver.frequency = 20 #f +mcp1_c.sender.ip = 192.168.5.13 #i +#mcp1.sender.ip = 127.0.0.1 #i +mcp1_c.sender.port = 4013 #n +mcp1_c.sender.frequency = 20 #f +mcp1_c.writeHistory = false #b + +# Eth +mcp1_m.sender.ip = 192.168.5.13 #i +mcp1_m.sender.port = 4014 #n +mcp1_m.sender.frequency = 20 #f +mcp1_m.writeHistory = false #b + +# Eth +mcp1_i.receiver.ip = 192.168.5.36 #i +mcp1_i.receiver.port = 4016 #n +mcp1_i.sender.ip = 192.168.5.13 #i +mcp1_i.sender.port = 4015 #n +mcp1_i.writeHistory = false #b + +# Eth +mcp2.receiver.ip = 192.168.6.36 #i +mcp2.receiver.port = 4014 #n +mcp2.receiver.frequency = 20 #f +mcp2.sender.ip = 192.168.6.133 #i +mcp2.sender.port = 4015 #n +mcp2.sender.frequency = 20 #f +mcp2.writeHistory = false #b + +# RS +#slk.receiver.ip = 192.168.0.190 #i +slk.receiver.ip = 192.168.6.36 #i +slk.receiver.port = 3108 #n +slk.receiver.frequency = 10 #f +#slk.sender.ip = 192.168.0.175 #i +slk.sender.ip = 192.168.6.133 #i +slk.sender.port = 3109 #n +slk.sender.frequency = 10 #f +slk.disconnectTimeout = 1.5 #f +slk.writeHistory = false #b + +# RS +#ts.receiver.device = /dev/ttyS0 +#ts.receiver.speed = 57600 +#ts.receiver.parity = false +#ts.receiver.twoStopBits = false +ts.receiver.ip = 192.168.0.190 #i +ts.receiver.port = 4023 #n +ts.receiver.frequency = 23 #f +ts.sender.ip = 192.168.0.175 #i +ts.sender.port = 4023 #n +#ts.sender.frequency = 23 +ts_mcp1.receiver.ip = 192.168.0.190 #i +ts_mcp1.receiver.port = 4022 #n +ts_mcp1.sender.ip = 192.168.0.175 #i +ts_mcp1.sender.port = 4022 #n +ts.writeHistory = false #b + +# Eth +mv2.receiver.ip = 192.168.150.1 #i +mv2.receiver.port = 3003 #n +mv2.receiver.frequency = 20 #f +mv2.sender.ip = 192.168.150.16 #i +mv2.sender.port = 3003 #n +mv2.sender.frequency = 20 #f +mv2.writeHistory = false #b +mv2.historyID = 43079 #n + +#RS422 +mv2_res.device = /dev/ttyMI0 #s +mv2_res.speed = 115200 #n +mv2_res.frequency = 10 #f +mv2_res.twoStopBits = false #b +mv2_res.parity = false #b + + +# Eth +ki.mcp1.receiver.ip = 192.168.5.36 #i +ki.mcp1.receiver.port = 4102 #n +ki.mcp1.sender.ip = 192.168.5.13 #i +ki.mcp1.sender.port = 4101 #n +ki.mv2.receiver.ip = 192.168.150.1 #i +ki.mv2.receiver.port = 4104 #n +ki.mv2.sender.ip = 192.168.150.16 #i +ki.mv2.sender.port = 4103 #n + +# Eth +kpi_mcp1.receiver.ip = 192.168.5.36 #i +kpi_mcp1.receiver.port = 4204 #n +kpi_mcp1.sender.ip = 192.168.5.13 #i +kpi_mcp1.sender.port = 4203 #n + +# Eth +kpi_mcp2.receiver.ip = 192.168.6.36 #i +kpi_mcp2.receiver.port = 4206 #n +kpi_mcp2.sender.ip = 192.168.6.133 #i +kpi_mcp2.sender.port = 4205 #n + +# Eth +#rud.receiver.ip = 192.168.5.36 #i +rud.receiver.ip = 192.168.6.36 #i +rud.receiver.port = 4050 #n +rud.receiver.frequency = 20 #f + +# Eth +vpu.ip = 127.0.0.1 #i +vpu.receiver.port = 6001 #n +vpu.sender.port = 6000 #n +vpu.frequency = 20 #f + +# Eth +#kku.receiver.ip = 192.168.6.36 #i +kku.receiver.ip = 192.168.5.36 #i +kku.receiver.port = 5011 #n +kku.receiver.frequency = 20 #f +#kku.sender.ip = 192.168.6.133 #i +kku.sender.ip = 192.168.5.133 #i +kku.sender.port = 5010 #n +kku.sender.frequency = 20 #f + +# ??? +sep.receiver.ip = 192.168.150.1 #i +sep.receiver.port = 4031 #n +sep.receiver.frequency = 4 #f +sep.sender.ip = 192.168.150.16 #i +sep.sender.port = 4030 #n +#sep.sender.frequency = 4 #f + +# Eth +108ua.receiver.ip = 192.168.5.36 #i +108ua.receiver.port = 2002 #n +108ua.receiver.frequency = 10 #f +108ua.sender.ip = 192.168.5.36 #i +108ua.sender.port = 2011 #n +108ua.sender.frequency = 10 #f + +# Eth +108ua_r.receiver.ip = 192.168.6.36 #i +108ua_r.receiver.port = 2002 #n +108ua_r.receiver.frequency = 10 #f +108ua_r.sender.ip = 192.168.6.2 #i +108ua_r.sender.port = 2011 #n +108ua_r.sender.frequency = 10 #f + +# Eth +vpu_driver.ip = 127.0.0.1 #i +vpu_driver.receiver.port = 6000 #n +vpu_driver.sender.port = 6001 #n +vpu_driver.frequency = 20 #f + +# Eth +tvk.mv2.receiver.ip = 192.168.150.1 #i +tvk.mv2.receiver.port = 4024 #n +tvk.mv2.sender.ip = 192.168.150.16 #i +tvk.mv2.sender.port = 4024 #n +tvk.mcp2.receiver.ip = 192.168.6.36 #i +tvk.mcp2.receiver.port = 4024 #n +tvk.mcp2.sender.ip = 192.168.6.133 #i +tvk.mcp2.sender.port = 4024 #n + +#Eth +bpd.receiver.ip = 127.0.0.1 #i +bpd.receiver.port = 2012 #n +bpd.sender.ip = 127.0.0.1 #i +bpd.sender.port = 2013 #n + +# Eth +astd.receiver.ip = 192.168.5.36 #i +astd.receiver.port = 5298 #n +astd.sender.ip = 192.168.5.2 #i +astd.sender.port = 1101 #n +astd.frequency = 1 #f +astd.writeHistory = false #b diff --git a/system_test/CMakeLists.txt b/system_test/CMakeLists.txt new file mode 100644 index 00000000..8dd7e8a7 --- /dev/null +++ b/system_test/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 2.6) +include_directories(${CMAKE_CURRENT_SOURCE_DIR} . ../) +file(GLOB CPPS "*.cpp") +add_definitions(-Wall -O2) +add_executable(pip_sys_test "main.cpp") +target_link_libraries(pip_sys_test pip) diff --git a/system_test/main.cpp b/system_test/main.cpp new file mode 100644 index 00000000..91e87ca3 --- /dev/null +++ b/system_test/main.cpp @@ -0,0 +1,106 @@ +/* + PIP - Platform Independent Primitives + System tests program + Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "pip.h" +#include "pisystemtests.h" + + +int main(int argc, char * argv[]) { +#ifdef WINDOWS + cout << "This program is useless for Windows" << endl; + return 0; +#else + if (getuid() != 0) { + cout << "You should run this program as root!" << endl; + return 0; + } + PIConfig conf( +#ifndef WINDOWS + "/etc/pip.conf" +#else + "pip.conf" +#endif + ); + PITimer timer, tm; + timespec ts; + long stc = 0; + double st; + llong sts = 0; + clock_getres(CLOCK_REALTIME, &ts); + stc = long(ts.tv_sec) * 1000000000l + long(ts.tv_nsec); + conf.setValue("time_resolution_ns", stc); + cout << "Timer resolution is " << stc << " ns" << endl; + + cout << "\"PITimer.elapsed_*\" test ... " << flush; + stc = 0; + ts.tv_sec = 0; + ts.tv_nsec = 1000; + PIVector times; + times.resize(8192); + tm.reset(); + PISystemTests::time_elapsed_ns = 0; + while (tm.elapsed_s() < 3.) { + for (int i = 0; i < times.size_s(); ++i) { + timer.reset(); + times[i] = timer.elapsed_m(); + times[i] = timer.elapsed_s(); + times[i] = timer.elapsed_u(); + } + st = 0; + for (int i = 0; i < times.size_s(); ++i) + st += times[i]; + //cout << times[0] << endl; + //cout << st / times.size_s() / 3. * 1000. << endl; + sts += piRoundd(st / times.size_s() / 3. * 1000.); + //cout << sts << endl; + stc++; + } + sts /= stc; + conf.setValue("time_elapsed_ns", long(sts)); + cout << "ok, cost " << sts << " ns, average in " << stc << " series (" << (stc * 3 * times.size_s()) << " executes)" << endl; + + cout << "\"usleep\" offset test ... " << flush; + PISystemTests::time_elapsed_ns = sts; + tm.reset(); + stc = 0; + sts = 0; + times.resize(128); + while (tm.elapsed_s() < 3.) { + for (int i = 0; i < times.size_s(); ++i) { + timer.reset(); + usleep(1000); + times[i] = timer.elapsed_u(); + } + st = 0; + for (int i = 0; i < times.size_s(); ++i) + st += times[i] - 1000; + //cout << times[0] << endl; + //cout << st / times.size_s() / 3. * 1000. << endl; + sts += piRoundd(st / times.size_s()); + //cout << sts << endl; + stc++; + } + sts /= stc; + conf.setValue("usleep_offset_us", long(sts)); + cout << "ok, " << sts << " us, average in " << stc << " series (" << (stc * times.size_s()) << " executes)" << endl; + + //WAIT_FOR_EXIT + return 0; +#endif +}; diff --git a/Описание.odt b/Описание.odt old mode 100755 new mode 100644 index 3ccc99e6..0b887c4a Binary files a/Описание.odt and b/Описание.odt differ diff --git a/Описание.pdf b/Описание.pdf old mode 100755 new mode 100644