18.03.2013 - Bug fixes, add in/out speed diagnostic to PIProtocol, fixed PIConsole tab switch segfault, PIObject EVENT / EVENT_HANDLER mechanism update - new EVENT macros that use EVENT_HANDLER with raiseEvent implementation.

This allow compile check event for CONNECT and use EVENT as CONNECT target, also raise event now is simple execute EVENT function.
This commit is contained in:
peri4
2013-03-18 12:07:44 +04:00
parent cfc5eed75e
commit 66c53a27fc
72 changed files with 4407 additions and 960 deletions

View File

@@ -1,22 +1,23 @@
project(pip) project(pip)
find_package(Qt4) find_package(Qt4)
cmake_minimum_required(VERSION 2.6) 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") file(GLOB CPPS "pi*.cpp")
if (${WIN32}) if (${WIN32})
add_definitions(-Wall -O2) add_definitions(-Wall -O2)
else (${WIN32}) else (${WIN32})
add_definitions(-Wall -O2 -g3) add_definitions(-Wall -O2 -g3 --fast-math)
endif (${WIN32}) endif (${WIN32})
add_library(pip SHARED ${CPPS}) add_library(pip SHARED ${CPPS})
if (${WIN32}) if (${WIN32})
target_link_libraries(pip pthread ws2_32) target_link_libraries(pip pthread ws2_32 Iphlpapi)
else (${WIN32}) else (${WIN32})
target_link_libraries(pip pthread rt) target_link_libraries(pip pthread rt)
endif (${WIN32}) endif (${WIN32})
add_executable(pip_test "main.cpp") add_executable(pip_test "main.cpp")
if (${WIN32}) if (${WIN32})
target_link_libraries(pip_test pthread ws2_32 pip) target_link_libraries(pip_test pthread ws2_32 Iphlpapi pip)
else (${WIN32}) 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}) endif (${WIN32})
add_subdirectory(system_test)

22
clean
View File

@@ -1,19 +1,7 @@
#! /bin/bash #! /bin/sh
VERBOSE=1 make clean 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 -rvf ./CMakeFiles
rm -vf ./CMakeCache.txt ./Makefile ./cmake_install.cmake ./install_manifest.txt ./*~ ./*cxx ./moc_* ./*.o rm -vf ./CMakeCache.txt ./Makefile ./cmake_install.cmake ./install_manifest.txt ./*~ ./*cxx ./moc_* ./*.o ./core
#cd ./include cd system_test
#for i in $( ls -1 ); do rm -rvf ./CMakeFiles
# if [ "`ls -1 --file-type $i | grep -v @`" = "" ]; then rm -vf ./CMakeCache.txt ./Makefile ./cmake_install.cmake ./install_manifest.txt ./*~ ./*cxx ./moc_* ./*.o ./core
# rm -v $i
# fi
#done

264
main.cpp Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Test program 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 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 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; cout << " tick from constuctor, delimiter = " << delim << ", data = " << data << endl;
}; };
bool bool t2 = false;
t2 = false;
void timerEvent2(void * data, int delim) { void timerEvent2(void * data, int delim) {
t2 = true; t2 = true;
cout << " tick from delimiter " << delim << ", data = " << data << endl; cout << " tick from delimiter " << delim << ", data = " << data << endl;
@@ -86,12 +85,16 @@ public:
ObjectTest2(const PIString & name = PIString()): PIObject(name) {;} ObjectTest2(const PIString & name = PIString()): PIObject(name) {;}
void raise0(const PIString & e) {cout << " event \"" << e << "\" from \"" << name() << "\"" << endl; raiseEvent(this, e);} 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<int, PIString>(this, e, i, s);} void raise2(const PIString & e, int i, const PIString & s) {cout << " event \"" << e << "\" from \"" << name() << "\"" << endl; raiseEvent<int, PIString>(this, e, i, s);}
EVENT(ObjectTest2, event0)
EVENT(ObjectTest2, event2)
}; };
class CA: public PIObject { class CA: public PIObject {
public: public:
CA(const PIString & n): PIObject(n) {;} CA(const PIString & n): PIObject(n) {;}
EVENT_HANDLER(CA, void, handler_ca) {a = true; cout << " handler CA" << endl;} EVENT_HANDLER(CA, void, handler_ca) {a = true; cout << " handler CA" << endl;}
EVENT(CA, event_ca)
bool a; bool a;
}; };
@@ -124,60 +127,212 @@ struct Packet {
int cs; 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) { #pragma pack(pop)
cout << "rec " << size << endl;
return true;
};
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[]) { int main(int argc, char * argv[]) {
/*Packet p, mp; /*tm_.start(10.);
p.from = mp.from = 1; PIConsole con(false, ke);
p.to = mp.to = 2; con.enableExitCapture();
PISerial ser("/dev/ttyS0"); //ser.setParameter(PISerial::HardwareFlowControl);
ser.setSpeed(PISerial::S115200);
ser.open(); ser.open();
ser.setReadIsBlocking(true); con.addVariable("1 (CAR)", pins);
PIPacketExtractor pe(&ser, &mp, 8, 8); con.addVariable("2 (SR) ", pins + 1);
pe.setThreadedReadSlot(retF); con.addVariable("3 (ST) ", pins + 2);
pe.setHeaderCheckSlot(retH); con.addVariable("4 (DTR)", pins + 3);
pe.startThreadedRead(); con.addVariable("5 (GND)", pins + 4);
ser.write(&p, sizeof(p)); con.addVariable("6 (DSR)", pins + 5);
p.from = 2; con.addVariable("7 (RTS)", pins + 6);
ser.write(&p, sizeof(p)); con.addVariable("8 (CTS)", pins + 7);
msleep(1000); con.addVariable("9 (RNG)", pins + 8);
exit(0);*/ con.start();
PICodec codec; 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); /*PIDir dir(argv[1]);
/* FILE*f = popen("cd ../ && pwd", "w");
vec<int> my_v; vector<int> stl_v; QVector<int> qt_v; char fd[4096];
double el; int ret = fread(fd, 4096, 1, f);
PITimer tm; 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<PIDir::DirEntry> 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<complexd> 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<complexd> * out = fft.calcFFT(in);
cout << timer_.elapsed_m() << endl;
Graphic * g = new Graphic();
QVector<QPointF> res;
fft.getAmplitude();
for (int i=0; i<out->size(); 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(); return app.exec();*/
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);
*/
bool r_string = true, r_thread = true, r_mutex = true, r_timer = true, r_file = true, r_eval = true, r_event = true; 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; bool succ = true;
cout << "== PIP test program ==" << endl; cout << "== PIP test program ==" << endl;
@@ -189,8 +344,10 @@ int main(int argc, char * argv[]) {
cout << " to char * = \"" << string.data() << "\"" << endl; cout << " to char * = \"" << string.data() << "\"" << endl;
cout << " to std::string = \"" << string.stdString() << "\"" << endl; cout << " to std::string = \"" << string.stdString() << "\"" << endl;
if (string.stdString().length() != 11) succ = r_string = false; if (string.stdString().length() != 11) succ = r_string = false;
#ifdef HAS_LOCALE
cout << " to std::wstring = \"" << string.stdWString() << "\"" << endl; cout << " to std::wstring = \"" << string.stdWString() << "\"" << endl;
if (string.stdWString().length() != 11) succ = r_string = false; if (string.stdWString().length() != 11) succ = r_string = false;
#endif
if (succ) cout << " convertions success" << endl; if (succ) cout << " convertions success" << endl;
else cout << " convertions fail" << endl; else cout << " convertions fail" << endl;
succ = true; succ = true;
@@ -199,9 +356,11 @@ int main(int argc, char * argv[]) {
if (string.length() != 5) succ = r_string = false; if (string.length() != 5) succ = r_string = false;
cout << " to char * = \"" << string.data() << "\"" << endl; cout << " to char * = \"" << string.data() << "\"" << endl;
cout << " to std::string = \"" << string.stdString() << "\"" << 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; cout << " to std::wstring = \"" << string.stdWString() << "\"" << endl;
if (string.stdWString().length() != 5) succ = r_string = false; if (string.stdWString().length() != 5) succ = r_string = false;
#endif
if (succ) cout << " complex convertions success" << endl; if (succ) cout << " complex convertions success" << endl;
else cout << " complex convertions fail" << endl; else cout << " complex convertions fail" << endl;
if (r_string) cout << "== Success ==" << endl; if (r_string) cout << "== Success ==" << endl;
@@ -244,6 +403,7 @@ int main(int argc, char * argv[]) {
cout << " file \"" << file.path() << "\" is "; cout << " file \"" << file.path() << "\" is ";
if (!file.isOpened()) cout << "not "; if (!file.isOpened()) cout << "not ";
cout << "opened" << endl; cout << "opened" << endl;
file.clear();
file << "test string"; file << "test string";
cout << " write " << file.pos() << " bytes" << endl; cout << " write " << file.pos() << " bytes" << endl;
if (file.pos() != 11) r_file = false; if (file.pos() != 11) r_file = false;
@@ -264,7 +424,7 @@ int main(int argc, char * argv[]) {
cout << " error = \"" << evaluator.error() << '\"' << endl; cout << " error = \"" << evaluator.error() << '\"' << endl;
cout << " \"x\" = " << evaluator.content.variable("x").value << endl; cout << " \"x\" = " << evaluator.content.variable("x").value << endl;
cout << " result = " << evaluator.evaluate() << 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; if (r_eval) cout << "== Success ==" << endl;
else cout << "== Fail ==" << endl; else cout << "== Fail ==" << endl;

2
make.sh Executable file → Normal file
View File

@@ -1,3 +1,3 @@
#! /bin/bash #! /bin/sh
cmake ./ cmake ./
make $@ make $@

View File

@@ -1,4 +1,4 @@
#! /bin/bash #! /bin/sh
cmake . cmake .
make $@ make $@
cp -vf *.h /usr/include/ cp -vf *.h /usr/include/

2
pibitarray.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Bit array 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 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 it under the terms of the GNU General Public License as published by

50
pibytearray.cpp Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Byte array 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 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 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; if (size() == 0) return *this;
int sz = (size_s() / 3) * 3; int sz = (size_s() / 3) * 3;
for (int i = 0; i < sz; ++i) { for (int i = 0; i < sz; ++i) {
hs.byte0 = hs.byte1 = hs.byte2 = 0; hs.byte.byte0 = hs.byte.byte1 = hs.byte.byte2 = 0;
hs.byte0 = at(i); hs.byte.byte0 = at(i);
hs.byte1 = at(++i); hs.byte.byte1 = at(++i);
hs.byte2 = at(++i); hs.byte.byte2 = at(++i);
t.push_back(base64Table[hs.ascii0]); t.push_back(base64Table[hs.ascii.ascii0]);
t.push_back(base64Table[hs.ascii1]); t.push_back(base64Table[hs.ascii.ascii1]);
t.push_back(base64Table[hs.ascii2]); t.push_back(base64Table[hs.ascii.ascii2]);
t.push_back(base64Table[hs.ascii3]); 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) { switch (sz) {
case 1: case 1:
hs.byte0 = back(); hs.byte.byte0 = back();
t.push_back(base64Table[hs.ascii0]); t.push_back(base64Table[hs.ascii.ascii0]);
t.push_back(base64Table[hs.ascii1]); t.push_back(base64Table[hs.ascii.ascii1]);
t.push_back('='); t.push_back('=');
t.push_back('='); t.push_back('=');
break; break;
case 2: case 2:
hs.byte0 = at(size() - 2); hs.byte1 = back(); hs.byte.byte0 = at(size() - 2); hs.byte.byte1 = back();
t.push_back(base64Table[hs.ascii0]); t.push_back(base64Table[hs.ascii.ascii0]);
t.push_back(base64Table[hs.ascii1]); t.push_back(base64Table[hs.ascii.ascii1]);
t.push_back(base64Table[hs.ascii2]); t.push_back(base64Table[hs.ascii.ascii2]);
t.push_back('='); t.push_back('=');
break; break;
default: break; default: break;
@@ -97,14 +97,14 @@ PIByteArray & PIByteArray::convertFromBase64() {
uint sz = size(); uint sz = size();
if (sz == 0) return *this; if (sz == 0) return *this;
for (uint i = 0; i < sz; ++i) { for (uint i = 0; i < sz; ++i) {
hs.byte0 = hs.byte1 = hs.byte2 = 0; hs.byte.byte0 = hs.byte.byte1 = hs.byte.byte2 = 0;
hs.ascii0 = base64InvTable[at(i)]; hs.ascii.ascii0 = base64InvTable[at(i)];
hs.ascii1 = base64InvTable[at(++i)]; hs.ascii.ascii1 = base64InvTable[at(++i)];
hs.ascii2 = base64InvTable[at(++i)]; hs.ascii.ascii2 = base64InvTable[at(++i)];
hs.ascii3 = base64InvTable[at(++i)]; hs.ascii.ascii3 = base64InvTable[at(++i)];
t.push_back(hs.byte0); t.push_back(hs.byte.byte0);
t.push_back(hs.byte1); t.push_back(hs.byte.byte1);
t.push_back(hs.byte2); t.push_back(hs.byte.byte2);
} }
if (back() == '=') t.pop_back(); if (back() == '=') t.pop_back();
if (sz > 1) if (at(sz - 2) == '=') t.pop_back(); if (sz > 1) if (at(sz - 2) == '=') t.pop_back();

51
pibytearray.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Byte array 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 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 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 & 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(); uchar checksumPlain8();
uint checksumPlain32(); uint checksumPlain32();
uchar checksumCRC8(); uchar checksumCRC8();
@@ -125,12 +134,12 @@ private:
uchar ascii1: 6; uchar ascii1: 6;
uchar ascii2: 6; uchar ascii2: 6;
uchar ascii3: 6; uchar ascii3: 6;
}; } ascii;
struct { struct {
uchar byte0; uchar byte0;
uchar byte1; uchar byte1;
uchar byte2; uchar byte2;
}; } byte;
}; };
static PIHuffman huffman; 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 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 <typename T>
inline PIByteArray & operator <<(PIByteArray & s, const PIVector<T> & v) {s << v.size_s(); for (uint i = 0; i < v.size(); ++i) s << v[i]; return s;}
template <typename T>
inline PIByteArray & operator <<(PIByteArray & s, const PIList<T> & v) {s << v.size_s(); for (uint i = 0; i < v.size(); ++i) s << v[i]; return s;}
template <typename T>
inline PIByteArray & operator <<(PIByteArray & s, const PIDeque<T> & 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 <typename T>
inline PIByteArray & operator >>(PIByteArray & s, PIVector<T> & v) {int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;}
template <typename T>
inline PIByteArray & operator >>(PIByteArray & s, PIList<T> & v) {int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;}
template <typename T>
inline PIByteArray & operator >>(PIByteArray & s, PIDeque<T> & v) {int sz; s >> sz; v.resize(sz); for (int i = 0; i < sz; ++i) s >> v[i]; return s;}
#endif // PIBYTEARRAY_H #endif // PIBYTEARRAY_H

27
pichar.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Unicode char 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 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 it under the terms of the GNU General Public License as published by
@@ -20,11 +20,13 @@
#ifndef PICHAR_H #ifndef PICHAR_H
#define PICHAR_H #define PICHAR_H
#include "piincludes.h" #include "pibytearray.h"
class PIChar class PIChar
{ {
friend class PIString; friend class PIString;
friend PIByteArray & operator <<(PIByteArray & s, const PIChar & v);
friend PIByteArray & operator >>(PIByteArray & s, PIChar & v);
public: public:
PIChar(const char c) {ch = c; ch &= 0xFF;} PIChar(const char c) {ch = c; ch &= 0xFF;}
PIChar(const short c) {ch = c; ch &= 0xFFFF;} PIChar(const short c) {ch = c; ch &= 0xFFFF;}
@@ -33,17 +35,17 @@ public:
PIChar(const ushort c) {ch = c; ch &= 0xFFFF;} PIChar(const ushort c) {ch = c; ch &= 0xFFFF;}
PIChar(const uint c) {ch = c;} PIChar(const uint c) {ch = c;}
PIChar(const char * c) {ch = *reinterpret_cast<const int * >(c);} PIChar(const char * c) {ch = *reinterpret_cast<const int * >(c);}
//inline operator const int() {return static_cast<const int>(ch);} //inline operator const int() {return static_cast<const int>(ch);}
//inline operator const char() {return toAscii();} //inline operator const char() {return toAscii();}
PIChar & operator =(const char v) {ch = v; return *this;} PIChar & operator =(const char v) {ch = v; return *this;}
/*inline PIChar & operator =(const short 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 int v) {ch = v; return *this;}
inline PIChar & operator =(const uchar 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 ushort v) {ch = v; return *this;}
inline PIChar & operator =(const uint 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;} 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; /*inline bool operator ==(const PIChar & o) const {if (o.isAscii() ^ isAscii()) return false;
if (isAscii()) return (o.toAscii() == toAscii()); 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 uchar o) const {return (PIChar(o) == *this);}
inline bool operator ==(const ushort 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);}*/ inline bool operator ==(const uint o) const {return (PIChar(o) == *this);}*/
bool operator !=(const PIChar & o) const {return !(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 char o) const {return (PIChar(o) != *this);}
inline bool operator !=(const short 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 uchar o) const {return (PIChar(o) != *this);}
inline bool operator !=(const ushort 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);}*/ 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 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 isDigit() const {return isdigit(ch) != 0;}
bool isHex() const {return isxdigit(ch) != 0;} bool isHex() const {return isxdigit(ch) != 0;}
bool isGraphical() const {return isgraph(ch) != 0;} bool isGraphical() const {return isgraph(ch) != 0;}
@@ -78,7 +80,7 @@ public:
bool isSpace() const {return isspace(ch) != 0;} bool isSpace() const {return isspace(ch) != 0;}
bool isAlpha() const {return isalpha(ch) != 0;} bool isAlpha() const {return isalpha(ch) != 0;}
bool isAscii() const {return isascii(ch) != 0;} bool isAscii() const {return isascii(ch) != 0;}
int toInt() const {return static_cast<const int>(ch);} int toInt() const {return static_cast<const int>(ch);}
const wchar_t * toWCharPtr() const {return &ch;} const wchar_t * toWCharPtr() const {return &ch;}
const char * toCharPtr() const {return reinterpret_cast<const char * >(&ch);} const char * toCharPtr() const {return reinterpret_cast<const char * >(&ch);}
@@ -92,14 +94,17 @@ public:
PIChar toUpper() const {return PIChar(toupper(ch));} PIChar toUpper() const {return PIChar(toupper(ch));}
PIChar toLower() const {return PIChar(tolower(ch));} PIChar toLower() const {return PIChar(tolower(ch));}
//#endif //#endif
private: private:
wchar_t ch; wchar_t ch;
}; };
inline std::ostream & operator <<(std::ostream & s, const PIChar & v) {s << v.toCharPtr(); return s;} 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);} 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);}

4
picli.cpp Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Command-Line Parser 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 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 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_short = "-";
_prefix_full = "--"; _prefix_full = "--";
_count_opt = 0; _count_opt = 0;
_count_mand = 1; _count_mand = 0;
for (int i = 0; i < argc; ++i) for (int i = 0; i < argc; ++i)
_args_raw << argv[i]; _args_raw << argv[i];
} }

2
picli.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Command-Line Parser 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 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 it under the terms of the GNU General Public License as published by

2
picodec.cpp Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Text codings coder, based on "iconv" 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 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 it under the terms of the GNU General Public License as published by

2
picodec.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Text codings coder, based on "iconv" 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 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 it under the terms of the GNU General Public License as published by

5
piconfig.cpp Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Config parser 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 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 it under the terms of the GNU General Public License as published by
@@ -396,6 +396,7 @@ void PIConfig::writeAll() {
*this << other[i]; *this << other[i];
if (i < other.size_s() - 1) *this << '\n'; if (i < other.size_s() - 1) *this << '\n';
} }
//cout << other[i] << endl;
} }
flush(); flush();
readAll(); readAll();
@@ -433,9 +434,9 @@ void PIConfig::parse() {
while (!isEnd()) { while (!isEnd()) {
other.push_back(PIString()); other.push_back(PIString());
src = str = readLine(); src = str = readLine();
//cout << str << endl;
tab = str.left(str.find(str.trimmed().left(1))); tab = str.left(str.find(str.trimmed().left(1)));
str.trim(); str.trim();
//cout << endl << str << endl << endl;
all = str; all = str;
ind = str.find('='); ind = str.find('=');
if ((ind > 0) && !(str[0] == '#')) { if ((ind > 0) && !(str[0] == '#')) {

2
piconfig.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Config parser 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 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 it under the terms of the GNU General Public License as published by

159
piconsole.cpp Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Console output/input 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 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 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) { int PIConsole::addTab(const PIString & name, char bind_key) {
if (isRunning()) lock();
tabs.push_back(Tab(name, bind_key)); tabs.push_back(Tab(name, bind_key));
cur_tab = tabs.size() - 1; cur_tab = tabs.size() - 1;
if (isRunning()) unlock();
return tabs.size(); return tabs.size();
} }
void PIConsole::removeTab(uint index) { void PIConsole::removeTab(uint index) {
if (index >= tabs.size()) return; if (index >= tabs.size()) return;
if (isRunning()) lock();
tabs.remove(index); tabs.remove(index);
if (cur_tab >= tabs.size()) cur_tab = tabs.size() - 1; 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) { bool PIConsole::setTab(uint index) {
if (index >= tabs.size()) if (index >= tabs.size())
return false; return false;
cur_tab = index; if (!isRunning()) {
if (!isRunning()) return true; cur_tab = index;
return true;
}
lock(); lock();
cur_tab = index;
clearScreen(); clearScreen();
fillLabels(); fillLabels();
unlock(); unlock();
@@ -156,6 +163,7 @@ PIString PIConsole::fstr(PIFlags<PIConsole::Format> f) {
if (f[PIConsole::Dec]) num_format = 0; if (f[PIConsole::Dec]) num_format = 0;
if (f[PIConsole::Hex]) num_format = 1; if (f[PIConsole::Hex]) num_format = 1;
if (f[PIConsole::Oct]) num_format = 2; if (f[PIConsole::Oct]) num_format = 2;
if (f[PIConsole::Bin]) num_format = 4;
if (f[PIConsole::Scientific]) num_format = 3; if (f[PIConsole::Scientific]) num_format = 3;
#ifdef WINDOWS #ifdef WINDOWS
@@ -232,15 +240,15 @@ PIString PIConsole::fstr(PIFlags<PIConsole::Format> f) {
#endif #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 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; default: return printf("%d", 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; default: return printf("%ld", 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; default: return printf("%lld", 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; default: return printf("%u", 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; default: return printf("%hu", 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; default: return printf("%u", 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; default: return printf("%lu", 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; default: return printf("%llu", 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 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;} #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 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 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 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 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 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 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 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 10: clen = printValue(tv.ush != 0 ? *tv.ush : ushort(0), tv.format); break;
case 11: clen = printValue(tv.uc != 0 ? *tv.uc : 0u, 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 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 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; case 14: clen = printValue(bitsValue(tv.ptr, tv.bitFrom, tv.bitCount), tv.format); break;
} }
if (clen + tv.offset < (uint)col_wid) { 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(); string ts = PIString(col_wid - clen - tv.offset - 1, ' ').stdString();
#else #else
string ts = PIString(col_wid - clen - tv.offset, ' ').stdString(); string ts = PIString(col_wid - clen - tv.offset, ' ').stdString();
@@ -340,6 +348,7 @@ void PIConsole::run() {
void PIConsole::fillLabels() { void PIConsole::fillLabels() {
if (!isRunning()) return;
uint cx, cy, my = 0, mx = 0, dx; uint cx, cy, my = 0, mx = 0, dx;
#ifdef WINDOWS #ifdef WINDOWS
GetConsoleScreenBufferInfo(hOut, &sbi); GetConsoleScreenBufferInfo(hOut, &sbi);
@@ -359,7 +368,7 @@ void PIConsole::fillLabels() {
if (ccol.alignment != Nothing) { if (ccol.alignment != Nothing) {
mx = 0; mx = 0;
piForeachC (Variable & j, cvars) piForeachC (Variable & j, cvars)
if (j.type != 0 && j.s != 0) if (j.s != 0)
if (mx < j.name.size()) if (mx < j.name.size())
mx = j.name.size(); mx = j.name.size();
mx += 2; mx += 2;
@@ -390,25 +399,27 @@ void PIConsole::fillLabels() {
cy++; cy++;
continue; continue;
} }
switch (ccol.alignment) { if (tv.s != 0) {
case Nothing: switch (ccol.alignment) {
cvars[j].offset = (tv.name + ": ").length(); case Nothing:
cvars[j].nx += cvars[j].offset; cvars[j].offset = (tv.name + ": ").length();
printValue(tv.name + ": ", tv.format); cvars[j].nx += cvars[j].offset;
break; printValue(tv.name + ": ", tv.format);
case Left: break;
cvars[j].offset = mx; case Left:
cvars[j].nx += cvars[j].offset; cvars[j].offset = mx;
printValue(tv.name + ": ", tv.format); cvars[j].nx += cvars[j].offset;
break; printValue(tv.name + ": ", tv.format);
case Right: break;
cvars[j].offset = mx; case Right:
cvars[j].nx += cvars[j].offset; cvars[j].offset = mx;
dx = mx - (tv.name + ": ").length(); cvars[j].nx += cvars[j].offset;
moveRight(dx); dx = mx - (tv.name + ": ").length();
printValue(tv.name + ": ", tv.format); moveRight(dx);
moveLeft(dx); printValue(tv.name + ": ", tv.format);
break; moveLeft(dx);
break;
}
} }
newLine(); newLine();
cy++; 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; int ret = 0, stbyte = offset / 8, cbit = offset - stbyte * 8;
char cbyte = reinterpret_cast<char * >(src)[stbyte]; char cbyte = reinterpret_cast<const char * >(src)[stbyte];
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
ret |= ((cbyte >> cbit & 1) << i); ret |= ((cbyte >> cbit & 1) << i);
cbit++; cbit++;
if (cbit == 8) { if (cbit == 8) {
cbit = 0; cbit = 0;
stbyte++; stbyte++;
cbyte = reinterpret_cast<char * >(src)[stbyte]; cbyte = reinterpret_cast<const char * >(src)[stbyte];
} }
} }
return ret; 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); #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<PIConsole::Format> format) { void PIConsole::addString(const PIString & name, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 0; tv.s = 0; column(col).push_back(tv);} 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<PIConsole::Format> format) { void PIConsole::addVariable(const PIString & name, const PIString* ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 0; tv.s = ptr; column(col).push_back(tv);} 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<PIConsole::Format> format) { void PIConsole::addVariable(const PIString & name, const bool * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 1; tv.b = ptr; column(col).push_back(tv);} 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<PIConsole::Format> format) { void PIConsole::addVariable(const PIString & name, const int * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 2; tv.i = ptr; column(col).push_back(tv);} 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<PIConsole::Format> format) { void PIConsole::addVariable(const PIString & name, const long * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 3; tv.l = ptr; column(col).push_back(tv);} 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<PIConsole::Format> format) { void PIConsole::addVariable(const PIString & name, const char * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 4; tv.c = ptr; column(col).push_back(tv);} 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<PIConsole::Format> format) { void PIConsole::addVariable(const PIString & name, const float * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 5; tv.f = ptr; column(col).push_back(tv);} 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<PIConsole::Format> format) { void PIConsole::addVariable(const PIString & name, const double * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 6; tv.d = ptr; column(col).push_back(tv);} 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<PIConsole::Format> format) { void PIConsole::addVariable(const PIString & name, const short * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 7; tv.sh = ptr; column(col).push_back(tv);} 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<PIConsole::Format> format) { void PIConsole::addVariable(const PIString & name, const uint * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 8; tv.ui = ptr; column(col).push_back(tv);} 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<PIConsole::Format> format) { void PIConsole::addVariable(const PIString & name, const ulong * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 9; tv.ul = ptr; column(col).push_back(tv);} 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<PIConsole::Format> format) { void PIConsole::addVariable(const PIString & name, const ushort * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 10; tv.ush = ptr; column(col).push_back(tv);} 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<PIConsole::Format> format) { void PIConsole::addVariable(const PIString & name, const uchar * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 11; tv.uc = ptr; column(col).push_back(tv);} 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<PIConsole::Format> format) { void PIConsole::addVariable(const PIString & name, const llong * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 12; tv.ll = ptr; column(col).push_back(tv);} 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<PIConsole::Format> format) { void PIConsole::addVariable(const PIString & name, const ullong * ptr, int col, PIFlags<PIConsole::Format> format) {
ADD_VAR_BODY tv.type = 13; tv.ull = ptr; column(col).push_back(tv);} 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<PIConsole::Format> format) { void PIConsole::addVariable(const PIString & name, const PIProtocol * ptr, int col, PIFlags<PIConsole::Format> format) {
addString("protocol " + name, col, format | PIConsole::Bold); addString("protocol " + name, col, format | PIConsole::Bold);
addVariable("Rec :" + ptr->receiverDeviceName() + " ", ptr->receiverDeviceState_ptr(), col, format); addVariable("Rec - " + ptr->receiverDeviceName(), ptr->receiverDeviceState_ptr(), col, format);
addVariable("Send:" + ptr->senderDeviceName() + " ", ptr->senderDeviceState_ptr(), col, format); addVariable("Send - " + ptr->senderDeviceName(), ptr->senderDeviceState_ptr(), col, format);
addVariable("Sended count", ptr->sendCount_ptr(), col, format); addVariable("Sended count", ptr->sendCount_ptr(), col, format);
addVariable("Received count", ptr->receiveCount_ptr(), col, format); addVariable("Received count", ptr->receiveCount_ptr(), col, format);
addVariable("Invalid count", ptr->wrongCount_ptr(), col, format); addVariable("Invalid count", ptr->wrongCount_ptr(), col, format);
addVariable("Missed count", ptr->missedCount_ptr(), col, format); addVariable("Missed count", ptr->missedCount_ptr(), col, format);
addVariable("Immediate Frequency, Hz", ptr->immediateFrequency_ptr(), col, format); addVariable("Immediate Frequency, Hz", ptr->immediateFrequency_ptr(), col, format);
addVariable("Integral Frequency, Hz", ptr->integralFrequency_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("Receiver history size", ptr->receiverHistorySize_ptr(), col, format);
addVariable("Sender history size", ptr->senderHistorySize_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); addVariable("Quality", ptr->quality_ptr(), col, format);
} }
void PIConsole::addVariable(const PIString & name, PISystemMonitor * ptr, int col, PIFlags<PIConsole::Format> format) { void PIConsole::addVariable(const PIString & name, const PISystemMonitor * ptr, int col, PIFlags<PIConsole::Format> format) {
addString("monitor " + name, col, format | PIConsole::Bold); addString("monitor " + name, col, format | PIConsole::Bold);
addVariable("state ", &(ptr->statistic().state), col, format); addVariable("state", &(ptr->statistic().state), col, format);
addVariable("threads ", &(ptr->statistic().threads), col, format); addVariable("threads", &(ptr->statistic().threads), col, format);
addVariable("priority", &(ptr->statistic().priority), col, format); addVariable("priority", &(ptr->statistic().priority), col, format);
addVariable("memory physical", &(ptr->statistic().physical_memsize_readable), 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); 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<PIConsole::Format> format) { void PIConsole::addBitVariable(const PIString & name, const void * ptr, int fromBit, int bitCount, int col, PIFlags<PIConsole::Format> format) {
tv.name = name; tv.bitFrom = fromBit; tv.bitCount = bitCount; tv.type = 14; tv.ptr = ptr; tv.format = 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);} checkColumn(col); column(col).push_back(tv);}
void PIConsole::addEmptyLine(int col, uint count) { 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<PIConsole::Format> format) { inline void PIConsole::printLine(const PIString & value, int dx, PIFlags<PIConsole::Format> format) {
int i = width - value.length() - dx; int i = width - value.length() - dx;
#ifdef QNX #if defined(QNX) || defined(FREE_BSD)
--i; --i;
#endif #endif
PIString ts = fstr(format); PIString ts = fstr(format);

77
piconsole.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Console output/input 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 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 it under the terms of the GNU General Public License as published by
@@ -28,6 +28,10 @@
# include <fcntl.h> # include <fcntl.h>
#endif #endif
/// handlers:
/// void clearVariables(bool clearScreen = true)
/// void start(bool wait = false)
/// void stop(bool clear = false)
class PIConsole: public PIThread class PIConsole: public PIThread
{ {
public: public:
@@ -60,27 +64,28 @@ public:
Dec = 0x1000000, Dec = 0x1000000,
Hex = 0x2000000, Hex = 0x2000000,
Oct = 0x4000000, Oct = 0x4000000,
Scientific = 0x8000000}; Bin = 0x8000000,
Scientific = 0x10000000};
enum Alignment {Nothing, Left, Right}; enum Alignment {Nothing, Left, Right};
void addString(const PIString & name, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal); void addString(const PIString & name, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, PIString * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal); void addVariable(const PIString & name, const PIString * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, char * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal); void addVariable(const PIString & name, const char * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, bool * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal); void addVariable(const PIString & name, const bool * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, short * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal); void addVariable(const PIString & name, const short * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, int * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal); void addVariable(const PIString & name, const int * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, long * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal); void addVariable(const PIString & name, const long * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, llong * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal); void addVariable(const PIString & name, const llong * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, uchar * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal); void addVariable(const PIString & name, const uchar * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, ushort * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal); void addVariable(const PIString & name, const ushort * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, uint * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal); void addVariable(const PIString & name, const uint * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, ulong * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal); void addVariable(const PIString & name, const ulong * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, ullong * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal); void addVariable(const PIString & name, const ullong * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, float * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal); void addVariable(const PIString & name, const float * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, double * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal); void addVariable(const PIString & name, const double * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, PIProtocol * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal); void addVariable(const PIString & name, const PIProtocol * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addVariable(const PIString & name, PISystemMonitor * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal); void addVariable(const PIString & name, const PISystemMonitor * ptr, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addBitVariable(const PIString & name, void * ptr, int fromBit, int bitCount, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal); void addBitVariable(const PIString & name, const void * ptr, int fromBit, int bitCount, int column = 1, PIFlags<PIConsole::Format> format = PIConsole::Normal);
void addEmptyLine(int column = 1, uint count = 1); void addEmptyLine(int column = 1, uint count = 1);
PIString getString(int x, int y); PIString getString(int x, int y);
@@ -162,7 +167,8 @@ private:
#endif #endif
void status(); void status();
void checkColumn(uint col) {while (columns().size() < col) columns().push_back(Column(def_align));} 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<PIConsole::Format> format = PIConsole::Normal); inline void printLine(const PIString & str, int dx = 0, PIFlags<PIConsole::Format> format = PIConsole::Normal);
inline int printValue(const PIString & str, PIFlags<PIConsole::Format> format = PIConsole::Normal); inline int printValue(const PIString & str, PIFlags<PIConsole::Format> format = PIConsole::Normal);
inline int printValue(const char * str, PIFlags<PIConsole::Format> format = PIConsole::Normal); inline int printValue(const char * str, PIFlags<PIConsole::Format> format = PIConsole::Normal);
@@ -191,21 +197,21 @@ private:
int bitFrom; int bitFrom;
int bitCount; int bitCount;
union { union {
PIString * s; const PIString * s;
bool * b; const bool * b;
short * sh; const short * sh;
int * i; const int * i;
long * l; const long * l;
llong * ll; const llong * ll;
float * f; const float * f;
double * d; const double * d;
char * c; const char * c;
uchar * uc; const uchar * uc;
ushort * ush; const ushort * ush;
uint * ui; const uint * ui;
ulong * ul; const ulong * ul;
ullong * ull; const ullong * ull;
void * ptr; const void * ptr;
}; };
void operator =(const Variable & src) {name = src.name; format = src.format; type = src.type; offset = src.offset; 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;} bitFrom = src.bitFrom; bitCount = src.bitCount; ptr = src.ptr; nx = src.nx; ny = src.ny;}
@@ -261,6 +267,7 @@ private:
struct termios sterm, vterm; struct termios sterm, vterm;
#endif #endif
PIVector<Tab> tabs; PIVector<Tab> tabs;
PIString binstr;
Variable tv; Variable tv;
PIKbdListener * listener; PIKbdListener * listener;
Alignment def_align; Alignment def_align;

26
picontainers.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Generic containers, based on STL 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 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 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 ^(PIFlags f) const {PIFlags tf(flags ^ f.flags); return tf;}
PIFlags operator ^(Enum e) const {PIFlags tf(flags ^ e); return tf;} PIFlags operator ^(Enum e) const {PIFlags tf(flags ^ e); return tf;}
PIFlags operator ^(int i) const {PIFlags tf(flags ^ i); return tf;} PIFlags operator ^(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;} operator int() const {return flags;}
private: private:
int flags; int flags;
@@ -394,12 +394,15 @@ public:
_CVector & fill(const Type & t) {_stlc::assign(_stlc::size(), t); return *this;} _CVector & fill(const Type & t) {_stlc::assign(_stlc::size(), t); return *this;}
_CVector & pop_front() {_stlc::erase(_stlc::begin()); return *this;} _CVector & pop_front() {_stlc::erase(_stlc::begin()); return *this;}
_CVector & push_front(const Type & t) {_stlc::insert(_stlc::begin(), t); 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) {_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(uint num, uint count) {_stlc::erase(_stlc::begin() + num, _stlc::begin() + num + count); return *this;}
//_CVector & remove(const Type & t) {for (typename _stlc::iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) {_stlc::erase(i); --i;} return *this;} //_CVector & remove(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 & 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 & 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 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 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;} _CVector & operator <<(const _CVector & t) {for (typename _stlc::const_iterator i = t.begin(); i != t.end(); i++) _stlc::push_back(*i); return *this;}
bool operator ==(const _CVector & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return false; return true;} bool operator ==(const _CVector & t) {for (uint i = 0; i < _stlc::size(); ++i) if (t[i] != at(i)) return false; return true;}
@@ -518,16 +521,19 @@ template<typename Type0, typename Type1>
inline bool operator <(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {return value0.first < value1.first;} inline bool operator <(const PIPair<Type0, Type1> & value0, const PIPair<Type0, Type1> & value1) {return value0.first < value1.first;}
template<typename Type, typename Key = int> template<typename Key, typename Type>
class PIMap: public PISet<PIPair<Key, Type> > { class PIMap: public map<Key, Type> {
typedef PIMap<Type, Key> _CMap; typedef PIMap<Key, Type> _CMap;
typedef PISet<PIPair<Key, Type> > _CSet; typedef map<Key, Type> _stlc;
typedef std::pair<Key, Type> _stlpair;
public: public:
PIMap() {;} PIMap() {;}
PIMap(const Type & value, const Key & key) {insert(value, key);} PIMap(const Key & key_, const Type & value_) {insert(key_, value_);}
_CMap & insert(const Type & value, const Key & key) {_CSet::insert(PIPair<Key, Type>(key, value)); return *this;} _CMap & insert(const Key & key_, const Type & value_) {_stlc::insert(std::pair<Key, Type>(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();} _CMap & insert(PIPair<Key, Type> entry_) {_stlc::insert(std::pair<Key, Type>(entry_.first, entry_.second)); return *this;}
Type operator[](Key key) const {return value(key);} 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 #endif // PICONTAINERS_H

216
picrc.h Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef PICRC_H
#define PICRC_H
#include "pistring.h"
template <int L>
class uint_cl {
public:
uint_cl() {for (int i = 0; i < L / 8; ++i) data_[i] = 0;}
uint_cl(const uint_cl<L> & 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<uint>(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<uint>(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<uint>(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<uint>(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<uint>(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<uint>(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<uint>(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<uint>(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<uint>(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;}
operator int() {int t(0); int l = piMin<uint>(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;}
operator long() {long t(0); int l = piMin<uint>(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;}
operator llong() {llong t(0); int l = piMin<uint>(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;}
operator uchar() {return data_[0];}
operator ushort() {ushort t(0); int l = piMin<uint>(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;}
operator uint() {uint t(0); int l = piMin<uint>(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;}
operator ulong() {ulong t(0); int l = piMin<uint>(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;}
operator ullong() {ullong t(0); int l = piMin<uint>(L / 8, sizeof(t)); memcpy(&t, data_, l); return t;}
uint_cl<L> operator +(const uint_cl<L> & v) {
uint_cl<L> 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<L> operator &(const uint_cl<L> & v) const {uint_cl<L> t; for (int i = 0; i < L / 8; ++i) t.data_[i] = v.data_[i] & data_[i]; return t;}
uint_cl<L> operator &(const uchar & v) const {return *this & uint_cl<L>(v);}
uint_cl<L> operator &(const ushort & v) const {return *this & uint_cl<L>(v);}
uint_cl<L> operator &(const uint & v) const {return *this & uint_cl<L>(v);}
uint_cl<L> operator &(const ulong & v) const {return *this & uint_cl<L>(v);}
uint_cl<L> operator &(const ullong & v) const {return *this & uint_cl<L>(v);}
uint_cl<L> operator &(const char & v) const {return *this & uint_cl<L>(v);}
uint_cl<L> operator &(const short & v) const {return *this & uint_cl<L>(v);}
uint_cl<L> operator &(const int & v) const {return *this & uint_cl<L>(v);}
uint_cl<L> operator &(const long & v) const {return *this & uint_cl<L>(v);}
uint_cl<L> operator &(const llong & v) const {return *this & uint_cl<L>(v);}
uint_cl<L> operator |(const uint_cl<L> & v) const {uint_cl<L> t; for (int i = 0; i < L / 8; ++i) t.data_[i] = v.data_[i] | data_[i]; return t;}
uint_cl<L> operator |(const uchar & v) const {return *this | uint_cl<L>(v);}
uint_cl<L> operator |(const ushort & v) const {return *this | uint_cl<L>(v);}
uint_cl<L> operator |(const uint & v) const {return *this | uint_cl<L>(v);}
uint_cl<L> operator |(const ulong & v) const {return *this | uint_cl<L>(v);}
uint_cl<L> operator |(const ullong & v) const {return *this | uint_cl<L>(v);}
uint_cl<L> operator |(const char & v) const {return *this | uint_cl<L>(v);}
uint_cl<L> operator |(const short & v) const {return *this | uint_cl<L>(v);}
uint_cl<L> operator |(const int & v) const {return *this | uint_cl<L>(v);}
uint_cl<L> operator |(const long & v) const {return *this | uint_cl<L>(v);}
uint_cl<L> operator |(const llong & v) const {return *this | uint_cl<L>(v);}
uint_cl<L> operator ^(const uint_cl<L> & v) const {uint_cl<L> t; for (int i = 0; i < L / 8; ++i) t.data_[i] = v.data_[i] ^ data_[i]; return t;}
uint_cl<L> operator ^(const uchar & v) const {return *this ^ uint_cl<L>(v);}
uint_cl<L> operator ^(const ushort & v) const {return *this ^ uint_cl<L>(v);}
uint_cl<L> operator ^(const uint & v) const {return *this ^ uint_cl<L>(v);}
uint_cl<L> operator ^(const ulong & v) const {return *this ^ uint_cl<L>(v);}
uint_cl<L> operator ^(const ullong & v) const {return *this ^ uint_cl<L>(v);}
uint_cl<L> operator ^(const char & v) const {return *this ^ uint_cl<L>(v);}
uint_cl<L> operator ^(const short & v) const {return *this ^ uint_cl<L>(v);}
uint_cl<L> operator ^(const int & v) const {return *this ^ uint_cl<L>(v);}
uint_cl<L> operator ^(const long & v) const {return *this ^ uint_cl<L>(v);}
uint_cl<L> operator ^(const llong & v) const {return *this ^ uint_cl<L>(v);}
bool operator <(const uint_cl<L> & 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<L> & 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<L> & 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<L> & 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<L> & 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<L> & v) const {for (int i = 0; i < L / 8; ++i) if (v.data_[i] != data_[i]) return true; return false;}
uint_cl<L> operator >>(const int & c) const {
uint_cl<L> 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<L> operator >>(const uint & c) const {return (*this << (int)c);}
uint_cl<L> operator <<(const int & c) const {
uint_cl<L> 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<L> operator <<(const uint & c) const {return (*this >> (int)c);}
uint_cl<L> & inverse() const {for (int i = 0; i < L / 8; ++i) data_[i] = ~data_[i]; return *this;}
uint_cl<L> inversed() const {uint_cl<L> t(*this); for (int i = 0; i < L / 8; ++i) t.data_[i] = ~t.data_[i]; return t;}
uint_cl<L> reversed() const {
uint_cl<L> 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 <uint L>
inline std::ostream & operator <<(std::ostream & s, const uint_cl<L> & 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 <uint L>
class PICRC {
public:
PICRC(const uint_cl<L> & poly) {poly_ = poly; reverse_poly = true; init_ = uint_cl<L>(0).inversed(); out_ = uint_cl<L>(0).inversed(); initTable();}
PICRC(const uint_cl<L> & poly, bool reverse, const uint_cl<L> & initial, const uint_cl<L> & out_xor) {poly_ = poly; reverse_poly = reverse; init_ = initial; out_ = out_xor; initTable();}
void setInitial(const uint_cl<L> & v) {init_ = v;}
void setOutXor(const uint_cl<L> & v) {out_ = v;}
void setReversePolynome(bool yes) {reverse_poly = yes; initTable();}
void initTable() {
uint_cl<L> tmp, pol = reverse_poly ? poly_.reversed() : poly_;
//cout << std::hex << "poly " << (uint)uint_cl<L>(poly_) << " -> " << (uint)uint_cl<L>(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<L> calculate(const void * data, int size) {
uint_cl<L> 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<L> calculate(const PIByteArray & d) {return calculate(d.data(), d.size());}
uint_cl<L> calculate(const char * str) {string s(str); return calculate((void * )s.data(), s.size());}
private:
uint_cl<L> table[256];
uint_cl<L> 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

30
pidir.cpp Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Directory 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 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 it under the terms of the GNU General Public License as published by
@@ -78,17 +78,11 @@ PIDir & PIDir::cleanPath() {
open(); open();
return *this; return *this;
} }
path_.replaceAll(PIString(separator) + PIString(separator), PIString(separator));
bool isAbs = isAbsolute(); 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); PIStringList l = PIString(p).split(separator);
l.removeStrings("."); l.removeAll(".");
l.removeStrings(""); l.removeAll("");
bool found = true; bool found = true;
while (found) { while (found) {
found = false; found = false;
@@ -118,20 +112,19 @@ PIDir & PIDir::cleanPath() {
PIDir & PIDir::cd(const PIString & path) { PIDir & PIDir::cd(const PIString & path) {
if (path_.size() == 0) return *this; if (path_.size() == 0) return *this;
if (path_[path_.size() - 1] == separator) path_ << path; if (path_[path_.size() - 1] != separator) path_ << separator;
else path_ << separator << path; path_ << path;
return cleanPath(); return cleanPath();
} }
bool PIDir::mkDir(bool withParents) { bool PIDir::mkDir(bool withParents) {
PIDir d = cleanedPath(); PIDir d = cleanedPath();
string p = d.path_;
PIString tp; PIString tp;
int ret; int ret;
bool isAbs = isAbsolute(); bool isAbs = isAbsolute();
if (withParents) { if (withParents) {
PIStringList l = PIString(p).split(separator); PIStringList l = d.path_.split(separator);
for (int i = l.size_s() - 1; i >= 0; --i) { for (int i = l.size_s() - 1; i >= 0; --i) {
if (i > 1) tp = PIStringList(l).remove(i, l.size_s() - i).join(separator); if (i > 1) tp = PIStringList(l).remove(i, l.size_s() - i).join(separator);
else { else {
@@ -143,19 +136,18 @@ bool PIDir::mkDir(bool withParents) {
for (int j = i + 1; j <= l.size_s(); ++j) { for (int j = i + 1; j <= l.size_s(); ++j) {
tp = PIStringList(l).remove(j, l.size_s() - j).join(separator); tp = PIStringList(l).remove(j, l.size_s() - j).join(separator);
//cout << tp << endl; //cout << tp << endl;
p = tp.stdString(); ret = mkdir(tp.data(), 16877);
ret = mkdir(p.c_str(), 16877);
if (ret == 0) continue; 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; return false;
} }
break; break;
}; };
} }
} else { } else {
ret = mkdir(p.c_str(), 16877); ret = mkdir(d.path_.data(), 16877);
if (ret == 0) return true; 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; return false;
} }

23
pidir.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Directory 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 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 it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@
#define PIDIR_H #define PIDIR_H
#include "pifile.h" #include "pifile.h"
#include "pistring.h"
#ifndef WINDOWS #ifndef WINDOWS
#include <sys/dir.h> #include <sys/dir.h>
#include <sys/stat.h> #include <sys/stat.h>
@@ -43,23 +44,23 @@ public:
bool isDir() const {return (mode & S_IFDIR);} bool isDir() const {return (mode & S_IFDIR);}
bool isFile() const {return (mode & S_IFREG);} bool isFile() const {return (mode & S_IFREG);}
bool isSymLink() const {return (mode & S_IFLNK);} bool isSymbolicLink() const {return (mode & S_IFLNK);}
bool isBlkDevice() const {return (mode & S_IFBLK);} bool isBlockDevice() const {return (mode & S_IFBLK);}
bool isChrDevice() const {return (mode & S_IFCHR);} bool isCharacterDevice() const {return (mode & S_IFCHR);}
bool isSocket() const {return (mode & S_IFSOCK);} bool isSocket() const {return (mode & S_IFSOCK);}
}; };
inline const bool isExists() {return (dir_ != 0);} const bool isExists() {return (dir_ != 0);}
inline const bool isAbsolute() {if (path_.size() == 0) return false; return (path_[0] == separator);} const bool isAbsolute() {if (path_.size() == 0) return false; return (path_[0] == separator);}
inline PIString path() {return PIString(path_);} PIString path() {return PIString(path_);}
PIDir & cleanPath(); PIDir & cleanPath();
inline PIDir cleanedPath() {PIDir d(path_); d.cleanPath(); return d;} PIDir cleanedPath() {PIDir d(path_); d.cleanPath(); return d;}
PIString absolutePath(); PIString absolutePath();
bool mkDir(bool withParents = true); bool mkDir(bool withParents = true);
PIVector<DirEntry> entries(); PIVector<DirEntry> entries();
PIDir & cd(const PIString & path); PIDir & cd(const PIString & path);
inline PIDir & up() {return cd("..");} PIDir & up() {return cd("..");}
bool operator ==(const PIDir & d) const; bool operator ==(const PIDir & d) const;

351
piethernet.cpp Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Ethernet, UDP 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 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 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; ret_data_ = data;
ip_ = ip_s = ""; ip_ = ip_s = "";
port_ = port_s = 0; port_ = port_s = 0;
sock = -1; sock = sock_s = -1;
ret_func_ = slot; ret_func_ = slot;
connected_ = false; connected_ = false;
params = PIEthernet::ReuseAddress;
server_thread_.setData(this); server_thread_.setData(this);
setThreadedReadBufferSize(65536); setThreadedReadBufferSize(65536);
#ifdef WINDOWS if (type_ != UDP) init();
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
init();
} }
@@ -47,16 +44,13 @@ PIEthernet::PIEthernet(PIEthernet::Type type, void * data, ReadRetFunc slot): PI
ret_data_ = data; ret_data_ = data;
ip_ = ip_s = ""; ip_ = ip_s = "";
port_ = port_s = 0; port_ = port_s = 0;
sock = -1; sock = sock_s = -1;
ret_func_ = slot; ret_func_ = slot;
connected_ = false; connected_ = false;
params = PIEthernet::ReuseAddress;
server_thread_.setData(this); server_thread_.setData(this);
setThreadedReadBufferSize(65536); setThreadedReadBufferSize(65536);
#ifdef WINDOWS if (type_ != UDP) init();
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
init();
} }
@@ -66,13 +60,11 @@ PIEthernet::PIEthernet(int sock_, PIString ip_port): PIIODevice("", ReadWrite) {
type_ = TCP_Client; type_ = TCP_Client;
parseAddress(ip_port, &ip_s, &port_s); parseAddress(ip_port, &ip_s, &port_s);
sock = sock_; sock = sock_;
sock_s = -1;
server_thread_.setData(this); server_thread_.setData(this);
params = PIEthernet::ReuseAddress;
init_ = opened_ = connected_ = true; init_ = opened_ = connected_ = true;
setThreadedReadBufferSize(65536); setThreadedReadBufferSize(65536);
#ifdef WINDOWS
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
} }
@@ -80,9 +72,6 @@ PIEthernet::~PIEthernet() {
piMonitor.ethernets--; piMonitor.ethernets--;
if (server_thread_.isRunning()) server_thread_.terminate(); if (server_thread_.isRunning()) server_thread_.terminate();
closeSocket(sock); closeSocket(sock);
#ifdef WINDOWS
WSACleanup();
#endif
//if (buffer_ != 0) delete buffer_; //if (buffer_ != 0) delete buffer_;
//buffer_ = 0; //buffer_ = 0;
} }
@@ -91,15 +80,29 @@ PIEthernet::~PIEthernet() {
bool PIEthernet::init() { bool PIEthernet::init() {
//cout << "init " << type_ << endl; //cout << "init " << type_ << endl;
closeSocket(sock); 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_ == UDP) st = SOCK_DGRAM;
if (type_ == TCP_Client || type_ == TCP_Server) st = SOCK_STREAM; else st = SOCK_STREAM;
sock = socket(PF_INET, st, 0); #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) { if (sock == -1) {
piCout << "[PIEthernet] Cant`t create socket, " << errorString() << endl; piCout << "[PIEthernet] Cant`t create socket, " << EthErrorString() << endl;
return false; 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*/); //fcntl(sock, F_SETFL, 0/*O_NONBLOCK*/);
return true; return true;
} }
@@ -114,15 +117,24 @@ void PIEthernet::parseAddress(const PIString & ipp, PIString * ip, int * port) {
bool PIEthernet::openDevice() { bool PIEthernet::openDevice() {
if (connected_) return true; if (connected_) return true;
if (sock == -1) init(); if (sock == -1) init();
if (sock == -1) return false; if (sock == -1 || path_.isEmpty()) return false;
//cout << " bind to " << path_ << " ..." <<endl;
parseAddress(path_, &ip_, &port_); parseAddress(path_, &ip_, &port_);
//cout << " bind to " << sock << ": " << (params[PIEthernet::Broadcast] ? "0.0.0.0" : path_) << ": " << port_ << " ..." <<endl;
memset(&addr_, 0, sizeof(addr_));
addr_.sin_family = AF_INET;
addr_.sin_port = htons(port_); addr_.sin_port = htons(port_);
addr_.sin_addr.s_addr = inet_addr(ip_.data()); if (params[PIEthernet::Broadcast]) addr_.sin_addr.s_addr = INADDR_ANY;
addr_.sin_family = PF_INET; else addr_.sin_addr.s_addr = inet_addr(ip_.data());
//cout << "openDevice\n"; #ifdef QNX
if (bind(sock, (sockaddr * )&addr_, sizeof(addr_)) == -1) { addr_.sin_len = sizeof(addr_);
piCout << "[PIEthernet] Cant`t bind to " << ip_ << ":" << port_ << ", " << errorString() << endl; #endif
int tries = 0;
while ((bind(sock, (sockaddr * )&addr_, sizeof(addr_)) == -1) && (tries < 10)) {
init();
tries++;
}
if (tries == 10) {
piCout << "[PIEthernet] Cant`t bind to " << ip_ << ":" << port_ << ", " << EthErrorString() << endl;
return false; return false;
} }
//cout << "!" << endl; //cout << "!" << endl;
@@ -143,15 +155,89 @@ bool PIEthernet::closeDevice() {
} }
bool PIEthernet::connect(PIString ip, int port) { bool PIEthernet::joinMulticastGroup(const PIString & group) {
if (sock == -1) init();
if (sock == -1) return false; if (sock == -1) return false;
if (type_ != UDP) {
piCout << "[PIEthernet] Only UDP sockets can join multicast groups" << endl;
return false;
}
#ifdef WINDOWS
parseAddress(path_, &ip_, &port_);
memset(&addr_, 0, sizeof(addr_));
addr_.sin_family = AF_INET;
addr_.sin_port = htons(port_);
addr_.sin_addr.s_addr = inet_addr(group.data());
SOCKET ret = WSAJoinLeaf(sock, (sockaddr *)&addr_, sizeof(addr_), NULL, NULL, NULL, NULL, JL_BOTH);
if (ret == INVALID_SOCKET) {
piCout << "[PIEthernet] Cant`t join multicast group " << group << ", " << EthErrorString() << endl;
return false;
}
leafs.insert(group, ret);
#else
# ifndef QNX
parseAddress(path_, &ip_, &port_);
struct ip_mreqn mreq;
memset(&mreq, 0, sizeof(mreq));
if (params[PIEthernet::Broadcast]) mreq.imr_address.s_addr = INADDR_ANY;
else mreq.imr_address.s_addr = inet_addr(ip_.data());
mreq.imr_multiaddr.s_addr = inet_addr(group.data());
mreq.imr_ifindex = 0;
if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) {
piCout << "[PIEthernet] Cant`t join multicast group " << group << ", " << EthErrorString() << endl;
return false;
}
# endif
#endif
return true;
}
bool PIEthernet::leaveMulticastGroup(const PIString & group) {
if (sock == -1) init();
if (sock == -1) return false;
if (type_ != UDP) {
piCout << "[PIEthernet] Only UDP sockets can leave multicast groups" << endl;
return false;
}
#ifdef WINDOWS
SOCKET s = leafs[group];
if (s != SOCKET()) {
leafs.erase(group);
closesocket(s);
}
#else
# ifndef QNX
parseAddress(path_, &ip_, &port_);
struct ip_mreqn mreq;
memset(&mreq, 0, sizeof(mreq));
if (params[PIEthernet::Broadcast]) mreq.imr_address.s_addr = INADDR_ANY;
else mreq.imr_address.s_addr = inet_addr(ip_.data());
mreq.imr_multiaddr.s_addr = inet_addr(group.data());
mreq.imr_ifindex = 0;
if (setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) {
piCout << "[PIEthernet] Cant`t leave multicast group " << group << ", " << EthErrorString() << endl;
return false;
}
#endif
#endif
return true;
}
bool PIEthernet::connect(const PIString & ip, int port) {
if (sock == -1) return false;
memset(&addr_, 0, sizeof(addr_));
addr_.sin_port = htons(port); addr_.sin_port = htons(port);
addr_.sin_addr.s_addr = inet_addr(ip.data()); addr_.sin_addr.s_addr = inet_addr(ip.data());
addr_.sin_family = PF_INET; addr_.sin_family = AF_INET;
#ifdef QNX
addr_.sin_len = sizeof(addr_);
#endif
//piCout << "[PIEthernet] connect to " << ip << ":" << port << endl; //piCout << "[PIEthernet] connect to " << ip << ":" << port << endl;
connected_ = (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) == 0); connected_ = (::connect(sock, (sockaddr * )&addr_, sizeof(addr_)) == 0);
if (!connected_) if (!connected_)
piCout << "[PIEthernet] Cant`t connect to " << ip << ":" << port << ", " << errorString() << endl; piCout << "[PIEthernet] Cant`t connect to " << ip << ":" << port << ", " << EthErrorString() << endl;
opened_ = connected_; opened_ = connected_;
return connected_; return connected_;
} }
@@ -161,15 +247,24 @@ bool PIEthernet::listen() {
if (sock == -1) init(); if (sock == -1) init();
if (sock == -1) return false; if (sock == -1) return false;
parseAddress(path_, &ip_, &port_); parseAddress(path_, &ip_, &port_);
memset(&addr_, 0, sizeof(addr_));
addr_.sin_port = htons(port_); addr_.sin_port = htons(port_);
addr_.sin_addr.s_addr = inet_addr(ip_.data()); addr_.sin_addr.s_addr = inet_addr(ip_.data());
addr_.sin_family = PF_INET; addr_.sin_family = AF_INET;
if (bind(sock, (sockaddr * )&addr_, sizeof(addr_)) == -1) { #ifdef QNX
piCout << "[PIEthernet] Cant`t bind to " << ip_ << ":" << port_ << ", " << errorString() << endl; addr_.sin_len = sizeof(addr_);
#endif
int tries = 0;
while ((bind(sock, (sockaddr * )&addr_, sizeof(addr_)) == -1) && (tries < 10)) {
init();
tries++;
}
if (tries == 10) {
piCout << "[PIEthernet] Cant`t bind to " << ip_ << ":" << port_ << ", " << EthErrorString() << endl;
return false; return false;
} }
if (::listen(sock, 64) == -1) { if (::listen(sock, 64) == -1) {
piCout << "[PIEthernet] Can`t listen on "<< ip_ << ":" << port_ << ", " << errorString() << endl; piCout << "[PIEthernet] Can`t listen on "<< ip_ << ":" << port_ << ", " << EthErrorString() << endl;
return false; return false;
} }
//piCout << "[PIEthernet] listen on " << ip_ << ":" << port_ << endl; //piCout << "[PIEthernet] listen on " << ip_ << ":" << port_ << endl;
@@ -181,11 +276,30 @@ bool PIEthernet::listen() {
int PIEthernet::read(void * read_to, int max_size) { int PIEthernet::read(void * read_to, int max_size) {
//cout << "read " << sock << endl; //cout << "read " << sock << endl;
if (sock == -1) init(); if (sock == -1) init();
if (sock == -1) return -1; if (sock == -1 || read_to == 0) return -1;
int rs = 0, s = 0;
sockaddr_in client_addr;
socklen_t slen = sizeof(client_addr);
//piCout << "[PIEthernet] read from " << ip_ << ":" << port_ << endl; //piCout << "[PIEthernet] read from " << ip_ << ":" << port_ << endl;
switch (type_) { switch (type_) {
case TCP_SingleTCP:
::listen(sock, 64);
s = accept(sock, (sockaddr * )&client_addr, &slen);
if (s == -1) {
piCout << "[PIEthernet] Cant`t accept new connection, " << EthErrorString() << endl;
return -1;
}
rs = recv(s, (char * )read_to, max_size, 0);
closeSocket(s);
return rs;
case UDP: case TCP_Client: case UDP: case TCP_Client:
return recv(sock, read_to, max_size, 0); #ifdef WINDOWS
rs = recv(sock, (char * )read_to, max_size, 0);
#else
rs = recv(sock, read_to, max_size, 0);
#endif
if (rs >= 0) received(read_to, rs);
return rs;
//return ::read(sock, read_to, max_size); //return ::read(sock, read_to, max_size);
default: break; default: break;
//return ::read(sock, (char * )read_to, max_size); //return ::read(sock, (char * )read_to, max_size);
@@ -201,12 +315,34 @@ int PIEthernet::write(const void * data, int max_size) {
return -1; return -1;
} }
//piCout << "[PIEthernet] sending to " << ip_s << ":" << port_s << " " << max_size << " bytes" << endl; //piCout << "[PIEthernet] sending to " << ip_s << ":" << port_s << " " << max_size << " bytes" << endl;
int ret = 0;
switch (type_) { 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: case UDP:
saddr_.sin_port = htons(port_s); saddr_.sin_port = htons(port_s);
saddr_.sin_addr.s_addr = inet_addr(ip_s.data()); if (params[PIEthernet::Broadcast]) saddr_.sin_addr.s_addr = INADDR_BROADCAST;
saddr_.sin_family = PF_INET; 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_)); return sendto(sock, data, max_size, 0, (sockaddr * )&saddr_, sizeof(saddr_));
#endif
case TCP_Client: case TCP_Client:
return ::write(sock, data, max_size); return ::write(sock, data, max_size);
default: break; default: break;
@@ -219,18 +355,139 @@ void PIEthernet::server_func(void * eth) {
PIEthernet * ce = (PIEthernet * )eth; PIEthernet * ce = (PIEthernet * )eth;
sockaddr_in client_addr; sockaddr_in client_addr;
socklen_t slen = sizeof(client_addr); socklen_t slen = sizeof(client_addr);
int s; int s = accept(ce->sock, (sockaddr * )&client_addr, &slen);
s = accept(ce->sock, (sockaddr * )&client_addr, &slen);
if (s == -1) { if (s == -1) {
piCout << "[PIEthernet] Cant`t accept new connection, " << errorString() << endl; piCout << "[PIEthernet] Cant`t accept new connection, " << EthErrorString() << endl;
return; return;
} }
PIString ip(inet_ntoa(client_addr.sin_addr)); PIString ip(inet_ntoa(client_addr.sin_addr));
ip += ":" + PIString::fromNumber(htons(client_addr.sin_port)); ip += ":" + PIString::fromNumber(htons(client_addr.sin_port));
ce->clients_ << new PIEthernet(s, ip); ce->clients_ << new PIEthernet(s, ip);
cout << "connected " << ip << endl; //cout << "connected " << ip << endl;
//char d[256]; //char d[256];
//cout << " recv " << recv(s, d, 256, 0) << endl; //cout << " recv " << recv(s, d, 256, 0) << endl;
//cout << recv(ce->clients_.back()->sock, 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
}

82
piethernet.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Ethernet, UDP 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 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 it under the terms of the GNU General Public License as published by
@@ -22,61 +22,74 @@
#include "pitimer.h" #include "pitimer.h"
#include "piiodevice.h" #include "piiodevice.h"
#ifndef WINDOWS #include "piprocess.h"
# include <netinet/in.h>
# include <arpa/inet.h>
# include <sys/socket.h>
# include <fcntl.h>
#else
# ifdef CC_VC
# include <winsock.h>
# define SHUT_RDWR 2
# else
# include <winsock2.h>
# define SHUT_RDWR SD_BOTH
# endif
#endif
class PIEthernet: public PIIODevice class PIEthernet: public PIIODevice
{ {
friend class PIPeer;
public: public:
// slot is any function format "bool <func>(void*, uchar*, int)" // slot is any function format "bool <func>(void*, uchar*, int)"
PIEthernet(void * data, ReadRetFunc slot); 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(Type type = UDP, void * data = 0, ReadRetFunc slot = 0);
~PIEthernet(); ~PIEthernet();
void setReadAddress(PIString ip, int port) {path_ = ip + ":" + PIString::fromNumber(port);} void setReadAddress(const PIString & ip, int port) {path_ = ip + ":" + PIString::fromNumber(port);}
void setReadAddress(PIString ip_port) {path_ = ip_port;} void setReadAddress(const PIString & ip_port) {path_ = ip_port;}
void setSendAddress(PIString ip, int port) {ip_s = ip; port_s = port;} void setReadIP(const PIString & ip) {parseAddress(path_, &ip_, &port_); path_ = ip + ":" + PIString::fromNumber(port_);}
void setSendAddress(PIString ip_port) {parseAddress(ip_port, &ip_s, &port_s);} 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<PIEthernet::Parameters> 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<PIEthernet::Parameters> 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_;} Type type() const {return type_;}
bool connect(PIString ip, int port); bool joinMulticastGroup(const PIString & group);
bool connect(PIString ip_port) {parseAddress(ip_port, &ip_c, &port_c); return connect(ip_c, port_c);} 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 isConnected() const {return connected_;}
bool listen(); bool listen();
bool listen(PIString ip, int port) {setReadAddress(ip, port); return listen();} bool listen(const PIString & ip, int port) {setReadAddress(ip, port); return listen();}
bool listen(PIString ip_port) {setReadAddress(ip_port); return listen();} bool listen(const PIString & ip_port) {setReadAddress(ip_port); return listen();}
PIEthernet * client(int index) {return clients_[index];} PIEthernet * client(int index) {return clients_[index];}
int clientsCount() const {return clients_.size_s();} int clientsCount() const {return clients_.size_s();}
PIVector<PIEthernet * > clients() {return clients_;} PIVector<PIEthernet * > 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(const 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_port, const void * data, int size) {parseAddress(ip_port, &ip_s, &port_s); return send(data, size);}
bool send(const void * data, int size) {return (write(data, size) == size);} bool send(const void * data, int size) {return (write(data, size) == size);}
int read(void * read_to, int max_size); int read(void * read_to, int max_size);
int write(const void * data, 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: protected:
PIEthernet(int sock, PIString ip_port); PIEthernet(int sock, PIString ip_port);
virtual void received(void * data, int size) {;}
bool init(); bool init();
bool openDevice(); bool openDevice();
bool closeDevice(); bool closeDevice();
@@ -87,17 +100,32 @@ protected:
#endif #endif
void parseAddress(const PIString & ipp, PIString * ip, int * port); 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_; bool connected_;
sockaddr_in addr_, saddr_; sockaddr_in addr_, saddr_;
PIString ip_, ip_s, ip_c; PIString ip_, ip_s, ip_c;
PIThread server_thread_; PIThread server_thread_;
PIVector<PIEthernet * > clients_; PIVector<PIEthernet * > clients_;
#ifdef WINDOWS
PIMap<PIString, SOCKET> leafs;
#endif
PIFlags<PIEthernet::Parameters> params;
Type type_; Type type_;
private: private:
static void server_func(void * eth); 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 #endif // PIETHERNET_H

2
pievaluator.cpp Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Evaluator designed for stream computing 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 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 it under the terms of the GNU General Public License as published by

2
pievaluator.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Evaluator designed for stream computing 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 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 it under the terms of the GNU General Public License as published by

24
pifile.cpp Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
File 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 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 it under the terms of the GNU General Public License as published by
@@ -33,21 +33,20 @@ bool PIFile::openDevice() {
bool PIFile::closeDevice() { bool PIFile::closeDevice() {
if (!opened_) return true; if (!opened_) return true;
return (fclose(fd) != 0); return (fclose(fd) == 0);
} }
PIString PIFile::readLine() { PIString PIFile::readLine() {
PIString str; PIString str;
if (!opened_) return str; if (!opened_) return str;
char cc; int cc, cp = 0;
int cp = 0;
while (!isEnd() && cp < 4095) { while (!isEnd() && cp < 4095) {
cc = char(fgetc(fd)); cc = fgetc(fd);
if (cc == '\n') break; if (char(cc) == '\n' || cc == EOF) break;
str.push_back(cc); str.push_back(char(cc));
} }
//cout << "readline: " << buff << endl; //cout << "readline: " << str << endl;
return str; return str;
} }
@@ -66,17 +65,20 @@ llong PIFile::readAll(void * data) {
PIByteArray PIFile::readAll(bool forceRead) { PIByteArray PIFile::readAll(bool forceRead) {
llong cp = pos(), s = size();
PIByteArray a; PIByteArray a;
if (s < 0) { llong cp = pos();
if (!forceRead) return a; if (forceRead) {
seekToBegin();
while (!isEnd()) while (!isEnd())
a.push_back(readChar()); a.push_back(readChar());
seek(cp); seek(cp);
return a; return a;
} }
llong s = size();
if (s < 0) return a;
a.resize(s); a.resize(s);
s = readAll(a.data()); s = readAll(a.data());
seek(cp);
if (s >= 0) a.resize(s); if (s >= 0) a.resize(s);
return a; return a;
} }

57
pifile.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
File 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 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 it under the terms of the GNU General Public License as published by
@@ -23,10 +23,14 @@
#include "piiodevice.h" #include "piiodevice.h"
#include <cstdio> #include <cstdio>
/// handlers:
/// void clear()
/// void resize(llong new_size, char fill = 0)
/// void remove()
class PIFile: public PIIODevice class PIFile: public PIIODevice
{ {
public: 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;} //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 isEnd() {return (feof(fd) || ferror(fd));}
bool isEmpty() {return (size() <= 0);} 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 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);} 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;} 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 short v) {write(&v, sizeof(v)); return *this;}
PIFile & writeBinary(const int 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 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 uchar v) {write(&v, sizeof(v)); return *this;}
PIFile & writeBinary(const ushort 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 uint v) {write(&v, sizeof(v)); return *this;}
PIFile & writeBinary(const ulong 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 float v) {write(&v, sizeof(v)); return *this;}
PIFile & writeBinary(const double 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 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 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 <<(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 <<(short v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%hd", v); return *this;}
PIFile & operator <<(int v) {if (!isWriteable()) return *this; fprintf(fd, "%d", 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; fprintf(fd, "%ld", v); return *this;} PIFile & operator <<(long v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%ld", v); return *this;}
PIFile & operator <<(uchar v) {if (!isWriteable()) return *this; fprintf(fd, "%c", v); return *this;} PIFile & operator <<(llong v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%lld", v); return *this;}
PIFile & operator <<(ushort v) {if (!isWriteable()) return *this; fprintf(fd, "%hd", v); return *this;} PIFile & operator <<(uchar v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%c", v); return *this;}
PIFile & operator <<(uint v) {if (!isWriteable()) return *this; fprintf(fd, "%d", v); return *this;} PIFile & operator <<(ushort v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%hd", v); return *this;}
PIFile & operator <<(ulong v) {if (!isWriteable()) return *this; fprintf(fd, "%ld", v); return *this;} PIFile & operator <<(uint v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%d", v); return *this;}
PIFile & operator <<(float v) {if (!isWriteable()) return *this; fprintf(fd, "%f", v); return *this;} PIFile & operator <<(ulong v) {if (!isWriteable()) return *this; ret = fprintf(fd, "%ld", v); return *this;}
PIFile & operator <<(double v) {if (!isWriteable()) return *this; fprintf(fd, "%lf", 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 >>(char & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%hhn", &v); return *this;}
PIFile & operator >>(short & v) {if (!isWriteable()) return *this; fscanf(fd, "%hn", &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; fscanf(fd, "%n", &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; fscanf(fd, "%ln", &v); return *this;} PIFile & operator >>(long & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%ln", &v); return *this;}
PIFile & operator >>(uchar & v) {if (!isWriteable()) return *this; fscanf(fd, "%hhn", &v); return *this;} PIFile & operator >>(llong & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%lln", &v); return *this;}
PIFile & operator >>(ushort & v) {if (!isWriteable()) return *this; fscanf(fd, "%hn", &v); return *this;} PIFile & operator >>(uchar & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%hhn", &v); return *this;}
PIFile & operator >>(uint & v) {if (!isWriteable()) return *this; fscanf(fd, "%n", &v); return *this;} PIFile & operator >>(ushort & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%hn", &v); return *this;}
PIFile & operator >>(ulong & v) {if (!isWriteable()) return *this; fscanf(fd, "%ln", &v); return *this;} PIFile & operator >>(uint & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%n", &v); return *this;}
PIFile & operator >>(float & v) {if (!isWriteable()) return *this; fscanf(fd, "%f", &v); return *this;} PIFile & operator >>(ulong & v) {if (!isWriteable()) return *this; ret = fscanf(fd, "%ln", &v); return *this;}
PIFile & operator >>(double & v) {if (!isWriteable()) return *this; fscanf(fd, "%lf", &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 PIFile openTemporary(PIIODevice::DeviceMode mode = PIIODevice::ReadWrite) {return PIFile(PIString(tmpnam(0)), mode);}
static bool isExists(const PIString & path); 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";} 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; FILE * fd;
int ret, prec;
string prec_str;
}; };

2
pigeometry.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Geometry 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 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 it under the terms of the GNU General Public License as published by

View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Global includes 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 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 it under the terms of the GNU General Public License as published by
@@ -21,3 +21,7 @@
bool isPIInit = false; bool isPIInit = false;
bool piDebug = true; bool piDebug = true;
string ifconfigPath;
PIInit piInit;
lconv * currentLocale = std::localeconv();

185
piincludes.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Global includes 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 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 it under the terms of the GNU General Public License as published by
@@ -20,11 +20,11 @@
#ifndef PIINCLUDES_H #ifndef PIINCLUDES_H
#define PIINCLUDES_H #define PIINCLUDES_H
#define PIP_VERSION 0x000200 #define PIP_VERSION 0x000206
#define PIP_VERSION_MAJOR (PIP_VERSION & 0xFF0000) >> 16 #define PIP_VERSION_MAJOR (PIP_VERSION & 0xFF0000) >> 16
#define PIP_VERSION_MINOR (PIP_VERSION & 0xFF00) >> 8 #define PIP_VERSION_MINOR (PIP_VERSION & 0xFF00) >> 8
#define PIP_VERSION_REVISION PIP_VERSION & 0xFF #define PIP_VERSION_REVISION PIP_VERSION & 0xFF
#define PIP_VERSION_SUFFIX "" #define PIP_VERSION_SUFFIX "_beta"
#if WIN32 || WIN64 || _WIN32 || _WIN64 || __WIN32__ || __WIN64__ #if WIN32 || WIN64 || _WIN32 || _WIN64 || __WIN32__ || __WIN64__
# define WINDOWS # define WINDOWS
@@ -32,15 +32,33 @@
#if __QNX__ || __QNXNTO__ #if __QNX__ || __QNXNTO__
# define QNX # define QNX
#endif #endif
#if __FreeBSD__
# define FREE_BSD
#endif
#if __APPLE__ || __MACH__
# define MAC_OS
#endif
#ifndef WINDOWS #ifndef WINDOWS
# ifndef QNX # ifndef QNX
# define LINUX # ifndef FREE_BSD
# ifndef MAC_OS
# define LINUX
# endif
# endif
# endif # endif
#endif #endif
#if __GNUC__ #if __GNUC__
# define CC_GCC # 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 #elif _MSC_VER
# define CC_VC # define CC_VC
#else
# define CC_OTHER
#endif #endif
#ifdef WINDOWS #ifdef WINDOWS
@@ -70,6 +88,9 @@
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <cctype> #include <cctype>
#include <ctime>
#include <csignal>
//#include <signal.h>
#include <typeinfo> #include <typeinfo>
#include <algorithm> #include <algorithm>
#include <string.h> #include <string.h>
@@ -80,10 +101,46 @@
#include <deque> #include <deque>
#include <stack> #include <stack>
#include <set> #include <set>
#include <map>
#ifdef WINDOWS #ifdef WINDOWS
typedef int socklen_t;
# include <conio.h> # include <conio.h>
# include <io.h>
# include <winsock2.h>
# 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 <windows.h> # include <windows.h>
# include <wincon.h> # include <wincon.h>
# include <iphlpapi.h>
#else
# include <netinet/in.h>
# include <arpa/inet.h>
# include <sys/socket.h>
# include <fcntl.h>
# include <sys/ioctl.h>
# include <net/if.h>
#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 #endif
#include "pimonitor.h" #include "pimonitor.h"
@@ -110,18 +167,65 @@ using std::queue;
using std::deque; using std::deque;
using std::stack; using std::stack;
using std::set; using std::set;
using std::map;
using std::string; using std::string;
#ifndef QNX #ifndef QNX
using std::wstring; using std::wstring;
# ifndef WINDOWS //# ifndef WINDOWS
static locale_t currentLocale_t = 0; //static locale_t currentLocale_t = 0;
# endif //# endif
#else #else
typedef std::basic_string<wchar_t> wstring; typedef std::basic_string<wchar_t> wstring;
#endif #endif
#ifdef HAS_LOCALE
static locale_t currentLocale_t = 0;
#endif
template<typename T> inline void piSwap(T & f, T & s) {T t = f; f = s; s = t;}
template<typename T> inline int piRound(const T & v) {return int(v >= T(0.) ? v + T(0.5) : v - T(0.5));}
template<typename T> inline int piFloor(const T & v) {return v < T(0) ? int(v) - 1 : int(v);}
template<typename T> inline int piCeil(const T & v) {return v < T(0) ? int(v) : int(v) + 1;}
template<typename T> inline T piAbs(const T & v) {return (v >= T(0) ? v : -v);}
template<typename T> inline T piMin(const T & f, const T & s) {return (f > s) ? s : f;}
template<typename T> inline T piMin(const T & f, const T & s, const T & t) {return (f < s && f < t) ? f : ((s < t) ? s : t);}
template<typename T> inline T piMax(const T & f, const T & s) {return (f < s) ? s : f;}
template<typename T> inline T piMax(const T & f, const T & s, const T & t) {return (f > s && f > t) ? f : ((s > t) ? s : t);}
template<typename T> inline T piClamp(const T & v, const T & min, const T & max) {return (v > max ? max : (v < min ? min : v));}
#define piRoundf piRound<float>
#define piRoundd piRound<double>
#define piFloorf piFloor<float>
#define piFloord piFloor<double>
#define piCeilf piCeil<float>
#define piCeild piCeil<double>
#define piAbss piAbs<short>
#define piAbsi piAbs<int>
#define piAbsl piAbs<long>
#define piAbsll piAbs<llong>
#define piAbsf piAbs<float>
#define piAbsd piAbs<double>
#define piMins piMin<short>
#define piMini piMin<int>
#define piMinl piMin<long>
#define piMinll piMin<llong>
#define piMinf piMin<float>
#define piMind piMin<double>
#define piMaxs piMax<short>
#define piMaxi piMax<int>
#define piMaxl piMax<long>
#define piMaxll piMax<llong>
#define piMaxf piMax<float>
#define piMaxd piMax<double>
#define piClamps piClamp<short>
#define piClampi piClamp<int>
#define piClampl piClamp<long>
#define piClampll piClamp<llong>
#define piClampf piClamp<float>
#define piClampd piClamp<double>
extern bool isPIInit; extern bool isPIInit;
extern bool piDebug; extern bool piDebug;
extern string ifconfigPath;
#define piCout if (piDebug) cout #define piCout if (piDebug) cout
@@ -130,8 +234,34 @@ public:
PIInit() { PIInit() {
if (isPIInit) return; if (isPIInit) return;
isPIInit = true; 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; //piDebug = true;
#ifdef LINUX #ifdef HAS_LOCALE
//cout << "has locale" << endl;
if (currentLocale_t != 0) { if (currentLocale_t != 0) {
freelocale(currentLocale_t); freelocale(currentLocale_t);
currentLocale_t = 0; currentLocale_t = 0;
@@ -139,21 +269,26 @@ public:
currentLocale_t = newlocale(LC_ALL, setlocale(LC_ALL, ""), 0); currentLocale_t = newlocale(LC_ALL, setlocale(LC_ALL, ""), 0);
#else #else
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
#endif
#ifdef MAC_OS
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &__pi_mac_clock);
#endif #endif
} }
~PIInit() { ~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); //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; extern PIInit piInit;
static lconv * currentLocale = std::localeconv(); extern lconv * currentLocale;
#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
#ifdef WINDOWS #ifdef WINDOWS
inline int random() {return rand();} inline int random() {return rand();}
@@ -162,12 +297,6 @@ inline double round(const double & v) {return floor(v + 0.5);}
# endif # endif
#endif #endif
template<typename Type> inline void piSwap(Type & f, Type & s) {Type t = f; f = s; s = t;}
template<typename Type> inline Type piMin(const Type & f, const Type & s) {return (f > s) ? s : f;}
template<typename Type> inline Type piMin(const Type & f, const Type & s, const Type & t) {return (f < s && f < t) ? f : ((s < t) ? s : t);}
template<typename Type> inline Type piMax(const Type & f, const Type & s) {return (f < s) ? s : f;}
template<typename Type> inline Type piMax(const Type & f, const Type & s, const Type & t) {return (f > s && f > t) ? f : ((s > t) ? s : t);}
template<typename Type> 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 ushort letobe_s(ushort v) {return v = (v << 8) | (v >> 8);}
inline bool atob(const string & str) { return str == "1" ? true : false;}; inline bool atob(const string & str) { return str == "1" ? true : false;};
inline string btos(const bool num) { return num ? "0" : "1";}; inline string btos(const bool num) { return num ? "0" : "1";};
@@ -220,6 +349,18 @@ inline string dtos(const double num) {
#endif #endif
return string(ch); }; 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;} inline string PIPVersion() {return itos(PIP_VERSION_MAJOR) + "." + itos(PIP_VERSION_MINOR) + "." + itos(PIP_VERSION_REVISION) + PIP_VERSION_SUFFIX;}
#endif // PIINCLUDES_H #endif // PIINCLUDES_H

3
piiodevice.cpp Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Abstract input/output device 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 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 it under the terms of the GNU General Public License as published by
@@ -96,7 +96,6 @@ void PIIODevice::run() {
//cout << "not started\n"; //cout << "not started\n";
return; return;
} }
readed_ = read(buffer_tr.data(), buffer_tr.size_s()); readed_ = read(buffer_tr.data(), buffer_tr.size_s());
if (readed_ <= 0) { if (readed_ <= 0) {
msleep(10); msleep(10);

34
piiodevice.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Abstract input/output device 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 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 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 // function executed from threaded read, pass ThreadedReadData, readedData, sizeOfData
typedef bool (*ReadRetFunc)(void * , uchar * , int ); 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 { class PIIODevice: public PIThread {
public: public:
PIIODevice(); PIIODevice();
@@ -32,7 +44,7 @@ public:
enum DeviceMode {ReadOnly = 0x01, WriteOnly = 0x02, ReadWrite = 0x03}; enum DeviceMode {ReadOnly = 0x01, WriteOnly = 0x02, ReadWrite = 0x03};
PIIODevice(const PIString & path, DeviceMode type = ReadWrite, bool initNow = true); 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_;} DeviceMode mode() const {return mode_;}
@@ -66,15 +78,19 @@ public:
void startThreadedRead(ReadRetFunc func) {ret_func_ = func; if (!isRunning()) start();} void startThreadedRead(ReadRetFunc func) {ret_func_ = func; if (!isRunning()) start();}
EVENT_HANDLER(PIIODevice, bool, open) {if (!init_) init(); opened_ = openDevice(); 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(); 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(); 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(); 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(); 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 // Flush device
EVENT_VHANDLER(PIIODevice, void, flush) {;} 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 // Read from device to "read_to" maximum "max_size" bytes, return readed bytes count
virtual int read(void * read_to, int max_size) {piCout << "[PIIODevice] \"read\" not implemented!" << endl; return -2;} virtual int read(void * read_to, int max_size) {piCout << "[PIIODevice] \"read\" not implemented!" << endl; return -2;}
@@ -84,6 +100,7 @@ public:
// Read from device maximum "max_size" bytes and return them as PIByteArray // 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);} 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: protected:
@@ -97,6 +114,8 @@ protected:
// Function executed when thread read some data, default implementation execute external slot "ret_func_" // 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;} virtual bool threadedRead(uchar * readed, int size) {if (ret_func_ != 0) return ret_func_(ret_data_, readed, size); return true;}
void terminate();
PIString path_; PIString path_;
DeviceMode mode_; DeviceMode mode_;
ReadRetFunc ret_func_; ReadRetFunc ret_func_;
@@ -106,7 +125,6 @@ protected:
private: private:
EVENT_HANDLER2(PIIODevice, void, check_start, void * , data, int, delim); EVENT_HANDLER2(PIIODevice, void, check_start, void * , data, int, delim);
void terminate();
void begin(); void begin();
void run(); void run();

3
pikbdlistener.cpp Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Keyboard grabber for console 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 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 it under the terms of the GNU General Public License as published by
@@ -64,6 +64,7 @@ void PIKbdListener::run() {
PIKbdListener::exiting = true; PIKbdListener::exiting = true;
return; return;
} }
keyPressed(rc, data);
if (ret_func != 0 && ret > 0) ret_func(rc, data); if (ret_func != 0 && ret > 0) ret_func(rc, data);
} }

24
pikbdlistener.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Keyboard grabber for console 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 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 it under the terms of the GNU General Public License as published by
@@ -29,29 +29,39 @@
typedef void (*KBFunc)(char, void * ); 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 { class PIKbdListener: public PIThread {
friend class PIConsole; friend class PIConsole;
public: public:
// slot is any function format "void <func>(char, void * )" // slot is any function format "void <func>(char, void * )"
PIKbdListener(KBFunc slot = 0, void * data = 0); PIKbdListener(KBFunc slot = 0, void * data = 0);
~PIKbdListener() {terminate(); end();} ~PIKbdListener() {terminate(); end();}
void setData(void * data_) {data = data_;} void setData(void * data_) {data = data_;}
void setSlot(KBFunc slot_) {ret_func = slot_;} 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;} void disableExitCapture() {exit_enabled = false;}
bool exitCaptured() const {return exit_enabled;} bool exitCaptured() const {return exit_enabled;}
char exitKey() const {return exit_key;} char exitKey() const {return exit_key;}
bool isActive() {return is_active;} 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; static bool exiting;
private: private:
void begin(); void begin();
void run(); void run();
void end(); void end();
KBFunc ret_func; KBFunc ret_func;
char exit_key; char exit_key;
bool exit_enabled, is_active; bool exit_enabled, is_active;
@@ -65,7 +75,7 @@ private:
int ret; int ret;
struct termios sterm, tterm; struct termios sterm, tterm;
#endif #endif
}; };
#endif // PIKBDLISTENER_H #endif // PIKBDLISTENER_H

1134
pimath.cpp Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Math 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 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 it under the terms of the GNU General Public License as published by
@@ -19,160 +19,6 @@
#include "pimath.h" #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:}\ const char Solver::methods_desc[] = "b{Methods:}\
\n -1 - Global settings\ \n -1 - Global settings\
@@ -401,3 +247,981 @@ void Solver::solvePA(double u, double h, uint deg) {
} }
moveF(); moveF();
} }
PIFFT::PIFFT() {
prepared = false;
}
PIVector<complexd> * PIFFT::calcFFT(const PIVector<complexd> & val) {
// for (uint i=0; i<result.size(); i+=2)
// {
// result[i] = val.at(indexes[i]) + val.at(indexes[i+1]);
// result[i+1] = val.at(indexes[i]) - val.at(indexes[i+1]);
// }
// return &result;
result.clear();
if (val.size_s() < 4) return &result;
fftc1d(val, val.size());
return &result;
}
PIVector<complexd> *PIFFT::calcFFTinverse(const PIVector<complexd> &val)
{
result.clear();
if (val.size_s() < 4) return &result;
fftc1dinv(val, val.size());
return &result;
}
PIVector<complexd> *PIFFT::calcHilbert(const PIVector<double> &val)
{
result.clear();
if (val.size_s() < 4) return &result;
fftc1r(val, val.size());
for (uint i=0; i<result.size()/2; i++) result[i] = result[i]*2.;
for (uint i=result.size()/2; i<result.size(); i++) result[i] = 0;
fftc1dinv(result, result.size());
return &result;
}
PIVector< complexd >* PIFFT::calcFFT(const PIVector<double> & val) {
result.clear();
if (val.size_s() < 4) return &result;
fftc1r(val, val.size());
return &result;
}
PIVector<double> PIFFT::getAmplitude() {
PIVector<double> a;
double tmp;
for (uint i=0; i<result.size(); i++) {
tmp = sqrt(result.at(i).real()*result.at(i).real()+result.at(i).imag()*result.at(i).imag());
a.push_back(tmp);
}
return a;
}
void PIFFT::fftc1d(const PIVector<complexd> &a, uint n) {
createPlan(n);
uint i;
PIVector<double> buf;
buf.resize(2*n);
for(i=0; i<n; i++) {
buf[2*i+0] = a.at(i).real();// a->ptr.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<n; i++)
result[i]=complexd(buf[2*i+0],buf[2*i+1]);
}
void PIFFT::fftc1r(const PIVector<double> & a, uint n) {
uint i;
if( n%2==0 ) {
PIVector<double> 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<n; i++)
result[i] = conj(result[n-i]);
} else {
PIVector<complexd> cbuf;
cbuf.resize(n);
for(i=0; i<n; i++)
cbuf[i] = complexd(a[i], 0.);
fftc1d(cbuf, n);
}
}
void PIFFT::fftc1dinv(const PIVector<complexd> &a, uint n)
{
PIVector<complexd> cbuf;
cbuf.resize(n);
uint i;
for(i=0; i<n; i++)
{
cbuf[i] = conj(a[i]);
}
fftc1d(cbuf, n);
// result.resize(n);
for(i=0; i<n; i++)
{
result[i] = conj(result[i] / (double)n);
}
}
void PIFFT::createPlan(uint n) {
curplan.plan.clear();
curplan.precomputed.clear();
curplan.stackbuf.clear();
curplan.tmpbuf.clear();
if (n<2) return;
ftbasegeneratecomplexfftplan(n, &curplan);
prepared = true;
}
void PIFFT::ftbasegeneratecomplexfftplan(uint n, ftplan* plan) {
int planarraysize;
int plansize;
int precomputedsize;
int tmpmemsize;
int stackmemsize;
ae_int_t stackptr;
planarraysize = 1;
plansize = 0;
precomputedsize = 0;
stackmemsize = 0;
stackptr = 0;
tmpmemsize = 2*n;
curplan.plan.resize(planarraysize);
int ftbase_ftbasecffttask = 0;
ftbase_ftbasegenerateplanrec(n, ftbase_ftbasecffttask, plan, &plansize, &precomputedsize, &planarraysize, &tmpmemsize, &stackmemsize, stackptr);
if (stackptr!=0) { return;}//ae_assert(stackptr==0, "Internal error in FTBaseGenerateComplexFFTPlan: stack ptr!");
curplan.stackbuf.resize(piMax(stackmemsize,1));//ae_vector_set_length(&curplan.stackbuf, ae_maxint(stackmemsize, 1));
curplan.tmpbuf.resize(piMax(tmpmemsize,1));//ae_vector_set_length(&(curplan.tmpbuf), ae_maxint(tmpmemsize, 1));
curplan.precomputed.resize(piMax(precomputedsize,1));//ae_vector_set_length(&curplan.precomputed, ae_maxint(precomputedsize, 1));
stackptr = 0;
ftbase_ftbaseprecomputeplanrec(plan, 0, stackptr);
if (stackptr!=0) { return;}//ae_assert(stackptr==0, "Internal error in FTBaseGenerateComplexFFTPlan: stack ptr!");
}
/*************************************************************************
Recurrent subroutine for the FFTGeneratePlan:
PARAMETERS:
N plan size
IsReal whether input is real or not.
subroutine MUST NOT ignore this flag because real
inputs comes with non-initialized imaginary parts,
so ignoring this flag will result in corrupted output
HalfOut whether full output or only half of it from 0 to
floor(N/2) is needed. This flag may be ignored if
doing so will simplify calculations
Plan plan array
PlanSize size of used part (in integers)
PrecomputedSize size of precomputed array allocated yet
PlanArraySize plan array size (actual)
TmpMemSize temporary memory required size
BluesteinMemSize temporary memory required size
-- ALGLIB --
Copyright 01.05.2009 by Bochkanov Sergey
*************************************************************************/
void PIFFT::ftbase_ftbasegenerateplanrec(
int n,
int tasktype,
ftplan* plan,
int* plansize,
int* precomputedsize,
int* planarraysize,
int* tmpmemsize,
int* stackmemsize,
ae_int_t stackptr, int debugi)
{
int k, m, n1, n2, esize, entryoffset;
int ftbase_ftbaseplanentrysize = 8;
int ftbase_ftbasecffttask = 0;
int ftbase_fftcooleytukeyplan = 0;
int ftbase_fftbluesteinplan = 1;
int ftbase_fftcodeletplan = 2;
int ftbase_fftrealcooleytukeyplan = 5;
int ftbase_fftemptyplan = 6;
if( *plansize+ftbase_ftbaseplanentrysize>(*planarraysize) ) {
curplan.plan.resize(8*(*planarraysize));
*planarraysize = 8*(*planarraysize);
}
entryoffset = *plansize;
esize = ftbase_ftbaseplanentrysize;
*plansize = *plansize+esize;
if( n==1 ) {
curplan.plan[entryoffset+0] = esize;
curplan.plan[entryoffset+1] = -1;
curplan.plan[entryoffset+2] = -1;
curplan.plan[entryoffset+3] = ftbase_fftemptyplan;
curplan.plan[entryoffset+4] = -1;
curplan.plan[entryoffset+5] = -1;
curplan.plan[entryoffset+6] = -1;
curplan.plan[entryoffset+7] = -1;
return;
}
ftbasefactorize(n, &n1, &n2);
if( n1!=1 ) {
*tmpmemsize = piMax(*tmpmemsize, 2*n1*n2);
curplan.plan[entryoffset+0] = esize;
curplan.plan[entryoffset+1] = n1;
curplan.plan[entryoffset+2] = n2;
if( tasktype==ftbase_ftbasecffttask )
curplan.plan[entryoffset+3] = ftbase_fftcooleytukeyplan;
else
curplan.plan[entryoffset+3] = ftbase_fftrealcooleytukeyplan;
curplan.plan[entryoffset+4] = 0;
curplan.plan[entryoffset+5] = *plansize;
debugi++;
ftbase_ftbasegenerateplanrec(n1, ftbase_ftbasecffttask, plan, plansize, precomputedsize, planarraysize, tmpmemsize, stackmemsize, stackptr,debugi);
curplan.plan[entryoffset+6] = *plansize;
ftbase_ftbasegenerateplanrec(n2, ftbase_ftbasecffttask, plan, plansize, precomputedsize, planarraysize, tmpmemsize, stackmemsize, stackptr,debugi);
curplan.plan[entryoffset+7] = -1;
return;
} else {
if (n>=2 && n<=5) {
curplan.plan[entryoffset+0] = esize;
curplan.plan[entryoffset+1] = n1;
curplan.plan[entryoffset+2] = n2;
curplan.plan[entryoffset+3] = ftbase_fftcodeletplan;
curplan.plan[entryoffset+4] = 0;
curplan.plan[entryoffset+5] = -1;
curplan.plan[entryoffset+6] = -1;
curplan.plan[entryoffset+7] = *precomputedsize;
if( n==3 )
*precomputedsize = *precomputedsize+2;
if( n==5 )
*precomputedsize = *precomputedsize+5;
return;
} else {
k = 2*n2-1;
m = ftbasefindsmooth(k);
*tmpmemsize = piMax(*tmpmemsize, 2*m);
curplan.plan[entryoffset+0] = esize;
curplan.plan[entryoffset+1] = n2;
curplan.plan[entryoffset+2] = -1;
curplan.plan[entryoffset+3] = ftbase_fftbluesteinplan;
curplan.plan[entryoffset+4] = m;
curplan.plan[entryoffset+5] = *plansize;
stackptr = stackptr+2*2*m;
*stackmemsize = piMax(*stackmemsize, stackptr);
ftbase_ftbasegenerateplanrec(m, ftbase_ftbasecffttask, plan, plansize, precomputedsize, planarraysize, tmpmemsize, stackmemsize, stackptr);
stackptr = stackptr-2*2*m;
curplan.plan[entryoffset+6] = -1;
curplan.plan[entryoffset+7] = *precomputedsize;
*precomputedsize = *precomputedsize+2*m+2*n;
return;
}
}
}
/*************************************************************************
Recurrent subroutine for precomputing FFT plans
-- ALGLIB --
Copyright 01.05.2009 by Bochkanov Sergey
*************************************************************************/
void PIFFT::ftbase_ftbaseprecomputeplanrec(ftplan* plan,
int entryoffset,
ae_int_t stackptr)
{
int n1, n2, n, m, offs;
double v, bx, by;
int ftbase_fftcooleytukeyplan = 0;
int ftbase_fftbluesteinplan = 1;
int ftbase_fftcodeletplan = 2;
int ftbase_fhtcooleytukeyplan = 3;
int ftbase_fhtcodeletplan = 4;
int ftbase_fftrealcooleytukeyplan = 5;
if( (curplan.plan[entryoffset+3]==ftbase_fftcooleytukeyplan||curplan.plan[entryoffset+3]==ftbase_fftrealcooleytukeyplan)||curplan.plan[entryoffset+3]==ftbase_fhtcooleytukeyplan ) {
ftbase_ftbaseprecomputeplanrec(plan, curplan.plan[entryoffset+5], stackptr);
ftbase_ftbaseprecomputeplanrec(plan, curplan.plan[entryoffset+6], stackptr);
return;
}
if( curplan.plan[entryoffset+3]==ftbase_fftcodeletplan||curplan.plan[entryoffset+3]==ftbase_fhtcodeletplan ) {
n1 = curplan.plan[entryoffset+1];
n2 = curplan.plan[entryoffset+2];
n = n1*n2;
if( n==3 ) {
offs = curplan.plan[entryoffset+7];
curplan.precomputed[offs+0] = cos(2*M_PI/3)-1;
curplan.precomputed[offs+1] = sin(2*M_PI/3);
return;
}
if( n==5 ) {
offs = curplan.plan[entryoffset+7];
v = 2*M_PI/5;
curplan.precomputed[offs+0] = (cos(v)+cos(2*v))/2-1;
curplan.precomputed[offs+1] = (cos(v)-cos(2*v))/2;
curplan.precomputed[offs+2] = -sin(v);
curplan.precomputed[offs+3] = -(sin(v)+sin(2*v));
curplan.precomputed[offs+4] = sin(v)-sin(2*v);
return;
}
}
if( curplan.plan[entryoffset+3]==ftbase_fftbluesteinplan ) {
ftbase_ftbaseprecomputeplanrec(plan, curplan.plan[entryoffset+5], stackptr);
n = curplan.plan[entryoffset+1];
m = curplan.plan[entryoffset+4];
offs = curplan.plan[entryoffset+7];
for(int i=0; i<=2*m-1; i++)
curplan.precomputed[offs+i] = 0;
for(int i=0; i<n; i++) {
bx = cos(M_PI*sqr(i)/n);
by = sin(M_PI*sqr(i)/n);
curplan.precomputed[offs+2*i+0] = bx;
curplan.precomputed[offs+2*i+1] = by;
curplan.precomputed[offs+2*m+2*i+0] = bx;
curplan.precomputed[offs+2*m+2*i+1] = by;
if( i>0 ) {
curplan.precomputed[offs+2*(m-i)+0] = bx;
curplan.precomputed[offs+2*(m-i)+1] = by;
}
}
ftbaseexecuteplanrec(&curplan.precomputed, offs, plan, curplan.plan[entryoffset+5], stackptr);
return;
}
}
void PIFFT::ftbasefactorize(int n, int* n1, int* n2) {
*n1 = *n2 = 0;
int ftbase_ftbasecodeletrecommended = 5;
if( (*n1)*(*n2)!=n ) {
for(int j=ftbase_ftbasecodeletrecommended; j>=2; j--) {
if( n%j==0 ) {
*n1 = j;
*n2 = n/j;
break;
}
}
}
if( (*n1)*(*n2)!=n ) {
for(int j=ftbase_ftbasecodeletrecommended+1; j<=n-1; j++) {
if( n%j==0 ) {
*n1 = j;
*n2 = n/j;
break;
}
}
}
if( (*n1)*(*n2)!=n ) {
*n1 = 1;
*n2 = n;
}
if( (*n2)==1 && (*n1)!=1 ) {
*n2 = *n1;
*n1 = 1;
}
}
/*************************************************************************
Is number smooth?
-- ALGLIB --
Copyright 01.05.2009 by Bochkanov Sergey
*************************************************************************/
void PIFFT::ftbase_ftbasefindsmoothrec(int n, int seed, int leastfactor, int* best) {
if( seed>=n ) {
*best = 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<n)
best = 2*best;
ftbase_ftbasefindsmoothrec(n, 1, 2, &best);
result = best;
return result;
}
void PIFFT::ftbase_internalreallintranspose(PIVector<double>* a, int m, int n, int astart, PIVector<double>* 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<double>* a, int astart, int astride, PIVector<double>* 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<double>* a, int m, int n, int astart, PIVector<double>* 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<double>* a, int astart, int astride, PIVector<double>* 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<double>* 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<double>* 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<double> & 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<n; i++) {
bx = curplan.precomputed[offsp+0];
by = curplan.precomputed[offsp+1];
x = (*a)[offsa+0];
y = (*a)[offsa+1];
curplan.stackbuf[offsb+0] = x*bx-y*(-by);
curplan.stackbuf[offsb+1] = x*(-by)+y*bx;
offsp = offsp+2;
offsa = offsa+2;
offsb = offsb+2;
}
ftbaseexecuteplanrec(&curplan.stackbuf, stackptr, plan, curplan.plan[entryoffset+5], stackptr+2*2*m);
offsb = stackptr;
offsp = offs;
for(int i=0; i<=m-1; i++) {
x = curplan.stackbuf[offsb+0];
y = curplan.stackbuf[offsb+1];
bx = curplan.precomputed[offsp+0];
by = curplan.precomputed[offsp+1];
curplan.stackbuf[offsb+0] = x*bx-y*by;
curplan.stackbuf[offsb+1] = -(x*by+y*bx);
offsb = offsb+2;
offsp = offsp+2;
}
ftbaseexecuteplanrec(&curplan.stackbuf, stackptr, plan, curplan.plan[entryoffset+5], stackptr+2*2*m);
offsb = stackptr;
offsp = offs+2*m;
offsa = aoffset;
for(int i=0; i<n; i++) {
x = curplan.stackbuf[offsb+0]/m;
y = -curplan.stackbuf[offsb+1]/m;
bx = curplan.precomputed[offsp+0];
by = curplan.precomputed[offsp+1];
(*a)[offsa+0] = x*bx-y*(-by);
(*a)[offsa+1] = x*(-by)+y*bx;
offsp = offsp+2;
offsa = offsa+2;
offsb = offsb+2;
}
return;
}
}
/*************************************************************************
Twiddle factors calculation
-- ALGLIB --
Copyright 01.05.2009 by Bochkanov Sergey
*************************************************************************/
void PIFFT::ftbase_ffttwcalc(PIVector<double> * a, int aoffset, int n1, int n2) {
int n, idx, offs;
double x, y, twxm1, twy, twbasexm1, twbasey, twrowxm1, twrowy, tmpx, tmpy, v;
int ftbase_ftbaseupdatetw = 4;
n = n1*n2;
v = -2*M_PI/n;
twbasexm1 = -2*sqr(sin(0.5*v));
twbasey = sin(v);
twrowxm1 = 0;
twrowy = 0;
for(int i=0, j = 0; i<=n2-1; i++) {
twxm1 = 0;
twy = 0;
for(j=0; j<=n1-1; j++) {
idx = i*n1+j;
offs = aoffset+2*idx;
x = (*a)[offs+0];
y = (*a)[offs+1];
tmpx = x*twxm1-y*twy;
tmpy = x*twy+y*twxm1;
(*a)[offs+0] = x+tmpx;
(*a)[offs+1] = y+tmpy;
if( j<n1-1 ) {
if( j%ftbase_ftbaseupdatetw==0 ) {
v = -2*M_PI*i*(j+1)/n;
twxm1 = -2*sqr(sin(0.5*v));
twy = sin(v);
} else {
tmpx = twrowxm1+twxm1*twrowxm1-twy*twrowy;
tmpy = twrowy+twxm1*twrowy+twy*twrowxm1;
twxm1 = twxm1+tmpx;
twy = twy+tmpy;
}
}
}
if( i<n2-1 ) {
if( j%ftbase_ftbaseupdatetw==0 ) {
v = -2*M_PI*(i+1)/n;
twrowxm1 = -2*sqr(sin(0.5*v));
twrowy = sin(v);
} else {
tmpx = twbasexm1+twrowxm1*twbasexm1-twrowy*twbasey;
tmpy = twbasey+twrowxm1*twbasey+twrowy*twbasexm1;
twrowxm1 = twrowxm1+tmpx;
twrowy = twrowy+tmpy;
}
}
}
}
PIStatistic::PIStatistic() {
mean = 0.;
variance = 0.;
skewness = 0.;
kurtosis = 0.;
}
bool PIStatistic::calculate(const PIVector<double> & 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;
}

203
pimath.h Executable file → Normal file
View File

@@ -1,20 +1,20 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Math 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 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PIMATH_H #ifndef PIMATH_H
@@ -22,18 +22,37 @@
#include "picontainers.h" #include "picontainers.h"
#ifndef QNX #ifndef QNX
# include <cmath> # include <complex>
# include <complex> # include <cmath>
#else #else
# include <math.h> # include <complex.h>
# include <complex.h> # include <math.h>
#endif
#ifdef CC_VC
#define M_PI 3.14159265358979323846
#endif #endif
#define M_2PI 6.28318530717958647692 #ifndef M_LN2
#define M_PI_3 1.04719755119659774615 # 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; using std::complex;
@@ -48,30 +67,47 @@ const complexd complexd_i(0., 1.);
const complexd complexd_0(0.); const complexd complexd_0(0.);
const complexd complexd_1(1.); const complexd complexd_1(1.);
const double deg2rad = atan(1.) / 45.; const double deg2rad = M_PI_180;
const double rad2deg = 45. / atan(1.); const double rad2deg = M_180_PI;
inline int pow2(const int p) {return 1 << p;} inline int pow2(const int p) {return 1 << p;}
inline double sqr(const double & v) {return v * v;} 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 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(round(c.real()), round(c.imag()));} inline complexd round(const complexd & c) {return complexd(piRound<double>(c.real()), piRound<double>(c.imag()));}
inline complexd floor(const complexd & c) {return complexd(floor(c.real()), floor(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 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 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 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));} 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 tan(const complexd & c) {return sin(c) / cos(c);}
inline complexd tanh(const complexd & c) {return sinh(c) / cosh(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 log2(const complexd & c) {return log(c) / M_LN2;}
inline complexd log10(const complexd & c) {return log(c) / M_LN10;} 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 j1(const double & v) {v;}
inline double jn(const int & n, const double & v) {v;} inline double jn(const int & n, const double & v) {return v;}
inline double y0(const double & v) {v;} inline double y0(const double & v) {return v;}
inline double y1(const double & v) {v;} inline double y1(const double & v) {return v;}
inline double yn(const int & n, const double & v) {v;} inline double yn(const int & n, const double & v) {return v;}
#endif #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<double> abs(const PIVector<complexd> &v) {
PIVector<double> result;
result.resize(v.size());
for(uint i=0; i<v.size(); i++) result[i] = abs(v.at(i));
return result;
}
inline PIVector<double> abs(const PIVector<double> &v) {
PIVector<double> result;
result.resize(v.size());
for(uint i=0; i<v.size(); i++) result[i] = abs(v.at(i));
return result;
}
template<uint Cols, uint Rows, typename Type> template<uint Cols, uint Rows, typename Type>
class PIMathMatrixT; 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 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 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 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 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 & 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;} _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 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 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 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 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 & 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;} _CVector normalized() {_CVector tv(*this); tv.normalize(); return tv;}
@@ -624,7 +660,7 @@ inline std::ostream & operator <<(std::ostream & s, const PIMathMatrix<Type> & m
/// Multiply matrices {CR x Rows0} on {Cols1 x CR}, result is {Cols1 x Rows0} /// Multiply matrices {CR x Rows0} on {Cols1 x CR}, result is {Cols1 x Rows0}
template<typename Type> template<typename Type>
inline PIMathMatrix<Type> operator *(const PIMathMatrix<Type> & fm, inline PIMathMatrix<Type> operator *(const PIMathMatrix<Type> & fm,
const PIMathMatrix<Type> & sm) { const PIMathMatrix<Type> & sm) {
uint cr = fm.cols(), rows0 = fm.rows(), cols1 = sm.cols(); uint cr = fm.cols(), rows0 = fm.rows(), cols1 = sm.cols();
PIMathMatrix<Type> tm(cols1, rows0); PIMathMatrix<Type> tm(cols1, rows0);
if (fm.cols() != sm.rows()) return tm; if (fm.cols() != sm.rows()) return tm;
@@ -643,7 +679,7 @@ inline PIMathMatrix<Type> operator *(const PIMathMatrix<Type> & fm,
/// Multiply matrix {Cols x Rows} on vector {Cols}, result is vector {Rows} /// Multiply matrix {Cols x Rows} on vector {Cols}, result is vector {Rows}
template<typename Type> template<typename Type>
inline PIMathVector<Type> operator *(const PIMathMatrix<Type> & fm, inline PIMathVector<Type> operator *(const PIMathMatrix<Type> & fm,
const PIMathVector<Type> & sv) { const PIMathVector<Type> & sv) {
uint c = fm.cols(), r = fm.rows(); uint c = fm.cols(), r = fm.rows();
PIMathVector<Type> tv(r); PIMathVector<Type> tv(r);
if (c != sv.size()) return tv; if (c != sv.size()) return tv;
@@ -669,13 +705,6 @@ typedef PIMathMatrix<double> PIMathMatrixd;
#undef PIMM_FOR_R #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 /// Differential evaluations
struct TransferFunction { // Для задания передаточной функции struct TransferFunction { // Для задания передаточной функции
@@ -691,18 +720,18 @@ class Solver
{ {
public: public:
enum Method {Global = -1, enum Method {Global = -1,
Eyler_1 = 01, Eyler_1 = 01,
Eyler_2 = 02, Eyler_2 = 02,
EylerKoshi = 03, EylerKoshi = 03,
RungeKutta_4 = 14, RungeKutta_4 = 14,
AdamsBashfortMoulton_2 = 22, AdamsBashfortMoulton_2 = 22,
AdamsBashfortMoulton_3 = 23, AdamsBashfortMoulton_3 = 23,
AdamsBashfortMoulton_4 = 24, AdamsBashfortMoulton_4 = 24,
PolynomialApproximation_2 = 32, PolynomialApproximation_2 = 32,
PolynomialApproximation_3 = 33, PolynomialApproximation_3 = 33,
PolynomialApproximation_4 = 34, PolynomialApproximation_4 = 34,
PolynomialApproximation_5 = 35 PolynomialApproximation_5 = 35
}; };
Solver() {times.resize(4); step = 0;} Solver() {times.resize(4); step = 0;}
@@ -744,4 +773,68 @@ private:
}; };
class PIFFT
{
public:
PIFFT();
// const PIVector<uint> & getIndexes() {return indexes;}
// const PIVector<complexd> & getCoefs() {return coefs;}
PIVector<complexd> * calcFFT(const PIVector<complexd> &val);
PIVector<complexd> * calcFFT(const PIVector<double> &val);
PIVector<complexd> * calcFFTinverse(const PIVector<complexd> &val);
PIVector<complexd> * calcHilbert(const PIVector<double> &val);
PIVector<double> getAmplitude();
private:
// PIVector<uint> indexes;
// PIVector<complexd> coefs;
PIVector<complexd> 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<int> plan;
PIVector<double> precomputed;
PIVector<double> tmpbuf;
PIVector<double> stackbuf;
};
ftplan curplan;
void fftc1d(const PIVector<complexd> &a, uint n);
void fftc1r(const PIVector<double> &a, uint n);
void fftc1dinv(const PIVector<complexd> &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<double> *a, int aoffset, int n, ftplan *plan);
void ftbaseexecuteplanrec(PIVector<double> *a, int aoffset, ftplan *plan, int entryoffset, ae_int_t stackptr);
void ftbase_internalcomplexlintranspose(PIVector<double> *a, int m, int n, int astart, PIVector<double> *buf);
void ftbase_ffticltrec(PIVector<double> *a, int astart, int astride, PIVector<double> *b, int bstart, int bstride, int m, int n);
void ftbase_internalreallintranspose(PIVector<double> *a, int m, int n, int astart, PIVector<double> *buf);
void ftbase_fftirltrec(PIVector<double> *a, int astart, int astride, PIVector<double> *b, int bstart, int bstride, int m, int n);
void ftbase_ffttwcalc(PIVector<double> *a, int aoffset, int n1, int n2);
};
class PIStatistic {
public:
PIStatistic();
bool calculate(const PIVector<double> &val);
double mean;
double variance;
double skewness;
double kurtosis;
};
#endif // PIMATH_H #endif // PIMATH_H

2
pimonitor.cpp Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Counter of some PIP types 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 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 it under the terms of the GNU General Public License as published by

2
pimonitor.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Counter of some PIP types 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 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 it under the terms of the GNU General Public License as published by

6
pimultiprotocol.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Multiprotocol 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 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 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";} 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() {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() {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: 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);} void received(PIProtocol * prot, bool , uchar * data, int size) {if (prot == protocol(0)) protocol(1)->send(data, size); else protocol(0)->send(data, size);}

2
pimutex.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Mutex 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 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 it under the terms of the GNU General Public License as published by

4
piobject.cpp Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism 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 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 it under the terms of the GNU General Public License as published by
@@ -36,4 +36,4 @@ PIStringList PIObject::eventHandlers() {
l << (*i).first; l << (*i).first;
return l; return l;
} }
*/ */

120
piobject.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism 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 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 it under the terms of the GNU General Public License as published by
@@ -22,37 +22,62 @@
#include "pistring.h" #include "pistring.h"
//#ifdef CC_VC /// declare event handler \"event\" inside class \"obj\" with name \"name\", ret name()
//#define HANDLER(c,s) #s,PIObject::handlerPtr<c>((void(c::*)())&c::s) #define EVENT_HANDLER0(obj, ret, name) static ret __stat_eh_##name##__(void * o) {return ((obj*)o)->name();} ret name()
//#else #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 HANDLER(c,s) #s,(void*)&c::s #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)
//#endif #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_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)
#define EVENT_HANDLER EVENT_HANDLER0 #define EVENT_HANDLER EVENT_HANDLER0
#define EVENT_VHANDLER0(obj, ret, name) static ret __stat_##name##__(void * o) {return ((obj*)o)->name();} virtual ret name() /// declare virtual event handler \"event\" inside class \"obj\" with name \"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_VHANDLER0(obj, ret, name) static ret __stat_eh_##name##__(void * o) {return ((obj*)o)->name();} virtual ret name()
#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_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_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_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_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) #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 EVENT_VHANDLER EVENT_VHANDLER0
#define CONNECT0(ret, src, event, dst, handler) PIObject::connect(src, #event, dst, (void*)(ret(*)(void*))(&(dst)->__stat_##handler##__)); /// declare event \"event\" inside class \"obj\" with name \"name\", void name();
#define CONNECT1(ret, a0, src, event, dst, handler) PIObject::connect(src, #event, dst, (void*)(ret(*)(void*, a0))(&(dst)->__stat_##handler##__)); #define EVENT0(obj, name) EVENT_HANDLER0(obj, void, name) {PIObject::raiseEvent(this, #name);}
#define CONNECT2(ret, a0, a1, src, event, dst, handler) PIObject::connect(src, #event, dst, (void*)(ret(*)(void*, a0, a1))(&(dst)->__stat_##handler##__)); #define EVENT1(obj, name, a0, n0) EVENT_HANDLER1(obj, void, name, a0, n0) {PIObject::raiseEvent(this, #name, n0);}
#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 EVENT2(obj, name, a0, n0, a1, n1) EVENT_HANDLER2(obj, void, name, a0, n0, a1, n1) {PIObject::raiseEvent(this, #name, n0, n1);}
#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##__)); #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 #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 class PIObject
{ {
friend class PIObjectManager; friend class PIObjectManager;
@@ -109,24 +134,34 @@ public:
} }
*/ */
/// Direct connect /// Direct connect
static void connect(PIObject * src, const PIString & sig, void * 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 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, void * e_h) {src->connections << Connection(ev_h, e_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 piDisconnect(PIObject * src, const PIString & sig, void * dest, void * ev_h) {
//static void connect(PIObject & src, const PIString & sig, PIObject & dest, void * ev_h) {src.connections << Connection(ev_h, sig, &dest);} 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 /*/// 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); PIObject * src = findByName(srcObject);
if (src == 0) { 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; return false;
} }
PIObject * dest = findByName(destObject); PIObject * dest = findByName(destObject);
if (dest == 0) { 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 false;
} }
return PIObject::connect(src, event, dest, handler, force); return PIObject::piConnect(src, event, dest, handler, force);
}*/ }*/
/// Raise events /// Raise events
@@ -195,7 +230,7 @@ public:
static void raiseEvent(const PIString & destObject, const PIString & name) { static void raiseEvent(const PIString & destObject, const PIString & name) {
PIObject * dest = findByName(destObject); PIObject * dest = findByName(destObject);
if (dest == 0) { 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; return;
} }
raiseEvent(dest, name); raiseEvent(dest, name);
@@ -204,7 +239,7 @@ public:
static void raiseEvent(const PIString & destObject, const PIString & name, const T0 & v0 = T0()) { static void raiseEvent(const PIString & destObject, const PIString & name, const T0 & v0 = T0()) {
PIObject * dest = findByName(destObject); PIObject * dest = findByName(destObject);
if (dest == 0) { 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; return;
} }
raiseEvent<T0>(dest, name, v0); raiseEvent<T0>(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()) { static void raiseEvent(const PIString & destObject, const PIString & name, const T0 & v0 = T0(), const T1 & v1 = T1()) {
PIObject * dest = findByName(destObject); PIObject * dest = findByName(destObject);
if (dest == 0) { 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; return;
} }
raiseEvent<T0, T1>(dest, name, v0, v1); raiseEvent<T0, T1>(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()) { 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); PIObject * dest = findByName(destObject);
if (dest == 0) { 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; return;
} }
raiseEvent<T0, T1, T2>(name, dest, v0, v1, v2); raiseEvent<T0, T1, T2>(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()) { 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); PIObject * dest = findByName(destObject);
if (dest == 0) { 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; return;
} }
raiseEvent<T0, T1, T2, T3>(name,dest , v0, v1, v2, v3); raiseEvent<T0, T1, T2, T3>(name,dest , v0, v1, v2, v3);
} }
protected:
PIString name_;
private: private:
struct Connection { 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 * slot;
void * signal;
PIString event; PIString event;
void * dest; void * dest;
}; };
PIString name_;
PIVector<Connection> connections; PIVector<Connection> connections;
static PIVector<PIObject * > objects; static PIVector<PIObject * > objects;

4
pip.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
All includes 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 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 it under the terms of the GNU General Public License as published by
@@ -27,3 +27,5 @@
#include "pisignals.h" #include "pisignals.h"
#include "piobject.h" #include "piobject.h"
#include "pisystemmonitor.h" #include "pisystemmonitor.h"
#include "pipeer.h"
#include "picrc.h"

View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Packets extractor 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 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 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) { PIPacketExtractor::PIPacketExtractor(PIIODevice * device_, void * recHeaderPtr, int recHeaderSize, int recDataSize) {
ret_func_header = 0; ret_func_header = 0;
setPacketData(recHeaderPtr, recHeaderSize, recDataSize); setPacketData(recHeaderPtr, recHeaderSize, recDataSize);
setBufferSize(4096); setThreadedReadBufferSize(65536);
setBufferSize(65536);
setDevice(device_); setDevice(device_);
allReaded = addSize = curInd = 0; allReaded = addSize = curInd = missed = 0;
} }
@@ -55,7 +56,8 @@ bool PIPacketExtractor::threadedRead(uchar * readed, int size_) {
return true; 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)) { if (!packetValidate(buffer.data(curInd + headerSize), dataSize)) {
curInd++; missed++; curInd++; missed++;
if (packetSize > 0) missed_packets = missed / packetSize; if (packetSize > 0) missed_packets = missed / packetSize;
@@ -66,10 +68,17 @@ bool PIPacketExtractor::threadedRead(uchar * readed, int size_) {
allReaded -= packetSize + curInd; allReaded -= packetSize + curInd;
curInd = addSize = 0; curInd = addSize = 0;
} else { } else {
packetValidate(buffer.data(), dataSize); if (dataSize == 0) {
memcpy(sbuffer.data(), buffer.data(), allReaded); packetValidate(buffer.data(), size_);
memcpy(buffer.data(), sbuffer.data(packetSize), allReaded); memcpy(sbuffer.data(), buffer.data(), allReaded);
allReaded -= packetSize; 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; return true;
} }

View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Packets extractor 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 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 it under the terms of the GNU General Public License as published by
@@ -30,18 +30,19 @@ class PIPacketExtractor: public PIIODevice
{ {
public: public:
PIPacketExtractor(PIIODevice * device_ = 0, void * recHeaderPtr = 0, int recHeaderSize = 0, int recDataSize = 0); PIPacketExtractor(PIIODevice * device_ = 0, void * recHeaderPtr = 0, int recHeaderSize = 0, int recDataSize = 0);
virtual ~PIPacketExtractor() {}
PIIODevice * device() {return dev;} PIIODevice * device() {return dev;}
void setDevice(PIIODevice * device_); void setDevice(PIIODevice * device_);
int bufferSize() const {return buffer_size;} 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 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);} 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 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 * missedBytes_ptr() const {return &missed;}
const ullong * missedPackets_ptr() const {return &missed_packets;} const ullong * missedPackets_ptr() const {return &missed_packets;}
@@ -56,7 +57,7 @@ protected:
private: private:
bool threadedRead(uchar * readed, int size); 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; PIIODevice * dev;
PIByteArray mheader, buffer, sbuffer; PIByteArray mheader, buffer, sbuffer;

186
pipeer.cpp Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#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<PeerInfo> 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<PeerInfo * > cwave;
for (int d = 0; d <= max_dist; ++d) {
//if ()
}
}

81
pipeer.h Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#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<PIEthernet * > eths;
PIEthernet * eth_send;
PITimer timer;
PeerInfo self_info;
PIVector<PeerInfo> 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

29
piprocess.cpp Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Process 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 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 it under the terms of the GNU General Public License as published by
@@ -55,7 +55,7 @@ void PIProcess::run() {
//cout << "run" << endl; //cout << "run" << endl;
string str; string str;
/// arguments convertion /// arguments convertion
int as = 0; as = 0;
#ifdef WINDOWS #ifdef WINDOWS
//args.pop_front(); //args.pop_front();
piForeachC (PIString & i, args) piForeachC (PIString & i, args)
@@ -96,30 +96,31 @@ void PIProcess::run() {
f_in = PIFile::openTemporary(PIIODevice::ReadWrite); f_in = PIFile::openTemporary(PIIODevice::ReadWrite);
t_in = true; t_in = true;
} }
f_in.open(PIIODevice::ReadWrite); f_in.close(); //f_in.open(PIIODevice::ReadWrite); f_in.close();
if (f_out.path().isEmpty()) { if (f_out.path().isEmpty()) {
f_out = PIFile::openTemporary(PIIODevice::ReadWrite); f_out = PIFile::openTemporary(PIIODevice::ReadWrite);
t_out = true; t_out = true;
} }
f_out.open(PIIODevice::WriteOnly); f_out.close(); //f_out.open(PIIODevice::WriteOnly); f_out.close();
if (f_err.path().isEmpty()) { if (f_err.path().isEmpty()) {
f_err = PIFile::openTemporary(PIIODevice::ReadWrite); f_err = PIFile::openTemporary(PIIODevice::ReadWrite);
t_err = true; t_err = true;
} }
f_err.open(PIIODevice::WriteOnly); f_err.close(); //f_err.open(PIIODevice::WriteOnly); f_err.close();
str = args.front().stdString(); str = args.front().stdString();
is_exec = true; is_exec = true;
execStarted(PIString(str));
#ifndef WINDOWS #ifndef WINDOWS
pid = fork(); pid = fork();
if (pid == 0) { if (pid == 0) {
#endif #endif
FILE * tf = 0; tf_in = tf_out = tf_err = 0;
//cout << "exec" << endl; //cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl;
//cout << f_out.path() << endl; //cout << f_out.path() << endl;
if (g_in) tf = freopen(f_in.path().data(), "r", stdin); if (g_in) tf_in = freopen(f_in.path().data(), "r", stdin);
if (g_out) tf = freopen(f_out.path().data(), "w", stdout); if (g_out) tf_out = freopen(f_out.path().data(), "w", stdout);
if (g_err) tf = freopen(f_err.path().data(), "w", stderr); if (g_err) tf_err = freopen(f_err.path().data(), "w", stderr);
#ifndef WINDOWS #ifndef WINDOWS
if (!wd.isEmpty()) as = chdir(wd.data()); if (!wd.isEmpty()) as = chdir(wd.data());
#endif #endif
@@ -142,16 +143,22 @@ void PIProcess::run() {
} else } else
piCout << "[PIProcess] \"CreateProcess\" error, " << errorString() << endl; piCout << "[PIProcess] \"CreateProcess\" error, " << errorString() << endl;
#else #else
//cout << "exec " << tf_in << ", " << tf_out << ", " << tf_err << endl;
if (execve(str.c_str(), a, e) < 0) if (execve(str.c_str(), a, e) < 0)
piCout << "[PIProcess] \"execve\" error, " << errorString() << endl; piCout << "[PIProcess] \"execve\" error, " << errorString() << endl;
} else { } else {
msleep(1); msleep(1);
//cout << "wait" << endl; //cout << "wait" << endl;
wait(&exit_code); 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; pid = 0;
//cout << "wait done" << endl; //cout << "wait done" << endl;
} }
#endif #endif
execFinished(PIString(str), exit_code);
is_exec = false; is_exec = false;
for (int i = 0; i < env.size_s(); ++i) for (int i = 0; i < env.size_s(); ++i)
delete e[i]; delete e[i];
@@ -162,7 +169,7 @@ void PIProcess::run() {
for (int i = 0; i < args.size_s(); ++i) for (int i = 0; i < args.size_s(); ++i)
delete a[i]; delete a[i];
#endif #endif
//cout << "end" << endl; //cout << "end " << tf_in << ", " << tf_out << ", " << tf_err << endl;
} }

37
piprocess.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Process 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 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 it under the terms of the GNU General Public License as published by
@@ -28,6 +28,18 @@
# include <sys/wait.h> # include <sys/wait.h>
#endif #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 class PIProcess: private PIThread
{ {
public: public:
@@ -53,17 +65,18 @@ public:
PIString workingDirectory() const {return wd;} PIString workingDirectory() const {return wd;}
void setWorkingDirectory(const PIString & path) {wd = path;} void setWorkingDirectory(const PIString & path) {wd = path;}
void resetWorkingDirectory() {wd.clear();} void resetWorkingDirectory() {wd.clear();}
void exec(const PIString & program) {args.clear(); args << program; exec_();} EVENT_HANDLER1(PIProcess, void, exec, const PIString & , program) {args.clear(); args << program; exec_();}
void exec(const PIString & program, const PIString & arg) {args.clear(); args << program << arg; exec_();} EVENT_HANDLER2(PIProcess, 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_();} EVENT_HANDLER3(PIProcess, 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_();} 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_();}
void exec(const PIString & program, const PIStringList & args_) {args << program << args_; exec_();} EVENT_HANDLER2(PIProcess, void, exec, const PIString & , program, const PIStringList & , args_) {args << program << args_; exec_();}
#ifdef WINDOWS #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 #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 #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 readOutput() {f_out.open(PIIODevice::ReadOnly); return f_out.readAll();}
PIByteArray readError() {f_err.open(PIIODevice::ReadOnly); return f_err.readAll();} PIByteArray readError() {f_err.open(PIIODevice::ReadOnly); return f_err.readAll();}
@@ -79,6 +92,9 @@ public:
static int currentPID() {return getpid();} static int currentPID() {return getpid();}
#endif #endif
EVENT1(PIProcess, execStarted, PIString, program)
EVENT2(PIProcess, execFinished, PIString, program, int, exit_code)
private: private:
virtual void run(); virtual void run();
void exec_(); void exec_();
@@ -94,7 +110,8 @@ private:
#else #else
pid_t pid; pid_t pid;
#endif #endif
int exit_code, sz; FILE * tf_in, * tf_out, * tf_err;
int exit_code, sz, as;
bool is_exec; bool is_exec;
}; };

145
piprotocol.cpp Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Protocol, input/output channel (COM, UDP) 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 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 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; int ps, gps;
bool ok, gok, flag, gflag, has_dev = false; bool ok, gok, flag, gflag, has_dev = false;
float freq, gfreq; float freq, gfreq;
PIFlags<PISerial::Parameters> pp; PIFlags<PISerial::Parameters> pp(0);
PIConfig::Entry & b(conf.getValue(name)), PIConfig::Entry & b(conf.getValue(name)),
& rb(b.getValue("receiver")), & rb(b.getValue("receiver")),
& sb(b.getValue("sender")); & sb(b.getValue("sender"));
@@ -65,7 +65,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
} }
type_rec = PIProtocol::Ethernet; type_rec = PIProtocol::Ethernet;
eth = new PIEthernet(); eth = new PIEthernet();
packet_ext.setDevice(eth); packet_ext->setDevice(eth);
//setSenderAddress(dev, ps); //setSenderAddress(dev, ps);
setReceiverAddress(dev, ps); setReceiverAddress(dev, ps);
has_dev = true; has_dev = true;
@@ -128,7 +128,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
devReceiverState = "Config error"; devReceiverState = "Config error";
return; return;
} }
pp |= PISerial::ParityControl; pp.setFlag(PISerial::ParityControl, flag);
} }
flag = rb.getValue("twoStopBits", false, &ok); flag = rb.getValue("twoStopBits", false, &ok);
gflag = b.getValue("twoStopBits", false, &gok); gflag = b.getValue("twoStopBits", false, &gok);
@@ -139,12 +139,12 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
devReceiverState = "Config error"; devReceiverState = "Config error";
return; return;
} }
pp |= PISerial::TwoStopBits; pp.setFlag(PISerial::TwoStopBits, flag);
} }
type_rec = PIProtocol::Serial; type_rec = PIProtocol::Serial;
type_send = PIProtocol::Serial; type_send = PIProtocol::Serial;
ser = new PISerial(dev); ser = new PISerial(dev);
packet_ext.setDevice(ser); packet_ext->setDevice(ser);
//setSenderDevice(dev, (PISerial::Speed)ps); //setSenderDevice(dev, (PISerial::Speed)ps);
setReceiverDevice(dev, (PISerial::Speed)ps); setReceiverDevice(dev, (PISerial::Speed)ps);
ser->setInSpeed((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"; devSenderState = "Config error";
return; return;
} }
pp |= PISerial::ParityControl; pp.setFlag(PISerial::ParityControl, flag);
} }
flag = sb.getValue("twoStopBits", false, &ok); flag = sb.getValue("twoStopBits", false, &ok);
gflag = b.getValue("twoStopBits", false, &gok); gflag = b.getValue("twoStopBits", false, &gok);
@@ -308,7 +308,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
devSenderState = "Config error"; devSenderState = "Config error";
return; return;
} }
pp |= PISerial::TwoStopBits; pp.setFlag(PISerial::TwoStopBits, flag);
} }
} else { } else {
piCout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".sender.speed\" or \"" << name << ".speed\" in \"" << config << "\"!" << endl; piCout << "[PIProtocol \"" << name << "\"] Can`t find \"" << name << ".sender.speed\" or \"" << name << ".speed\" in \"" << config << "\"!" << endl;
@@ -365,14 +365,7 @@ PIProtocol::PIProtocol(const PIString & config, const PIString & name, void * re
dataSize = recDataSize; dataSize = recDataSize;
sendDataPtr = (uchar * )sendDataPtr_; sendDataPtr = (uchar * )sendDataPtr_;
sendDataSize = sendDataSize_; sendDataSize = sendDataSize_;
packet_ext.setPacketData(recHeaderPtr, recHeaderSize, recDataSize); 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];
} }
@@ -394,16 +387,18 @@ PIProtocol::~PIProtocol() {
} }
delete diagTimer; delete diagTimer;
delete sendTimer; delete sendTimer;
if (packet != 0) delete packet; delete secTimer;
if (eth != 0) delete eth; if (eth != 0) delete eth;
if (ser != 0) delete ser; if (ser != 0) delete ser;
delete packet_ext;
} }
void PIProtocol::init() { void PIProtocol::init() {
packet_ext.setThreadedReadData(this); packet_ext = new PIPacketExtractor();
packet_ext.setThreadedReadSlot(receiveEvent); packet_ext->setThreadedReadData(this);
packet_ext.setHeaderCheckSlot(headerValidateEvent); packet_ext->setThreadedReadSlot(receiveEvent);
packet_ext->setHeaderCheckSlot(headerValidateEvent);
work = new_mp_prot = history_write_rec = history_write_send = false; work = new_mp_prot = history_write_rec = history_write_send = false;
eth = 0; eth = 0;
ser = 0; ser = 0;
@@ -412,18 +407,20 @@ void PIProtocol::init() {
net_diag = PIProtocol::Unknown; net_diag = PIProtocol::Unknown;
cur_pckt = 0; cur_pckt = 0;
diagTimer = 0; diagTimer = 0;
packet = 0;
timeout_ = 3.f; timeout_ = 3.f;
sendTimer = new PITimer(sendEvent, this); sendTimer = new PITimer(sendEvent, this);
diagTimer = new PITimer(diagEvent, this); diagTimer = new PITimer(diagEvent, this);
secTimer = new PITimer(secEvent, this);
wrong_count = receive_count = send_count = missed_count = 0; 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; headerPtr = dataPtr = sendDataPtr = 0;
headerSize = dataSize = sendDataSize = 0; headerSize = dataSize = sendDataSize = 0;
type_rec = type_send = PIProtocol::None; type_rec = type_send = PIProtocol::None;
devSenderState = devReceiverState = "Unknown"; devSenderState = devReceiverState = "Unknown";
devSenderName = devReceiverName = "no device"; devSenderName = devReceiverName = "no device";
history_rsize_rec = history_rsize_send = "no file"; history_rsize_rec = history_rsize_send = "no file";
secTimer->start(1000.);
/*addEvent("receiver started"); /*addEvent("receiver started");
addEvent("receiver stopped"); addEvent("receiver stopped");
addEvent("sender started"); addEvent("sender started");
@@ -444,7 +441,7 @@ void PIProtocol::setReceiverDevice(const PIString & device, PISerial::Speed spee
type_send = type_rec = PIProtocol::Serial; type_send = type_rec = PIProtocol::Serial;
if (ser == 0) { if (ser == 0) {
ser = new PISerial(); ser = new PISerial();
packet_ext.setDevice(ser); packet_ext->setDevice(ser);
} }
} }
if (type_rec == PIProtocol::Serial && ser != 0) { 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; type_rec = PIProtocol::Ethernet;
if (eth == 0) { if (eth == 0) {
eth = new PIEthernet(); eth = new PIEthernet();
packet_ext.setDevice(eth); packet_ext->setDevice(eth);
} }
} }
if (type_rec == PIProtocol::Ethernet && eth != 0) { 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) { if (type_send == PIProtocol::Ethernet && eth != 0) {
eth->setSendAddress(ip, port); eth->setSendAddress(ip, port);
eth->open();
if (ip.isEmpty()) devSenderName = "no ip"; if (ip.isEmpty()) devSenderName = "no ip";
else devSenderName = ip + ":" + PIString::fromNumber(port); 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) { void PIProtocol::setExpectedFrequency(float frequency) {
exp_freq = frequency; exp_freq = frequency;
changeDisconnectTimeout(); changeDisconnectTimeout();
@@ -517,29 +539,35 @@ void PIProtocol::startReceive(float exp_frequency) {
if (exp_frequency > 0.f) exp_freq = exp_frequency; if (exp_frequency > 0.f) exp_freq = exp_frequency;
//if (type_rec == PIProtocol::Serial) ser->start(); //if (type_rec == PIProtocol::Serial) ser->start();
//if (type_rec == PIProtocol::Ethernet) eth->start(); //if (type_rec == PIProtocol::Ethernet) eth->start();
packet_ext->startThreadedRead();
msleep(1);
check_state();
if (exp_freq <= 0.f) return; if (exp_freq <= 0.f) return;
packet_ext.startThreadedRead();
setExpectedFrequency(exp_freq); setExpectedFrequency(exp_freq);
diagTimer->start(1000. / exp_freq); diagTimer->start(1000. / exp_freq);
diagTimer->reset(); diagTimer->reset();
raiseEvent(this, "receiver started"); receiverStarted();
} }
void PIProtocol::startSend(float frequency) { void PIProtocol::startSend(float frequency) {
//cout << "** start send " << send_freq << ", " << frequency << endl;
if (frequency > 0.f) send_freq = frequency; if (frequency > 0.f) send_freq = frequency;
msleep(1);
check_state();
if (send_freq <= 0.f) return; if (send_freq <= 0.f) return;
sendTimer->start(1000. / send_freq); sendTimer->start(1000. / send_freq);
raiseEvent(this, "sender started"); diagTimer->reset();
senderStarted();
} }
void PIProtocol::stopReceive() { void PIProtocol::stopReceive() {
//if (type_rec == PIProtocol::Serial) ser->stop(); //if (type_rec == PIProtocol::Serial) ser->stop();
//if (type_rec == PIProtocol::Ethernet) eth->stop(); //if (type_rec == PIProtocol::Ethernet) eth->stop();
packet_ext.stop(); packet_ext->stop();
diagTimer->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_file_rec.writeToBinLog(p->history_id_rec, data, size);
p->history_rsize_rec.setReadableSize(p->history_file_rec.pos()); p->history_rsize_rec.setReadableSize(p->history_file_rec.pos());
} }
raiseEvent<bool>(p, "received", true); p->received(true);
//p->unlock(); //p->unlock();
p->ifreq = p->diagTimer->elapsed_m();
if (p->ifreq > 0.) p->ifreq = 1000. / p->ifreq;
p->diagTimer->reset();
p->receive_count++; p->receive_count++;
p->packets_in_sec++;
p->bytes_in_sec += size;
p->cur_pckt = 1; p->cur_pckt = 1;
if (p->ret_func != 0) p->ret_func(p); if (p->ret_func != 0) p->ret_func(p);
if (p->mp_owner != 0) PIMultiProtocolBase::receiveEvent(p->mp_owner, p, true, data, size); if (p->mp_owner != 0) PIMultiProtocolBase::receiveEvent(p->mp_owner, p, true, data, size);
return true; return true;
} }
raiseEvent<bool>(p, "received", false); p->received(false);
//p->unlock(); //p->unlock();
p->wrong_count++; p->wrong_count++;
if (p->mp_owner != 0) PIMultiProtocolBase::receiveEvent(p->mp_owner, p, false, data, size); 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) { void PIProtocol::diagEvent(void * t, int) {
PIProtocol * p = (PIProtocol * )t; PIProtocol * p = (PIProtocol * )t;
p->calc_freq(); p->calc_freq();
p->calc_diag(); p->calc_diag();
p->check_state(); 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 if (good_percents > 20.f && good_percents <= 80.f) diag = PIProtocol::Average;
else diag = PIProtocol::Good; else diag = PIProtocol::Good;
if (diag != net_diag) { if (diag != net_diag) {
qualityChanged(net_diag, diag);
net_diag = diag; net_diag = diag;
raiseEvent<PIProtocol::Quality>(this, "quality changed", diag);
} }
} }
void PIProtocol::calc_freq() { void PIProtocol::calc_freq() {
float tf = float(1000.f / diagTimer->elapsed_m()); float tf;// = float(1000.f / diagTimer->elapsed_m());
diagTimer->reset(); tf = immediate_freq = ifreq;
if (cur_pckt != 1) tf = 0.f; ifreq = 0.f;
immediate_freq = tf;
if (last_freq.size_s() >= pckt_cnt_max && last_freq.size_s() > 0) last_freq.pop_front(); if (last_freq.size_s() >= pckt_cnt_max && last_freq.size_s() > 0) last_freq.pop_front();
last_freq.push_back(tf); last_freq.push_back(tf);
tf = last_freq[0]; 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()); history_rsize_send.setReadableSize(history_file_send.pos());
} }
if (type_send == PIProtocol::Serial) if (type_send == PIProtocol::Serial)
if (ser->send(data, size)) if (ser->send(data, size)) {
send_count++; send_count++;
packets_out_sec++;
bytes_out_sec += size;
}
if (type_send == PIProtocol::Ethernet) if (type_send == PIProtocol::Ethernet)
if (eth->send(data, size)) if (eth->send(data, size)) {
send_count++; send_count++;
packets_out_sec++;
bytes_out_sec += size;
}
} }
@@ -682,6 +722,7 @@ void PIProtocol::send() {
//lock(); //lock();
//memcpy(packet, sendDataPtr, sendDataSize); //memcpy(packet, sendDataPtr, sendDataSize);
//unlock(); //unlock();
//cout << "**send" << endl;
if (!aboutSend()) return; if (!aboutSend()) return;
if (sendDataPtr == 0 || sendDataSize == 0) return; if (sendDataPtr == 0 || sendDataSize == 0) return;
if (history_write_send) { if (history_write_send) {
@@ -689,9 +730,15 @@ void PIProtocol::send() {
history_rsize_send.setReadableSize(history_file_send.pos()); history_rsize_send.setReadableSize(history_file_send.pos());
} }
if (type_send == PIProtocol::Serial) if (type_send == PIProtocol::Serial)
if (ser->send(sendDataPtr, sendDataSize)) if (ser->send(sendDataPtr, sendDataSize)) {
send_count++; send_count++;
packets_out_sec++;
bytes_out_sec += sendDataSize;
}
if (type_send == PIProtocol::Ethernet) if (type_send == PIProtocol::Ethernet)
if (eth->send(sendDataPtr, sendDataSize)) if (eth->send(sendDataPtr, sendDataSize)) {
send_count++; send_count++;
packets_out_sec++;
bytes_out_sec += sendDataSize;
}
} }

102
piprotocol.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Protocol, input/output channel (COM, UDP) 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 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 it under the terms of the GNU General Public License as published by
@@ -34,7 +34,7 @@ class PIMultiProtocolBase
friend class PIProtocol; friend class PIProtocol;
public: public:
PIMultiProtocolBase() {;} PIMultiProtocolBase() {;}
~PIMultiProtocolBase() {;} virtual ~PIMultiProtocolBase() {;}
protected: protected:
virtual void received(PIProtocol * prot, bool corrected, uchar * data, int size) {;} virtual void received(PIProtocol * prot, bool corrected, uchar * data, int size) {;}
@@ -48,6 +48,23 @@ private:
typedef void (*ReceiveFunc)(void * ); 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 class PIProtocol: public PIObject
{ {
friend class PIMultiProtocolBase; friend class PIMultiProtocolBase;
@@ -58,7 +75,7 @@ public:
PIProtocol(): PIObject() {init();} PIProtocol(): PIObject() {init();}
PIProtocol(const PIString & config, const PIString & name, void * recHeaderPtr = 0, int recHeaderSize = 0, 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 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}; enum Quality {Unknown = 1, Failure = 2, Bad = 3, Average = 4, Good = 5};
@@ -67,8 +84,8 @@ public:
EVENT_HANDLER0(PIProtocol, void, stopReceive); EVENT_HANDLER0(PIProtocol, void, stopReceive);
void setExpectedFrequency(float frequency); // for connection quality diagnostic void setExpectedFrequency(float frequency); // for connection quality diagnostic
void setReceiverDevice(const PIString & device, PISerial::Speed speed, bool force = false); // for Serial 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 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 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 setReceiverAddress(const PIString & ip, int port, bool force = false); // for Ethernet
void setReceiverParameters(PIFlags<PISerial::Parameters> parameters) {if (type_rec == PIProtocol::Serial || type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial void setReceiverParameters(PIFlags<PISerial::Parameters> parameters) {if (type_rec == PIProtocol::Serial || type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial
void setReceiveSlot(ReceiveFunc slot) {ret_func = slot;} 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_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_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 setSenderFrequency(float frequency) {send_freq = frequency;}
void setSenderDevice(const PIString & device, PISerial::Speed speed, bool force = false); // for Serial 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 setSenderData(void * dataPtr, int dataSize) {sendDataPtr = (uchar * )dataPtr; sendDataSize = dataSize;}
void setSenderAddress(const PIString & ip, int port, bool force = false); // for Ethernet 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<PISerial::Parameters> parameters) {if (type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial void setSenderParameters(PIFlags<PISerial::Parameters> parameters) {if (type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial
float senderFrequency() const {return send_freq;} float senderFrequency() const {return send_freq;}
@@ -94,40 +113,60 @@ public:
PIString name() const {return protName;} PIString name() const {return protName;}
void setDisconnectTimeout(float timeout) {timeout_ = timeout; changeDisconnectTimeout();} void setDisconnectTimeout(float timeout) {timeout_ = timeout; changeDisconnectTimeout();}
float disconnectTimeout() const {return timeout_;} float disconnectTimeout() const {return timeout_;}
float * disconnectTimeout_ptr() {return &timeout_;} const float * disconnectTimeout_ptr() const {return &timeout_;}
float immediateFrequency() const {return immediate_freq;} float immediateFrequency() const {return immediate_freq;}
float integralFrequency() const {return integral_freq;} float integralFrequency() const {return integral_freq;}
float * immediateFrequency_ptr() {return &immediate_freq;} const float * immediateFrequency_ptr() const {return &immediate_freq;}
float * integralFrequency_ptr() {return &integral_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() 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() 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() 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() 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 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 receiverDeviceName() const {return devReceiverName;}
PIString senderDeviceName() const {return devSenderName;} PIString senderDeviceName() const {return devSenderName;}
PIString receiverDeviceState() const {return devReceiverState;} PIString receiverDeviceState() const {return devReceiverState;}
PIString * receiverDeviceState_ptr() {return &devReceiverState;} const PIString * receiverDeviceState_ptr() const {return &devReceiverState;}
PIString senderDeviceState() const {return devSenderState;} 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() 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() 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() 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() 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 * receiveData() {return dataPtr;}
void * sendData() {return sendDataPtr;} 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: protected:
virtual bool receive(uchar * data, int size) {if (dataPtr != 0) memcpy(dataPtr, data, size); return true;} // executed when raw data received, break if 'false' return virtual bool 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; uint c = 0;
for (int i = 0; i < size; ++i) for (int i = 0; i < size; ++i)
c += ((uchar*)data)[i]; c += ((uchar*)data)[i];
c = ~(c + 1); return ~(c + 1);
return c;
} }
virtual uchar checksum_c(void * data, int size) { // function for checksum (uchar) virtual uchar checksum_c(void * data, int size) { // function for checksum (uchar)
uchar c = 0; uchar c = 0;
for (int i = 0; i < size; ++i) for (int i = 0; i < size; ++i)
c += ((uchar*)data)[i]; c += ((uchar*)data)[i];
c = ~(c + 1); return ~(c + 1);
return c;
} }
virtual bool aboutSend() {return true;} // executed before send data, if return 'false' then data is not sending virtual bool aboutSend() {return true;} // executed before send data, if return 'false' then data is not sending
@@ -162,30 +199,31 @@ protected:
private: private:
static void sendEvent(void * e, int) {((PIProtocol * )e)->send();} static void sendEvent(void * e, int) {((PIProtocol * )e)->send();}
static bool receiveEvent(void * t, uchar * data, int size); 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 diagEvent(void * t, int);
static void secEvent(void * t, int);
void setMultiProtocolOwner(PIMultiProtocolBase * mp) {mp_owner = mp;} void setMultiProtocolOwner(PIMultiProtocolBase * mp) {mp_owner = mp;}
PIMultiProtocolBase * multiProtocolOwner() const {return mp_owner;} PIMultiProtocolBase * multiProtocolOwner() const {return mp_owner;}
void changeDisconnectTimeout(); void changeDisconnectTimeout();
ReceiveFunc ret_func; ReceiveFunc ret_func;
PIPacketExtractor packet_ext; PIPacketExtractor * packet_ext;
PITimer * diagTimer, * sendTimer; PITimer * diagTimer, * sendTimer, * secTimer;
PIMultiProtocolBase * mp_owner; PIMultiProtocolBase * mp_owner;
PIProtocol::Type type_send, type_rec; PIProtocol::Type type_send, type_rec;
PIProtocol::Quality net_diag; PIProtocol::Quality net_diag;
PIDeque<float> last_freq; PIDeque<float> last_freq;
PIDeque<char> last_packets; PIDeque<char> 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; PIString history_path_rec, history_path_send, history_rsize_rec, history_rsize_send;
PIFile history_file_rec, history_file_send; PIFile history_file_rec, history_file_send;
ushort history_id_rec, history_id_send; ushort history_id_rec, history_id_send;
bool work, new_mp_prot, history_write_rec, history_write_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; int packets[2], pckt_cnt, pckt_cnt_max;
char * packet, cur_pckt; char cur_pckt;
ullong wrong_count, receive_count, send_count, missed_count; ullong wrong_count, receive_count, send_count, missed_count, packets_in_sec, packets_out_sec, bytes_in_sec, bytes_out_sec;
}; };

190
piserial.cpp Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
COM 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 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 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() { bool PISerial::closeDevice() {
if (!isInitialized()) return true; if (!isInitialized()) return true;
if (isRunning()) { if (isRunning()) {
@@ -86,6 +161,8 @@ bool PISerial::closeDevice() {
int PISerial::convertSpeed(PISerial::Speed speed) { int PISerial::convertSpeed(PISerial::Speed speed) {
switch (speed) { switch (speed) {
case S50: return B50;
case S75: return B75;
case S110: return B110; case S110: return B110;
case S300: return B300; case S300: return B300;
case S600: return B600; case S600: return B600;
@@ -97,6 +174,13 @@ int PISerial::convertSpeed(PISerial::Speed speed) {
case S38400: return B38400; case S38400: return B38400;
case S57600: return B57600; case S57600: return B57600;
case S115200: return B115200; 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; return B115200;
} }
@@ -114,6 +198,7 @@ bool PISerial::read(void * data, int size, double timeout_ms) {
if (ret > 0) all += ret; if (ret > 0) all += ret;
else msleep(1); else msleep(1);
} }
received(data, all);
return (all == size); return (all == size);
} else { } else {
setReadIsBlocking(true); setReadIsBlocking(true);
@@ -122,15 +207,96 @@ bool PISerial::read(void * data, int size, double timeout_ms) {
ret = ::read(fd, &((uchar * )data)[all], size - all); ret = ::read(fd, &((uchar * )data)[all], size - all);
if (ret > 0) all += ret; if (ret > 0) all += ret;
} }
received(data, all);
return (all == size); return (all == size);
} }
return false; 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() { bool PISerial::openDevice() {
#ifdef WINDOWS #ifdef WINDOWS
DWORD da = 0, sm = 0; DWORD ds = 0, sm = 0;
if (isReadable()) {ds |= GENERIC_READ; sm |= FILE_SHARE_READ;} if (isReadable()) {ds |= GENERIC_READ; sm |= FILE_SHARE_READ;}
if (isWriteable()) {ds |= GENERIC_WRITE; sm |= FILE_SHARE_WRITE;} if (isWriteable()) {ds |= GENERIC_WRITE; sm |= FILE_SHARE_WRITE;}
hCom = CreateFileA(path_.data(), ds, sm, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0); 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::WriteOnly: om = O_WRONLY; break;
case PIIODevice::ReadWrite: om = O_RDWR; 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); fd = ::open(path_.data(), O_NOCTTY | om);
if(fd == -1) { if(fd == -1) {
piCout << "[PISerial] Unable to open \"" << path_ << "\"" << endl; piCout << "[PISerial] Unable to open \"" << path_ << "\"" << endl;
return false; return false;
} }
fcntl(fd, F_SETFL, 0);
tcgetattr(fd, &desc); tcgetattr(fd, &desc);
sdesc = 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; desc.c_cflag = CLOCAL | CSIZE | CS8;
if (isReadable()) desc.c_cflag |= CREAD; 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::TwoStopBits]) desc.c_cflag |= CSTOPB;
if (params[PISerial::ParityControl]) { if (params[PISerial::ParityControl]) {
desc.c_iflag |= INPCK; desc.c_iflag |= INPCK;
@@ -201,12 +367,14 @@ bool PISerial::openDevice() {
cfsetispeed(&desc, convertSpeed(ispeed)); cfsetispeed(&desc, convertSpeed(ispeed));
cfsetospeed(&desc, convertSpeed(ospeed)); cfsetospeed(&desc, convertSpeed(ospeed));
tcflush(fd, TCIOFLUSH);
fcntl(fd, F_SETFL, 0);
if(tcsetattr(fd, TCSANOW, &desc) < 0) { if(tcsetattr(fd, TCSANOW, &desc) < 0) {
piCout << "[PISerial] Can`t set attributes for \"" << path_ << "\"" << endl; piCout << "[PISerial] Can`t set attributes for \"" << path_ << "\"" << endl;
::close(fd); ::close(fd);
return false; return false;
} }
tcflush(fd, TCIOFLUSH);
//piCout << "[PISerial] Initialized " << path_ << endl; //piCout << "[PISerial] Initialized " << path_ << endl;
#endif #endif
return true; return true;
@@ -214,7 +382,7 @@ bool PISerial::openDevice() {
int PISerial::write(const void * data, int max_size, bool wait) { 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()) { if (fd == -1 || !canWrite()) {
//piCout << "[PISerial] Can`t write to uninitialized COM" << endl; //piCout << "[PISerial] Can`t write to uninitialized COM" << endl;
return -1; return -1;
@@ -222,12 +390,18 @@ int PISerial::write(const void * data, int max_size, bool wait) {
#ifdef WINDOWS #ifdef WINDOWS
DWORD wrote; DWORD wrote;
WriteFile(hCom, data, max_size, &wrote, 0); WriteFile(hCom, data, max_size, &wrote, 0);
if (wait) {
DWORD event;
SetCommMask(hCom, EV_TXEMPTY);
WaitCommEvent(hCom, &event, NULL);
SetCommMask(hCom, EV_RXCHAR);
}
#else #else
int wrote; int wrote;
wrote = ::write(fd, data, max_size); wrote = ::write(fd, data, max_size);
if (wait) tcdrain(fd); if (wait) tcdrain(fd);
#endif #endif
return (int)wrote; return (int)wrote;
//piCout << "[PISerial] Error while sending" << endl; //piCout << "[PISerial] Error while sending" << endl;
//piCout << "[PISerial] Wrote " << wrote << " bytes in " << path_ << endl; //piCout << "[PISerial] Wrote " << wrote << " bytes in " << path_ << endl;
} }

138
piserial.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
COM 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 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 it under the terms of the GNU General Public License as published by
@@ -25,21 +25,63 @@
#ifndef WINDOWS #ifndef WINDOWS
# include <termios.h> # include <termios.h>
# include <fcntl.h> # include <fcntl.h>
# include <sys/ioctl.h>
# 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 #else
# define B110 110 # define TIOCM_LE 1
# define B300 300 # define TIOCM_DTR 4
# define B600 600 # define TIOCM_RTS 7
# define B1200 1200 # define TIOCM_CTS 8
# define B2400 2400 # define TIOCM_ST 3
# define B4800 4800 # define TIOCM_SR 2
# define B9600 9600 # define TIOCM_CAR 1
# define B14400 14400 # define TIOCM_RNG 9
# define B19200 19200 # define TIOCM_DSR 6
# define B38400 38400 # define B50 50
# define B57600 57600 # define B75 75
# define B115200 115200 # define B110 110
# define B128000 128000 # define B300 300
# define B256000 256000 # 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 #endif
class PISerial: public PIIODevice { class PISerial: public PIIODevice {
@@ -50,8 +92,10 @@ public:
PISerial(void * data = 0, ReadRetFunc slot = 0); PISerial(void * data = 0, ReadRetFunc slot = 0);
~PISerial(); ~PISerial();
enum Parameters {ParityControl = 0x01, ParityOdd = 0x02, TwoStopBits = 0x04}; enum Parameters {ParityControl = 0x1, ParityOdd = 0x2, TwoStopBits = 0x4, HardwareFlowControl = 0x8};
enum Speed { enum Speed {
S50 = 50,
S75 = 75,
S110 = 110, S110 = 110,
S300 = 300, S300 = 300,
S600 = 600, S600 = 600,
@@ -62,7 +106,13 @@ public:
S19200 = 19200, S19200 = 19200,
S38400 = 38400, S38400 = 38400,
S57600 = 57600, 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;} void setData(void * d) {data = d;}
@@ -72,12 +122,39 @@ public:
void setOutSpeed(PISerial::Speed speed) {ospeed = speed;} void setOutSpeed(PISerial::Speed speed) {ospeed = speed;}
void setInSpeed(PISerial::Speed speed) {ispeed = speed;} void setInSpeed(PISerial::Speed speed) {ispeed = speed;}
void setDevice(const PIString & dev) {path_ = dev;} void setDevice(const PIString & dev) {path_ = dev;}
void setParameters(PIFlags<PISerial::Parameters> parameters) {params = parameters;}
void setParameters(PIFlags<PISerial::Parameters> parameters_) {params = parameters_;}
void setParameter(PISerial::Parameters parameter, bool on = true) {params.setFlag(parameter, on);} void setParameter(PISerial::Parameters parameter, bool on = true) {params.setFlag(parameter, on);}
bool isParameterSet(PISerial::Parameters parameter) const {return params[parameter];}
PIFlags<PISerial::Parameters> 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;} void setVTime(int t) {vtime = t;}
#ifdef WINDOWS
void setReadIsBlocking(bool yes) { void setReadIsBlocking(bool yes) {
#ifdef WINDOWS
COMMTIMEOUTS times; COMMTIMEOUTS times;
times.ReadIntervalTimeout = yes ? vtime : MAXDWORD; times.ReadIntervalTimeout = yes ? vtime : MAXDWORD;
times.ReadTotalTimeoutConstant = yes ? 1 : 0; times.ReadTotalTimeoutConstant = yes ? 1 : 0;
@@ -85,35 +162,48 @@ public:
times.WriteTotalTimeoutConstant = 1; times.WriteTotalTimeoutConstant = 1;
times.WriteTotalTimeoutMultiplier = 0; times.WriteTotalTimeoutMultiplier = 0;
if (isOpened()) SetCommTimeouts(hCom, &times); if (isOpened()) SetCommTimeouts(hCom, &times);
}
#else #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 #endif
}
const PIString & device() const {return path_;} const PIString & device() const {return path_;}
PISerial::Speed outSpeed() const {return ospeed;} PISerial::Speed outSpeed() const {return ospeed;}
PISerial::Speed inSpeed() const {return ispeed;} PISerial::Speed inSpeed() const {return ispeed;}
int VTime() const {return vtime;} 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) { int read(void * read_to, int max_size) {
#ifdef WINDOWS
if (!canRead()) return -1; if (!canRead()) return -1;
WaitCommEvent(hCom, 0, 0); WaitCommEvent(hCom, 0, 0);
ReadFile(hCom, read_to, max_size, &readed, 0); ReadFile(hCom, read_to, max_size, &readed, 0);
return readed; return readed;
}
#else #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 #endif
}
bool read(void * data, int size, double timeout_ms); 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, bool wait);
int write(const void * data, int max_size) {return write(data, max_size, false);} 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 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: protected:
virtual void received(void * data, int size) {;}
int convertSpeed(PISerial::Speed speed); 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;} 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(); bool openDevice();

2
pisignals.cpp Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Signals 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 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 it under the terms of the GNU General Public License as published by

2
pisignals.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Signals 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 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 it under the terms of the GNU General Public License as published by

58
pistring.cpp Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
String 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 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 it under the terms of the GNU General Public License as published by
@@ -20,6 +20,28 @@
#include "pistring.h" #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) { void PIString::appendFromChars(const char * c, int s) {
int sz; int sz;
wchar_t wc; wchar_t wc;
@@ -88,11 +110,13 @@ PIString & PIString::operator +=(const wchar_t * str) {
} }
#ifdef HAS_LOCALE
PIString & PIString::operator +=(const wstring & str) { PIString & PIString::operator +=(const wstring & str) {
uint l = str.size(); uint l = str.size();
for (uint i = 0; i < l; ++i) push_back(str[i]); for (uint i = 0; i < l; ++i) push_back(str[i]);
return *this; return *this;
} }
#endif
PIString & PIString::operator +=(const PIString & str) { PIString & PIString::operator +=(const PIString & str) {
@@ -324,13 +348,20 @@ int PIString::lengthAscii() const {
const char * PIString::data() const { const char * PIString::data() const {
PIByteArray & d_(*(const_cast<PIByteArray * >(&data_))); PIByteArray & d_(*(const_cast<PIByteArray * >(&data_)));
d_.clear(); d_.clear();
for (int i = 0, j = 0; i < size_s(); ++i, ++j) { int wc;
if (at(i).isAscii()) 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())); d_.push_back(uchar(at(i).toAscii()));
else { else {
d_.push_back((at(i).toCharPtr()[0])); ++j; d_.push_back((at(i).toCharPtr()[0])); ++j;
d_.push_back((at(i).toCharPtr()[1])); d_.push_back((at(i).toCharPtr()[1]));
} }*/
} }
d_.push_back(uchar('\0')); d_.push_back(uchar('\0'));
return (const char * )d_.data(); return (const char * )d_.data();
@@ -339,14 +370,21 @@ const char * PIString::data() const {
string PIString::convertToStd() const { string PIString::convertToStd() const {
string s; string s;
int wc;
uchar tc;
if (size() > 0) { if (size() > 0) {
for (int i = 0; i < length(); ++i) { 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()); s.push_back(at(i).toAscii());
else { else {
s.push_back(at(i).toCharPtr()[0]); s.push_back(at(i).toCharPtr()[0]);
s.push_back(at(i).toCharPtr()[1]); s.push_back(at(i).toCharPtr()[1]);
} }*/
} }
} }
return s; return s;
@@ -360,7 +398,7 @@ char PIString::toChar() const {
return v; return v;
} }
/*
short PIString::toShort() const { short PIString::toShort() const {
PIString s(trimmed().toLowerCase().toNativeDecimalPoints()); PIString s(trimmed().toLowerCase().toNativeDecimalPoints());
short v; short v;
@@ -399,7 +437,7 @@ llong PIString::toLLong() const {
sscanf(s.data(), "%lld", &v); sscanf(s.data(), "%lld", &v);
return v; return v;
} }
*/
PIString & PIString::setReadableSize(long bytes) { PIString & PIString::setReadableSize(long bytes) {
clear(); 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 >= 'a' && c <= 'z') return c + 'A' - 'a';
//if (c >= 'а' && c <= 'я') return c + 'А' - 'а'; //if (c >= 'а' && c <= 'я') return 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 >= 'A' && c <= 'Z') return c + 'a' - 'A';
//if (c >= 'А' && c <= 'Я') return c + 'а' - 'А'; //if (c >= 'А' && c <= 'Я') return c + 'а' - 'А';
return c; return c;

123
pistring.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
String 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 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 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 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 PIByteArray & ba) {appendFromChars((const char * )ba.data(), ba.size_s()); return *this;}
PIString & operator +=(const PIString & str); PIString & operator +=(const PIString & str);
#ifdef HAS_LOCALE
PIString & operator +=(const wstring & str); PIString & operator +=(const wstring & str);
#endif
//PIString(const char c) {*this += c;} //PIString(const char c) {*this += c;}
PIString(const PIChar c) {piMonitor.strings++; piMonitor.containers--;*this += c;} PIString(const PIChar c) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += c;}
PIString(const char * str) {piMonitor.strings++; piMonitor.containers--;*this += str;} PIString(const char * str) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
PIString(const wchar_t * str) {piMonitor.strings++; piMonitor.containers--;*this += str;} PIString(const wchar_t * str) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
PIString(const string & str) {piMonitor.strings++; piMonitor.containers--;*this += str;} PIString(const string & str) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
PIString(const wstring & str) {piMonitor.strings++; piMonitor.containers--;*this += str;} #ifdef HAS_LOCALE
PIString(const PIByteArray & ba) {piMonitor.strings++; piMonitor.containers--;*this += ba;} PIString(const wstring & str) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += str;}
PIString(const char * str, const int len) {piMonitor.strings++; piMonitor.containers--;*this += string(str, len);} #endif
PIString(const int len, const char c) {piMonitor.strings++; piMonitor.containers--;for (int i = 0; i < len; ++i) push_back(c);} PIString(const PIByteArray & ba) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += ba;}
PIString(const int len, const PIChar & c) {piMonitor.strings++; piMonitor.containers--;for (int i = 0; i < len; ++i) push_back(c);} PIString(const char * str, const int len) {reserve(256); piMonitor.strings++; piMonitor.containers--; *this += string(str, len);}
PIString(const PIString & str) {piMonitor.strings++; piMonitor.containers--;*this += str;} 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++;} ~PIString() {piMonitor.strings--; piMonitor.containers++;}
operator const char*() {return data();} operator const char*() {return data();}
@@ -133,16 +137,18 @@ public:
int lengthAscii() const; int lengthAscii() const;
const char * data() const; const char * data() const;
const string stdString() const {return convertToStd();} const string stdString() const {return convertToStd();}
#ifdef HAS_LOCALE
wstring stdWString() const {return convertToWString();} 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; PIStringList split(const PIString & delim) const;
PIString toUpperCase() const; PIString toUpperCase() const;
PIString toLowerCase() const; PIString toLowerCase() const;
#ifdef QNX #ifdef HAS_LOCALE
PIString toNativeDecimalPoints() const {PIString s(*this); return s;}
#else
PIString toNativeDecimalPoints() const {PIString s(*this); if (currentLocale == 0) return s; return s.replaceAll(".", currentLocale->decimal_point);} 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 #endif
int find(const char str, const int start = 0) const; int find(const char str, const int start = 0) const;
@@ -157,30 +163,43 @@ public:
int length() const {return size();} int length() const {return size();}
bool isEmpty() const {return (size() == 0 || *this == "");} 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; char toChar() const;
short toShort() const; short toShort(int base = -1, bool * ok = 0) const {return short(toNumberBase(*this, base, ok));}
int toInt() const; ushort toUShort(int base = -1, bool * ok = 0) const {return ushort(toNumberBase(*this, base, ok));}
long toLong() const; int toInt(int base = -1, bool * ok = 0) const {return int(toNumberBase(*this, base, ok));}
llong toLLong() const; 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());} float toFloat() const {PIString s(*this); return (float)atof(s.toNativeDecimalPoints().data());}
double toDouble() const {PIString s(*this); return 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());} ldouble toLDouble() const {PIString s(*this); return atof(s.toNativeDecimalPoints().data());}
//inline PIString & setNumber(const char value) {clear(); *this += itos(value); return *this;} //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, int base = 10, bool * ok = 0) {clear(); *this += PIString::fromNumber(value, base, ok); return *this;}
PIString & setNumber(const short value) {clear(); *this += itos(value); 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 long value) {clear(); *this += ltos(value); 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 float value) {clear(); *this += ftos(value); return *this;}
PIString & setNumber(const double value) {clear(); *this += dtos(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 & setNumber(const ldouble value) {clear(); *this += dtos(value); return *this;}
PIString & setReadableSize(long bytes); PIString & setReadableSize(long bytes);
//inline static PIString fromNumber(const char value) {return PIString(itos(value));} //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 short value, int base = 10, bool * ok = 0) {return fromNumberBase(llong(value), base, ok);}
static PIString fromNumber(const uint value) {return PIString(itos(value));} static PIString fromNumber(const ushort value, int base = 10, bool * ok = 0) {return fromNumberBase(llong(value), base, ok);}
static PIString fromNumber(const short value) {return PIString(itos(value));} static PIString fromNumber(const int value, int base = 10, bool * ok = 0) {return fromNumberBase(llong(value), base, ok);}
static PIString fromNumber(const long value) {return PIString(ltos(value));} 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 float value) {return PIString(ftos(value));}
static PIString fromNumber(const double value) {return PIString(dtos(value));} static PIString fromNumber(const double value) {return PIString(dtos(value));}
static PIString fromNumber(const ldouble 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;} static PIString readableSize(long bytes) {PIString s; s.setReadableSize(bytes); return s;}
private: 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); void appendFromChars(const char * c, int s);
string convertToStd() const; 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;} wstring convertToWString() const {wstring s; for (int i = 0; i < length(); ++i) s.push_back(at(i).toWChar()); return s;}
#endif
PIByteArray data_; PIByteArray data_;
//string std_string; //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::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 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 & 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;} //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 char * str, const PIString & f) {return PIString(str) + f;}
inline PIString operator +(const string & 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); inline char chrUpr(char c);
char chrLwr(char c); inline char chrLwr(char c);
class PIStringList: public PIVector<PIString> class PIStringList: public PIVector<PIString>
{ {

4
pisystemmonitor.cpp Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Process resource monitor 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 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 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() { void PISystemMonitor::run() {
#ifndef WINDOWS #ifndef WINDOWS
file.seekToBegin();
PIString str(file.readAll(true)); PIString str(file.readAll(true));
int si = str.find('(') + 1, fi = 0, cc = 1; int si = str.find('(') + 1, fi = 0, cc = 1;
for (int i = si; i < str.size_s(); ++i) { for (int i = si; i < str.size_s(); ++i) {
@@ -93,6 +94,7 @@ void PISystemMonitor::run() {
stat.priority = sl[16].toInt(); stat.priority = sl[16].toInt();
stat.threads = sl[18].toInt(); stat.threads = sl[18].toInt();
filem.seekToBegin();
str = filem.readAll(true); str = filem.readAll(true);
sl = str.split(" "); sl = str.split(" ");
if (sl.size_s() < 5) return; if (sl.size_s() < 5) return;

14
pisystemmonitor.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Process resource monitor 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 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 it under the terms of the GNU General Public License as published by
@@ -27,7 +27,7 @@ class PISystemMonitor: public PIThread
{ {
public: public:
PISystemMonitor(); PISystemMonitor();
struct ProcessStats { struct ProcessStats {
PIString exec_name; PIString exec_name;
PIString state; PIString state;
@@ -50,21 +50,21 @@ public:
float cpu_load_system; float cpu_load_system;
float cpu_load_user; float cpu_load_user;
}; };
bool startOnProcess(int pID); bool startOnProcess(int pID);
bool startOnSelf() {return startOnProcess(PIProcess::currentPID());} bool startOnSelf() {return startOnProcess(PIProcess::currentPID());}
ProcessStats & statistic() {return stat;} const ProcessStats & statistic() const {return stat;}
private: private:
void run(); void run();
PIFile file, filem; PIFile file, filem;
ProcessStats stat; ProcessStats stat;
int pID_, page_size, cpu_count, cycle; int pID_, page_size, cpu_count, cycle;
#ifndef WINDOWS #ifndef WINDOWS
llong cpu_u_cur, cpu_u_prev, cpu_s_cur, cpu_s_prev; llong cpu_u_cur, cpu_u_prev, cpu_s_cur, cpu_s_prev;
#endif #endif
}; };
#endif // PISYSTEMMONITOR_H #endif // PISYSTEMMONITOR_H

44
pisystemtests.cpp Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#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);
}

24
pimultiprotocol.cpp → pisystemtests.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Multiprotocol System tests results (see system_test folder)
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 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 it under the terms of the GNU General Public License as published by
@@ -17,5 +17,23 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#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

63
pithread.cpp Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Thread 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 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 it under the terms of the GNU General Public License as published by
@@ -18,6 +18,17 @@
*/ */
#include "pithread.h" #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() { 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; if (thread == 0) return;
running = false; running = false;
#ifndef WINDOWS #ifndef WINDOWS
if (hard) kill(thread, SIGKILL); if (hard) kill((ullong)thread, SIGKILL);
else pthread_cancel(thread); else pthread_cancel(thread);
#else #else
CloseHandle(thread); CloseHandle(thread);
@@ -114,20 +125,20 @@ void PIThread::terminate(bool hard) {
void * PIThread::thread_function(void * t) { void * PIThread::thread_function(void * t) {
PIThread * ct = (PIThread * )t; PIThread & ct = *((PIThread * )t);
ct->running = true; ct.running = true;
ct->begin(); ct.begin();
raiseEvent(ct, "started"); ct.started();
while (!ct->terminating) { while (!ct.terminating) {
if (ct->lockRun) ct->mutex_.lock(); if (ct.lockRun) ct.mutex_.lock();
ct->run(); ct.run();
if (ct->ret_func != 0) ct->ret_func(ct->data_); if (ct.ret_func != 0) ct.ret_func(ct.data_);
if (ct->lockRun) ct->mutex_.unlock(); if (ct.lockRun) ct.mutex_.unlock();
if (ct->timer > 0) msleep(ct->timer); if (ct.timer > 0) msleep(ct.timer);
} }
raiseEvent(ct, "stopped"); ct.stopped();
ct->end(); ct.end();
ct->running = false; ct.running = false;
//cout << "thread " << t << " exiting ... " << endl; //cout << "thread " << t << " exiting ... " << endl;
#ifndef WINDOWS #ifndef WINDOWS
pthread_exit(0); pthread_exit(0);
@@ -139,17 +150,17 @@ void * PIThread::thread_function(void * t) {
void * PIThread::thread_function_once(void * t) { void * PIThread::thread_function_once(void * t) {
PIThread * ct = (PIThread * )t; PIThread & ct = *((PIThread * )t);
ct->running = true; ct.running = true;
ct->begin(); ct.begin();
raiseEvent(ct, "started"); ct.started();
if (ct->lockRun) ct->mutex_.lock(); if (ct.lockRun) ct.mutex_.lock();
ct->run(); ct.run();
if (ct->ret_func != 0) ct->ret_func(ct->data_); if (ct.ret_func != 0) ct.ret_func(ct.data_);
if (ct->lockRun) ct->mutex_.unlock(); if (ct.lockRun) ct.mutex_.unlock();
raiseEvent(ct, "stopped"); ct.stopped();
ct->end(); ct.end();
ct->running = false; ct.running = false;
//cout << "thread " << t << " exiting ... " << endl; //cout << "thread " << t << " exiting ... " << endl;
#ifndef WINDOWS #ifndef WINDOWS
pthread_exit(0); pthread_exit(0);

24
pithread.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Thread 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 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 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 #else
inline void msleep(int msecs) {usleep(msecs * 1000);} inline void msleep(int msecs) {usleep(msecs * 1000);}
#endif #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 * ); typedef void (*ThreadFunc)(void * );
/// events:
/// void started()
/// void stopped()
///
/// handlers:
/// bool start(int timer_delay = -1)
/// bool start(ThreadFunc func, int timer_delay = -1)
/// bool startOnce()
/// bool startOnce(ThreadFunc func)
/// void stop(bool wait = false)
/// void terminate(bool hard = false)
/// bool waitForStart(int timeout_msecs = -1)
/// bool waitForFinish(int timeout_msecs = -1)
/// void lock()
/// void unlock()
class PIThread: public PIObject { class PIThread: public PIObject {
public: public:
PIThread(void * data, ThreadFunc func, bool startNow = false, int timer_delay = -1); PIThread(void * data, ThreadFunc func, bool startNow = false, int timer_delay = -1);
PIThread(bool startNow = false, int timer_delay = -1); PIThread(bool startNow = false, int timer_delay = -1);
~PIThread(); virtual ~PIThread();
#ifdef QNX #ifdef QNX
enum Priority {piHighest = 12, enum Priority {piHighest = 12,
@@ -76,6 +93,9 @@ public:
EVENT_HANDLER0(PIThread, void, lock) {mutex_.lock();} EVENT_HANDLER0(PIThread, void, lock) {mutex_.lock();}
EVENT_HANDLER0(PIThread, void, unlock) {mutex_.unlock();} EVENT_HANDLER0(PIThread, void, unlock) {mutex_.unlock();}
PIMutex & mutex() {return mutex_;} PIMutex & mutex() {return mutex_;}
EVENT(PIThread, started)
EVENT(PIThread, stopped)
protected: protected:
static void * thread_function(void * t); static void * thread_function(void * t);

View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Timer 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 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 it under the terms of the GNU General Public License as published by
@@ -18,49 +18,87 @@
*/ */
#include "pitimer.h" #include "pitimer.h"
#include "pisystemtests.h"
PITimer::PITimer(TimerEvent slot, void * data_) #ifdef PIP_TIMER_RT
#ifdef WINDOWS PITimer::TimerPool * pool = 0;
#endif
PITimer::PITimer(TimerEvent slot, void * data_, bool threaded_)
#ifndef PIP_TIMER_RT
: PIThread() { : PIThread() {
#else #else
: PIObject() { : PIObject() {
#endif #endif
ret_func = slot; ret_func = slot;
data = data_; data = data_;
#ifndef WINDOWS #ifdef PIP_TIMER_RT
piMonitor.timers++; piMonitor.timers++;
ti = -1; ti = -1;
threaded = threaded_;
running = false; running = false;
memset(&se, 0, sizeof(se));
se.sigev_notify = SIGEV_THREAD; se.sigev_notify = SIGEV_THREAD;
se.sigev_value.sival_ptr = this; 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; se.sigev_notify_attributes = 0;
lockRun = false; lockRun = false;
#endif #endif
reset(); reset();
/*addEvent<void*, int>("timeout");
addEventHandler<double>(HANDLER(PITimer, start));
addEventHandler(HANDLER(PITimer, stop));
addEventHandler(HANDLER(PITimer, reset));*/
} }
PITimer::~PITimer() { PITimer::~PITimer() {
#ifndef WINDOWS #ifdef PIP_TIMER_RT
piMonitor.timers--; piMonitor.timers--;
#endif #endif
stop(); stop();
} }
#ifndef WINDOWS #ifdef PIP_TIMER_RT
void PITimer::start(double msecs) { 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_nsec = ((int)(msecs * 1000) % 1000000) * 1000;
spec.it_interval.tv_sec = (time_t)(msecs / 1000); spec.it_interval.tv_sec = (time_t)(msecs / 1000);
spec.it_value = spec.it_interval; spec.it_value = spec.it_interval;
ti = timer_create(CLOCK_REALTIME, &se, &timer); ti = timer_create(CLOCK_REALTIME, &se, &timer);
//cout << "***create timer " << msecs << " msecs\n";
if (ti == -1) { if (ti == -1) {
piCout << "[PITimer] Can`t create timer for " << msecs << " msecs: " << errorString() << endl; piCout << "[PITimer] Can`t create timer for " << msecs << " msecs: " << errorString() << endl;
return; 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 "<<ct.first<<" tick start\n";
PITimer::timer_event(sv);
//cout << "*** timer "<<ct.first<<" tick end\n";
ct.second = 0;
}
}
mutex.unlock();
}
void PITimer::stop() {
if (!running) return;
running = false;
if (!threaded) {
if (pool != 0) {
pool->remove(this);
if (pool->isEmpty()) pool->terminate();
}
}
if (ti != -1) timer_delete(timer);
ti = -1;
}
void PITimer::timer_event(sigval e) { void PITimer::timer_event(sigval e) {
PITimer * ct = (PITimer * )e.sival_ptr; PITimer * ct = (PITimer * )e.sival_ptr;
if (!ct->running) return; if (!ct->running) return;
if (ct->lockRun) ct->lock(); if (ct->lockRun) ct->lock();
if (ct->ret_func != 0) ct->ret_func(ct->data, 1); if (ct->ret_func != 0) ct->ret_func(ct->data, 1);
raiseEvent<void*, int>(ct, "timeout", ct->data, 1); ct->timeout(ct->data, 1);
ct->tick(ct->data, 1);
piForeach (TimerSlot & i, ct->ret_funcs) { piForeach (TimerSlot & i, ct->ret_funcs) {
if (i.delim > ++(i.tick)) continue; if (i.delim > ++(i.tick)) continue;
i.tick = 0; i.tick = 0;
if (i.slot != 0) i.slot(ct->data, i.delim); if (i.slot != 0) i.slot(ct->data, i.delim);
else if (ct->ret_func != 0) ct->ret_func(ct->data, i.delim); else if (ct->ret_func != 0) ct->ret_func(ct->data, i.delim);
raiseEvent<void*, int>(ct, "timeout", ct->data, i.delim); ct->timeout(ct->data, i.delim);
ct->tick(ct->data, i.delim);
} }
if (ct->lockRun) ct->unlock(); if (ct->lockRun) ct->unlock();
} }
@@ -101,32 +267,48 @@ bool PITimer::waitForFinish(int timeout_msecs) {
return cnt < timeout_msecs; return cnt < timeout_msecs;
} }
#else #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() { void PITimer::run() {
if (!running) return; if (!running) return;
(st_time - currentSystemTime()).sleep();
st_time += inc_time;
if (lockRun) lock(); if (lockRun) lock();
if (ret_func != 0) ret_func(data, 1); if (ret_func != 0) ret_func(data, 1);
raiseEvent<void*, int>(this, "timeout", data, 1); timeout(data, 1);
tick(data, 1);
piForeach (TimerSlot & i, ret_funcs) { piForeach (TimerSlot & i, ret_funcs) {
if (i.delim > ++(i.tick)) continue; if (i.delim > ++(i.tick)) continue;
i.tick = 0; i.tick = 0;
if (i.slot != 0) i.slot(data, i.delim); if (i.slot != 0) i.slot(data, i.delim);
else if (ret_func != 0) ret_func(data, i.delim); else if (ret_func != 0) ret_func(data, i.delim);
raiseEvent<void*, int>(this, "timeout", data, i.delim); timeout(data, i.delim);
tick(data, i.delim);
} }
if (lockRun) unlock(); if (lockRun) unlock();
} }
#endif
#endif
double PITimer::elapsed_n() { double PITimer::elapsed_n() {
#ifdef WINDOWS #ifdef WINDOWS
t_cur = GetCurrentTime(); t_cur = GetCurrentTime();
return (t_cur - t_st) * 1000000.; return (t_cur - t_st) * 1000000.;
#else #else
# ifdef MAC_OS
clock_get_time(__pi_mac_clock, &t_cur);
# else
clock_gettime(0, &t_cur); 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 #endif
} }
@@ -136,8 +318,12 @@ double PITimer::elapsed_u() {
t_cur = GetCurrentTime(); t_cur = GetCurrentTime();
return (t_cur - t_st) * 1000.; return (t_cur - t_st) * 1000.;
#else #else
# ifdef MAC_OS
clock_get_time(__pi_mac_clock, &t_cur);
# else
clock_gettime(0, &t_cur); 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 #endif
} }
@@ -147,8 +333,12 @@ double PITimer::elapsed_m() {
t_cur = GetCurrentTime(); t_cur = GetCurrentTime();
return (double)(t_cur - t_st); return (double)(t_cur - t_st);
#else #else
# ifdef MAC_OS
clock_get_time(__pi_mac_clock, &t_cur);
# else
clock_gettime(0, &t_cur); 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 #endif
} }
@@ -158,18 +348,20 @@ double PITimer::elapsed_s() {
t_cur = GetCurrentTime(); t_cur = GetCurrentTime();
return (t_cur - t_st) / 1000.; return (t_cur - t_st) / 1000.;
#else #else
# ifdef MAC_OS
clock_get_time(__pi_mac_clock, &t_cur);
# else
clock_gettime(0, &t_cur); 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 #endif
} }
double PITimer::reset_time_n() { double PITimer::reset_time_n() {
#ifdef WINDOWS #ifdef WINDOWS
t_cur = GetCurrentTime(); return t_st * 1.e+6;
return t_st * 1000000.;
#else #else
clock_gettime(0, &t_cur);
return t_st.tv_sec * 1.e+9 + t_st.tv_nsec; return t_st.tv_sec * 1.e+9 + t_st.tv_nsec;
#endif #endif
} }
@@ -177,10 +369,8 @@ double PITimer::reset_time_n() {
double PITimer::reset_time_u() { double PITimer::reset_time_u() {
#ifdef WINDOWS #ifdef WINDOWS
t_cur = GetCurrentTime(); return t_st * 1.e+3;
return (t_cur - t_st) * 1000.;
#else #else
clock_gettime(0, &t_cur);
return t_st.tv_sec * 1.e+6 + t_st.tv_nsec / 1.e+3; return t_st.tv_sec * 1.e+6 + t_st.tv_nsec / 1.e+3;
#endif #endif
} }
@@ -188,10 +378,8 @@ double PITimer::reset_time_u() {
double PITimer::reset_time_m() { double PITimer::reset_time_m() {
#ifdef WINDOWS #ifdef WINDOWS
t_cur = GetCurrentTime(); return (double)t_st;
return (double)(t_cur - t_st);
#else #else
clock_gettime(0, &t_cur);
return t_st.tv_sec * 1.e+3 + t_st.tv_nsec / 1.e+6; return t_st.tv_sec * 1.e+3 + t_st.tv_nsec / 1.e+6;
#endif #endif
} }
@@ -199,22 +387,34 @@ double PITimer::reset_time_m() {
double PITimer::reset_time_s() { double PITimer::reset_time_s() {
#ifdef WINDOWS #ifdef WINDOWS
t_cur = GetCurrentTime(); return t_st / 1000.;
return (t_cur - t_st) / 1000.;
#else #else
clock_gettime(0, &t_cur);
return t_st.tv_sec + t_st.tv_nsec / 1.e+9; return t_st.tv_sec + t_st.tv_nsec / 1.e+9;
#endif #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() { double PITimer::elapsed_system_n() {
#ifdef WINDOWS #ifdef WINDOWS
long t_cur = GetCurrentTime(); long t_cur = GetCurrentTime();
return (t_cur * 1000000.); return (t_cur * 1000000.);
#else #else
# ifdef MAC_OS
mach_timespec_t t_cur;
clock_get_time(__pi_mac_clock, &t_cur);
# else
timespec t_cur; timespec t_cur;
clock_gettime(0, &t_cur); clock_gettime(0, &t_cur);
# endif
return (t_cur.tv_sec * 1.e+9 + t_cur.tv_nsec); return (t_cur.tv_sec * 1.e+9 + t_cur.tv_nsec);
#endif #endif
} }
@@ -225,8 +425,13 @@ double PITimer::elapsed_system_u() {
long t_cur = GetCurrentTime(); long t_cur = GetCurrentTime();
return (t_cur * 1000.); return (t_cur * 1000.);
#else #else
# ifdef MAC_OS
mach_timespec_t t_cur;
clock_get_time(__pi_mac_clock, &t_cur);
# else
timespec t_cur; timespec t_cur;
clock_gettime(0, &t_cur); clock_gettime(0, &t_cur);
# endif
return (t_cur.tv_sec * 1.e+6 + (t_cur.tv_nsec / 1.e+3)); return (t_cur.tv_sec * 1.e+6 + (t_cur.tv_nsec / 1.e+3));
#endif #endif
} }
@@ -237,8 +442,13 @@ double PITimer::elapsed_system_m() {
long t_cur = GetCurrentTime(); long t_cur = GetCurrentTime();
return (double)t_cur; return (double)t_cur;
#else #else
# ifdef MAC_OS
mach_timespec_t t_cur;
clock_get_time(__pi_mac_clock, &t_cur);
# else
timespec t_cur; timespec t_cur;
clock_gettime(0, &t_cur); clock_gettime(0, &t_cur);
# endif
return (t_cur.tv_sec * 1.e+3 + (t_cur.tv_nsec / 1.e+6)); return (t_cur.tv_sec * 1.e+3 + (t_cur.tv_nsec / 1.e+6));
#endif #endif
} }
@@ -249,8 +459,13 @@ double PITimer::elapsed_system_s() {
long t_cur = GetCurrentTime(); long t_cur = GetCurrentTime();
return (t_cur / 1000.); return (t_cur / 1000.);
#else #else
# ifdef MAC_OS
mach_timespec_t t_cur;
clock_get_time(__pi_mac_clock, &t_cur);
# else
timespec t_cur; timespec t_cur;
clock_gettime(0, &t_cur); clock_gettime(0, &t_cur);
# endif
return (t_cur.tv_sec + (t_cur.tv_nsec / 1.e+9)); return (t_cur.tv_sec + (t_cur.tv_nsec / 1.e+9));
#endif #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 PITime::toString(const PIString & format) {
PIString ts = format; PIString ts = format;
ts.replace("hh", PIString::fromNumber(hours).expandLeftTo(2, '0')); 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 PIDate::toString(const PIString & format) {
PIString ts = format; PIString ts = format;
ts.replace("yyyy", PIString::fromNumber(year).expandLeftTo(4, '0')); ts.replace("yyyy", PIString::fromNumber(year).expandLeftTo(4, '0'));
ts.replace("yy", PIString::fromNumber(year).expandLeftTo(2, '0')); ts.replace("yy", PIString::fromNumber(year).right(2));
ts.replace("y", PIString::fromNumber(year)); ts.replace("y", PIString::fromNumber(year).right(1));
ts.replace("mm", PIString::fromNumber(month).expandLeftTo(2, '0')); ts.replace("MM", PIString::fromNumber(month).expandLeftTo(2, '0'));
ts.replace("m", PIString::fromNumber(month)); 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("dd", PIString::fromNumber(day).expandLeftTo(2, '0'));
ts.replace("d", PIString::fromNumber(day)); ts.replace("d", PIString::fromNumber(day));
return ts; return ts;
@@ -318,10 +583,29 @@ PIString time2string(const PITime & time, const PIString & format) {
PIString date2string(const PIDate & date, const PIString & format) { PIString date2string(const PIDate & date, const PIString & format) {
PIString ts = format; PIString ts = format;
ts.replace("yyyy", PIString::fromNumber(date.year).expandLeftTo(4, '0')); ts.replace("yyyy", PIString::fromNumber(date.year).expandLeftTo(4, '0'));
ts.replace("yy", PIString::fromNumber(date.year).expandLeftTo(2, '0')); ts.replace("yy", PIString::fromNumber(date.year).right(2));
ts.replace("y", PIString::fromNumber(date.year)); ts.replace("y", PIString::fromNumber(date.year).right(1));
ts.replace("mm", PIString::fromNumber(date.month).expandLeftTo(2, '0')); ts.replace("MM", PIString::fromNumber(date.month).expandLeftTo(2, '0'));
ts.replace("m", PIString::fromNumber(date.month)); 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("dd", PIString::fromNumber(date.day).expandLeftTo(2, '0'));
ts.replace("d", PIString::fromNumber(date.day)); ts.replace("d", PIString::fromNumber(date.day));
return ts; return ts;

160
pitimer.h
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Timer 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 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 it under the terms of the GNU General Public License as published by
@@ -28,6 +28,45 @@
typedef void (*TimerEvent)(void * , int ); 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 { struct PITime {
int seconds; int seconds;
int minutes; int minutes;
@@ -38,29 +77,67 @@ struct PITime {
struct PIDate { struct PIDate {
int day; int day;
int month; int month;
int year; // since 1900 int year;
PIString toString(const PIString & format = "d.mm.yyyy"); 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 class PITimer
#ifdef WINDOWS #ifndef PIP_TIMER_RT
: public PIThread : public PIThread
#else #else
: public PIObject : public PIObject
#endif #endif
{ {
public: public:
PITimer(TimerEvent slot = 0, void * data = 0); PITimer(TimerEvent slot = 0, void * data = 0, bool threaded = true);
~PITimer(); PITimer(bool threaded);
virtual ~PITimer();
void setData(void * data_) {data = data_;} void setData(void * data_) {data = data_;}
void setSlot(TimerEvent slot) {ret_func = slot;} void setSlot(TimerEvent slot) {ret_func = slot;}
#ifdef WINDOWS #ifndef PIP_TIMER_RT
void reset() {t_st = GetCurrentTime();} # 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 #else
EVENT_HANDLER0(PITimer, void, reset) {clock_gettime(0, &t_st);} EVENT_HANDLER0(PITimer, void, reset) {clock_gettime(0, &t_st);}
EVENT_HANDLER1(PITimer, void, start, double, msecs); 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_HANDLER0(PITimer, bool, waitForFinish) {return waitForFinish(-1);}
EVENT_HANDLER1(PITimer, bool, waitForFinish, int, timeout_msecs); EVENT_HANDLER1(PITimer, bool, waitForFinish, int, timeout_msecs);
bool isRunning() const {return running;} bool isRunning() const {return running;}
@@ -83,29 +160,71 @@ public:
double reset_time_u(); // microseconds double reset_time_u(); // microseconds
double reset_time_m(); // miliseconds double reset_time_m(); // miliseconds
double reset_time_s(); // seconds double reset_time_s(); // seconds
PISystemTime reset_time();
static double elapsed_system_n(); // nanoseconds static double elapsed_system_n(); // nanoseconds
static double elapsed_system_u(); // microseconds static double elapsed_system_u(); // microseconds
static double elapsed_system_m(); // miliseconds static double elapsed_system_m(); // miliseconds
static double elapsed_system_s(); // seconds static double elapsed_system_s(); // seconds
private:
#ifdef WINDOWS
void run();
long t_st, t_cur; #ifdef PIP_TIMER_RT
#else 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<PITimer * , int> 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<TimerPair> timers;
PIMutex mutex;
};
static void timer_event(sigval e); 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; volatile bool lockRun;
PIMutex mutex_; PIMutex mutex_;
int ti; int ti;
itimerspec spec; itimerspec spec;
timespec t_st, t_cur;
timer_t timer; timer_t timer;
sigevent se; sigevent se;
#endif #endif
#ifdef WINDOWS
long
#elif defined(MAC_OS)
mach_timespec_t
#else
timespec
#endif
t_st, t_cur;
struct TimerSlot { struct TimerSlot {
TimerSlot(TimerEvent slot_ = 0, int delim_ = 1) {slot = slot_; delim = delim_; tick = 0;} TimerSlot(TimerEvent slot_ = 0, int delim_ = 1) {slot = slot_; delim = delim_; tick = 0;}
TimerEvent slot; TimerEvent slot;
@@ -119,9 +238,16 @@ private:
}; };
#ifdef PIP_TIMER_RT
extern PITimer::TimerPool * pool;
#endif
PITime currentTime(); PITime currentTime();
PIDate currentDate(); PIDate currentDate();
PIDateTime currentDateTime();
PISystemTime currentSystemTime();
PIString time2string(const PITime & time, const PIString & format = "h:mm:ss"); // obsolete, use PITime.toString() instead 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 #endif // PITIMER_H

2
pivariable.cpp Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Variable, Struct (simple serialization) 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 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 it under the terms of the GNU General Public License as published by

2
pivariable.h Executable file → Normal file
View File

@@ -1,7 +1,7 @@
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Variable, Struct (simple serialization) 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 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 it under the terms of the GNU General Public License as published by

192
protocols.conf Normal file
View File

@@ -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

View File

@@ -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)

106
system_test/main.cpp Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#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<double> 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
};

BIN
Описание.odt Executable file → Normal file

Binary file not shown.

0
Описание.pdf Executable file → Normal file
View File